Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -740,34 +740,67 @@ BinaryOperator *Op1 = dyn_cast(RHS); Instruction::BinaryOps TopLevelOpcode = I.getOpcode(); - { - // Factorization. - Value *A, *B, *C, *D; - Instruction::BinaryOps LHSOpcode, RHSOpcode; - if (Op0) - LHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op0, A, B); - if (Op1) - RHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op1, C, D); - - // The instruction has the form "(A op' B) op (C op' D)". Try to factorize - // a common term. - if (Op0 && Op1 && LHSOpcode == RHSOpcode) - if (Value *V = tryFactorization(I, LHSOpcode, A, B, C, D)) + // Factorization. + Value *A, *B, *C, *D; + Instruction::BinaryOps LHSOpcode, RHSOpcode; + if (Op0) + LHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op0, A, B); + if (Op1) + RHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op1, C, D); + + // The instruction has the form "(A op' B) op (C op' D)". Try to factorize + // a common term. + if (Op0 && Op1 && LHSOpcode == RHSOpcode) + if (Value *V = tryFactorization(I, LHSOpcode, A, B, C, D)) + return V; + + // The instruction has the form "(A op' B) op (C)". Try to factorize common + // term. + if (Op0) { + if (Value *Ident = getIdentityValue(LHSOpcode, RHS)) + if (Value *V = tryFactorization(I, LHSOpcode, A, B, RHS, Ident)) return V; + } + + // The instruction has the form "(B) op (C op' D)". Try to factorize common + // term. + if (Op1) { + if (Value *Ident = getIdentityValue(RHSOpcode, LHS)) + if (Value *V = tryFactorization(I, RHSOpcode, LHS, Ident, C, D)) + return V; + } + + // The instruction has the form "(A * B) op (C op D)". Try to factorize + // common term for "(A * B) op (C)". + if (Op0 && Op1 && LHSOpcode == Instruction::Mul && + TopLevelOpcode == RHSOpcode && Instruction::isCommutative(RHSOpcode)) + if (Value *Ident = getIdentityValue(LHSOpcode, C)) + if (Value *V = tryFactorization(I, LHSOpcode, A, B, C, Ident)) { + Value *New = Builder.CreateBinOp(RHSOpcode, V, D); + if (dyn_cast(&I)) { + cast(New)->setHasNoSignedWrap(I.hasNoSignedWrap()); + cast(New)->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); + } + return New; + } - // The instruction has the form "(A op' B) op (C)". Try to factorize common - // term. - if (Op0) - if (Value *Ident = getIdentityValue(LHSOpcode, RHS)) - if (Value *V = tryFactorization(I, LHSOpcode, A, B, RHS, Ident)) - return V; - - // The instruction has the form "(B) op (C op' D)". Try to factorize common - // term. - if (Op1) - if (Value *Ident = getIdentityValue(RHSOpcode, LHS)) - if (Value *V = tryFactorization(I, RHSOpcode, LHS, Ident, C, D)) - return V; + // The instruction has the form "(A op' B) op' (C * D)". See if expanding it + // out to "(C * D) op' (A op' B)" results in simplifications. + if (Op0 && Op1 && RHSOpcode == Instruction::Mul && A == C && + LHSOpcode == TopLevelOpcode && + rightDistributesOverLeft(TopLevelOpcode, RHSOpcode)) { + bool InnerCommutative = Instruction::isCommutative(TopLevelOpcode); + if (dyn_cast(B) && InnerCommutative) { + // They do! Return "RHS op' LHS". + ++NumExpand; + Value *New = Builder.CreateBinOp(TopLevelOpcode, RHS, LHS); + New->takeName(&I); + if (dyn_cast(&I)) { + cast(New)->setHasNoSignedWrap(I.hasNoSignedWrap()); + cast(New)->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); + } + return New; + } } // Expansion. Index: llvm/test/Transforms/InstCombine/add4.ll =================================================================== --- llvm/test/Transforms/InstCombine/add4.ll +++ llvm/test/Transforms/InstCombine/add4.ll @@ -127,3 +127,57 @@ %t4 = add i32 %t, %t3 ret i32 %t4 } + +; (x - 1) - (x * C) --> (1 + C) * x - 1 +define i32 @mul_add_common_factor_commute0(i32 %x) { +; CHECK-LABEL: @mul_add_common_factor_commute0( +; CHECK-NEXT: [[X3:%.*]] = mul i32 [[X:%.*]], 6 +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X3]], -1 +; CHECK-NEXT: ret i32 [[TMP1]] +; + %x1 = add i32 %x, -1 + %x2 = mul i32 %x, 5 + %x3 = add i32 %x1, %x2 + ret i32 %x3 +} + +; (x - 1) - (x * C) --> (1 + C) * x - 1 +define i32 @mul_add_common_factor_commute1(i32 %x) { +; CHECK-LABEL: @mul_add_common_factor_commute1( +; CHECK-NEXT: [[X3:%.*]] = mul i32 [[X:%.*]], 5 +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X3]], -1 +; CHECK-NEXT: ret i32 [[TMP1]] +; + %x1 = add i32 %x, -1 + %x2 = mul i32 %x, 4 + %x3 = add i32 %x2, %x1 + ret i32 %x3 +} + +; (x + y) - (x * C) --> (1 + C) * x + y +define i32 @mul_add_common_factor_commute2(i32 %x, i32 %y) { +; CHECK-LABEL: @mul_add_common_factor_commute2( +; CHECK-NEXT: [[X3:%.*]] = mul i32 [[X:%.*]], 5 +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X3]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[TMP1]] +; + %x1 = add i32 %x, %y + %x2 = mul i32 %x, 4 + %x3 = add i32 %x2, %x1 + ret i32 %x3 +} + +; (x + 2) - (x * t) --> (1 + t) * x + 2 +define i32 @mul_add_common_factor_commute3(i32 %x, i32 %t) { +; CHECK-LABEL: @mul_add_common_factor_commute3( +; CHECK-NEXT: [[X11:%.*]] = add i32 [[T:%.*]], 1 +; CHECK-NEXT: [[X3:%.*]] = mul i32 [[X11]], [[X:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X3]], 2 +; CHECK-NEXT: ret i32 [[TMP1]] +; + %x1 = add i32 %x, 2 + %x2 = mul i32 %x, %t + %x3 = add i32 %x2, %x1 + ret i32 %x3 +} + Index: llvm/test/Transforms/PGOProfile/chr.ll =================================================================== --- llvm/test/Transforms/PGOProfile/chr.ll +++ llvm/test/Transforms/PGOProfile/chr.ll @@ -1050,10 +1050,9 @@ ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[BB0]] ], [ [[TMP5]], [[BB2_NONCHR]] ], [ [[TMP5]], [[BB1_NONCHR]] ] -; CHECK-NEXT: [[TMP9:%.*]] = mul i32 [[TMP8]], 42 -; CHECK-NEXT: [[TMP10:%.*]] = add i32 [[TMP8]], -99 -; CHECK-NEXT: [[TMP11:%.*]] = add i32 [[TMP9]], [[TMP10]] -; CHECK-NEXT: ret i32 [[TMP11]] +; CHECK-NEXT: [[TMP9:%.*]] = mul i32 [[TMP8]], 43 +; CHECK-NEXT: [[TMP10:%.*]] = add i32 [[TMP9]], -99 +; CHECK-NEXT: ret i32 [[TMP10]] ; entry: %0 = load i32, ptr %i