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 FoldWithMultiUse = 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), + /*FoldWithMultiUse*/ 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 FoldWithMultiUse) { + // Don't modify shared select instructions unless set FoldWithMultiUse + if (!SI->hasOneUse() && !FoldWithMultiUse) 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 @@ -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