Home | History | Annotate | Download | only in InstCombine
      1 ; RUN: opt -S -instcombine < %s | FileCheck %s
      2 
      3 ; (-0.0 - X) * C => X * -C
      4 define float @test1(float %x) {
      5   %sub = fsub float -0.000000e+00, %x
      6   %mul = fmul float %sub, 2.0e+1
      7   ret float %mul
      8 
      9 ; CHECK-LABEL: @test1(
     10 ; CHECK: fmul float %x, -2.000000e+01
     11 }
     12 
     13 ; (0.0 - X) * C => X * -C
     14 define float @test2(float %x) {
     15   %sub = fsub nsz float 0.000000e+00, %x
     16   %mul = fmul float %sub, 2.0e+1
     17   ret float %mul
     18 
     19 ; CHECK-LABEL: @test2(
     20 ; CHECK: fmul float %x, -2.000000e+01
     21 }
     22 
     23 ; (-0.0 - X) * (-0.0 - Y) => X * Y
     24 define float @test3(float %x, float %y) {
     25   %sub1 = fsub float -0.000000e+00, %x
     26   %sub2 = fsub float -0.000000e+00, %y
     27   %mul = fmul fast float %sub1, %sub2
     28   ret float %mul
     29 ; CHECK-LABEL: @test3(
     30 ; CHECK: fmul fast float %x, %y
     31 }
     32 
     33 ; (0.0 - X) * (0.0 - Y) => X * Y
     34 define float @test4(float %x, float %y) {
     35   %sub1 = fsub nsz float 0.000000e+00, %x
     36   %sub2 = fsub nsz float 0.000000e+00, %y
     37   %mul = fmul float %sub1, %sub2
     38   ret float %mul
     39 ; CHECK-LABEL: @test4(
     40 ; CHECK: fmul float %x, %y
     41 }
     42 
     43 ; (-0.0 - X) * Y => -0.0 - (X * Y)
     44 define float @test5(float %x, float %y) {
     45   %sub1 = fsub float -0.000000e+00, %x
     46   %mul = fmul float %sub1, %y
     47   ret float %mul
     48 ; CHECK-LABEL: @test5(
     49 ; CHECK: %1 = fmul float %x, %y
     50 ; CHECK: %mul = fsub float -0.000000e+00, %1
     51 }
     52 
     53 ; (0.0 - X) * Y => 0.0 - (X * Y)
     54 define float @test6(float %x, float %y) {
     55   %sub1 = fsub nsz float 0.000000e+00, %x
     56   %mul = fmul float %sub1, %y
     57   ret float %mul
     58 ; CHECK-LABEL: @test6(
     59 ; CHECK: %1 = fmul float %x, %y
     60 ; CHECK: %mul = fsub float -0.000000e+00, %1
     61 }
     62 
     63 ; "(-0.0 - X) * Y => -0.0 - (X * Y)" is disabled if expression "-0.0 - X"
     64 ; has multiple uses.
     65 define float @test7(float %x, float %y) {
     66   %sub1 = fsub float -0.000000e+00, %x
     67   %mul = fmul float %sub1, %y
     68   %mul2 = fmul float %mul, %sub1
     69   ret float %mul2
     70 ; CHECK-LABEL: @test7(
     71 ; CHECK: fsub float -0.000000e+00, %x
     72 }
     73 
     74 ; Don't crash when attempting to cast a constant FMul to an instruction.
     75 define void @test8(i32* %inout) {
     76 entry:
     77   %0 = load i32, i32* %inout, align 4
     78   %conv = uitofp i32 %0 to float
     79   %vecinit = insertelement <4 x float> <float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float undef>, float %conv, i32 3
     80   %sub = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vecinit
     81   %1 = shufflevector <4 x float> %sub, <4 x float> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
     82   %mul = fmul <4 x float> zeroinitializer, %1
     83   br label %for.cond
     84 
     85 for.cond:                                         ; preds = %for.body, %entry
     86   %local_var_7.0 = phi <4 x float> [ %mul, %entry ], [ %2, %for.body ]
     87   br i1 undef, label %for.body, label %for.end
     88 
     89 for.body:                                         ; preds = %for.cond
     90   %2 = insertelement <4 x float> %local_var_7.0, float 0.000000e+00, i32 2
     91   br label %for.cond
     92 
     93 for.end:                                          ; preds = %for.cond
     94   ret void
     95 }
     96 
     97 ; X * -1.0 => -0.0 - X
     98 define float @test9(float %x) {
     99   %mul = fmul float %x, -1.0
    100   ret float %mul
    101 
    102 ; CHECK-LABEL: @test9(
    103 ; CHECK-NOT: fmul
    104 ; CHECK: fsub
    105 }
    106 
    107 ; PR18532
    108 define <4 x float> @test10(<4 x float> %x) {
    109   %mul = fmul <4 x float> %x, <float -1.0, float -1.0, float -1.0, float -1.0>
    110   ret <4 x float> %mul
    111 
    112 ; CHECK-LABEL: @test10(
    113 ; CHECK-NOT: fmul
    114 ; CHECK: fsub
    115 }
    116 
    117 define float @test11(float %x, float %y) {
    118   %a = fadd fast float %x, 1.0
    119   %b = fadd fast float %y, 2.0
    120   %c = fadd fast float %a, %b
    121   ret float %c
    122 ; CHECK-LABEL: @test11(
    123 ; CHECK-NOT: fadd float
    124 ; CHECK: fadd fast float
    125 }
    126 
    127 ; PR21126: http://llvm.org/bugs/show_bug.cgi?id=21126
    128 ; With unsafe/fast math, sqrt(X) * sqrt(X) is just X.
    129 declare double @llvm.sqrt.f64(double)
    130 
    131 define double @sqrt_squared1(double %f) {
    132   %sqrt = call double @llvm.sqrt.f64(double %f)
    133   %mul = fmul fast double %sqrt, %sqrt
    134   ret double %mul
    135 ; CHECK-LABEL: @sqrt_squared1(
    136 ; CHECK-NEXT: ret double %f
    137 }
    138 
    139 ; With unsafe/fast math, sqrt(X) * sqrt(X) is just X, 
    140 ; but make sure another use of the sqrt is intact.
    141 ; Note that the remaining fmul is altered but is not 'fast'
    142 ; itself because it was not marked 'fast' originally. 
    143 ; Thus, we have an overall fast result, but no more indication of
    144 ; 'fast'ness in the code.
    145 define double @sqrt_squared2(double %f) {
    146   %sqrt = call double @llvm.sqrt.f64(double %f)
    147   %mul1 = fmul fast double %sqrt, %sqrt
    148   %mul2 = fmul double %mul1, %sqrt
    149   ret double %mul2
    150 ; CHECK-LABEL: @sqrt_squared2(
    151 ; CHECK-NEXT: %sqrt = call double @llvm.sqrt.f64(double %f)
    152 ; CHECK-NEXT: %mul2 = fmul double %sqrt, %f
    153 ; CHECK-NEXT: ret double %mul2
    154 }
    155