Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1649,15 +1649,14 @@ // X - A*-B -> X + A*B // X - -A*B -> X + A*B Value *A, *B; - Constant *CI; if (match(Op1, m_c_Mul(m_Value(A), m_Neg(m_Value(B))))) return BinaryOperator::CreateAdd(Op0, Builder.CreateMul(A, B)); // X - A*CI -> X + A*-CI // No need to handle commuted multiply because multiply handling will // ensure constant will be move to the right hand side. - if (match(Op1, m_Mul(m_Value(A), m_Constant(CI)))) { - Value *NewMul = Builder.CreateMul(A, ConstantExpr::getNeg(CI)); + if (match(Op1, m_Mul(m_Value(A), m_Constant(C))) && !isa(C)) { + Value *NewMul = Builder.CreateMul(A, ConstantExpr::getNeg(C)); return BinaryOperator::CreateAdd(Op0, NewMul); } } Index: test/Transforms/InstCombine/mul.ll =================================================================== --- test/Transforms/InstCombine/mul.ll +++ test/Transforms/InstCombine/mul.ll @@ -445,9 +445,9 @@ define i32 @test_mul_canonicalize_op0(i32 %x, i32 %y) { ; CHECK-LABEL: @test_mul_canonicalize_op0( -; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[MUL]] -; CHECK-NEXT: ret i32 [[NEG]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = sub i32 0, [[TMP1]] +; CHECK-NEXT: ret i32 [[MUL]] ; %neg = sub i32 0, %x %mul = mul i32 %neg, %y @@ -457,11 +457,11 @@ define i32 @test_mul_canonicalize_op1(i32 %x, i32 %z) { ; CHECK-LABEL: @test_mul_canonicalize_op1( ; CHECK-NEXT: [[Y:%.*]] = mul i32 [[Z:%.*]], 3 -; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[MUL]] -; CHECK-NEXT: ret i32 [[NEG]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[Y]], [[X:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = sub i32 0, [[TMP1]] +; CHECK-NEXT: ret i32 [[MUL]] ; - %y = mul i32 %z, 3 + %y = mul i32 %z, 3 %neg = sub i32 0, %x %mul = mul i32 %y, %neg ret i32 %mul @@ -469,9 +469,9 @@ define i32 @test_mul_canonicalize_nsw(i32 %x, i32 %y) { ; CHECK-LABEL: @test_mul_canonicalize_nsw( -; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[MUL]] -; CHECK-NEXT: ret i32 [[NEG]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = sub i32 0, [[TMP1]] +; CHECK-NEXT: ret i32 [[MUL]] ; %neg = sub nsw i32 0, %x %mul = mul nsw i32 %neg, %y @@ -480,9 +480,9 @@ define <2 x i32> @test_mul_canonicalize_vec(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @test_mul_canonicalize_vec( -; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i32> zeroinitializer, [[MUL]] -; CHECK-NEXT: ret <2 x i32> [[NEG]] +; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = sub <2 x i32> zeroinitializer, [[TMP1]] +; CHECK-NEXT: ret <2 x i32> [[MUL]] ; %neg = sub <2 x i32> , %x %mul = mul <2 x i32> %neg, %y @@ -501,3 +501,19 @@ %mul2 = mul i32 %mul, %neg ret i32 %mul2 } + +@X = global i32 5 + +define i64 @test_mul_canonicalize_neg_is_not_undone(i64 %L1) { +; Check we do not undo the canonicalization of 0 - (X * Y), if Y is a constant +; expr. +; CHECK-LABEL: @test_mul_canonicalize_neg_is_not_undone( +; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[L1:%.*]], ptrtoint (i32* @X to i64) +; CHECK-NEXT: [[B4:%.*]] = sub i64 0, [[TMP1]] +; CHECK-NEXT: ret i64 [[B4]] +; + %v1 = ptrtoint i32* @X to i64 + %B8 = sub i64 0, %v1 + %B4 = mul i64 %B8, %L1 + ret i64 %B4 +}