1 // RUN: %clang_cc1 -DEXCEPT=1 -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s 2 // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s 3 // RUN: %clang_cc1 -verify -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s 4 // RUN: %clang_cc1 -triple %itanium_abi_triple -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-O3 %s 5 6 // Verify float_control(precise, off) enables fast math flags on fp operations. 7 float fp_precise_1(float a, float b, float c) { 8 // CHECK-O3: _Z12fp_precise_1fff 9 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} 10 // CHECK-O3: fadd fast float %[[M]], %c 11 #pragma float_control(precise, off) 12 return a * b + c; 13 } 14 15 // Is float_control state cleared on exiting compound statements? 16 float fp_precise_2(float a, float b, float c) { 17 // CHECK-O3: _Z12fp_precise_2fff 18 // CHECK-O3: %[[M:.+]] = fmul float{{.*}} 19 // CHECK-O3: fadd float %[[M]], %c 20 { 21 #pragma float_control(precise, off) 22 } 23 return a * b + c; 24 } 25 26 // Does float_control survive template instantiation? 27 class Foo {}; 28 Foo operator+(Foo, Foo); 29 30 template <typename T> 31 T template_muladd(T a, T b, T c) { 32 #pragma float_control(precise, off) 33 return a * b + c; 34 } 35 36 float fp_precise_3(float a, float b, float c) { 37 // CHECK-O3: _Z12fp_precise_3fff 38 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} 39 // CHECK-O3: fadd fast float %[[M]], %c 40 return template_muladd<float>(a, b, c); 41 } 42 43 template <typename T> 44 class fp_precise_4 { 45 float method(float a, float b, float c) { 46 #pragma float_control(precise, off) 47 return a * b + c; 48 } 49 }; 50 51 template class fp_precise_4<int>; 52 // CHECK-O3: _ZN12fp_precise_4IiE6methodEfff 53 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} 54 // CHECK-O3: fadd fast float %[[M]], %c 55 56 // Check file-scoped float_control 57 #pragma float_control(push) 58 #pragma float_control(precise, off) 59 float fp_precise_5(float a, float b, float c) { 60 // CHECK-O3: _Z12fp_precise_5fff 61 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} 62 // CHECK-O3: fadd fast float %[[M]], %c 63 return a * b + c; 64 } 65 #pragma float_control(pop) 66 67 float fff(float x, float y) { 68 // CHECK-LABEL: define float @_Z3fffff{{.*}} 69 // CHECK: entry 70 #pragma float_control(except, on) 71 float z; 72 z = z * z; 73 //CHECK: llvm.experimental.constrained.fmul{{.*}} 74 { 75 z = x * y; 76 //CHECK: llvm.experimental.constrained.fmul{{.*}} 77 } 78 { 79 // This pragma has no effect since if there are any fp intrin in the 80 // function then all the operations need to be fp intrin 81 #pragma float_control(except, off) 82 z = z + x * y; 83 //CHECK: llvm.experimental.constrained.fmul{{.*}} 84 } 85 z = z * z; 86 //CHECK: llvm.experimental.constrained.fmul{{.*}} 87 return z; 88 } 89 float check_precise(float x, float y) { 90 // CHECK-LABEL: define float @_Z13check_preciseff{{.*}} 91 float z; 92 { 93 #pragma float_control(precise, on) 94 z = x * y + z; 95 //CHECK: llvm.fmuladd{{.*}} 96 } 97 { 98 #pragma float_control(precise, off) 99 z = x * y + z; 100 //CHECK: fmul fast float 101 //CHECK: fadd fast float 102 } 103 return z; 104 } 105 106 float fma_test2(float a, float b, float c) { 107 // CHECK-LABEL define float @_Z9fma_test2fff{{.*}} 108 #pragma float_control(precise, off) 109 float x = a * b + c; 110 //CHECK: fmuladd 111 return x; 112 } 113 114 float fma_test1(float a, float b, float c) { 115 // CHECK-LABEL define float @_Z9fma_test1fff{{.*}} 116 #pragma float_control(precise, on) 117 float x = a * b + c; 118 //CHECK: fmuladd 119 return x; 120 } 121 122 #if FENV_ON 123 // expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}} 124 #pragma STDC FENV_ACCESS ON 125 #endif 126 // CHECK-LABEL: define {{.*}}callt{{.*}} 127 128 void callt() { 129 volatile float z; 130 z = z * z; 131 //CHECK: = fmul float 132 } 133 134 #if EXCEPT 135 namespace ns { 136 // Check that pragma float_control can appear in namespace. 137 #pragma float_control(except, on, push) 138 float exc_on(double x, float zero) { 139 // CHECK-NS: define {{.*}}exc_on{{.*}} 140 {} try { 141 x = 1.0 / zero; /* division by zero, the result unused */ 142 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 143 } catch (...) {} 144 return zero; 145 } 146 } 147 148 // Check pragma is still effective after namespace closes 149 float exc_still_on(double x, float zero) { 150 // CHECK-NS: define {{.*}}exc_still_on{{.*}} 151 {} try { 152 x = 1.0 / zero; /* division by zero, the result unused */ 153 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 154 } catch (...) {} 155 return zero; 156 } 157 158 #pragma float_control(pop) 159 float exc_off(double x, float zero) { 160 // CHECK-NS: define {{.*}}exc_off{{.*}} 161 {} try { 162 x = 1.0 / zero; /* division by zero, the result unused */ 163 //CHECK-NS: fdiv double 164 } catch (...) {} 165 return zero; 166 } 167 168 namespace fc_template_namespace { 169 #pragma float_control(except, on, push) 170 template <class T> 171 T exc_on(double x, T zero) { 172 // CHECK-NS: define {{.*}}fc_template_namespace{{.*}} 173 {} try { 174 x = 1.0 / zero; /* division by zero, the result unused */ 175 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 176 } catch (...) {} 177 return zero; 178 } 179 } 180 181 #pragma float_control(pop) 182 float xx(double x, float z) { 183 return fc_template_namespace::exc_on<float>(x, z); 184 } 185 #endif // EXCEPT 186