1 // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DDEFAULT=1 -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-DDEFAULT %s 2 // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DEBSTRICT=1 -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-DEBSTRICT %s 3 // RUN: %clang_cc1 -triple x86_64-linux-gnu -DFAST=1 -ffast-math -ffp-contract=fast -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-FAST %s 4 // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DNOHONOR=1 -ffinite-math-only -menable-no-infs -menable-no-nans -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-NOHONOR %s 5 6 #define FUN(n) \ 7 (float z) { return n * z + n; } 8 9 // CHECK-DDEFAULT: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 10 // CHECK-DEBSTRICT: Function Attrs: mustprogress noinline nounwind optnone strictfp{{$$}} 11 // CHECK-FAST: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 12 // CHECK-NOHONOR: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 13 float fun_default FUN(1) 14 //CHECK-LABEL: define {{.*}} @_Z11fun_defaultf{{.*}} 15 #if DEFAULT 16 //CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}} 17 #endif 18 #if EBSTRICT 19 // Note that backend wants constrained intrinsics used 20 // throughout the function if they are needed anywhere in the function. 21 // In that case, operations are built with constrained intrinsics operator 22 // but using default settings for exception behavior and rounding mode. 23 //CHECK-DEBSTRICT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict 24 #endif 25 #if FAST 26 //CHECK-FAST: fmul fast float 27 //CHECK-FAST: fadd fast float 28 #endif 29 30 #pragma float_control(push) 31 #ifndef FAST 32 // Rule: precise must be enabled 33 #pragma float_control(except, on) 34 #endif 35 // CHECK-FAST: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 36 // CHECK-DDEFAULT: Function Attrs: mustprogress noinline nounwind optnone strictfp{{$$}} 37 // CHECK-DEBSTRICT: Function Attrs: mustprogress noinline nounwind optnone strictfp{{$$}} 38 // CHECK-NOHONOR: Function Attrs: mustprogress noinline nounwind optnone strictfp{{$$}} 39 float exc_on FUN(2) 40 //CHECK-LABEL: define {{.*}} @_Z6exc_onf{{.*}} 41 #if DEFAULT 42 //CHECK-DDEFAULT: llvm.experimental.constrained.fmul{{.*}} 43 #endif 44 #if EBSTRICT 45 //CHECK-DEBSTRICT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict 46 #endif 47 #if NOHONOR 48 //CHECK-NOHONOR: nnan ninf float {{.*}}llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict 49 #endif 50 #if FAST 51 //Not possible to enable float_control(except) in FAST mode. 52 //CHECK-FAST: fmul fast float 53 //CHECK-FAST: fadd fast float 54 #endif 55 56 #pragma float_control(pop) 57 // CHECK-DDEFAULT: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 58 // CHECK-DEBSTRICT: Function Attrs: mustprogress noinline nounwind optnone strictfp{{$$}} 59 // CHECK-FAST: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 60 // CHECK-NOHONOR: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 61 float exc_pop FUN(5) 62 //CHECK-LABEL: define {{.*}} @_Z7exc_popf{{.*}} 63 #if DEFAULT 64 //CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}} 65 #endif 66 #if EBSTRICT 67 //CHECK-DEBSTRICT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict 68 #endif 69 #if NOHONOR 70 //CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} 71 #endif 72 #if FAST 73 //CHECK-FAST: fmul fast float 74 //CHECK-FAST: fadd fast float 75 #endif 76 77 #pragma float_control(except, off) 78 float exc_off FUN(5) 79 //CHECK-LABEL: define {{.*}} @_Z7exc_offf{{.*}} 80 #if DEFAULT 81 //CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}} 82 #endif 83 #if EBSTRICT 84 //CHECK-DEBSTRICT: call float @llvm.fmuladd{{.*}} 85 #endif 86 #if NOHONOR 87 //CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} 88 #endif 89 #if FAST 90 //CHECK-FAST: fmul fast float 91 //CHECK-FAST: fadd fast float 92 #endif 93 94 #pragma float_control(precise, on, push) 95 float precise_on FUN(3) 96 //CHECK-LABEL: define {{.*}} @_Z10precise_onf{{.*}} 97 #if DEFAULT 98 //CHECK-DDEFAULT: float {{.*}}llvm.fmuladd{{.*}} 99 #endif 100 #if EBSTRICT 101 //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} 102 #endif 103 #if NOHONOR 104 // If precise is pushed then all fast-math should be off! 105 //CHECK-NOHONOR: call float {{.*}}llvm.fmuladd{{.*}} 106 #endif 107 #if FAST 108 //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} 109 #endif 110 111 #pragma float_control(pop) 112 float precise_pop FUN(3) 113 //CHECK-LABEL: define {{.*}} @_Z11precise_popf{{.*}} 114 #if DEFAULT 115 //CHECK-DDEFAULT: float {{.*}}llvm.fmuladd{{.*}} 116 #endif 117 #if EBSTRICT 118 //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} 119 #endif 120 #if NOHONOR 121 //CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} 122 #endif 123 #if FAST 124 //CHECK-FAST: fmul fast float 125 //CHECK-FAST: fadd fast float 126 #endif 127 #pragma float_control(precise, off) 128 float precise_off FUN(4) 129 //CHECK-LABEL: define {{.*}} @_Z11precise_offf{{.*}} 130 #if DEFAULT 131 // Note: precise_off enables fp_contract=fast and the instructions 132 // generated do not include the contract flag, although it was enabled 133 // in IRBuilder. 134 //CHECK-DDEFAULT: fmul fast float 135 //CHECK-DDEFAULT: fadd fast float 136 #endif 137 #if EBSTRICT 138 //CHECK-DEBSTRICT: fmul fast float 139 //CHECK-DEBSTRICT: fadd fast float 140 #endif 141 #if NOHONOR 142 // fast math should be enabled, and contract should be fast 143 //CHECK-NOHONOR: fmul fast float 144 //CHECK-NOHONOR: fadd fast float 145 #endif 146 #if FAST 147 //CHECK-FAST: fmul fast float 148 //CHECK-FAST: fadd fast float 149 #endif 150 151 #pragma float_control(precise, on) 152 float precise_on2 FUN(3) 153 //CHECK-LABEL: define {{.*}} @_Z11precise_on2f{{.*}} 154 #if DEFAULT 155 //CHECK-DDEFAULT: llvm.fmuladd{{.*}} 156 #endif 157 #if EBSTRICT 158 //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} 159 #endif 160 #if NOHONOR 161 // fast math should be off, and contract should be on 162 //CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}} 163 #endif 164 #if FAST 165 //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} 166 #endif 167 168 #pragma float_control(push) 169 float precise_push FUN(3) 170 //CHECK-LABEL: define {{.*}} @_Z12precise_pushf{{.*}} 171 #if DEFAULT 172 //CHECK-DDEFAULT: llvm.fmuladd{{.*}} 173 #endif 174 #if EBSTRICT 175 //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} 176 #endif 177 #if NOHONOR 178 //CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}} 179 #endif 180 #if FAST 181 //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} 182 #endif 183 184 #pragma float_control(precise, off) 185 float precise_off2 FUN(4) 186 //CHECK-LABEL: define {{.*}} @_Z12precise_off2f{{.*}} 187 #if DEFAULT 188 //CHECK-DDEFAULT: fmul fast float 189 //CHECK-DDEFAULT: fadd fast float 190 #endif 191 #if EBSTRICT 192 //CHECK-DEBSTRICT: fmul fast float 193 //CHECK-DEBSTRICT: fadd fast float 194 #endif 195 #if NOHONOR 196 // fast math settings since precise is off 197 //CHECK-NOHONOR: fmul fast float 198 //CHECK-NOHONOR: fadd fast float 199 #endif 200 #if FAST 201 //CHECK-FAST: fmul fast float 202 //CHECK-FAST: fadd fast float 203 #endif 204 205 #pragma float_control(pop) 206 float precise_pop2 FUN(3) 207 //CHECK-LABEL: define {{.*}} @_Z12precise_pop2f{{.*}} 208 #if DEFAULT 209 //CHECK-DDEFAULT: llvm.fmuladd{{.*}} 210 #endif 211 #if EBSTRICT 212 //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} 213 #endif 214 #if NOHONOR 215 //CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}} 216 #endif 217 #if FAST 218 //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} 219 #endif 220 221 #ifndef FAST 222 // Rule: precise must be enabled 223 #pragma float_control(except, on) 224 #endif 225 float y(); 226 // CHECK-DDEFAULT: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 227 // CHECK-DEBSTRICT: Function Attrs: mustprogress noinline nounwind optnone strictfp{{$$}} 228 // CHECK-FAST: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 229 // CHECK-NOHONOR: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 230 class ON { 231 // Settings for top level class initializer use program source setting. 232 float z = 2 + y() * 7; 233 //CHECK-LABEL: define {{.*}} void @_ZN2ONC2Ev{{.*}} 234 #if DEFAULT 235 // CHECK-DDEFAULT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict 236 #endif 237 #if EBSTRICT 238 // CHECK-DEBSTRICT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict 239 #endif 240 #if NOHONOR 241 // CHECK-NOHONOR: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict 242 #endif 243 #if FAST 244 // CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} 245 #endif 246 }; 247 ON on; 248 #pragma float_control(except, off) 249 // CHECK-DDEFAULT: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 250 // CHECK-DEBSTRICT: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 251 // CHECK-FAST: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 252 // CHECK-NOHONOR: Function Attrs: mustprogress noinline nounwind optnone{{$$}} 253 class OFF { 254 float w = 2 + y() * 7; 255 // CHECK-LABEL: define {{.*}} void @_ZN3OFFC2Ev{{.*}} 256 // CHECK: call float {{.*}}llvm.fmuladd 257 }; 258 OFF off; 259 260 #pragma clang fp reassociate(on) 261 struct MyComplex { 262 float xx; 263 float yy; 264 MyComplex(float x, float y) { 265 xx = x; 266 yy = y; 267 } 268 MyComplex() {} 269 const MyComplex operator+(const MyComplex other) const { 270 // CHECK-LABEL: define {{.*}} @_ZNK9MyComplexplES_ 271 // CHECK: fadd reassoc float 272 // CHECK: fadd reassoc float 273 return MyComplex(xx + other.xx, yy + other.yy); 274 } 275 }; 276 MyComplex useAdd() { 277 MyComplex a (1, 3); 278 MyComplex b (2, 4); 279 return a + b; 280 } 281 282 // CHECK-DDEFAULT: Function Attrs: noinline nounwind{{$$}} 283 // CHECK-DEBSTRICT: Function Attrs: noinline nounwind strictfp{{$$}} 284 // CHECK-FAST: Function Attrs: noinline nounwind{{$$}} 285 // CHECK-NOHONOR: Function Attrs: noinline nounwind{{$$}} 286 // CHECK-LABEL: define{{.*}} @_GLOBAL__sub_I_fp_floatcontrol_stack 287 288 // CHECK-DEBSTRICT: {{[ ]}}strictfp{{[ ]}} 289 // CHECK-DEBSTRICT-NOT: "strictfp" 290