diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -622,7 +622,8 @@ /// other operand, try to fold the binary operator into the select arguments. /// This also works for Cast instructions, which obviously do not have a /// second operand. - Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI); + Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI, + bool Tend = false); /// This is a convenience wrapper function for the above two functions. Instruction *foldBinOpIntoSelectOrPhi(BinaryOperator &I); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -772,7 +772,8 @@ // TODO: Adapt simplifyDivRemOfSelectWithZeroOp to allow this and other folds. if (match(Op0, m_ImmConstant()) && match(Op1, m_Select(m_Value(), m_ImmConstant(), m_ImmConstant()))) { - if (Instruction *R = FoldOpIntoSelect(I, cast(Op1))) + if (Instruction *R = FoldOpIntoSelect(I, cast(Op1), + /*Tend to transform*/ true)) return R; } diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1037,10 +1037,10 @@ return NewBO; } -Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, - SelectInst *SI) { - // Don't modify shared select instructions. - if (!SI->hasOneUse()) +Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI, + bool Tend) { + // Don't modify shared select instructions unless set Force + if (!SI->hasOneUse() && !Tend) return nullptr; Value *TV = SI->getTrueValue(); diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll --- a/llvm/test/Transforms/InstCombine/div.ll +++ b/llvm/test/Transforms/InstCombine/div.ll @@ -13,8 +13,8 @@ define i32 @test2(i32 %A) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: [[B:%.*]] = lshr i32 [[A:%.*]], 3 -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: [[B1:%.*]] = lshr i32 [[A:%.*]], 3 +; CHECK-NEXT: ret i32 [[B1]] ; %B = udiv i32 %A, 8 ret i32 %B @@ -205,9 +205,9 @@ define i32 @test10(i32 %X, i1 %C) { ; CHECK-LABEL: @test10( -; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i32 6, i32 3 -; CHECK-NEXT: [[R:%.*]] = lshr i32 [[X:%.*]], [[R_V]] -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i32 6, i32 3 +; CHECK-NEXT: [[R1:%.*]] = lshr i32 [[X:%.*]], [[TMP1]] +; CHECK-NEXT: ret i32 [[R1]] ; %V = select i1 %C, i32 64, i32 8 %R = udiv i32 %X, %V @@ -216,9 +216,9 @@ define i32 @test11(i32 %X, i1 %C) { ; CHECK-LABEL: @test11( -; CHECK-NEXT: [[B_V:%.*]] = select i1 [[C:%.*]], i32 10, i32 5 -; CHECK-NEXT: [[B:%.*]] = lshr i32 [[X:%.*]], [[B_V]] -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i32 10, i32 5 +; CHECK-NEXT: [[B1:%.*]] = lshr i32 [[X:%.*]], [[TMP1]] +; CHECK-NEXT: ret i32 [[B1]] ; %A = select i1 %C, i32 1024, i32 32 %B = udiv i32 %X, %A @@ -255,8 +255,8 @@ define i32 @test15(i32 %a, i32 %b) { ; CHECK-LABEL: @test15( ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[B:%.*]], -2 -; CHECK-NEXT: [[DIV2:%.*]] = lshr i32 [[A:%.*]], [[TMP1]] -; CHECK-NEXT: ret i32 [[DIV2]] +; CHECK-NEXT: [[DIV21:%.*]] = lshr i32 [[A:%.*]], [[TMP1]] +; CHECK-NEXT: ret i32 [[DIV21]] ; %shl = shl i32 1, %b %div = lshr i32 %shl, 2 @@ -348,8 +348,8 @@ define i32 @test24(i32 %a) { ; CHECK-LABEL: @test24( -; CHECK-NEXT: [[DIV:%.*]] = lshr i32 [[A:%.*]], 2 -; CHECK-NEXT: ret i32 [[DIV]] +; CHECK-NEXT: [[DIV1:%.*]] = lshr i32 [[A:%.*]], 2 +; CHECK-NEXT: ret i32 [[DIV1]] ; %mul = mul nuw i32 %a, 3 %div = udiv i32 %mul, 12 @@ -579,8 +579,8 @@ define i32 @test36(i32 %A) { ; CHECK-LABEL: @test36( ; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 2147483647 -; CHECK-NEXT: [[MUL:%.*]] = lshr exact i32 [[AND]], [[A]] -; CHECK-NEXT: ret i32 [[MUL]] +; CHECK-NEXT: [[MUL1:%.*]] = lshr exact i32 [[AND]], [[A]] +; CHECK-NEXT: ret i32 [[MUL1]] ; %and = and i32 %A, 2147483647 %shl = shl nsw i32 1, %A @@ -591,8 +591,8 @@ define <2 x i32> @test36vec(<2 x i32> %A) { ; CHECK-LABEL: @test36vec( ; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[A:%.*]], -; CHECK-NEXT: [[MUL:%.*]] = lshr exact <2 x i32> [[AND]], [[A]] -; CHECK-NEXT: ret <2 x i32> [[MUL]] +; CHECK-NEXT: [[MUL1:%.*]] = lshr exact <2 x i32> [[AND]], [[A]] +; CHECK-NEXT: ret <2 x i32> [[MUL1]] ; %and = and <2 x i32> %A, %shl = shl nsw <2 x i32> , %A @@ -1098,13 +1098,11 @@ ret i32 %r } -; TODO: sdiv should still be replaced by select. - define i32 @sdiv_constant_dividend_select_of_constants_divisor_use(i1 %b) { ; CHECK-LABEL: @sdiv_constant_dividend_select_of_constants_divisor_use( ; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 -3 ; CHECK-NEXT: call void @use(i32 [[S]]) -; CHECK-NEXT: [[R:%.*]] = sdiv i32 42, [[S]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[B]], i32 3, i32 -14 ; CHECK-NEXT: ret i32 [[R]] ; %s = select i1 %b, i32 12, i32 -3 @@ -1204,13 +1202,11 @@ ret i32 %r } -; TODO: udiv should still be replaced by select. - define i32 @udiv_constant_dividend_select_of_constants_divisor_use(i1 %b) { ; CHECK-LABEL: @udiv_constant_dividend_select_of_constants_divisor_use( ; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 -3 ; CHECK-NEXT: call void @use(i32 [[S]]) -; CHECK-NEXT: [[R:%.*]] = udiv i32 42, [[S]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[B]], i32 3, i32 0 ; CHECK-NEXT: ret i32 [[R]] ; %s = select i1 %b, i32 12, i32 -3