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 #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 // expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}} 142 #pragma STDC FENV_ACCESS ON 143 #endif 144 // CHECK-LABEL: define {{.*}}callt{{.*}} 145 146 void callt() { 147 volatile float z; 148 z = z * z; 149 //CHECK: = fmul float 150 } 151 152 #if EXCEPT 153 namespace ns { 154 // Check that pragma float_control can appear in namespace. 155 #pragma float_control(except, on, push) 156 float exc_on(double x, float zero) { 157 // CHECK-NS: define {{.*}}exc_on{{.*}} 158 {} try { 159 x = 1.0 / zero; /* division by zero, the result unused */ 160 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 161 } catch (...) {} 162 return zero; 163 } 164 } 165 166 // Check pragma is still effective after namespace closes 167 float exc_still_on(double x, float zero) { 168 // CHECK-NS: define {{.*}}exc_still_on{{.*}} 169 {} try { 170 x = 1.0 / zero; /* division by zero, the result unused */ 171 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 172 } catch (...) {} 173 return zero; 174 } 175 176 #pragma float_control(pop) 177 float exc_off(double x, float zero) { 178 // CHECK-NS: define {{.*}}exc_off{{.*}} 179 {} try { 180 x = 1.0 / zero; /* division by zero, the result unused */ 181 //CHECK-NS: fdiv double 182 } catch (...) {} 183 return zero; 184 } 185 186 namespace fc_template_namespace { 187 #pragma float_control(except, on, push) 188 template <class T> 189 T exc_on(double x, T zero) { 190 // CHECK-NS: define {{.*}}fc_template_namespace{{.*}} 191 {} try { 192 x = 1.0 / zero; /* division by zero, the result unused */ 193 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} 194 } catch (...) {} 195 return zero; 196 } 197 } 198 199 #pragma float_control(pop) 200 float xx(double x, float z) { 201 return fc_template_namespace::exc_on<float>(x, z); 202 } 203 #endif // EXCEPT 204