1 // RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 \ 2 // RUN: -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s \ 3 // RUN: | FileCheck -check-prefix=CHECK-NS %s 4 5 // RUN: %clang_cc1 -fexperimental-strict-floating-point \ 6 // RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s \ 7 // RUN: -check-prefixes=CHECK-DEFAULT,CHECK-CONST-ARGS 8 9 // RUN: %clang_cc1 -fexperimental-strict-floating-point -DFENV_ON=1 \ 10 // RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s \ 11 // RUN: | FileCheck -check-prefix=CHECK-FENV %s 12 13 // RUN: %clang_cc1 -fexperimental-strict-floating-point -DNF128 \ 14 // RUN: -triple %itanium_abi_triple -O3 -emit-llvm -o - %s \ 15 // RUN: | FileCheck -check-prefix=CHECK-O3 %s 16 17 // RUN: %clang_cc1 -fexperimental-strict-floating-point \ 18 // RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source \ 19 // RUN: | FileCheck %s -check-prefixes=CHECK-SOURCE,CHECK-CONST-ARGS 20 21 // RUN: %clang_cc1 -fexperimental-strict-floating-point \ 22 // RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=double \ 23 // RUN: | FileCheck %s -check-prefixes=CHECK-DOUBLE,CHECK-CONST-ARGS 24 25 // RUN: %clang_cc1 -fexperimental-strict-floating-point \ 26 // RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=extended \ 27 // RUN: -mlong-double-80 | FileCheck %s \ 28 // RUN: -check-prefixes=CHECK-EXTENDED,CHECK-CONST-ARGS 29 30 // RUN: %clang_cc1 -fexperimental-strict-floating-point \ 31 // RUN: -triple i386-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source \ 32 // RUN: | FileCheck %s -check-prefix=CHECK-SOURCE 33 34 // RUN: %clang_cc1 -fexperimental-strict-floating-point -triple i386-linux-gnu \ 35 // RUN: -emit-llvm -o - %s -ffp-eval-method=double | FileCheck %s \ 36 // RUN: -check-prefix=CHECK-DOUBLE 37 38 // RUN: %clang_cc1 -fexperimental-strict-floating-point -triple i386-linux-gnu \ 39 // RUN: -emit-llvm -o - %s -ffp-eval-method=extended -mlong-double-80 \ 40 // RUN: | FileCheck %s -check-prefix=CHECK-EXTENDED 41 42 // RUN: %clang_cc1 -triple powerpc-unknown-aix -DNF128 -emit-llvm -o - %s \ 43 // RUN: | FileCheck %s -check-prefix=CHECK-AIX 44 45 bool f() { 46 // CHECK: define {{.*}}f{{.*}} 47 return __FLT_EVAL_METHOD__ < 0 && 48 __FLT_EVAL_METHOD__ == -1; 49 // CHECK: ret {{.*}} true 50 } 51 52 // Verify float_control(precise, off) enables fast math flags on fp operations. 53 float fp_precise_1(float a, float b, float c) { 54 // CHECK-O3: _Z12fp_precise_1fff 55 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} 56 // CHECK-O3: fadd fast float %[[M]], %c 57 #pragma float_control(precise, off) 58 return a * b + c; 59 } 60 61 // Is float_control state cleared on exiting compound statements? 62 float fp_precise_2(float a, float b, float c) { 63 // CHECK-O3: _Z12fp_precise_2fff 64 // CHECK-O3: %[[M:.+]] = fmul float{{.*}} 65 // CHECK-O3: fadd float %[[M]], %c 66 { 67 #pragma float_control(precise, off) 68 } 69 return a * b + c; 70 } 71 72 // Does float_control survive template instantiation? 73 class Foo {}; 74 Foo operator+(Foo, Foo); 75 76 template <typename T> 77 T template_muladd(T a, T b, T c) { 78 #pragma float_control(precise, off) 79 return a * b + c; 80 } 81 82 float fp_precise_3(float a, float b, float c) { 83 // CHECK-O3: _Z12fp_precise_3fff 84 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} 85 // CHECK-O3: fadd fast float %[[M]], %c 86 return template_muladd<float>(a, b, c); 87 } 88 89 template <typename T> 90 class fp_precise_4 { 91 float method(float a, float b, float c) { 92 #pragma float_control(precise, off) 93 return a * b + c; 94 } 95 }; 96 97 template class fp_precise_4<int>; 98 // CHECK-O3: _ZN12fp_precise_4IiE6methodEfff 99 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} 100 // CHECK-O3: fadd fast float %[[M]], %c 101 102 // Check file-scoped float_control 103 #pragma float_control(push) 104 #pragma float_control(precise, off) 105 float fp_precise_5(float a, float b, float c) { 106 // CHECK-O3: _Z12fp_precise_5fff 107 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} 108 // CHECK-O3: fadd fast float %[[M]], %c 109 return a * b + c; 110 } 111 #pragma float_control(pop) 112 113 float fff(float x, float y) { 114 // CHECK-LABEL: define{{.*}} float @_Z3fffff{{.*}} 115 // CHECK: entry 116 #pragma float_control(except, on) 117 float z; 118 z = z * z; 119 //CHECK: llvm.experimental.constrained.fmul{{.*}} 120 { 121 z = x * y; 122 //CHECK: llvm.experimental.constrained.fmul{{.*}} 123 } 124 { 125 // This pragma has no effect since if there are any fp intrin in the 126 // function then all the operations need to be fp intrin 127 #pragma float_control(except, off) 128 z = z + x * y; 129 //CHECK: llvm.experimental.constrained.fmul{{.*}} 130 } 131 z = z * z; 132 //CHECK: llvm.experimental.constrained.fmul{{.*}} 133 return z; 134 } 135 float check_precise(float x, float y) { 136 // CHECK-LABEL: define{{.*}} float @_Z13check_preciseff{{.*}} 137 float z; 138 { 139 #pragma float_control(precise, on) 140 z = x * y + z; 141 //CHECK: llvm.fmuladd{{.*}} 142 } 143 { 144 #pragma float_control(precise, off) 145 z = x * y + z; 146 //CHECK: fmul fast float 147 //CHECK: fadd fast float 148 } 149 return z; 150 } 151 152 float fma_test2(float a, float b, float c) { 153 // CHECK-LABEL define{{.*}} float @_Z9fma_test2fff{{.*}} 154 #pragma float_control(precise, off) 155 float x = a * b + c; 156 //CHECK: fmuladd 157 return x; 158 } 159 160 float fma_test1(float a, float b, float c) { 161 // CHECK-LABEL define{{.*}} float @_Z9fma_test1fff{{.*}} 162 #pragma float_control(precise, on) 163 float x = a * b + c; 164 //CHECK: fmuladd 165 return x; 166 } 167 168 #pragma float_control(push) 169 #pragma float_control(precise, on) 170 struct Distance {}; 171 Distance operator+(Distance, Distance); 172 173 template <class T> 174 T add(T lhs, T rhs) { 175 #pragma float_control(except, on) 176 return lhs + rhs; 177 } 178 #pragma float_control(pop) 179 180 float test_OperatorCall() { 181 return add(1.0f, 2.0f); 182 //CHECK: llvm.experimental.constrained.fadd{{.*}}fpexcept.strict 183 } 184 // CHECK-LABEL define{{.*}} float {{.*}}test_OperatorCall{{.*}} 185 186 #if FENV_ON 187 #pragma STDC FENV_ACCESS ON 188 #endif 189 // CHECK-LABEL: define {{.*}}callt{{.*}} 190 191 void callt() { 192 volatile float z; 193 z = z * z; 194 //CHECK-FENV: llvm.experimental.constrained.fmul{{.*}} 195 } 196 197 // CHECK-LABEL: define {{.*}}myAdd{{.*}} 198 float myAdd(int i, float f) { 199 if (i<0) 200 return 1.0 + 2.0; 201 // Check that floating point constant folding doesn't occur if 202 // #pragma STC FENV_ACCESS is enabled. 203 //CHECK-FENV: llvm.experimental.constrained.fadd{{.*}}double 1.0{{.*}}double 2.0{{.*}} 204 //CHECK: store float 3.0{{.*}}retval{{.*}} 205 static double v = 1.0 / 3.0; 206 //CHECK-FENV: llvm.experimental.constrained.fptrunc.f32.f64{{.*}} 207 //CHECK-NOT: fdiv 208 return v; 209 } 210 211 #if EXCEPT 212 namespace ns { 213 // Check that pragma float_control can appear in namespace. 214 #pragma float_control(except, on, push) 215 float exc_on(double x, float zero) { 216 // CHECK-NS: define {{.*}}exc_on{{.*}} 217 {} try { 218 x = 1.0 / zero; /* division by zero, the result unused */ 219 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 220 } catch (...) {} 221 return zero; 222 } 223 } 224 225 // Check pragma is still effective after namespace closes 226 float exc_still_on(double x, float zero) { 227 // CHECK-NS: define {{.*}}exc_still_on{{.*}} 228 {} try { 229 x = 1.0 / zero; /* division by zero, the result unused */ 230 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 231 } catch (...) {} 232 return zero; 233 } 234 235 #pragma float_control(pop) 236 float exc_off(double x, float zero) { 237 // CHECK-NS: define {{.*}}exc_off{{.*}} 238 {} try { 239 x = 1.0 / zero; /* division by zero, the result unused */ 240 //CHECK-NS: fdiv double 241 } catch (...) {} 242 return zero; 243 } 244 245 namespace fc_template_namespace { 246 #pragma float_control(except, on, push) 247 template <class T> 248 T exc_on(double x, T zero) { 249 // CHECK-NS: define {{.*}}fc_template_namespace{{.*}} 250 {} try { 251 x = 1.0 / zero; /* division by zero, the result unused */ 252 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 253 } catch (...) {} 254 return zero; 255 } 256 } 257 258 #pragma float_control(pop) 259 float xx(double x, float z) { 260 return fc_template_namespace::exc_on<float>(x, z); 261 } 262 #endif // EXCEPT 263 264 float try_lam(float x, unsigned n) { 265 // CHECK: define {{.*}}try_lam{{.*}}class.anon{{.*}} 266 float result; 267 auto t = 268 // Lambda expression begins 269 [](float a, float b) { 270 #pragma float_control( except, on) 271 return a * b; 272 //CHECK: llvm.experimental.constrained.fmul{{.*}}fpexcept.strict 273 } // end of lambda expression 274 (1.0f,2.0f); 275 result = x + t; 276 return result; 277 } 278 279 float mySub(float x, float y) { 280 // CHECK: define {{.*}}float {{.*}}mySub{{.*}} 281 // CHECK-NS: fsub float 282 // CHECK-SOURCE: fsub float 283 // CHECK-DOUBLE: fpext float 284 // CHECK-DOUBLE: fpext float 285 // CHECK-DOUBLE: fsub double 286 // CHECK-DOUBLE: fptrunc double {{.*}} to float 287 // CHECK-EXTENDED: fpext float 288 // CHECK-EXTENDED: fpext float 289 // CHECK-EXTENDED: fsub double 290 // CHECK-EXTENDED: fptrunc double {{.*}} to float 291 return x - y; 292 } 293 294 float mySubSource(float x, float y) { 295 // CHECK: define {{.*}}float {{.*}}mySubSource{{.*}} 296 #pragma clang fp eval_method(source) 297 return x - y; 298 // CHECK: fsub float 299 } 300 301 float mySubExtended(float x, float y) { 302 // CHECK: define {{.*}}float {{.*}}mySubExtended{{.*}} 303 #pragma clang fp eval_method(extended) 304 return x - y; 305 // CHECK: fpext float 306 // CHECK: fpext float 307 // CHECK: fsub x86_fp80 308 // CHECK: fptrunc x86_fp80 {{.*}} to float 309 // CHECK-AIX: fsub double 310 // CHECK-AIX: fptrunc double 311 } 312 313 float mySubDouble(float x, float y) { 314 // CHECK: define {{.*}}float {{.*}}mySubDouble{{.*}} 315 #pragma clang fp eval_method(double) 316 return x - y; 317 // CHECK: fpext float 318 // CHECK: fpext float 319 // CHECK: fsub double 320 // CHECK: fptrunc double {{.*}} to float 321 } 322 323 #ifndef NF128 324 __float128 mySub128(__float128 x, __float128 y) { 325 // CHECK: define {{.*}}mySub128{{.*}} 326 // Expect no fpext since fp128 is already widest 327 // CHECK: load fp128 328 // CHECK-NEXT: load fp128 329 // CHECK-NEXT: fsub fp128 330 // CHECK-NEXT: ret fp128 331 return x - y; 332 } 333 #endif 334 335 void mySubfp16(__fp16 *res, __fp16 *x, __fp16 *y) { 336 // CHECK: define {{.*}}mySubfp16{{.*}} 337 *res = *x - *y; 338 // CHECK: load half 339 // CHECK-NEXT: load half 340 // CHECK-NEXT: fpext half{{.*}} 341 // CHECK-NEXT: load half 342 // CHECK-NEXT: load half 343 // CHECK-NS: fpext half{{.*}} to float 344 // CHECK-DEFAULT: fpext half{{.*}} to float 345 // CHECK-DOUBLE: fpext half{{.*}} to float 346 // CHECK-EXTENDED: fpext half{{.*}} to float 347 // CHECK-NEXT: fsub 348 // CHECK-NEXT: fptrunc {{.*}}to half 349 // CHECK-NS: fptrunc float {{.*}} to half 350 // CHECK-DOUBLE: fptrunc float {{.*}} to half 351 // CHECK-EXTENDED: fptrunc float {{.*}} to half 352 } 353 354 float Div(float x, float y, float z) { 355 // CHECK: define{{.*}}float {{.*}}Div{{.*}} 356 // CHECK-CONST-ARGS: fdiv float 357 return x / (y / z); 358 } 359 360 float DivExtended(float x, float y, float z) { 361 // CHECK: define{{.*}}float {{.*}}DivExtended{{.*}} 362 #pragma clang fp eval_method(extended) 363 // CHECK-CONST-ARGS: fdiv x86_fp80 364 // CHECK-CONST-ARGS: fptrunc x86_fp80 365 return x / (y / z); 366 } 367 368 float DivDouble(float x, float y, float z) { 369 // CHECK: define{{.*}}float {{.*}}DivDouble{{.*}} 370 #pragma clang fp eval_method(double) 371 // CHECK-CONST-ARGS: fdiv double 372 // CHECK-CONST-ARGS: fptrunc double 373 return x / (y / z); 374 } 375 376 float DivSource(float x, float y, float z) { 377 // CHECK: define{{.*}}float {{.*}}DivSource{{.*}} 378 #pragma clang fp eval_method(source) 379 // CHECK-CONST-ARGS: fdiv float 380 return x / (y / z); 381 } 382 383 int main() { 384 float f = Div(4.2f, 1.0f, 3.0f); 385 float fextended = DivExtended(4.2f, 1.0f, 3.0f); 386 float fdouble = DivDouble(4.2f, 1.0f, 3.0f); 387 float fsource = DivSource(4.2f, 1.0f, 3.0f); 388 // CHECK: store float 389 } 390