llvm.org GIT mirror llvm / 79df64c
[InstCombine] canonicalize fneg before fmul/fdiv Reverse the canonicalization of fneg relative to fmul/fdiv. That makes it easier to implement the transforms (and possibly other fneg transforms) in 1 place because we can always start the pattern match from fneg (either the legacy binop or the new unop). There's a secondary practical benefit seen in PR21914 and PR42681: https://bugs.llvm.org/show_bug.cgi?id=21914 https://bugs.llvm.org/show_bug.cgi?id=42681 ...hoisting fneg rather than sinking seems to play nicer with LICM in IR (although this change may expose analysis holes in the other direction). 1. The instcombine test changes show the expected neutral IR diffs from reversing the order. 2. The reassociation tests show that we were missing an optimization opportunity to fold away fneg-of-fneg. My reading of IEEE-754 says that all of these transforms are allowed (regardless of binop/unop fneg version) because: "For all other operations [besides copy/abs/negate/copysign], this standard does not specify the sign bit of a NaN result." In all of these transforms, we always have some other binop (fadd/fsub/fmul/fdiv), so we are free to flip the sign bit of a potential intermediate NaN operand. (If that interpretation is wrong, then we must already have a bug in the existing transforms?) 3. The clang tests shouldn't exist as-is, but that's effectively a revert of rL367149 (the test broke with an extension of the pre-existing fneg canonicalization in rL367146). Differential Revision: https://reviews.llvm.org/D65399 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@367447 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel a month ago
7 changed file(s) with 101 addition(s) and 89 deletion(s). Raw diff Collapse all Expand all
18991899 return nullptr;
19001900 }
19011901
1902 static Instruction *hoistFNegAboveFMulFDiv(Instruction &I,
1903 InstCombiner::BuilderTy &Builder) {
1904 Value *FNeg;
1905 if (!match(&I, m_FNeg(m_Value(FNeg))))
1906 return nullptr;
1907
1908 Value *X, *Y;
1909 if (match(FNeg, m_OneUse(m_FMul(m_Value(X), m_Value(Y)))))
1910 return BinaryOperator::CreateFMulFMF(Builder.CreateFNegFMF(X, &I), Y, &I);
1911
1912 if (match(FNeg, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))))
1913 return BinaryOperator::CreateFDivFMF(Builder.CreateFNegFMF(X, &I), Y, &I);
1914
1915 return nullptr;
1916 }
1917
19021918 Instruction *InstCombiner::visitFNeg(UnaryOperator &I) {
19031919 Value *Op = I.getOperand(0);
19041920
19151931 if (I.hasNoSignedZeros() &&
19161932 match(Op, m_OneUse(m_FSub(m_Value(X), m_Value(Y)))))
19171933 return BinaryOperator::CreateFSubFMF(Y, X, &I);
1934
1935 if (Instruction *R = hoistFNegAboveFMulFDiv(I, Builder))
1936 return R;
19181937
19191938 return nullptr;
19201939 }
19361955
19371956 if (Instruction *X = foldFNegIntoConstant(I))
19381957 return X;
1958
1959 if (Instruction *R = hoistFNegAboveFMulFDiv(I, Builder))
1960 return R;
19391961
19401962 Value *X, *Y;
19411963 Constant *C;
372372 if (match(Op0, m_FNeg(m_Value(X))) && match(Op1, m_Constant(C)))
373373 return BinaryOperator::CreateFMulFMF(X, ConstantExpr::getFNeg(C), &I);
374374
375 // Sink negation: -X * Y --> -(X * Y)
376 // But don't transform constant expressions because there's an inverse fold.
377 if (match(Op0, m_OneUse(m_FNeg(m_Value(X)))) && !isa(Op0))
378 return BinaryOperator::CreateFNegFMF(Builder.CreateFMulFMF(X, Op1, &I), &I);
379
380 // Sink negation: Y * -X --> -(X * Y)
381 // But don't transform constant expressions because there's an inverse fold.
382 if (match(Op1, m_OneUse(m_FNeg(m_Value(X)))) && !isa(Op1))
383 return BinaryOperator::CreateFNegFMF(Builder.CreateFMulFMF(X, Op0, &I), &I);
384
385375 // fabs(X) * fabs(X) -> X * X
386376 if (Op0 == Op1 && match(Op0, m_Intrinsic(m_Value(X))))
387377 return BinaryOperator::CreateFMulFMF(X, X, &I);
12331223 return &I;
12341224 }
12351225
1236 // Sink negation: -X / Y --> -(X / Y)
1237 // But don't transform constant expressions because there's an inverse fold.
1238 if (match(Op0, m_OneUse(m_FNeg(m_Value(X)))) && !isa(Op0))
1239 return BinaryOperator::CreateFNegFMF(Builder.CreateFDivFMF(X, Op1, &I), &I);
1240
1241 // Sink negation: Y / -X --> -(Y / X)
1242 // But don't transform constant expressions because there's an inverse fold.
1243 if (match(Op1, m_OneUse(m_FNeg(m_Value(X)))) && !isa(Op1))
1244 return BinaryOperator::CreateFNegFMF(Builder.CreateFDivFMF(Op0, X, &I), &I);
1245
12461226 // X / (X * Y) --> 1.0 / Y
12471227 // Reassociate to (X / X -> 1.0) is legal when NaNs are not allowed.
12481228 // We can ignore the possibility that X is infinity because INF/INF is NaN.
159159 ret double %r
160160 }
161161
162 ; Z + (-X / Y) --> Z - (X / Y)
162 ; Z + (-X / Y) - extra use means we can't transform to fsub without an extra instruction
163163
164164 define float @fdiv_fneg1_extra_use(float %x, float %y, float %pz) {
165165 ; CHECK-LABEL: @fdiv_fneg1_extra_use(
166166 ; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
167 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
168 ; CHECK-NEXT: [[DIV:%.*]] = fsub float -0.000000e+00, [[TMP1]]
167 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
168 ; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
169169 ; CHECK-NEXT: call void @use(float [[DIV]])
170 ; CHECK-NEXT: [[R:%.*]] = fsub float [[Z]], [[TMP1]]
170 ; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[DIV]]
171171 ; CHECK-NEXT: ret float [[R]]
172172 ;
173173 %z = frem float 42.0, %pz ; thwart complexity-based canonicalization
178178 ret float %r
179179 }
180180
181 ; Z + (Y / -X) --> Z - (Y / X)
181 ; Z + (Y / -X) - extra use means we can't transform to fsub without an extra instruction
182182
183183 define float @fdiv_fneg2_extra_use(float %x, float %py, float %pz) {
184184 ; CHECK-LABEL: @fdiv_fneg2_extra_use(
185185 ; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
186186 ; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
187 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[Y]], [[X:%.*]]
188 ; CHECK-NEXT: [[DIV:%.*]] = fsub float -0.000000e+00, [[TMP1]]
187 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
188 ; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y]], [[NEG]]
189189 ; CHECK-NEXT: call void @use(float [[DIV]])
190 ; CHECK-NEXT: [[R:%.*]] = fsub float [[Z]], [[TMP1]]
190 ; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[DIV]]
191191 ; CHECK-NEXT: ret float [[R]]
192192 ;
193193 %y = frem float -42.0, %py ; thwart complexity-based canonicalization
199199 ret float %r
200200 }
201201
202 ; Z + (-X * Y) --> Z - (X * Y)
202 ; Z + (-X * Y) - extra use means we can't transform to fsub without an extra instruction
203203
204204 define <2 x float> @fmul_fneg1_extra_use(<2 x float> %x, <2 x float> %y, <2 x float> %pz) {
205205 ; CHECK-LABEL: @fmul_fneg1_extra_use(
206206 ; CHECK-NEXT: [[Z:%.*]] = frem <2 x float> , [[PZ:%.*]]
207 ; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
208 ; CHECK-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[TMP1]]
207 ; CHECK-NEXT: [[NEG:%.*]] = fsub <2 x float> , [[X:%.*]]
208 ; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[NEG]], [[Y:%.*]]
209209 ; CHECK-NEXT: call void @use_vec(<2 x float> [[MUL]])
210 ; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Z]], [[TMP1]]
210 ; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[Z]], [[MUL]]
211211 ; CHECK-NEXT: ret <2 x float> [[R]]
212212 ;
213213 %z = frem <2 x float> , %pz ; thwart complexity-based canonicalization
218218 ret <2 x float> %r
219219 }
220220
221 ; Z + (Y * -X) --> Z - (Y * X)
221 ; Z + (Y * -X) - extra use means we can't transform to fsub without an extra instruction
222222
223223 define float @fmul_fneg2_extra_use(float %x, float %py, float %pz) {
224224 ; CHECK-LABEL: @fmul_fneg2_extra_use(
225225 ; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
226226 ; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
227 ; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[Y]], [[X:%.*]]
228 ; CHECK-NEXT: [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
227 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
228 ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[Y]], [[NEG]]
229229 ; CHECK-NEXT: call void @use(float [[MUL]])
230 ; CHECK-NEXT: [[R:%.*]] = fsub float [[Z]], [[TMP1]]
230 ; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[MUL]]
231231 ; CHECK-NEXT: ret float [[R]]
232232 ;
233233 %y = frem float -42.0, %py ; thwart complexity-based canonicalization
500500
501501 define double @fdiv_fneg1(double %x, double %y) {
502502 ; CHECK-LABEL: @fdiv_fneg1(
503 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
504 ; CHECK-NEXT: [[DIV:%.*]] = fsub double -0.000000e+00, [[TMP1]]
503 ; CHECK-NEXT: [[NEG:%.*]] = fsub double -0.000000e+00, [[X:%.*]]
504 ; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]]
505505 ; CHECK-NEXT: ret double [[DIV]]
506506 ;
507507 %neg = fsub double -0.0, %x
511511
512512 define double @fdiv_unary_fneg1(double %x, double %y) {
513513 ; CHECK-LABEL: @fdiv_unary_fneg1(
514 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
515 ; CHECK-NEXT: [[DIV:%.*]] = fsub double -0.000000e+00, [[TMP1]]
514 ; CHECK-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]]
515 ; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]]
516516 ; CHECK-NEXT: ret double [[DIV]]
517517 ;
518518 %neg = fneg double %x
522522
523523 define <2 x float> @fdiv_fneg2(<2 x float> %x, <2 x float> %y) {
524524 ; CHECK-LABEL: @fdiv_fneg2(
525 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x float> [[Y:%.*]], [[X:%.*]]
526 ; CHECK-NEXT: [[DIV:%.*]] = fsub <2 x float> , [[TMP1]]
525 ; CHECK-NEXT: [[NEG:%.*]] = fsub <2 x float> , [[X:%.*]]
526 ; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]]
527527 ; CHECK-NEXT: ret <2 x float> [[DIV]]
528528 ;
529529 %neg = fsub <2 x float> , %x
533533
534534 define <2 x float> @fdiv_unary_fneg2(<2 x float> %x, <2 x float> %y) {
535535 ; CHECK-LABEL: @fdiv_unary_fneg2(
536 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x float> [[Y:%.*]], [[X:%.*]]
537 ; CHECK-NEXT: [[DIV:%.*]] = fsub <2 x float> , [[TMP1]]
536 ; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
537 ; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]]
538538 ; CHECK-NEXT: ret <2 x float> [[DIV]]
539539 ;
540540 %neg = fneg <2 x float> %x
276276 ret float %mul
277277 }
278278
279 ; (-0.0 - X) * Y => -0.0 - (X * Y)
280 define float @neg_sink(float %x, float %y) {
281 ; CHECK-LABEL: @neg_sink(
282 ; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
283 ; CHECK-NEXT: [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
279 ; (-0.0 - X) * Y
280 define float @neg_mul(float %x, float %y) {
281 ; CHECK-LABEL: @neg_mul(
282 ; CHECK-NEXT: [[SUB:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
283 ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUB]], [[Y:%.*]]
284284 ; CHECK-NEXT: ret float [[MUL]]
285285 ;
286286 %sub = fsub float -0.0, %x
288288 ret float %mul
289289 }
290290
291 define float @unary_neg_sink(float %x, float %y) {
292 ; CHECK-LABEL: @unary_neg_sink(
293 ; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
294 ; CHECK-NEXT: [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
291 define float @unary_neg_mul(float %x, float %y) {
292 ; CHECK-LABEL: @unary_neg_mul(
293 ; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
294 ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NEG]], [[Y:%.*]]
295295 ; CHECK-NEXT: ret float [[MUL]]
296296 ;
297297 %neg = fneg float %x
299299 ret float %mul
300300 }
301301
302 define <2 x float> @neg_sink_vec(<2 x float> %x, <2 x float> %y) {
303 ; CHECK-LABEL: @neg_sink_vec(
304 ; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
305 ; CHECK-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[TMP1]]
302 define <2 x float> @neg_mul_vec(<2 x float> %x, <2 x float> %y) {
303 ; CHECK-LABEL: @neg_mul_vec(
304 ; CHECK-NEXT: [[SUB:%.*]] = fsub <2 x float> , [[X:%.*]]
305 ; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[SUB]], [[Y:%.*]]
306306 ; CHECK-NEXT: ret <2 x float> [[MUL]]
307307 ;
308308 %sub = fsub <2 x float> , %x
310310 ret <2 x float> %mul
311311 }
312312
313 ; FIXME: Should generate a unary FNeg.
314 define <2 x float> @unary_neg_sink_vec(<2 x float> %x, <2 x float> %y) {
315 ; CHECK-LABEL: @unary_neg_sink_vec(
316 ; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
317 ; CHECK-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[TMP1]]
313 define <2 x float> @unary_neg_mul_vec(<2 x float> %x, <2 x float> %y) {
314 ; CHECK-LABEL: @unary_neg_mul_vec(
315 ; CHECK-NEXT: [[SUB:%.*]] = fneg <2 x float> [[X:%.*]]
316 ; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[SUB]], [[Y:%.*]]
318317 ; CHECK-NEXT: ret <2 x float> [[MUL]]
319318 ;
320319 %sub = fneg <2 x float> %x
322321 ret <2 x float> %mul
323322 }
324323
325 define <2 x float> @neg_sink_vec_undef(<2 x float> %x, <2 x float> %y) {
326 ; CHECK-LABEL: @neg_sink_vec_undef(
327 ; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
328 ; CHECK-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[TMP1]]
324 define <2 x float> @neg_mul_vec_undef(<2 x float> %x, <2 x float> %y) {
325 ; CHECK-LABEL: @neg_mul_vec_undef(
326 ; CHECK-NEXT: [[SUB:%.*]] = fsub <2 x float> , [[X:%.*]]
327 ; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[SUB]], [[Y:%.*]]
329328 ; CHECK-NEXT: ret <2 x float> [[MUL]]
330329 ;
331330 %sub = fsub <2 x float> , %x
333332 ret <2 x float> %mul
334333 }
335334
336 ; (0.0 - X) * Y => 0.0 - (X * Y)
335 ; (0.0 - X) * Y
337336 define float @neg_sink_nsz(float %x, float %y) {
338337 ; CHECK-LABEL: @neg_sink_nsz(
339 ; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
340 ; CHECK-NEXT: [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
338 ; CHECK-NEXT: [[SUB1:%.*]] = fsub nsz float -0.000000e+00, [[X:%.*]]
339 ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUB1]], [[Y:%.*]]
341340 ; CHECK-NEXT: ret float [[MUL]]
342341 ;
343342 %sub1 = fsub nsz float 0.0, %x
345344 ret float %mul
346345 }
347346
348 ; "(-0.0 - X) * Y => -0.0 - (X * Y)" is disabled if expression "-0.0 - X"
349 ; has multiple uses.
350347 define float @neg_sink_multi_use(float %x, float %y) {
351348 ; CHECK-LABEL: @neg_sink_multi_use(
352349 ; CHECK-NEXT: [[SUB1:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
360357 ret float %mul2
361358 }
362359
363 define float @unary_neg_sink_multi_use(float %x, float %y) {
364 ; CHECK-LABEL: @unary_neg_sink_multi_use(
360 define float @unary_neg_mul_multi_use(float %x, float %y) {
361 ; CHECK-LABEL: @unary_neg_mul_multi_use(
365362 ; CHECK-NEXT: [[SUB1:%.*]] = fneg float [[X:%.*]]
366363 ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUB1]], [[Y:%.*]]
367364 ; CHECK-NEXT: [[MUL2:%.*]] = fmul float [[MUL]], [[SUB1]]
453453
454454 define float @fsub_fdiv_fneg1_extra_use(float %x, float %y, float %z) {
455455 ; CHECK-LABEL: @fsub_fdiv_fneg1_extra_use(
456 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
457 ; CHECK-NEXT: [[DIV:%.*]] = fsub float -0.000000e+00, [[TMP1]]
456 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
457 ; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
458458 ; CHECK-NEXT: call void @use(float [[DIV]])
459 ; CHECK-NEXT: [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
459 ; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]
460460 ; CHECK-NEXT: ret float [[R]]
461461 ;
462462 %neg = fsub float -0.000000e+00, %x
468468
469469 define float @fsub_fdiv_fneg2_extra_use(float %x, float %y, float %z) {
470470 ; CHECK-LABEL: @fsub_fdiv_fneg2_extra_use(
471 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[Y:%.*]], [[X:%.*]]
472 ; CHECK-NEXT: [[DIV:%.*]] = fsub float -0.000000e+00, [[TMP1]]
471 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
472 ; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y:%.*]], [[NEG]]
473473 ; CHECK-NEXT: call void @use(float [[DIV]])
474 ; CHECK-NEXT: [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
474 ; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]
475475 ; CHECK-NEXT: ret float [[R]]
476476 ;
477477 %neg = fsub float -0.000000e+00, %x
485485
486486 define <2 x float> @fsub_fmul_fneg1_extra_use(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
487487 ; CHECK-LABEL: @fsub_fmul_fneg1_extra_use(
488 ; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
489 ; CHECK-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[TMP1]]
488 ; CHECK-NEXT: [[NEG:%.*]] = fsub <2 x float> , [[X:%.*]]
489 ; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[NEG]], [[Y:%.*]]
490490 ; CHECK-NEXT: call void @use_vec(<2 x float> [[MUL]])
491 ; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[TMP1]], [[Z:%.*]]
491 ; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Z:%.*]], [[MUL]]
492492 ; CHECK-NEXT: ret <2 x float> [[R]]
493493 ;
494494 %neg = fsub <2 x float> , %x
500500
501501 define float @fsub_fmul_fneg2_extra_use(float %x, float %y, float %z) {
502502 ; CHECK-LABEL: @fsub_fmul_fneg2_extra_use(
503 ; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
504 ; CHECK-NEXT: [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
503 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
504 ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NEG]], [[Y:%.*]]
505505 ; CHECK-NEXT: call void @use(float [[MUL]])
506 ; CHECK-NEXT: [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
506 ; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[MUL]]
507507 ; CHECK-NEXT: ret float [[R]]
508508 ;
509509 %neg = fsub float -0.000000e+00, %x
613613 ret float %f
614614 }
615615
616 ; It is not safe to reassociate unary fneg without nnan.
616 ; fneg of fneg is an identity operation, so no FMF are needed to remove those instructions.
617
618 define float @test18_unary_fneg_no_FMF(float %a, float %b, float %z) {
619 ; CHECK-LABEL: @test18_unary_fneg_no_FMF(
620 ; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[Z:%.*]], 4.000000e+01
621 ; CHECK-NEXT: [[F:%.*]] = fmul float [[TMP1]], [[A:%.*]]
622 ; CHECK-NEXT: ret float [[F]]
623 ;
624 %d = fmul float %z, 4.000000e+01
625 %c = fneg float %d
626 %e = fmul float %a, %c
627 %f = fneg float %e
628 ret float %f
629 }
630
617631 define float @test18_reassoc_unary_fneg(float %a, float %b, float %z) {
618632 ; CHECK-LABEL: @test18_reassoc_unary_fneg(
619 ; CHECK-NEXT: [[C:%.*]] = fmul reassoc float [[Z:%.*]], -4.000000e+01
620 ; CHECK-NEXT: [[E:%.*]] = fmul reassoc float [[C]], [[A:%.*]]
621 ; CHECK-NEXT: [[F:%.*]] = fneg reassoc float [[E]]
633 ; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc float [[Z:%.*]], 4.000000e+01
634 ; CHECK-NEXT: [[F:%.*]] = fmul reassoc float [[TMP1]], [[A:%.*]]
622635 ; CHECK-NEXT: ret float [[F]]
623636 ;
624637 %d = fmul reassoc float %z, 4.000000e+01