MadeChange = true;
}
-// Canonicalize expressions of the following form:
-// x + (-Constant * y) -> x - (Constant * y)
-// x - (-Constant * y) -> x + (Constant * y)
-Instruction *ReassociatePass::canonicalizeNegConstExpr(Instruction *I) {
- if (!I->hasOneUse() || I->getType()->isVectorTy())
- return nullptr;
-
- // Must be a fmul or fdiv instruction.
- unsigned Opcode = I->getOpcode();
- if (Opcode != Instruction::FMul && Opcode != Instruction::FDiv)
- return nullptr;
-
- auto *C0 = dyn_cast<ConstantFP>(I->getOperand(0));
- auto *C1 = dyn_cast<ConstantFP>(I->getOperand(1));
-
- // Both operands are constant, let it get constant folded away.
- if (C0 && C1)
- return nullptr;
-
- ConstantFP *CF = C0 ? C0 : C1;
-
- // Must have one constant operand.
- if (!CF)
- return nullptr;
+/// Recursively analyze an expression to build a list of instructions that have
+/// negative floating-point constant operands. The caller can then transform
+/// the list to create positive constants for better reassociation and CSE.
+static void getNegatibleInsts(Value *V,
+ SmallVectorImpl<Instruction *> &Candidates) {
+ // Handle only one-use instructions. Combining negations does not justify
+ // replicating instructions.
+ Instruction *I;
+ if (!match(V, m_OneUse(m_Instruction(I))))
+ return;
- // Must be a negative ConstantFP.
- if (!CF->isNegative())
- return nullptr;
+ // Handle expressions of multiplications and divisions.
+ // TODO: This could look through floating-point casts.
+ const APFloat *C;
+ switch (I->getOpcode()) {
+ case Instruction::FMul:
+ // Not expecting non-canonical code here. Bail out and wait.
+ if (match(I->getOperand(0), m_Constant()))
+ break;
- // User must be a binary operator with one or more uses.
- Instruction *User = I->user_back();
- if (!isa<BinaryOperator>(User) || User->use_empty())
- return nullptr;
+ if (match(I->getOperand(1), m_APFloat(C)) && C->isNegative()) {
+ Candidates.push_back(I);
+ LLVM_DEBUG(dbgs() << "FMul with negative constant: " << *I << '\n');
+ }
+ getNegatibleInsts(I->getOperand(0), Candidates);
+ getNegatibleInsts(I->getOperand(1), Candidates);
+ break;
+ case Instruction::FDiv:
+ // Not expecting non-canonical code here. Bail out and wait.
+ if (match(I->getOperand(0), m_Constant()) &&
+ match(I->getOperand(1), m_Constant()))
+ break;
- unsigned UserOpcode = User->getOpcode();
- if (UserOpcode != Instruction::FAdd && UserOpcode != Instruction::FSub)
- return nullptr;
+ if ((match(I->getOperand(0), m_APFloat(C)) && C->isNegative()) ||
+ (match(I->getOperand(1), m_APFloat(C)) && C->isNegative())) {
+ Candidates.push_back(I);
+ LLVM_DEBUG(dbgs() << "FDiv with negative constant: " << *I << '\n');
+ }
+ getNegatibleInsts(I->getOperand(0), Candidates);
+ getNegatibleInsts(I->getOperand(1), Candidates);
+ break;
+ default:
+ break;
+ }
+}
- // Subtraction is not commutative. Explicitly, the following transform is
- // not valid: (-Constant * y) - x -> x + (Constant * y)
- if (!User->isCommutative() && User->getOperand(1) != I)
+/// Given an fadd/fsub with an operand that is a one-use instruction
+/// (the fadd/fsub), try to change negative floating-point constants into
+/// positive constants to increase potential for reassociation and CSE.
+Instruction *ReassociatePass::canonicalizeNegFPConstantsForOp(Instruction *I,
+ Instruction *Op,
+ Value *OtherOp) {
+ assert((I->getOpcode() == Instruction::FAdd ||
+ I->getOpcode() == Instruction::FSub) && "Expected fadd/fsub");
+
+ // Collect instructions with negative FP constants from the subtree that ends
+ // in Op.
+ SmallVector<Instruction *, 4> Candidates;
+ getNegatibleInsts(Op, Candidates);
+ if (Candidates.empty())
return nullptr;
// Don't canonicalize x + (-Constant * y) -> x - (Constant * y), if the
// resulting subtract will be broken up later. This can get us into an
// infinite loop during reassociation.
- if (UserOpcode == Instruction::FAdd && ShouldBreakUpSubtract(User))
+ bool IsFSub = I->getOpcode() == Instruction::FSub;
+ bool NeedsSubtract = !IsFSub && Candidates.size() % 2 == 1;
+ if (NeedsSubtract && ShouldBreakUpSubtract(I))
return nullptr;
- // Change the sign of the constant.
- APFloat Val = CF->getValueAPF();
- Val.changeSign();
- I->setOperand(C0 ? 0 : 1, ConstantFP::get(CF->getContext(), Val));
-
- // Canonicalize I to RHS to simplify the next bit of logic. E.g.,
- // ((-Const*y) + x) -> (x + (-Const*y)).
- if (User->getOperand(0) == I && User->isCommutative())
- cast<BinaryOperator>(User)->swapOperands();
-
- Value *Op0 = User->getOperand(0);
- Value *Op1 = User->getOperand(1);
- BinaryOperator *NI;
- switch (UserOpcode) {
- default:
- llvm_unreachable("Unexpected Opcode!");
- case Instruction::FAdd:
- NI = BinaryOperator::CreateFSub(Op0, Op1);
- NI->setFastMathFlags(cast<FPMathOperator>(User)->getFastMathFlags());
- break;
- case Instruction::FSub:
- NI = BinaryOperator::CreateFAdd(Op0, Op1);
- NI->setFastMathFlags(cast<FPMathOperator>(User)->getFastMathFlags());
- break;
+ for (Instruction *Negatible : Candidates) {
+ const APFloat *C;
+ if (match(Negatible->getOperand(0), m_APFloat(C))) {
+ assert(!match(Negatible->getOperand(1), m_Constant()) &&
+ "Expecting only 1 constant operand");
+ assert(C->isNegative() && "Expected negative FP constant");
+ Negatible->setOperand(0, ConstantFP::get(Negatible->getType(), abs(*C)));
+ MadeChange = true;
+ }
+ if (match(Negatible->getOperand(1), m_APFloat(C))) {
+ assert(!match(Negatible->getOperand(0), m_Constant()) &&
+ "Expecting only 1 constant operand");
+ assert(C->isNegative() && "Expected negative FP constant");
+ Negatible->setOperand(1, ConstantFP::get(Negatible->getType(), abs(*C)));
+ MadeChange = true;
+ }
}
+ assert(MadeChange == true && "Negative constant candidate was not changed");
- NI->insertBefore(User);
- NI->setName(User->getName());
- User->replaceAllUsesWith(NI);
- NI->setDebugLoc(I->getDebugLoc());
+ // Negations cancelled out.
+ if (Candidates.size() % 2 == 0)
+ return I;
+
+ // Negate the final operand in the expression by flipping the opcode of this
+ // fadd/fsub.
+ assert(Candidates.size() % 2 == 1 && "Expected odd number");
+ IRBuilder<> Builder(I);
+ Value *NewInst = IsFSub ? Builder.CreateFAddFMF(OtherOp, Op, I)
+ : Builder.CreateFSubFMF(OtherOp, Op, I);
+ I->replaceAllUsesWith(NewInst);
RedoInsts.insert(I);
- MadeChange = true;
- return NI;
+ return dyn_cast<Instruction>(NewInst);
+}
+
+/// Canonicalize expressions that contain a negative floating-point constant
+/// of the following form:
+/// OtherOp + (subtree) -> OtherOp {+/-} (canonical subtree)
+/// (subtree) + OtherOp -> OtherOp {+/-} (canonical subtree)
+/// OtherOp - (subtree) -> OtherOp {+/-} (canonical subtree)
+///
+/// The fadd/fsub opcode may be switched to allow folding a negation into the
+/// input instruction.
+Instruction *ReassociatePass::canonicalizeNegFPConstants(Instruction *I) {
+ LLVM_DEBUG(dbgs() << "Combine negations for: " << *I << '\n');
+ Value *X;
+ Instruction *Op;
+ if (match(I, m_FAdd(m_Value(X), m_OneUse(m_Instruction(Op)))))
+ if (Instruction *R = canonicalizeNegFPConstantsForOp(I, Op, X))
+ I = R;
+ if (match(I, m_FAdd(m_OneUse(m_Instruction(Op)), m_Value(X))))
+ if (Instruction *R = canonicalizeNegFPConstantsForOp(I, Op, X))
+ I = R;
+ if (match(I, m_FSub(m_Value(X), m_OneUse(m_Instruction(Op)))))
+ if (Instruction *R = canonicalizeNegFPConstantsForOp(I, Op, X))
+ I = R;
+ return I;
}
/// Inspect and optimize the given instruction. Note that erasing
I = NI;
}
- // Canonicalize negative constants out of expressions.
- if (Instruction *Res = canonicalizeNegConstExpr(I))
- I = Res;
-
// Commute binary operators, to canonicalize the order of their operands.
// This can potentially expose more CSE opportunities, and makes writing other
// transformations simpler.
if (I->isCommutative())
canonicalizeOperands(I);
+ // Canonicalize negative constants out of expressions.
+ if (Instruction *Res = canonicalizeNegFPConstants(I))
+ I = Res;
+
// Don't optimize floating-point instructions unless they are 'fast'.
if (I->getType()->isFPOrFPVectorTy() && !I->isFast())
return;
define double @fadd_fmul_neg_const1(double %a, double %b, double %c) {
; CHECK-LABEL: @fadd_fmul_neg_const1(
-; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], 3.000000e+00
; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[C:%.*]]
-; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A:%.*]], [[MUL1]]
-; CHECK-NEXT: ret double [[ADD]]
+; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[A:%.*]], [[MUL1]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%mul0 = fmul double %b, -3.0
%mul1 = fmul double %mul0, %c
define double @fadd_fmul_neg_const2(double %a, double %b, double %c) {
; CHECK-LABEL: @fadd_fmul_neg_const2(
-; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
-; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[A]], [[MUL2]]
-; CHECK-NEXT: ret double [[ADD1]]
+; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A]], [[MUL2]]
+; CHECK-NEXT: ret double [[ADD]]
;
%mul0 = fmul double %a, -3.0
%mul1 = fmul double %mul0, %b
define double @fadd_fmul_neg_const3(double %a, double %b, double %c) {
; CHECK-LABEL: @fadd_fmul_neg_const3(
-; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
-; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], -4.000000e+00
+; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
; CHECK-NEXT: [[MUL3:%.*]] = fmul double [[MUL2]], 5.000000e+00
-; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[C:%.*]], [[MUL3]]
-; CHECK-NEXT: ret double [[ADD1]]
+; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[C:%.*]], [[MUL3]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%mul0 = fmul double %a, -3.0
%mul1 = fmul double %mul0, %b
define double @fsub_fmul_neg_const1(double %a, double %b, double %c) {
; CHECK-LABEL: @fsub_fmul_neg_const1(
-; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], 3.000000e+00
; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[C:%.*]]
-; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A:%.*]], [[MUL1]]
-; CHECK-NEXT: ret double [[SUB]]
+; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[A:%.*]], [[MUL1]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%mul0 = fmul double %b, -3.0
%mul1 = fmul double %mul0, %c
define double @fsub_fmul_neg_const2(double %a, double %b, double %c) {
; CHECK-LABEL: @fsub_fmul_neg_const2(
-; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
-; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A]], [[MUL2]]
-; CHECK-NEXT: ret double [[SUB]]
+; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[A]], [[MUL2]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%mul0 = fmul double %a, -3.0
%mul1 = fmul double %mul0, %b
; CHECK-LABEL: @fsub_fmul_neg_const3(
; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
-; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], -4.000000e+00
+; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
; CHECK-NEXT: [[MUL3:%.*]] = fmul double [[MUL2]], 5.000000e+00
-; CHECK-NEXT: [[SUB1:%.*]] = fadd double [[C:%.*]], [[MUL3]]
-; CHECK-NEXT: ret double [[SUB1]]
+; CHECK-NEXT: [[SUB:%.*]] = fsub double [[C:%.*]], [[MUL3]]
+; CHECK-NEXT: ret double [[SUB]]
;
%mul0 = fmul double %a, 3.0
%mul1 = fmul double %mul0, %b
define double @fadd_fdiv_neg_const1(double %a, double %b, double %c) {
; CHECK-LABEL: @fadd_fdiv_neg_const1(
-; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], 3.000000e+00
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[C:%.*]]
-; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A:%.*]], [[DIV1]]
-; CHECK-NEXT: ret double [[ADD]]
+; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[A:%.*]], [[DIV1]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%div0 = fdiv double %b, -3.0
%div1 = fdiv double %div0, %c
define double @fadd_fdiv_neg_const2(double %a, double %b, double %c) {
; CHECK-LABEL: @fadd_fdiv_neg_const2(
-; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[DIV1]], 7.000000e+00
-; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[A]], [[DIV2]]
-; CHECK-NEXT: ret double [[ADD1]]
+; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A]], [[DIV2]]
+; CHECK-NEXT: ret double [[ADD]]
;
%div0 = fdiv double -3.0, %a
%div1 = fdiv double %div0, %b
define double @fadd_fdiv_neg_const3(double %a, double %b, double %c) {
; CHECK-LABEL: @fadd_fdiv_neg_const3(
-; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[A:%.*]], 3.000000e+00
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
-; CHECK-NEXT: [[DIV2:%.*]] = fdiv double -4.000000e+00, [[DIV1]]
+; CHECK-NEXT: [[DIV2:%.*]] = fdiv double 4.000000e+00, [[DIV1]]
; CHECK-NEXT: [[DIV3:%.*]] = fdiv double [[DIV2]], 5.000000e+00
; CHECK-NEXT: [[ADD:%.*]] = fadd double [[C:%.*]], [[DIV3]]
; CHECK-NEXT: ret double [[ADD]]
define double @fsub_fdiv_neg_const1(double %a, double %b, double %c) {
; CHECK-LABEL: @fsub_fdiv_neg_const1(
-; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], 3.000000e+00
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[C:%.*]]
-; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A:%.*]], [[DIV1]]
-; CHECK-NEXT: ret double [[SUB]]
+; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[A:%.*]], [[DIV1]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%div0 = fdiv double %b, -3.0
%div1 = fdiv double %div0, %c
define double @fsub_fdiv_neg_const2(double %a, double %b, double %c) {
; CHECK-LABEL: @fsub_fdiv_neg_const2(
-; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[DIV1]], 7.000000e+00
-; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A]], [[DIV2]]
-; CHECK-NEXT: ret double [[SUB]]
+; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[A]], [[DIV2]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%div0 = fdiv double -3.0, %a
%div1 = fdiv double %div0, %b
define double @fsub_fdiv_neg_const3(double %a, double %b, double %c) {
; CHECK-LABEL: @fsub_fdiv_neg_const3(
-; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
-; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[DIV1]], -7.000000e+00
+; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[DIV1]], 7.000000e+00
; CHECK-NEXT: [[DIV3:%.*]] = fdiv double 5.000000e+00, [[DIV2]]
-; CHECK-NEXT: [[SUB1:%.*]] = fadd double [[C:%.*]], [[DIV3]]
-; CHECK-NEXT: ret double [[SUB1]]
+; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[C:%.*]], [[DIV3]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%div0 = fdiv double -3.0, %a
%div1 = fdiv double %div0, %b
define double @fadd_mix_neg_const1(double %a, double %b, double %c) {
; CHECK-LABEL: @fadd_mix_neg_const1(
-; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], 3.000000e+00
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[MUL0]], [[C:%.*]]
-; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A:%.*]], [[DIV1]]
-; CHECK-NEXT: ret double [[ADD]]
+; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[A:%.*]], [[DIV1]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%mul0 = fmul double %b, -3.0
%div1 = fdiv double %mul0, %c
define double @fadd_mix_neg_const2(double %a, double %b, double %c) {
; CHECK-LABEL: @fadd_mix_neg_const2(
-; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[DIV0]], [[B:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[MUL1]], 5.000000e+00
-; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[A]], [[DIV2]]
-; CHECK-NEXT: ret double [[ADD1]]
+; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A]], [[DIV2]]
+; CHECK-NEXT: ret double [[ADD]]
;
%div0 = fdiv double -3.0, %a
%mul1 = fmul double %div0, %b
define double @fadd_mix_neg_const3(double %a, double %b, double %c) {
; CHECK-LABEL: @fadd_mix_neg_const3(
-; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[MUL0]], [[B:%.*]]
-; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[DIV1]], -4.000000e+00
+; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[DIV1]], 4.000000e+00
; CHECK-NEXT: [[DIV3:%.*]] = fdiv double [[MUL2]], 5.000000e+00
-; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[C:%.*]], [[DIV3]]
-; CHECK-NEXT: ret double [[ADD1]]
+; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[C:%.*]], [[DIV3]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%mul0 = fmul double %a, -3.0
%div1 = fdiv double %mul0, %b
define double @fsub_mix_neg_const1(double %a, double %b, double %c) {
; CHECK-LABEL: @fsub_mix_neg_const1(
-; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], 3.000000e+00
; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[DIV0]], [[C:%.*]]
-; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A:%.*]], [[MUL1]]
-; CHECK-NEXT: ret double [[SUB]]
+; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[A:%.*]], [[MUL1]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%div0 = fdiv double %b, -3.0
%mul1 = fmul double %div0, %c
}
define double @fsub_mix_neg_const2(double %a, double %b, double %c) {
; CHECK-LABEL: @fsub_mix_neg_const2(
-; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[MUL0]], [[B:%.*]]
; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[DIV1]], 5.000000e+00
-; CHECK-NEXT: [[SUB1:%.*]] = fadd double [[A]], [[MUL2]]
-; CHECK-NEXT: ret double [[SUB1]]
+; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A]], [[MUL2]]
+; CHECK-NEXT: ret double [[SUB]]
;
%mul0 = fmul double -3.0, %a
%div1 = fdiv double %mul0, %b
define double @fsub_mix_neg_const3(double %a, double %b, double %c) {
; CHECK-LABEL: @fsub_mix_neg_const3(
-; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[DIV0]], [[B:%.*]]
-; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[MUL1]], -7.000000e+00
+; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[MUL1]], 7.000000e+00
; CHECK-NEXT: [[MUL3:%.*]] = fmul double [[DIV2]], 5.000000e+00
-; CHECK-NEXT: [[SUB1:%.*]] = fadd double [[C:%.*]], [[MUL3]]
-; CHECK-NEXT: ret double [[SUB1]]
+; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[C:%.*]], [[MUL3]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%div0 = fdiv double -3.0, %a
%mul1 = fmul double %div0, %b
; CHECK-LABEL: @fadd_both_ops_mix_neg_const1(
; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[MUL0]], [[C:%.*]]
-; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[A:%.*]], -4.000000e+00
+; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[A:%.*]], 4.000000e+00
; CHECK-NEXT: [[DIV3:%.*]] = fdiv double [[MUL2]], [[C]]
-; CHECK-NEXT: [[ADD:%.*]] = fadd double [[DIV1]], [[DIV3]]
-; CHECK-NEXT: ret double [[ADD]]
+; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[DIV1]], [[DIV3]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%mul0 = fmul double %b, -3.0
%div1 = fdiv double %mul0, %c
define double @fadd_both_ops_mix_neg_const2(double %a, double %b, double %c) {
; CHECK-LABEL: @fadd_both_ops_mix_neg_const2(
-; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[DIV0]], [[B:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[MUL1]], 7.000000e+00
-; CHECK-NEXT: [[DIV3:%.*]] = fdiv double -5.000000e+00, [[C:%.*]]
+; CHECK-NEXT: [[DIV3:%.*]] = fdiv double 5.000000e+00, [[C:%.*]]
; CHECK-NEXT: [[MUL4:%.*]] = fmul double [[B]], [[DIV3]]
-; CHECK-NEXT: [[DIV5:%.*]] = fdiv double [[MUL4]], -6.000000e+00
-; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[DIV5]], [[DIV2]]
-; CHECK-NEXT: ret double [[ADD1]]
+; CHECK-NEXT: [[DIV5:%.*]] = fdiv double [[MUL4]], 6.000000e+00
+; CHECK-NEXT: [[ADD:%.*]] = fadd double [[DIV2]], [[DIV5]]
+; CHECK-NEXT: ret double [[ADD]]
;
%div0 = fdiv double -3.0, %a
%mul1 = fmul double %div0, %b
; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[MUL0]], [[B:%.*]]
; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[DIV1]], -4.000000e+00
-; CHECK-NEXT: [[DIV3:%.*]] = fdiv double [[MUL2]], 5.000000e+00
-; CHECK-NEXT: [[MUL4:%.*]] = fmul double [[C:%.*]], -6.000000e+00
+; CHECK-NEXT: [[DIV3:%.*]] = fdiv double [[MUL2]], -5.000000e+00
+; CHECK-NEXT: [[MUL4:%.*]] = fmul double [[C:%.*]], 6.000000e+00
; CHECK-NEXT: [[DIV5:%.*]] = fdiv double [[MUL4]], [[B]]
-; CHECK-NEXT: [[MUL6:%.*]] = fmul double [[DIV5]], -7.000000e+00
-; CHECK-NEXT: [[MUL7:%.*]] = fdiv double [[MUL6]], -9.000000e+00
-; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[MUL7]], [[DIV3]]
-; CHECK-NEXT: ret double [[ADD1]]
+; CHECK-NEXT: [[MUL6:%.*]] = fmul double [[DIV5]], 7.000000e+00
+; CHECK-NEXT: [[MUL7:%.*]] = fdiv double [[MUL6]], 9.000000e+00
+; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[DIV3]], [[MUL7]]
+; CHECK-NEXT: ret double [[TMP1]]
;
%mul0 = fmul double %a, -3.0
%div1 = fdiv double %mul0, %b