Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2622,6 +2622,12 @@ return BinaryOperator::CreateXor(Or, ConstantInt::get(Ty, *CV)); } + // or (mul X, CV), X --> mul X, CV+1 + if (match(&I, + m_c_Or(m_OneUse(m_Mul(m_Value(X), m_APInt(CV))), m_Deferred(X)))) + if (haveNoCommonBitsSet(Op0, Op1, DL)) + return BinaryOperator::CreateMul(X, ConstantInt::get(Ty, *CV + 1)); + // (A & C) | (B & D) Value *A, *B, *C, *D; if (match(Op0, m_And(m_Value(A), m_Value(C))) && Index: llvm/test/Transforms/InstCombine/or.ll =================================================================== --- llvm/test/Transforms/InstCombine/or.ll +++ llvm/test/Transforms/InstCombine/or.ll @@ -1445,8 +1445,7 @@ define i32 @mul_no_common_bits(i32 %p) { ; CHECK-LABEL: @mul_no_common_bits( ; CHECK-NEXT: [[X:%.*]] = and i32 [[P:%.*]], 7 -; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[X]], 24 -; CHECK-NEXT: [[R:%.*]] = or i32 [[M]], [[X]] +; CHECK-NEXT: [[R:%.*]] = mul nuw nsw i32 [[X]], 25 ; CHECK-NEXT: ret i32 [[R]] ; %x = and i32 %p, 7 @@ -1458,8 +1457,7 @@ define <2 x i12> @mul_no_common_bits_commute(<2 x i12> %p) { ; CHECK-LABEL: @mul_no_common_bits_commute( ; CHECK-NEXT: [[X:%.*]] = and <2 x i12> [[P:%.*]], -; CHECK-NEXT: [[M:%.*]] = mul nuw nsw <2 x i12> [[X]], -; CHECK-NEXT: [[R:%.*]] = or <2 x i12> [[X]], [[M]] +; CHECK-NEXT: [[R:%.*]] = mul nuw nsw <2 x i12> [[X]], ; CHECK-NEXT: ret <2 x i12> [[R]] ; %x = and <2 x i12> %p, @@ -1468,6 +1466,8 @@ ret <2 x i12> %r } +; negative test - probably not good to create an extra mul + define i32 @mul_no_common_bits_uses(i32 %p) { ; CHECK-LABEL: @mul_no_common_bits_uses( ; CHECK-NEXT: [[X:%.*]] = and i32 [[P:%.*]], 7 @@ -1482,3 +1482,18 @@ %r = or i32 %m, %x ret i32 %r } + +; negative test - %x and %m may have set 3rd bit + +define i32 @mul_common_bits(i32 %p) { +; CHECK-LABEL: @mul_common_bits( +; CHECK-NEXT: [[X:%.*]] = and i32 [[P:%.*]], 7 +; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[X]], 12 +; CHECK-NEXT: [[R:%.*]] = or i32 [[M]], [[X]] +; CHECK-NEXT: ret i32 [[R]] +; + %x = and i32 %p, 7 + %m = mul i32 %x, 12 + %r = or i32 %m, %x + ret i32 %r +}