Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -221,11 +221,14 @@ return replaceInstUsesWith(I, FoldedMul); // Simplify mul instructions with a constant RHS. - if (isa(Op1)) { + if (match(Op1, m_ImmConstant())) { // Canonicalize (X+C1)*CI -> X*CI+C1*CI. + // Canonicalize (X|C1)*CI -> X*CI+C1*CI. Value *X; Constant *C1; - if (match(Op0, m_OneUse(m_Add(m_Value(X), m_Constant(C1))))) { + if ((match(Op0, m_OneUse(m_Add(m_Value(X), m_ImmConstant(C1))))) || + (match(Op0, m_OneUse(m_Or(m_Value(X), m_ImmConstant(C1)))) && + haveNoCommonBitsSet(X, C1, DL))) { Value *Mul = Builder.CreateMul(C1, Op1); // Only go forward with the transform if C1*CI simplifies to a tidier // constant. Index: llvm/test/Transforms/InstCombine/mul.ll =================================================================== --- llvm/test/Transforms/InstCombine/mul.ll +++ llvm/test/Transforms/InstCombine/mul.ll @@ -624,6 +624,58 @@ ret i32 %mul } +define i32 @PR57278_shl(i32 %a) { +; CHECK-LABEL: @PR57278_shl( +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 12 +; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9 +; CHECK-NEXT: ret i32 [[MUL]] +; + %shl = shl nsw i32 %a, 2 + %add = or i32 %shl, 3 + %mul = mul nsw i32 %add, 3 + ret i32 %mul +} + +; Negative test: Have common bits set +define i32 @PR57278_shl_1(i32 %a) { +; CHECK-LABEL: @PR57278_shl_1( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[A:%.*]], 2 +; CHECK-NEXT: [[ADD:%.*]] = or i32 [[SHL]], 4 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ADD]], 3 +; CHECK-NEXT: ret i32 [[MUL]] +; + %shl = shl nsw i32 %a, 2 + %add = or i32 %shl, 4 + %mul = mul nsw i32 %add, 3 + ret i32 %mul +} + +define i32 @PR57278_mul(i32 %a) { +; CHECK-LABEL: @PR57278_mul( +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 36 +; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9 +; CHECK-NEXT: ret i32 [[MUL]] +; + %mul0 = mul nsw i32 %a, 12 + %add = or i32 %mul0, 3 + %mul = mul nsw i32 %add, 3 + ret i32 %mul +} + +; Negative test: Have common bits set +define i32 @PR57278_mul_1(i32 %a) { +; CHECK-LABEL: @PR57278_mul_1( +; CHECK-NEXT: [[MUL0:%.*]] = mul nsw i32 [[A:%.*]], 12 +; CHECK-NEXT: [[ADD:%.*]] = or i32 [[MUL0]], 4 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ADD]], 3 +; CHECK-NEXT: ret i32 [[MUL]] +; + %mul0 = mul nsw i32 %a, 12 + %add = or i32 %mul0, 4 + %mul = mul nsw i32 %add, 3 + ret i32 %mul +} + define <2 x i1> @test21(<2 x i1> %A, <2 x i1> %B) { ; CHECK-LABEL: @test21( ; CHECK-NEXT: [[C:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]]