llvm.org GIT mirror llvm / 9c2eeb6
[Reassociate] try harder to convert negative FP constants to positive This is an extension of a transform that tries to produce positive floating-point constants to improve canonicalization (and hopefully lead to more reassociation and CSE). The original patches were: D4904 D5363 (rL221721) But as the test diffs show, these were limited to basic patterns by walking from an instruction to its single user rather than recursively moving up the def-use sequence. No fast-math is required here because we're only rearranging implicit FP negations in intermediate ops. A motivating bug is: https://bugs.llvm.org/show_bug.cgi?id=32939 Differential Revision: https://reviews.llvm.org/D65954 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368512 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel a month ago
5 changed file(s) with 210 addition(s) and 165 deletion(s). Raw diff Collapse all Expand all
121121 void EraseInst(Instruction *I);
122122 void RecursivelyEraseDeadInsts(Instruction *I, OrderedSet &Insts);
123123 void OptimizeInst(Instruction *I);
124 Instruction *canonicalizeNegConstExpr(Instruction *I);
124 Instruction *canonicalizeNegFPConstantsForOp(Instruction *I, Instruction *Op,
125 Value *OtherOp);
126 Instruction *canonicalizeNegFPConstants(Instruction *I);
125127 void BuildPairMap(ReversePostOrderTraversal &RPOT);
126128 };
127129
19371937 MadeChange = true;
19381938 }
19391939
1940 // Canonicalize expressions of the following form:
1941 // x + (-Constant * y) -> x - (Constant * y)
1942 // x - (-Constant * y) -> x + (Constant * y)
1943 Instruction *ReassociatePass::canonicalizeNegConstExpr(Instruction *I) {
1944 if (!I->hasOneUse() || I->getType()->isVectorTy())
1945 return nullptr;
1946
1947 // Must be a fmul or fdiv instruction.
1948 unsigned Opcode = I->getOpcode();
1949 if (Opcode != Instruction::FMul && Opcode != Instruction::FDiv)
1950 return nullptr;
1951
1952 auto *C0 = dyn_cast(I->getOperand(0));
1953 auto *C1 = dyn_cast(I->getOperand(1));
1954
1955 // Both operands are constant, let it get constant folded away.
1956 if (C0 && C1)
1957 return nullptr;
1958
1959 ConstantFP *CF = C0 ? C0 : C1;
1960
1961 // Must have one constant operand.
1962 if (!CF)
1963 return nullptr;
1964
1965 // Must be a negative ConstantFP.
1966 if (!CF->isNegative())
1967 return nullptr;
1968
1969 // User must be a binary operator with one or more uses.
1970 Instruction *User = I->user_back();
1971 if (!isa(User) || User->use_empty())
1972 return nullptr;
1973
1974 unsigned UserOpcode = User->getOpcode();
1975 if (UserOpcode != Instruction::FAdd && UserOpcode != Instruction::FSub)
1976 return nullptr;
1977
1978 // Subtraction is not commutative. Explicitly, the following transform is
1979 // not valid: (-Constant * y) - x -> x + (Constant * y)
1980 if (!User->isCommutative() && User->getOperand(1) != I)
1940 /// Recursively analyze an expression to build a list of instructions that have
1941 /// negative floating-point constant operands. The caller can then transform
1942 /// the list to create positive constants for better reassociation and CSE.
1943 static void getNegatibleInsts(Value *V,
1944 SmallVectorImpl &Candidates) {
1945 // Handle only one-use instructions. Combining negations does not justify
1946 // replicating instructions.
1947 Instruction *I;
1948 if (!match(V, m_OneUse(m_Instruction(I))))
1949 return;
1950
1951 // Handle expressions of multiplications and divisions.
1952 // TODO: This could look through floating-point casts.
1953 const APFloat *C;
1954 switch (I->getOpcode()) {
1955 case Instruction::FMul:
1956 // Not expecting non-canonical code here. Bail out and wait.
1957 if (match(I->getOperand(0), m_Constant()))
1958 break;
1959
1960 if (match(I->getOperand(1), m_APFloat(C)) && C->isNegative()) {
1961 Candidates.push_back(I);
1962 LLVM_DEBUG(dbgs() << "FMul with negative constant: " << *I << '\n');
1963 }
1964 getNegatibleInsts(I->getOperand(0), Candidates);
1965 getNegatibleInsts(I->getOperand(1), Candidates);
1966 break;
1967 case Instruction::FDiv:
1968 // Not expecting non-canonical code here. Bail out and wait.
1969 if (match(I->getOperand(0), m_Constant()) &&
1970 match(I->getOperand(1), m_Constant()))
1971 break;
1972
1973 if ((match(I->getOperand(0), m_APFloat(C)) && C->isNegative()) ||
1974 (match(I->getOperand(1), m_APFloat(C)) && C->isNegative())) {
1975 Candidates.push_back(I);
1976 LLVM_DEBUG(dbgs() << "FDiv with negative constant: " << *I << '\n');
1977 }
1978 getNegatibleInsts(I->getOperand(0), Candidates);
1979 getNegatibleInsts(I->getOperand(1), Candidates);
1980 break;
1981 default:
1982 break;
1983 }
1984 }
1985
1986 /// Given an fadd/fsub with an operand that is a one-use instruction
1987 /// (the fadd/fsub), try to change negative floating-point constants into
1988 /// positive constants to increase potential for reassociation and CSE.
1989 Instruction *ReassociatePass::canonicalizeNegFPConstantsForOp(Instruction *I,
1990 Instruction *Op,
1991 Value *OtherOp) {
1992 assert((I->getOpcode() == Instruction::FAdd ||
1993 I->getOpcode() == Instruction::FSub) && "Expected fadd/fsub");
1994
1995 // Collect instructions with negative FP constants from the subtree that ends
1996 // in Op.
1997 SmallVector Candidates;
1998 getNegatibleInsts(Op, Candidates);
1999 if (Candidates.empty())
19812000 return nullptr;
19822001
19832002 // Don't canonicalize x + (-Constant * y) -> x - (Constant * y), if the
19842003 // resulting subtract will be broken up later. This can get us into an
19852004 // infinite loop during reassociation.
1986 if (UserOpcode == Instruction::FAdd && ShouldBreakUpSubtract(User))
2005 bool IsFSub = I->getOpcode() == Instruction::FSub;
2006 bool NeedsSubtract = !IsFSub && Candidates.size() % 2 == 1;
2007 if (NeedsSubtract && ShouldBreakUpSubtract(I))
19872008 return nullptr;
19882009
1989 // Change the sign of the constant.
1990 APFloat Val = CF->getValueAPF();
1991 Val.changeSign();
1992 I->setOperand(C0 ? 0 : 1, ConstantFP::get(CF->getContext(), Val));
1993
1994 // Canonicalize I to RHS to simplify the next bit of logic. E.g.,
1995 // ((-Const*y) + x) -> (x + (-Const*y)).
1996 if (User->getOperand(0) == I && User->isCommutative())
1997 cast(User)->swapOperands();
1998
1999 Value *Op0 = User->getOperand(0);
2000 Value *Op1 = User->getOperand(1);
2001 BinaryOperator *NI;
2002 switch (UserOpcode) {
2003 default:
2004 llvm_unreachable("Unexpected Opcode!");
2005 case Instruction::FAdd:
2006 NI = BinaryOperator::CreateFSub(Op0, Op1);
2007 NI->setFastMathFlags(cast(User)->getFastMathFlags());
2008 break;
2009 case Instruction::FSub:
2010 NI = BinaryOperator::CreateFAdd(Op0, Op1);
2011 NI->setFastMathFlags(cast(User)->getFastMathFlags());
2012 break;
2013 }
2014
2015 NI->insertBefore(User);
2016 NI->setName(User->getName());
2017 User->replaceAllUsesWith(NI);
2018 NI->setDebugLoc(I->getDebugLoc());
2010 for (Instruction *Negatible : Candidates) {
2011 const APFloat *C;
2012 if (match(Negatible->getOperand(0), m_APFloat(C))) {
2013 assert(!match(Negatible->getOperand(1), m_Constant()) &&
2014 "Expecting only 1 constant operand");
2015 assert(C->isNegative() && "Expected negative FP constant");
2016 Negatible->setOperand(0, ConstantFP::get(Negatible->getType(), abs(*C)));
2017 MadeChange = true;
2018 }
2019 if (match(Negatible->getOperand(1), m_APFloat(C))) {
2020 assert(!match(Negatible->getOperand(0), m_Constant()) &&
2021 "Expecting only 1 constant operand");
2022 assert(C->isNegative() && "Expected negative FP constant");
2023 Negatible->setOperand(1, ConstantFP::get(Negatible->getType(), abs(*C)));
2024 MadeChange = true;
2025 }
2026 }
2027 assert(MadeChange == true && "Negative constant candidate was not changed");
2028
2029 // Negations cancelled out.
2030 if (Candidates.size() % 2 == 0)
2031 return I;
2032
2033 // Negate the final operand in the expression by flipping the opcode of this
2034 // fadd/fsub.
2035 assert(Candidates.size() % 2 == 1 && "Expected odd number");
2036 IRBuilder<> Builder(I);
2037 Value *NewInst = IsFSub ? Builder.CreateFAddFMF(OtherOp, Op, I)
2038 : Builder.CreateFSubFMF(OtherOp, Op, I);
2039 I->replaceAllUsesWith(NewInst);
20192040 RedoInsts.insert(I);
2020 MadeChange = true;
2021 return NI;
2041 return dyn_cast(NewInst);
2042 }
2043
2044 /// Canonicalize expressions that contain a negative floating-point constant
2045 /// of the following form:
2046 /// OtherOp + (subtree) -> OtherOp {+/-} (canonical subtree)
2047 /// (subtree) + OtherOp -> OtherOp {+/-} (canonical subtree)
2048 /// OtherOp - (subtree) -> OtherOp {+/-} (canonical subtree)
2049 ///
2050 /// The fadd/fsub opcode may be switched to allow folding a negation into the
2051 /// input instruction.
2052 Instruction *ReassociatePass::canonicalizeNegFPConstants(Instruction *I) {
2053 LLVM_DEBUG(dbgs() << "Combine negations for: " << *I << '\n');
2054 Value *X;
2055 Instruction *Op;
2056 if (match(I, m_FAdd(m_Value(X), m_OneUse(m_Instruction(Op)))))
2057 if (Instruction *R = canonicalizeNegFPConstantsForOp(I, Op, X))
2058 I = R;
2059 if (match(I, m_FAdd(m_OneUse(m_Instruction(Op)), m_Value(X))))
2060 if (Instruction *R = canonicalizeNegFPConstantsForOp(I, Op, X))
2061 I = R;
2062 if (match(I, m_FSub(m_Value(X), m_OneUse(m_Instruction(Op)))))
2063 if (Instruction *R = canonicalizeNegFPConstantsForOp(I, Op, X))
2064 I = R;
2065 return I;
20222066 }
20232067
20242068 /// Inspect and optimize the given instruction. Note that erasing
20412085 I = NI;
20422086 }
20432087
2044 // Canonicalize negative constants out of expressions.
2045 if (Instruction *Res = canonicalizeNegConstExpr(I))
2046 I = Res;
2047
20482088 // Commute binary operators, to canonicalize the order of their operands.
20492089 // This can potentially expose more CSE opportunities, and makes writing other
20502090 // transformations simpler.
20512091 if (I->isCommutative())
20522092 canonicalizeOperands(I);
2093
2094 // Canonicalize negative constants out of expressions.
2095 if (Instruction *Res = canonicalizeNegFPConstants(I))
2096 I = Res;
20532097
20542098 // Don't optimize floating-point instructions unless they are 'fast'.
20552099 if (I->getType()->isFPOrFPVectorTy() && !I->isFast())
186186
187187 define double @fadd_fmul_neg_const1(double %a, double %b, double %c) {
188188 ; CHECK-LABEL: @fadd_fmul_neg_const1(
189 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
189 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], 3.000000e+00
190190 ; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[C:%.*]]
191 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A:%.*]], [[MUL1]]
192 ; CHECK-NEXT: ret double [[ADD]]
191 ; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[A:%.*]], [[MUL1]]
192 ; CHECK-NEXT: ret double [[TMP1]]
193193 ;
194194 %mul0 = fmul double %b, -3.0
195195 %mul1 = fmul double %mul0, %c
199199
200200 define double @fadd_fmul_neg_const2(double %a, double %b, double %c) {
201201 ; CHECK-LABEL: @fadd_fmul_neg_const2(
202 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
202 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
203203 ; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
204204 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
205 ; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[A]], [[MUL2]]
206 ; CHECK-NEXT: ret double [[ADD1]]
205 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A]], [[MUL2]]
206 ; CHECK-NEXT: ret double [[ADD]]
207207 ;
208208 %mul0 = fmul double %a, -3.0
209209 %mul1 = fmul double %mul0, %b
214214
215215 define double @fadd_fmul_neg_const3(double %a, double %b, double %c) {
216216 ; CHECK-LABEL: @fadd_fmul_neg_const3(
217 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
217 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
218218 ; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
219 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], -4.000000e+00
219 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
220220 ; CHECK-NEXT: [[MUL3:%.*]] = fmul double [[MUL2]], 5.000000e+00
221 ; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[C:%.*]], [[MUL3]]
222 ; CHECK-NEXT: ret double [[ADD1]]
221 ; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[C:%.*]], [[MUL3]]
222 ; CHECK-NEXT: ret double [[TMP1]]
223223 ;
224224 %mul0 = fmul double %a, -3.0
225225 %mul1 = fmul double %mul0, %b
231231
232232 define double @fsub_fmul_neg_const1(double %a, double %b, double %c) {
233233 ; CHECK-LABEL: @fsub_fmul_neg_const1(
234 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
234 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], 3.000000e+00
235235 ; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[C:%.*]]
236 ; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A:%.*]], [[MUL1]]
237 ; CHECK-NEXT: ret double [[SUB]]
236 ; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[A:%.*]], [[MUL1]]
237 ; CHECK-NEXT: ret double [[TMP1]]
238238 ;
239239 %mul0 = fmul double %b, -3.0
240240 %mul1 = fmul double %mul0, %c
244244
245245 define double @fsub_fmul_neg_const2(double %a, double %b, double %c) {
246246 ; CHECK-LABEL: @fsub_fmul_neg_const2(
247 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
247 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
248248 ; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
249249 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
250 ; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A]], [[MUL2]]
251 ; CHECK-NEXT: ret double [[SUB]]
250 ; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[A]], [[MUL2]]
251 ; CHECK-NEXT: ret double [[TMP1]]
252252 ;
253253 %mul0 = fmul double %a, -3.0
254254 %mul1 = fmul double %mul0, %b
261261 ; CHECK-LABEL: @fsub_fmul_neg_const3(
262262 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
263263 ; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
264 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], -4.000000e+00
264 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
265265 ; CHECK-NEXT: [[MUL3:%.*]] = fmul double [[MUL2]], 5.000000e+00
266 ; CHECK-NEXT: [[SUB1:%.*]] = fadd double [[C:%.*]], [[MUL3]]
267 ; CHECK-NEXT: ret double [[SUB1]]
266 ; CHECK-NEXT: [[SUB:%.*]] = fsub double [[C:%.*]], [[MUL3]]
267 ; CHECK-NEXT: ret double [[SUB]]
268268 ;
269269 %mul0 = fmul double %a, 3.0
270270 %mul1 = fmul double %mul0, %b
276276
277277 define double @fadd_fdiv_neg_const1(double %a, double %b, double %c) {
278278 ; CHECK-LABEL: @fadd_fdiv_neg_const1(
279 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], -3.000000e+00
279 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], 3.000000e+00
280280 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[C:%.*]]
281 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A:%.*]], [[DIV1]]
282 ; CHECK-NEXT: ret double [[ADD]]
281 ; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[A:%.*]], [[DIV1]]
282 ; CHECK-NEXT: ret double [[TMP1]]
283283 ;
284284 %div0 = fdiv double %b, -3.0
285285 %div1 = fdiv double %div0, %c
289289
290290 define double @fadd_fdiv_neg_const2(double %a, double %b, double %c) {
291291 ; CHECK-LABEL: @fadd_fdiv_neg_const2(
292 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
292 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
293293 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
294294 ; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[DIV1]], 7.000000e+00
295 ; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[A]], [[DIV2]]
296 ; CHECK-NEXT: ret double [[ADD1]]
295 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A]], [[DIV2]]
296 ; CHECK-NEXT: ret double [[ADD]]
297297 ;
298298 %div0 = fdiv double -3.0, %a
299299 %div1 = fdiv double %div0, %b
304304
305305 define double @fadd_fdiv_neg_const3(double %a, double %b, double %c) {
306306 ; CHECK-LABEL: @fadd_fdiv_neg_const3(
307 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[A:%.*]], -3.000000e+00
307 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[A:%.*]], 3.000000e+00
308308 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
309 ; CHECK-NEXT: [[DIV2:%.*]] = fdiv double -4.000000e+00, [[DIV1]]
309 ; CHECK-NEXT: [[DIV2:%.*]] = fdiv double 4.000000e+00, [[DIV1]]
310310 ; CHECK-NEXT: [[DIV3:%.*]] = fdiv double [[DIV2]], 5.000000e+00
311311 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[C:%.*]], [[DIV3]]
312312 ; CHECK-NEXT: ret double [[ADD]]
321321
322322 define double @fsub_fdiv_neg_const1(double %a, double %b, double %c) {
323323 ; CHECK-LABEL: @fsub_fdiv_neg_const1(
324 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], -3.000000e+00
324 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], 3.000000e+00
325325 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[C:%.*]]
326 ; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A:%.*]], [[DIV1]]
327 ; CHECK-NEXT: ret double [[SUB]]
326 ; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[A:%.*]], [[DIV1]]
327 ; CHECK-NEXT: ret double [[TMP1]]
328328 ;
329329 %div0 = fdiv double %b, -3.0
330330 %div1 = fdiv double %div0, %c
334334
335335 define double @fsub_fdiv_neg_const2(double %a, double %b, double %c) {
336336 ; CHECK-LABEL: @fsub_fdiv_neg_const2(
337 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
337 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
338338 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
339339 ; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[DIV1]], 7.000000e+00
340 ; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A]], [[DIV2]]
341 ; CHECK-NEXT: ret double [[SUB]]
340 ; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[A]], [[DIV2]]
341 ; CHECK-NEXT: ret double [[TMP1]]
342342 ;
343343 %div0 = fdiv double -3.0, %a
344344 %div1 = fdiv double %div0, %b
349349
350350 define double @fsub_fdiv_neg_const3(double %a, double %b, double %c) {
351351 ; CHECK-LABEL: @fsub_fdiv_neg_const3(
352 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
352 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
353353 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
354 ; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[DIV1]], -7.000000e+00
354 ; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[DIV1]], 7.000000e+00
355355 ; CHECK-NEXT: [[DIV3:%.*]] = fdiv double 5.000000e+00, [[DIV2]]
356 ; CHECK-NEXT: [[SUB1:%.*]] = fadd double [[C:%.*]], [[DIV3]]
357 ; CHECK-NEXT: ret double [[SUB1]]
356 ; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[C:%.*]], [[DIV3]]
357 ; CHECK-NEXT: ret double [[TMP1]]
358358 ;
359359 %div0 = fdiv double -3.0, %a
360360 %div1 = fdiv double %div0, %b
366366
367367 define double @fadd_mix_neg_const1(double %a, double %b, double %c) {
368368 ; CHECK-LABEL: @fadd_mix_neg_const1(
369 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
369 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], 3.000000e+00
370370 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[MUL0]], [[C:%.*]]
371 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A:%.*]], [[DIV1]]
372 ; CHECK-NEXT: ret double [[ADD]]
371 ; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[A:%.*]], [[DIV1]]
372 ; CHECK-NEXT: ret double [[TMP1]]
373373 ;
374374 %mul0 = fmul double %b, -3.0
375375 %div1 = fdiv double %mul0, %c
379379
380380 define double @fadd_mix_neg_const2(double %a, double %b, double %c) {
381381 ; CHECK-LABEL: @fadd_mix_neg_const2(
382 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
382 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
383383 ; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[DIV0]], [[B:%.*]]
384384 ; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[MUL1]], 5.000000e+00
385 ; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[A]], [[DIV2]]
386 ; CHECK-NEXT: ret double [[ADD1]]
385 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A]], [[DIV2]]
386 ; CHECK-NEXT: ret double [[ADD]]
387387 ;
388388 %div0 = fdiv double -3.0, %a
389389 %mul1 = fmul double %div0, %b
394394
395395 define double @fadd_mix_neg_const3(double %a, double %b, double %c) {
396396 ; CHECK-LABEL: @fadd_mix_neg_const3(
397 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
397 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
398398 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[MUL0]], [[B:%.*]]
399 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[DIV1]], -4.000000e+00
399 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[DIV1]], 4.000000e+00
400400 ; CHECK-NEXT: [[DIV3:%.*]] = fdiv double [[MUL2]], 5.000000e+00
401 ; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[C:%.*]], [[DIV3]]
402 ; CHECK-NEXT: ret double [[ADD1]]
401 ; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[C:%.*]], [[DIV3]]
402 ; CHECK-NEXT: ret double [[TMP1]]
403403 ;
404404 %mul0 = fmul double %a, -3.0
405405 %div1 = fdiv double %mul0, %b
411411
412412 define double @fsub_mix_neg_const1(double %a, double %b, double %c) {
413413 ; CHECK-LABEL: @fsub_mix_neg_const1(
414 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], -3.000000e+00
414 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double [[B:%.*]], 3.000000e+00
415415 ; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[DIV0]], [[C:%.*]]
416 ; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A:%.*]], [[MUL1]]
417 ; CHECK-NEXT: ret double [[SUB]]
416 ; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[A:%.*]], [[MUL1]]
417 ; CHECK-NEXT: ret double [[TMP1]]
418418 ;
419419 %div0 = fdiv double %b, -3.0
420420 %mul1 = fmul double %div0, %c
423423 }
424424 define double @fsub_mix_neg_const2(double %a, double %b, double %c) {
425425 ; CHECK-LABEL: @fsub_mix_neg_const2(
426 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
426 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
427427 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[MUL0]], [[B:%.*]]
428428 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[DIV1]], 5.000000e+00
429 ; CHECK-NEXT: [[SUB1:%.*]] = fadd double [[A]], [[MUL2]]
430 ; CHECK-NEXT: ret double [[SUB1]]
429 ; CHECK-NEXT: [[SUB:%.*]] = fsub double [[A]], [[MUL2]]
430 ; CHECK-NEXT: ret double [[SUB]]
431431 ;
432432 %mul0 = fmul double -3.0, %a
433433 %div1 = fdiv double %mul0, %b
438438
439439 define double @fsub_mix_neg_const3(double %a, double %b, double %c) {
440440 ; CHECK-LABEL: @fsub_mix_neg_const3(
441 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
441 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
442442 ; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[DIV0]], [[B:%.*]]
443 ; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[MUL1]], -7.000000e+00
443 ; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[MUL1]], 7.000000e+00
444444 ; CHECK-NEXT: [[MUL3:%.*]] = fmul double [[DIV2]], 5.000000e+00
445 ; CHECK-NEXT: [[SUB1:%.*]] = fadd double [[C:%.*]], [[MUL3]]
446 ; CHECK-NEXT: ret double [[SUB1]]
445 ; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[C:%.*]], [[MUL3]]
446 ; CHECK-NEXT: ret double [[TMP1]]
447447 ;
448448 %div0 = fdiv double -3.0, %a
449449 %mul1 = fmul double %div0, %b
457457 ; CHECK-LABEL: @fadd_both_ops_mix_neg_const1(
458458 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
459459 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[MUL0]], [[C:%.*]]
460 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[A:%.*]], -4.000000e+00
460 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[A:%.*]], 4.000000e+00
461461 ; CHECK-NEXT: [[DIV3:%.*]] = fdiv double [[MUL2]], [[C]]
462 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[DIV1]], [[DIV3]]
463 ; CHECK-NEXT: ret double [[ADD]]
462 ; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[DIV1]], [[DIV3]]
463 ; CHECK-NEXT: ret double [[TMP1]]
464464 ;
465465 %mul0 = fmul double %b, -3.0
466466 %div1 = fdiv double %mul0, %c
472472
473473 define double @fadd_both_ops_mix_neg_const2(double %a, double %b, double %c) {
474474 ; CHECK-LABEL: @fadd_both_ops_mix_neg_const2(
475 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
475 ; CHECK-NEXT: [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
476476 ; CHECK-NEXT: [[MUL1:%.*]] = fmul double [[DIV0]], [[B:%.*]]
477477 ; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[MUL1]], 7.000000e+00
478 ; CHECK-NEXT: [[DIV3:%.*]] = fdiv double -5.000000e+00, [[C:%.*]]
478 ; CHECK-NEXT: [[DIV3:%.*]] = fdiv double 5.000000e+00, [[C:%.*]]
479479 ; CHECK-NEXT: [[MUL4:%.*]] = fmul double [[B]], [[DIV3]]
480 ; CHECK-NEXT: [[DIV5:%.*]] = fdiv double [[MUL4]], -6.000000e+00
481 ; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[DIV5]], [[DIV2]]
482 ; CHECK-NEXT: ret double [[ADD1]]
480 ; CHECK-NEXT: [[DIV5:%.*]] = fdiv double [[MUL4]], 6.000000e+00
481 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[DIV2]], [[DIV5]]
482 ; CHECK-NEXT: ret double [[ADD]]
483483 ;
484484 %div0 = fdiv double -3.0, %a
485485 %mul1 = fmul double %div0, %b
496496 ; CHECK-NEXT: [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
497497 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[MUL0]], [[B:%.*]]
498498 ; CHECK-NEXT: [[MUL2:%.*]] = fmul double [[DIV1]], -4.000000e+00
499 ; CHECK-NEXT: [[DIV3:%.*]] = fdiv double [[MUL2]], 5.000000e+00
500 ; CHECK-NEXT: [[MUL4:%.*]] = fmul double [[C:%.*]], -6.000000e+00
499 ; CHECK-NEXT: [[DIV3:%.*]] = fdiv double [[MUL2]], -5.000000e+00
500 ; CHECK-NEXT: [[MUL4:%.*]] = fmul double [[C:%.*]], 6.000000e+00
501501 ; CHECK-NEXT: [[DIV5:%.*]] = fdiv double [[MUL4]], [[B]]
502 ; CHECK-NEXT: [[MUL6:%.*]] = fmul double [[DIV5]], -7.000000e+00
503 ; CHECK-NEXT: [[MUL7:%.*]] = fdiv double [[MUL6]], -9.000000e+00
504 ; CHECK-NEXT: [[ADD1:%.*]] = fsub double [[MUL7]], [[DIV3]]
505 ; CHECK-NEXT: ret double [[ADD1]]
502 ; CHECK-NEXT: [[MUL6:%.*]] = fmul double [[DIV5]], 7.000000e+00
503 ; CHECK-NEXT: [[MUL7:%.*]] = fdiv double [[MUL6]], 9.000000e+00
504 ; CHECK-NEXT: [[TMP1:%.*]] = fsub double [[DIV3]], [[MUL7]]
505 ; CHECK-NEXT: ret double [[TMP1]]
506506 ;
507507 %mul0 = fmul double %a, -3.0
508508 %div1 = fdiv double %mul0, %b
281281 define <2 x float> @test10(<2 x float> %a, <2 x float> %b, <2 x float> %z) {
282282 ; CHECK-LABEL: @test10(
283283 ; CHECK-NEXT: [[TMP1:%.*]] = fsub fast <2 x float> zeroinitializer, zeroinitializer
284 ; CHECK-NEXT: [[E:%.*]] = fmul fast <2 x float> [[A:%.*]],
285 ; CHECK-NEXT: [[F:%.*]] = fmul fast <2 x float> [[E]], [[Z:%.*]]
286 ; CHECK-NEXT: ret <2 x float> [[F]]
284 ; CHECK-NEXT: [[C:%.*]] = fmul fast <2 x float> [[A:%.*]],
285 ; CHECK-NEXT: [[E:%.*]] = fmul fast <2 x float> [[C]], [[Z:%.*]]
286 ; CHECK-NEXT: [[TMP2:%.*]] = fadd fast <2 x float> [[E]], zeroinitializer
287 ; CHECK-NEXT: ret <2 x float> [[TMP2]]
287288 ;
288289 %d = fmul fast <2 x float> %z,
289290 %c = fsub fast <2 x float> , %d
342343
343344 define <2 x double> @test11(<2 x double> %x, <2 x double> %y) {
344345 ; CHECK-LABEL: @test11(
345 ; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast <2 x double> [[X:%.*]], [[Y:%.*]]
346 ; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast <2 x double> [[Y:%.*]], [[X:%.*]]
346347 ; CHECK-NEXT: [[REASS_MUL:%.*]] = fmul fast <2 x double> [[FACTOR]],
347348 ; CHECK-NEXT: ret <2 x double> [[REASS_MUL]]
348349 ;
380381 ret <2 x i64> %shl
381382 }
382383
383 ; FIXME: expressions with a negative const should be canonicalized to assist
384 ; further reassociation.
385 ; We would expect (-5*b)+a -> a-(5*b) but only the constant operand is commuted.
384 ; (-5*b)+a -> a-(5*b)
386385
387386 define <4 x float> @test13(<4 x float> %a, <4 x float> %b) {
388387 ; CHECK-LABEL: @test13(
389 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast <4 x float> [[B:%.*]],
390 ; CHECK-NEXT: [[ADD:%.*]] = fadd fast <4 x float> [[MUL]], [[A:%.*]]
391 ; CHECK-NEXT: ret <4 x float> [[ADD]]
388 ; CHECK-NEXT: [[MUL:%.*]] = fmul fast <4 x float> [[B:%.*]],
389 ; CHECK-NEXT: [[TMP1:%.*]] = fsub fast <4 x float> [[A:%.*]], [[MUL]]
390 ; CHECK-NEXT: ret <4 x float> [[TMP1]]
392391 ;
393392 %mul = fmul fast <4 x float> , %b
394393 %add = fadd fast <4 x float> %mul, %a
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
11 ; RUN: opt < %s -reassociate -S | FileCheck %s
22
3 ; Input is A op (B op C)
3 ; B * 5 + A * -5
4 ; TODO: (B - A) * 5
45
56 define half @faddsubAssoc1(half %a, half %b) {
67 ; CHECK-LABEL: @faddsubAssoc1(
7 ; CHECK-NEXT: [[T2_NEG:%.*]] = fmul fast half [[A:%.*]], 0xH4500
8 ; CHECK-NEXT: [[T2_NEG:%.*]] = fmul fast half [[A:%.*]], 0xHC500
89 ; CHECK-NEXT: [[REASS_MUL:%.*]] = fmul fast half [[B:%.*]], 0xH4500
9 ; CHECK-NEXT: [[T51:%.*]] = fsub fast half [[REASS_MUL]], [[T2_NEG]]
1010 ; CHECK-NEXT: [[T5:%.*]] = fadd fast half [[REASS_MUL]], [[T2_NEG]]
11 ; CHECK-NEXT: ret half [[T51]]
11 ; CHECK-NEXT: ret half [[T5]]
1212 ;
1313 %t1 = fmul fast half %b, 0xH4200 ; 3*b
1414 %t2 = fmul fast half %a, 0xH4500 ; 5*a
1818 ret half %t5 ; = 5 * (b - a)
1919 }
2020
21 ; Input is (A op B) op C
21 ; B + A * 5
2222
2323 define half @faddsubAssoc2(half %a, half %b) {
2424 ; CHECK-LABEL: @faddsubAssoc2(