Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -740,35 +740,33 @@ 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 "(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 "(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; // Expansion. if (Op0 && rightDistributesOverLeft(Op0->getOpcode(), TopLevelOpcode)) { Index: llvm/test/Transforms/InstCombine/add4.ll =================================================================== --- llvm/test/Transforms/InstCombine/add4.ll +++ llvm/test/Transforms/InstCombine/add4.ll @@ -127,3 +127,73 @@ %t4 = add i32 %t, %t3 ret i32 %t4 } + +; TODO: (x + (-1)) + (x * 5) --> (x * 6) + (-1) +define i32 @mul_add_common_factor_commute0(i32 %x) { +; CHECK-LABEL: @mul_add_common_factor_commute0( +; CHECK-NEXT: [[X1:%.*]] = add i32 [[X:%.*]], -1 +; CHECK-NEXT: [[X2:%.*]] = mul i32 [[X]], 5 +; CHECK-NEXT: [[X3:%.*]] = add i32 [[X1]], [[X2]] +; CHECK-NEXT: ret i32 [[X3]] +; + %x1 = add i32 %x, -1 + %x2 = mul i32 %x, 5 + %x3 = add i32 %x1, %x2 + ret i32 %x3 +} + +; TODO: (x * 4) + (x - 1) --> (x * 5) + (-1) +define i32 @mul_add_common_factor_commute1(i32 %x) { +; CHECK-LABEL: @mul_add_common_factor_commute1( +; CHECK-NEXT: [[X1:%.*]] = add i32 [[X:%.*]], -1 +; CHECK-NEXT: [[X2:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: [[X3:%.*]] = add i32 [[X2]], [[X1]] +; CHECK-NEXT: ret i32 [[X3]] +; + %x1 = add i32 %x, -1 + %x2 = mul i32 %x, 4 + %x3 = add i32 %x2, %x1 + ret i32 %x3 +} + +; TODO: (x + y) + (x * 4) --> (x * 5) + y +define i32 @mul_add_common_factor_commute2(i32 %x, i32 %y) { +; CHECK-LABEL: @mul_add_common_factor_commute2( +; CHECK-NEXT: [[X1:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[X2:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: [[X3:%.*]] = add i32 [[X2]], [[X1]] +; CHECK-NEXT: ret i32 [[X3]] +; + %x1 = add i32 %x, %y + %x2 = mul i32 %x, 4 + %x3 = add i32 %x2, %x1 + ret i32 %x3 +} + +; TODO: (x + y) + (x << 2) --> (x * 5) + y +define i32 @shl_add_common_factor_commute2(i32 %x, i32 %y) { +; CHECK-LABEL: @shl_add_common_factor_commute2( +; CHECK-NEXT: [[X1:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[X2:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: [[X3:%.*]] = add i32 [[X2]], [[X1]] +; CHECK-NEXT: ret i32 [[X3]] +; + %x1 = add i32 %x, %y + %x2 = shl i32 %x, 2 + %x3 = add i32 %x2, %x1 + ret i32 %x3 +} + +; TODO: (x + 2) + (x * t) --> (t + 1) * x + 2 +define i32 @mul_add_common_factor_commute3(i32 %x, i32 %t) { +; CHECK-LABEL: @mul_add_common_factor_commute3( +; CHECK-NEXT: [[X1:%.*]] = add i32 [[X:%.*]], 2 +; CHECK-NEXT: [[X2:%.*]] = mul i32 [[X]], [[T:%.*]] +; CHECK-NEXT: [[X3:%.*]] = add i32 [[X2]], [[X1]] +; CHECK-NEXT: ret i32 [[X3]] +; + %x1 = add i32 %x, 2 + %x2 = mul i32 %x, %t + %x3 = add i32 %x2, %x1 + ret i32 %x3 +}