kpn created this revision.
kpn added reviewers: steven.zhang, nemanjai.
kpn added a project: clang.
Herald added subscribers: shchenz, kbarton.
kpn requested review of this revision.
Herald added a subscriber: cfe-commits.

Currently clang is not correctly retrieving from the AST the metadata for 
constrained FP builtins. This patch fixes that for the PowerPC specific 
builtins.

For previous work in this vein see D92122 <https://reviews.llvm.org/D92122> for 
example.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D94186

Files:
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-ppc-fma.c
  clang/test/CodeGen/builtins-ppc-fpconstrained.c

Index: clang/test/CodeGen/builtins-ppc-fpconstrained.c
===================================================================
--- clang/test/CodeGen/builtins-ppc-fpconstrained.c
+++ clang/test/CodeGen/builtins-ppc-fpconstrained.c
@@ -2,16 +2,23 @@
 // RUN: %clang_cc1 -triple powerpc64le-gnu-linux -target-feature +vsx \
 // RUN: -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-UNCONSTRAINED %s
 // RUN: %clang_cc1 -triple powerpc64le-gnu-linux -target-feature +vsx \
-// RUN:  -ffp-exception-behavior=strict -emit-llvm %s -o - | FileCheck \
-// RUN: --check-prefix=CHECK-CONSTRAINED -vv %s
+// RUN:  -ffp-exception-behavior=maytrap -DSTRICT=1 -emit-llvm %s -o - | \
+// RUN: FileCheck --check-prefix=CHECK-CONSTRAINED -vv %s
 // RUN: %clang_cc1 -triple powerpc64le-gnu-linux -target-feature +vsx \
 // RUN: -fallow-half-arguments-and-returns -S -o - %s | \
 // RUN: FileCheck --check-prefix=CHECK-ASM --check-prefix=NOT-FIXME-CHECK  %s
 // RUN: %clang_cc1 -triple powerpc64le-gnu-linux -target-feature +vsx \
-// RUN: -fallow-half-arguments-and-returns -S -ffp-exception-behavior=strict \
-// RUN: -o - %s | FileCheck --check-prefix=CHECK-ASM \
+// RUN: -fallow-half-arguments-and-returns -S -ffp-exception-behavior=maytrap \
+// RUN: -DSTRICT=1 -o - %s | FileCheck --check-prefix=CHECK-ASM \
 // RUN: --check-prefix=FIXME-CHECK  %s
 
+#ifdef STRICT
+// Test that the constrained intrinsics are picking up the exception
+// metadata from the AST instead of the global default from the command line.
+
+#pragma float_control(except, on)
+#endif
+
 typedef __attribute__((vector_size(4 * sizeof(float)))) float vec_float;
 typedef __attribute__((vector_size(2 * sizeof(double)))) double vec_double;
 
Index: clang/test/CodeGen/builtins-ppc-fma.c
===================================================================
--- clang/test/CodeGen/builtins-ppc-fma.c
+++ clang/test/CodeGen/builtins-ppc-fma.c
@@ -1,6 +1,17 @@
 // RUN: %clang_cc1 -triple powerpc64le-gnu-linux \
-// RUN: -target-feature +altivec -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck      \
+// RUN: -target-feature +altivec -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck --check-prefix=NOSTRICT --check-prefix=SHARED    \
 // RUN: %s
+// RUN: %clang_cc1 -triple powerpc64le-gnu-linux \
+// RUN: -ffp-exception-behavior=maytrap -DSTRICT=1 \
+// RUN: -target-feature +altivec -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck --check-prefix=STRICT --check-prefix=SHARED    \
+// RUN: %s
+
+#ifdef STRICT
+// Test that the constrained intrinsics are picking up the exception
+// metadata from the AST instead of the global default from the command line.
+
+#pragma float_control(except, on)
+#endif
 
 typedef __attribute__((vector_size(4 * sizeof(float)))) float vec_float;
 typedef __attribute__((vector_size(2 * sizeof(double)))) double vec_double;
@@ -10,34 +21,42 @@
 
 void test_fma(void) {
   vf = __builtin_vsx_xvmaddasp(vf, vf, vf);
-  // CHECK: @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+  // NOSTRICT: @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+  // STRICT: @llvm.experimental.constrained.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
 
   vd = __builtin_vsx_xvmaddadp(vd, vd, vd);
-  // CHECK: @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+  // NOSTRICT: @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+  // STRICT: @llvm.experimental.constrained.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
 
   vf = __builtin_vsx_xvnmaddasp(vf, vf, vf);
-  // CHECK: [[RESULT:%[^ ]+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
-  // CHECK: fneg <4 x float> [[RESULT]]
+  // NOSTRICT: [[RESULT:%[^ ]+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+  // STRICT: [[RESULT:%[^ ]+]] = call <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+  // SHARED: fneg <4 x float> [[RESULT]]
 
   vd = __builtin_vsx_xvnmaddadp(vd, vd, vd);
-  // CHECK: [[RESULT:%[^ ]+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
-  // CHECK: fneg <2 x double> [[RESULT]]
+  // NOSTRICT: [[RESULT:%[^ ]+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+  // STRICT: [[RESULT:%[^ ]+]] = call <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+  // SHARED: fneg <2 x double> [[RESULT]]
 
   vf = __builtin_vsx_xvmsubasp(vf, vf, vf);
-  // CHECK: [[RESULT:%[^ ]+]] = fneg <4 x float> %{{.*}}
-  // CHECK: @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[RESULT]])
+  // SHARED: [[RESULT:%[^ ]+]] = fneg <4 x float> %{{.*}}
+  // NOSTRICT: @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[RESULT]])
+  // STRICT: @llvm.experimental.constrained.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[RESULT]], metadata !"round.tonearest", metadata !"fpexcept.strict")
 
   vd = __builtin_vsx_xvmsubadp(vd, vd, vd);
-  // CHECK: [[RESULT:%[^ ]+]] = fneg <2 x double> %{{.*}}
-  // CHECK: <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[RESULT]])
+  // SHARED: [[RESULT:%[^ ]+]] = fneg <2 x double> %{{.*}}
+  // NOSTRICT: <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[RESULT]])
+  // STRICT: <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[RESULT]], metadata !"round.tonearest", metadata !"fpexcept.strict")
 
   vf = __builtin_vsx_xvnmsubasp(vf, vf, vf);
-  // CHECK: [[RESULT:%[^ ]+]] = fneg <4 x float> %{{.*}}
-  // CHECK: [[RESULT2:%[^ ]+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[RESULT]])
-  // CHECK: fneg <4 x float> [[RESULT2]]
+  // SHARED: [[RESULT:%[^ ]+]] = fneg <4 x float> %{{.*}}
+  // NOSTRICT: [[RESULT2:%[^ ]+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[RESULT]])
+  // STRICT: [[RESULT2:%[^ ]+]] = call <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[RESULT]], metadata !"round.tonearest", metadata !"fpexcept.strict")
+  // SHARED: fneg <4 x float> [[RESULT2]]
 
   vd = __builtin_vsx_xvnmsubadp(vd, vd, vd);
-  // CHECK: [[RESULT:%[^ ]+]] = fneg <2 x double> %{{.*}}
-  // CHECK: [[RESULT2:%[^ ]+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[RESULT]])
-  // CHECK: fneg <2 x double> [[RESULT2]]
+  // SHARED: [[RESULT:%[^ ]+]] = fneg <2 x double> %{{.*}}
+  // NOSTRICT: [[RESULT2:%[^ ]+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[RESULT]])
+  // STRICT: [[RESULT2:%[^ ]+]] = call <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[RESULT]], metadata !"round.tonearest", metadata !"fpexcept.strict")
+  // SHARED: fneg <2 x double> [[RESULT2]]
 }
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -14526,6 +14526,7 @@
     llvm::Type *ResultType = ConvertType(E->getType());
     Value *X = EmitScalarExpr(E->getArg(0));
     if (Builder.getIsFPConstrained()) {
+      CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
       llvm::Function *F = CGM.getIntrinsic(
           Intrinsic::experimental_constrained_sqrt, ResultType);
       return Builder.CreateConstrainedFPCall(F, X);
@@ -14670,8 +14671,13 @@
                ? Intrinsic::experimental_constrained_trunc
                : Intrinsic::trunc;
     llvm::Function *F = CGM.getIntrinsic(ID, ResultType);
-    return Builder.getIsFPConstrained() ? Builder.CreateConstrainedFPCall(F, X)
-                                        : Builder.CreateCall(F, X);
+    if (Builder.getIsFPConstrained()) {
+      CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
+      return Builder.CreateConstrainedFPCall(F, X);
+    }
+    else {
+      return Builder.CreateCall(F, X);
+    }
   }
 
   // Absolute value
@@ -14704,35 +14710,47 @@
     switch (BuiltinID) {
       case PPC::BI__builtin_vsx_xvmaddadp:
       case PPC::BI__builtin_vsx_xvmaddasp:
-        if (Builder.getIsFPConstrained())
+        if (Builder.getIsFPConstrained()) {
+          CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
           return Builder.CreateConstrainedFPCall(F, {X, Y, Z});
-        else
+        }
+        else {
           return Builder.CreateCall(F, {X, Y, Z});
+        }
       case PPC::BI__builtin_vsx_xvnmaddadp:
       case PPC::BI__builtin_vsx_xvnmaddasp:
-        if (Builder.getIsFPConstrained())
+        if (Builder.getIsFPConstrained()) {
+          CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
           return Builder.CreateFNeg(
               Builder.CreateConstrainedFPCall(F, {X, Y, Z}), "neg");
-        else
+        }
+        else {
           return Builder.CreateFNeg(Builder.CreateCall(F, {X, Y, Z}), "neg");
+        }
       case PPC::BI__builtin_vsx_xvmsubadp:
       case PPC::BI__builtin_vsx_xvmsubasp:
-        if (Builder.getIsFPConstrained())
+        if (Builder.getIsFPConstrained()) {
+          CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
           return Builder.CreateConstrainedFPCall(
               F, {X, Y, Builder.CreateFNeg(Z, "neg")});
-        else
+        }
+        else {
           return Builder.CreateCall(F, {X, Y, Builder.CreateFNeg(Z, "neg")});
+        }
       case PPC::BI__builtin_vsx_xvnmsubadp:
       case PPC::BI__builtin_vsx_xvnmsubasp:
-        if (Builder.getIsFPConstrained())
+        if (Builder.getIsFPConstrained()) {
+          CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
           return Builder.CreateFNeg(
               Builder.CreateConstrainedFPCall(
                   F, {X, Y, Builder.CreateFNeg(Z, "neg")}),
               "neg");
-        else
+        }
+        else {
           return Builder.CreateFNeg(
               Builder.CreateCall(F, {X, Y, Builder.CreateFNeg(Z, "neg")}),
               "neg");
+        }
     }
     llvm_unreachable("Unknown FMA operation");
     return nullptr; // Suppress no-return warning
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to