brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.0 KiB · 966eaf6 Raw
390 lines · cpp
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 %s4 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-ARGS8 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 %s12 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 %s16 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-ARGS20 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-ARGS24 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-ARGS29 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-SOURCE33 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-DOUBLE37 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-EXTENDED41 42// RUN: %clang_cc1 -triple powerpc-unknown-aix -DNF128 -emit-llvm -o - %s \43// RUN: | FileCheck %s -check-prefix=CHECK-AIX44 45bool f() {46  // CHECK: define {{.*}}f{{.*}}47  return __FLT_EVAL_METHOD__ < 0 &&48         __FLT_EVAL_METHOD__ == -1;49  // CHECK: ret {{.*}} true50}51 52// Verify float_control(precise, off) enables fast math flags on fp operations.53float fp_precise_1(float a, float b, float c) {54// CHECK-O3: _Z12fp_precise_1fff55// CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}56// CHECK-O3: fadd fast float %[[M]], %c57#pragma float_control(precise, off)58  return a * b + c;59}60 61// Is float_control state cleared on exiting compound statements?62float fp_precise_2(float a, float b, float c) {63  // CHECK-O3: _Z12fp_precise_2fff64  // CHECK-O3: %[[M:.+]] = fmul float{{.*}}65  // CHECK-O3: fadd float %[[M]], %c66  {67#pragma float_control(precise, off)68  }69  return a * b + c;70}71 72// Does float_control survive template instantiation?73class Foo {};74Foo operator+(Foo, Foo);75 76template <typename T>77T template_muladd(T a, T b, T c) {78#pragma float_control(precise, off)79  return a * b + c;80}81 82float fp_precise_3(float a, float b, float c) {83  // CHECK-O3: _Z12fp_precise_3fff84  // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}85  // CHECK-O3: fadd fast float %[[M]], %c86  return template_muladd<float>(a, b, c);87}88 89template <typename T>90class 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 97template class fp_precise_4<int>;98// CHECK-O3: _ZN12fp_precise_4IiE6methodEfff99// CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}100// CHECK-O3: fadd fast float %[[M]], %c101 102// Check file-scoped float_control103#pragma float_control(push)104#pragma float_control(precise, off)105float fp_precise_5(float a, float b, float c) {106  // CHECK-O3: _Z12fp_precise_5fff107  // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}108  // CHECK-O3: fadd fast float %[[M]], %c109  return a * b + c;110}111#pragma float_control(pop)112 113float fff(float x, float y) {114// CHECK-LABEL: define{{.*}} float @_Z3fffff{{.*}}115// CHECK: entry116#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 the126// function then all the operations need to be fp intrin127#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}135float 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 float147    //CHECK: fadd fast float148  }149  return z;150}151 152float 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: fmuladd157  return x;158}159 160float 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: fmuladd165  return x;166}167 168#pragma float_control(push)169#pragma float_control(precise, on)170struct Distance {};171Distance operator+(Distance, Distance);172 173template <class T>174T add(T lhs, T rhs) {175#pragma float_control(except, on)176  return lhs + rhs;177}178#pragma float_control(pop)179 180float test_OperatorCall() {181  return add(1.0f, 2.0f);182  //CHECK: llvm.experimental.constrained.fadd{{.*}}fpexcept.strict183}184// CHECK-LABEL define{{.*}} float  {{.*}}test_OperatorCall{{.*}}185 186#if FENV_ON187#pragma STDC FENV_ACCESS ON188#endif189// CHECK-LABEL: define {{.*}}callt{{.*}}190 191void callt() {192  volatile float z;193  z = z * z;194  //CHECK-FENV: llvm.experimental.constrained.fmul{{.*}}195}196 197// CHECK-LABEL: define {{.*}}myAdd{{.*}}198float 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 if202  // #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: fdiv208  return v;209}210 211#if EXCEPT212namespace ns {213// Check that pragma float_control can appear in namespace.214#pragma float_control(except, on, push)215float 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 closes226float 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)236float 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 double241  } catch (...) {}242  return zero;243}244 245namespace fc_template_namespace {246#pragma float_control(except, on, push)247template <class T>248T 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)259float xx(double x, float z) {260  return fc_template_namespace::exc_on<float>(x, z);261}262#endif // EXCEPT263 264float try_lam(float x, unsigned n) {265// CHECK: define {{.*}}try_lam{{.*}}class.anon{{.*}}266  float result;267  auto t =268        // Lambda expression begins269        [](float a, float b) {270#pragma float_control( except, on)271            return a * b;272//CHECK: llvm.experimental.constrained.fmul{{.*}}fpexcept.strict273        } // end of lambda expression274  (1.0f,2.0f);275  result = x + t;276  return result;277}278 279float mySub(float x, float y) {280  // CHECK: define {{.*}}float {{.*}}mySub{{.*}}281  // CHECK-NS: fsub float282  // CHECK-SOURCE: fsub float283  // CHECK-DOUBLE: fpext float284  // CHECK-DOUBLE: fpext float285  // CHECK-DOUBLE: fsub double286  // CHECK-DOUBLE: fptrunc double {{.*}} to float287  // CHECK-EXTENDED: fpext float288  // CHECK-EXTENDED: fpext float289  // CHECK-EXTENDED: fsub double290  // CHECK-EXTENDED: fptrunc double {{.*}} to float291  return x - y;292}293 294float mySubSource(float x, float y) {295// CHECK: define {{.*}}float {{.*}}mySubSource{{.*}}296#pragma clang fp eval_method(source)297  return x - y;298  // CHECK: fsub float299}300 301float mySubExtended(float x, float y) {302// CHECK: define {{.*}}float {{.*}}mySubExtended{{.*}}303#pragma clang fp eval_method(extended)304  return x - y;305  // CHECK: fpext float306  // CHECK: fpext float307  // CHECK: fsub x86_fp80308  // CHECK: fptrunc x86_fp80 {{.*}} to float309  // CHECK-AIX: fsub double310  // CHECK-AIX: fptrunc double311}312 313float mySubDouble(float x, float y) {314// CHECK: define {{.*}}float {{.*}}mySubDouble{{.*}}315#pragma clang fp eval_method(double)316  return x - y;317  // CHECK: fpext float318  // CHECK: fpext float319  // CHECK: fsub double320  // CHECK: fptrunc double {{.*}} to float321}322 323#ifndef NF128324__float128 mySub128(__float128 x, __float128 y) {325  // CHECK: define {{.*}}mySub128{{.*}}326  // Expect no fpext since fp128 is already widest327  // CHECK: load fp128328  // CHECK-NEXT: load fp128329  // CHECK-NEXT: fsub fp128330  // CHECK-NEXT: ret fp128331  return x - y;332}333#endif334 335void mySubfp16(__fp16 *res, __fp16 *x, __fp16 *y) {336  // CHECK: define {{.*}}mySubfp16{{.*}}337  *res = *x - *y;338  // CHECK: load half339  // CHECK-NEXT: load half340  // CHECK-NEXT: fpext half{{.*}}341  // CHECK-NEXT: load half342  // CHECK-NEXT: load half343  // CHECK-NS: fpext half{{.*}} to float344  // CHECK-DEFAULT: fpext half{{.*}} to float345  // CHECK-DOUBLE: fpext half{{.*}} to float346  // CHECK-EXTENDED: fpext half{{.*}} to float347  // CHECK-NEXT: fsub348  // CHECK-NEXT: fptrunc {{.*}}to half349  // CHECK-NS: fptrunc float {{.*}} to half350  // CHECK-DOUBLE: fptrunc float {{.*}} to half351  // CHECK-EXTENDED: fptrunc float {{.*}} to half352}353 354float Div(float x, float y, float z) {355  // CHECK: define{{.*}}float {{.*}}Div{{.*}}356  // CHECK-CONST-ARGS: fdiv float357  return x / (y / z);358}359 360float 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_fp80364  // CHECK-CONST-ARGS: fptrunc x86_fp80365  return x / (y / z);366}367 368float DivDouble(float x, float y, float z) {369// CHECK: define{{.*}}float {{.*}}DivDouble{{.*}}370#pragma clang fp eval_method(double)371  // CHECK-CONST-ARGS: fdiv double372  // CHECK-CONST-ARGS: fptrunc double373  return x / (y / z);374}375 376float DivSource(float x, float y, float z) {377// CHECK: define{{.*}}float {{.*}}DivSource{{.*}}378#pragma clang fp eval_method(source)379  // CHECK-CONST-ARGS: fdiv float380  return x / (y / z);381}382 383int 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 float389}390