1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
  
     | 
    
      ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -instcombine < %s | FileCheck %s
; (-0.0 - X) * C => X * -C
define float @test1(float %x) {
; CHECK-LABEL: @test1(
; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], -2.000000e+01
; CHECK-NEXT:    ret float [[MUL]]
;
  %sub = fsub float -0.000000e+00, %x
  %mul = fmul float %sub, 2.0e+1
  ret float %mul
}
; (0.0 - X) * C => X * -C
define float @test2(float %x) {
; CHECK-LABEL: @test2(
; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], -2.000000e+01
; CHECK-NEXT:    ret float [[MUL]]
;
  %sub = fsub nsz float 0.000000e+00, %x
  %mul = fmul float %sub, 2.0e+1
  ret float %mul
}
; (-0.0 - X) * (-0.0 - Y) => X * Y
define float @test3(float %x, float %y) {
; CHECK-LABEL: @test3(
; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    ret float [[MUL]]
;
  %sub1 = fsub float -0.000000e+00, %x
  %sub2 = fsub float -0.000000e+00, %y
  %mul = fmul fast float %sub1, %sub2
  ret float %mul
}
; (0.0 - X) * (0.0 - Y) => X * Y
define float @test4(float %x, float %y) {
; CHECK-LABEL: @test4(
; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    ret float [[MUL]]
;
  %sub1 = fsub nsz float 0.000000e+00, %x
  %sub2 = fsub nsz float 0.000000e+00, %y
  %mul = fmul float %sub1, %sub2
  ret float %mul
}
; (-0.0 - X) * Y => -0.0 - (X * Y)
define float @test5(float %x, float %y) {
; CHECK-LABEL: @test5(
; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
; CHECK-NEXT:    ret float [[MUL]]
;
  %sub1 = fsub float -0.000000e+00, %x
  %mul = fmul float %sub1, %y
  ret float %mul
}
; (0.0 - X) * Y => 0.0 - (X * Y)
define float @test6(float %x, float %y) {
; CHECK-LABEL: @test6(
; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
; CHECK-NEXT:    ret float [[MUL]]
;
  %sub1 = fsub nsz float 0.000000e+00, %x
  %mul = fmul float %sub1, %y
  ret float %mul
}
; "(-0.0 - X) * Y => -0.0 - (X * Y)" is disabled if expression "-0.0 - X"
; has multiple uses.
define float @test7(float %x, float %y) {
; CHECK-LABEL: @test7(
; CHECK-NEXT:    [[SUB1:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB1]], [[Y:%.*]]
; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[MUL]], [[SUB1]]
; CHECK-NEXT:    ret float [[MUL2]]
;
  %sub1 = fsub float -0.000000e+00, %x
  %mul = fmul float %sub1, %y
  %mul2 = fmul float %mul, %sub1
  ret float %mul2
}
; Don't crash when attempting to cast a constant FMul to an instruction.
define void @test8(i32* %inout) {
; CHECK-LABEL: @test8(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[FOR_COND:%.*]]
; CHECK:       for.cond:
; CHECK-NEXT:    [[LOCAL_VAR_7_0:%.*]] = phi <4 x float> [ <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[FOR_BODY:%.*]] ]
; CHECK-NEXT:    br i1 undef, label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK:       for.body:
; CHECK-NEXT:    [[TMP0]] = insertelement <4 x float> [[LOCAL_VAR_7_0]], float 0.000000e+00, i32 2
; CHECK-NEXT:    br label [[FOR_COND]]
; CHECK:       for.end:
; CHECK-NEXT:    ret void
;
entry:
  %0 = load i32, i32* %inout, align 4
  %conv = uitofp i32 %0 to float
  %vecinit = insertelement <4 x float> <float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float undef>, float %conv, i32 3
  %sub = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vecinit
  %1 = shufflevector <4 x float> %sub, <4 x float> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
  %mul = fmul <4 x float> zeroinitializer, %1
  br label %for.cond
for.cond:                                         ; preds = %for.body, %entry
  %local_var_7.0 = phi <4 x float> [ %mul, %entry ], [ %2, %for.body ]
  br i1 undef, label %for.body, label %for.end
for.body:                                         ; preds = %for.cond
  %2 = insertelement <4 x float> %local_var_7.0, float 0.000000e+00, i32 2
  br label %for.cond
for.end:                                          ; preds = %for.cond
  ret void
}
; X * -1.0 => -0.0 - X
define float @test9(float %x) {
; CHECK-LABEL: @test9(
; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
; CHECK-NEXT:    ret float [[MUL]]
;
  %mul = fmul float %x, -1.0
  ret float %mul
}
; PR18532
define <4 x float> @test10(<4 x float> %x) {
; CHECK-LABEL: @test10(
; CHECK-NEXT:    [[MUL:%.*]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
; CHECK-NEXT:    ret <4 x float> [[MUL]]
;
  %mul = fmul <4 x float> %x, <float -1.0, float -1.0, float -1.0, float -1.0>
  ret <4 x float> %mul
}
define float @test11(float %x, float %y) {
; CHECK-LABEL: @test11(
; CHECK-NEXT:    [[B:%.*]] = fadd fast float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    [[C:%.*]] = fadd fast float [[B]], 3.000000e+00
; CHECK-NEXT:    ret float [[C]]
;
  %a = fadd fast float %x, 1.0
  %b = fadd fast float %y, 2.0
  %c = fadd fast float %a, %b
  ret float %c
}
; PR21126: http://llvm.org/bugs/show_bug.cgi?id=21126
; With unsafe/fast math, sqrt(X) * sqrt(X) is just X.
declare double @llvm.sqrt.f64(double)
define double @sqrt_squared1(double %f) {
; CHECK-LABEL: @sqrt_squared1(
; CHECK-NEXT:    ret double [[F:%.*]]
;
  %sqrt = call double @llvm.sqrt.f64(double %f)
  %mul = fmul fast double %sqrt, %sqrt
  ret double %mul
}
; With unsafe/fast math, sqrt(X) * sqrt(X) is just X,
; but make sure another use of the sqrt is intact.
; Note that the remaining fmul is altered but is not 'fast'
; itself because it was not marked 'fast' originally.
; Thus, we have an overall fast result, but no more indication of
; 'fast'ness in the code.
define double @sqrt_squared2(double %f) {
; CHECK-LABEL: @sqrt_squared2(
; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[F:%.*]])
; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[SQRT]], [[F]]
; CHECK-NEXT:    ret double [[MUL2]]
;
  %sqrt = call double @llvm.sqrt.f64(double %f)
  %mul1 = fmul fast double %sqrt, %sqrt
  %mul2 = fmul double %mul1, %sqrt
  ret double %mul2
}
declare float @llvm.fabs.f32(float) nounwind readnone
define float @fabs_squared(float %x) {
; CHECK-LABEL: @fabs_squared(
; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], [[X]]
; CHECK-NEXT:    ret float [[MUL]]
;
  %x.fabs = call float @llvm.fabs.f32(float %x)
  %mul = fmul float %x.fabs, %x.fabs
  ret float %mul
}
define float @fabs_squared_fast(float %x) {
; CHECK-LABEL: @fabs_squared_fast(
; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X:%.*]], [[X]]
; CHECK-NEXT:    ret float [[MUL]]
;
  %x.fabs = call float @llvm.fabs.f32(float %x)
  %mul = fmul fast float %x.fabs, %x.fabs
  ret float %mul
}
define float @fabs_x_fabs(float %x, float %y) {
; CHECK-LABEL: @fabs_x_fabs(
; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT:    [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]])
; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X_FABS]], [[Y_FABS]]
; CHECK-NEXT:    ret float [[MUL]]
;
  %x.fabs = call float @llvm.fabs.f32(float %x)
  %y.fabs = call float @llvm.fabs.f32(float %y)
  %mul = fmul float %x.fabs, %y.fabs
  ret float %mul
}
 
     |