Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -909,6 +909,13 @@ // 0-(trunc A) => trunc (0-A) if (Value *NegA = freelyNegateValue(A)) return Builder.CreateTrunc(NegA, V->getType()); + } else if (match(V, m_Mul(m_Value(A), m_Value(B)))) { + // 0-(A*B) => (0-A)*B + // 0-(A*B) => A*(0-B) + if (Value *NegA = freelyNegateValue(A)) + return Builder.CreateMul(NegA, B, V->getName() + ".neg"); + if (Value *NegB = freelyNegateValue(B)) + return Builder.CreateMul(A, NegB, V->getName() + ".neg"); } return nullptr; Index: llvm/test/Transforms/InstCombine/and-or-icmps.ll =================================================================== --- llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -208,12 +208,20 @@ ; CHECK-LABEL: @simplify_before_foldAndOfICmps( ; CHECK-NEXT: [[A8:%.*]] = alloca i16, align 2 ; CHECK-NEXT: [[L7:%.*]] = load i16, i16* [[A8]], align 2 -; CHECK-NEXT: [[C10:%.*]] = icmp ult i16 [[L7]], 2 +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[L7]], -1 +; CHECK-NEXT: [[B11:%.*]] = zext i1 [[TMP1]] to i16 +; CHECK-NEXT: [[C10:%.*]] = icmp ugt i16 [[L7]], [[B11]] +; CHECK-NEXT: [[C5:%.*]] = icmp slt i16 [[L7]], 1 +; CHECK-NEXT: [[C11:%.*]] = icmp ne i16 [[L7]], 0 ; CHECK-NEXT: [[C7:%.*]] = icmp slt i16 [[L7]], 0 -; CHECK-NEXT: [[C18:%.*]] = or i1 [[C7]], [[C10]] -; CHECK-NEXT: [[L7_LOBIT:%.*]] = ashr i16 [[L7]], 15 -; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[L7_LOBIT]] to i64 -; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, i1* null, i64 [[TMP1]] +; CHECK-NEXT: [[B15:%.*]] = xor i1 [[C7]], [[C10]] +; CHECK-NEXT: [[B19:%.*]] = xor i1 [[C11]], [[B15]] +; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[C10]], [[C5]] +; CHECK-NEXT: [[C3:%.*]] = and i1 [[B19]], [[TMP2]] +; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[C10]], true +; CHECK-NEXT: [[C18:%.*]] = or i1 [[C7]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = sext i1 [[C3]] to i64 +; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, i1* null, i64 [[TMP4]] ; CHECK-NEXT: store i16 [[L7]], i16* undef, align 2 ; CHECK-NEXT: store i1 [[C18]], i1* undef, align 1 ; CHECK-NEXT: store i1* [[G26]], i1** undef, align 8 Index: llvm/test/Transforms/InstCombine/mul.ll =================================================================== --- llvm/test/Transforms/InstCombine/mul.ll +++ llvm/test/Transforms/InstCombine/mul.ll @@ -456,10 +456,9 @@ 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: [[TMP1:%.*]] = mul i32 [[Y]], [[X:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = sub i32 0, [[TMP1]] -; CHECK-NEXT: ret i32 [[MUL]] +; CHECK-NEXT: [[Y_NEG:%.*]] = mul i32 [[Z:%.*]], -3 +; CHECK-NEXT: [[DOTNEG:%.*]] = mul i32 [[Y_NEG]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[DOTNEG]] ; %y = mul i32 %z, 3 %neg = sub i32 0, %x Index: llvm/test/Transforms/InstCombine/sub.ll =================================================================== --- llvm/test/Transforms/InstCombine/sub.ll +++ llvm/test/Transforms/InstCombine/sub.ll @@ -689,10 +689,9 @@ define i64 @test_neg_mul_sub(i64 %a, i64 %b, i64 %c) { ; CHECK-LABEL: @test_neg_mul_sub( -; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[SUB]], [[C:%.*]] -; CHECK-NEXT: [[NEG:%.*]] = sub i64 0, [[MUL]] -; CHECK-NEXT: ret i64 [[NEG]] +; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i64 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i64 [[SUB_NEG]], [[C:%.*]] +; CHECK-NEXT: ret i64 [[MUL_NEG]] ; %sub = sub i64 %a, %b %mul = mul i64 %sub, %c @@ -703,10 +702,9 @@ define i64 @test_neg_mul_sub_communted(i64 %a, i64 %b, i64 %c) { ; CHECK-LABEL: @test_neg_mul_sub_communted( ; CHECK-NEXT: [[COMPLEX:%.*]] = mul i64 [[C:%.*]], [[C]] -; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[COMPLEX]], [[SUB]] -; CHECK-NEXT: [[NEG:%.*]] = sub i64 0, [[MUL]] -; CHECK-NEXT: ret i64 [[NEG]] +; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i64 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i64 [[COMPLEX]], [[SUB_NEG]] +; CHECK-NEXT: ret i64 [[MUL_NEG]] ; %complex = mul i64 %c, %c %sub = sub i64 %a, %b