1 // RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s 2 // RUN: %clang_cc1 -fexperimental-strict-floating-point -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s 3 // RUN: %clang_cc1 -fexperimental-strict-floating-point -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-FENV %s 4 // RUN: %clang_cc1 -fexperimental-strict-floating-point -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 #pragma float_control(push) 123 #pragma float_control(precise, on) 124 struct Distance {}; 125 Distance operator+(Distance, Distance); 126 127 template <class T> 128 T add(T lhs, T rhs) { 129 #pragma float_control(except, on) 130 return lhs + rhs; 131 } 132 #pragma float_control(pop) 133 134 float test_OperatorCall() { 135 return add(1.0f, 2.0f); 136 //CHECK: llvm.experimental.constrained.fadd{{.*}}fpexcept.strict 137 } 138 // CHECK-LABEL define{{.*}} float {{.*}}test_OperatorCall{{.*}} 139 140 #if FENV_ON 141 #pragma STDC FENV_ACCESS ON 142 #endif 143 // CHECK-LABEL: define {{.*}}callt{{.*}} 144 145 void callt() { 146 volatile float z; 147 z = z * z; 148 //CHECK-FENV: llvm.experimental.constrained.fmul{{.*}} 149 } 150 151 // CHECK-LABEL: define {{.*}}myAdd{{.*}} 152 float myAdd(int i, float f) { 153 if (i<0) 154 return 1.0 + 2.0; 155 // Check that floating point constant folding doesn't occur if 156 // #pragma STC FENV_ACCESS is enabled. 157 //CHECK-FENV: llvm.experimental.constrained.fadd{{.*}}double 1.0{{.*}}double 2.0{{.*}} 158 //CHECK: store float 3.0{{.*}}retval{{.*}} 159 static double v = 1.0 / 3.0; 160 //CHECK-FENV: llvm.experimental.constrained.fptrunc.f32.f64{{.*}} 161 //CHECK-NOT: fdiv 162 return v; 163 } 164 165 #if EXCEPT 166 namespace ns { 167 // Check that pragma float_control can appear in namespace. 168 #pragma float_control(except, on, push) 169 float exc_on(double x, float zero) { 170 // CHECK-NS: define {{.*}}exc_on{{.*}} 171 {} try { 172 x = 1.0 / zero; /* division by zero, the result unused */ 173 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 174 } catch (...) {} 175 return zero; 176 } 177 } 178 179 // Check pragma is still effective after namespace closes 180 float exc_still_on(double x, float zero) { 181 // CHECK-NS: define {{.*}}exc_still_on{{.*}} 182 {} try { 183 x = 1.0 / zero; /* division by zero, the result unused */ 184 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 185 } catch (...) {} 186 return zero; 187 } 188 189 #pragma float_control(pop) 190 float exc_off(double x, float zero) { 191 // CHECK-NS: define {{.*}}exc_off{{.*}} 192 {} try { 193 x = 1.0 / zero; /* division by zero, the result unused */ 194 //CHECK-NS: fdiv double 195 } catch (...) {} 196 return zero; 197 } 198 199 namespace fc_template_namespace { 200 #pragma float_control(except, on, push) 201 template <class T> 202 T exc_on(double x, T zero) { 203 // CHECK-NS: define {{.*}}fc_template_namespace{{.*}} 204 {} try { 205 x = 1.0 / zero; /* division by zero, the result unused */ 206 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 207 } catch (...) {} 208 return zero; 209 } 210 } 211 212 #pragma float_control(pop) 213 float xx(double x, float z) { 214 return fc_template_namespace::exc_on<float>(x, z); 215 } 216 #endif // EXCEPT 217 218 float try_lam(float x, unsigned n) { 219 // CHECK: define {{.*}}try_lam{{.*}}class.anon{{.*}} 220 float result; 221 auto t = 222 // Lambda expression begins 223 [](float a, float b) { 224 #pragma float_control( except, on) 225 return a * b; 226 //CHECK: llvm.experimental.constrained.fmul{{.*}}fpexcept.strict 227 } // end of lambda expression 228 (1.0f,2.0f); 229 result = x + t; 230 return result; 231 } 232