[clang] 63f0833 - [clang] Fix missing contract flag in sqrt intrinsic

Yaxun Liu via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 24 16:16:07 PDT 2023


Author: Yaxun (Sam) Liu
Date: 2023-08-24T19:15:17-04:00
New Revision: 63f0833ec4beb7d6bc63759ad8b336ad6dce0f93

URL: https://github.com/llvm/llvm-project/commit/63f0833ec4beb7d6bc63759ad8b336ad6dce0f93
DIFF: https://github.com/llvm/llvm-project/commit/63f0833ec4beb7d6bc63759ad8b336ad6dce0f93.diff

LOG: [clang] Fix missing contract flag in sqrt intrinsic

The fp options specified through pragma are already encoded in Expr.

This patch takes the same approach used by clang codegen to emit
fastmath flags for fadd insts, basically use RAII to set the
current fastmath flags in IRBuilder, which is then used to emit
sqrt intrinsic.

Fixes: https://github.com/llvm/llvm-project/issues/64653

Added: 
    

Modified: 
    clang/lib/CodeGen/CGBuiltin.cpp
    clang/test/CodeGen/fp-contract-fast-pragma.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index a395c4979081e3..25e1b36d05fd97 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -495,8 +495,8 @@ static Value *emitUnaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
                                 unsigned ConstrainedIntrinsicID) {
   llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
 
+  CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
   if (CGF.Builder.getIsFPConstrained()) {
-    CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
     Function *F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID, Src0->getType());
     return CGF.Builder.CreateConstrainedFPCall(F, { Src0 });
   } else {

diff  --git a/clang/test/CodeGen/fp-contract-fast-pragma.cpp b/clang/test/CodeGen/fp-contract-fast-pragma.cpp
index c2e52f070e93b6..a88ddac4037bb6 100644
--- a/clang/test/CodeGen/fp-contract-fast-pragma.cpp
+++ b/clang/test/CodeGen/fp-contract-fast-pragma.cpp
@@ -1,19 +1,30 @@
-// RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -O3 -triple %itanium_abi_triple \
+// RUN:   -emit-llvm -o - %s \
+// RUN:   | FileCheck -check-prefixes=COMMON,CHECK %s
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN:   -ffp-exception-behavior=strict -O3 \
+// RUN:   -triple %itanium_abi_triple -emit-llvm -o - %s \
+// RUN:   | FileCheck -check-prefixes=COMMON,STRICT %s
 
 // Is FP_CONTRACT honored in a simple case?
 float fp_contract_1(float a, float b, float c) {
-// CHECK: _Z13fp_contract_1fff
+// COMMON: _Z13fp_contract_1fff
 // CHECK: %[[M:.+]] = fmul contract float %a, %b
 // CHECK-NEXT: fadd contract float %[[M]], %c
+// STRICT: %[[M:.+]] = tail call contract float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// STRICT-NEXT: tail call contract float @llvm.experimental.constrained.fadd.f32(float %[[M]], float %c, metadata !"round.tonearest", metadata !"fpexcept.strict")
+
 #pragma clang fp contract(fast)
   return a * b + c;
 }
 
 // Is FP_CONTRACT state cleared on exiting compound statements?
 float fp_contract_2(float a, float b, float c) {
-  // CHECK: _Z13fp_contract_2fff
+  // COMMON: _Z13fp_contract_2fff
   // CHECK: %[[M:.+]] = fmul float %a, %b
   // CHECK-NEXT: fadd float %[[M]], %c
+  // STRICT: %[[M:.+]] = tail call float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.strict")
+  // STRICT-NEXT: tail call float @llvm.experimental.constrained.fadd.f32(float %[[M]], float %c, metadata !"round.tonearest", metadata !"fpexcept.strict")
   {
 #pragma clang fp contract(fast)
   }
@@ -31,9 +42,11 @@ T template_muladd(T a, T b, T c) {
 }
 
 float fp_contract_3(float a, float b, float c) {
-  // CHECK: _Z13fp_contract_3fff
+  // COMMON: _Z13fp_contract_3fff
   // CHECK: %[[M:.+]] = fmul contract float %a, %b
   // CHECK-NEXT: fadd contract float %[[M]], %c
+  // STRICT: %[[M:.+]] = tail call contract float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.strict")
+  // STRICT-NEXT: tail call contract float @llvm.experimental.constrained.fadd.f32(float %[[M]], float %c, metadata !"round.tonearest", metadata !"fpexcept.strict")
   return template_muladd<float>(a, b, c);
 }
 
@@ -46,24 +59,47 @@ class fp_contract_4 {
 };
 
 template class fp_contract_4<int>;
-// CHECK: _ZN13fp_contract_4IiE6methodEfff
+// COMMON: _ZN13fp_contract_4IiE6methodEfff
 // CHECK: %[[M:.+]] = fmul contract float %a, %b
 // CHECK-NEXT: fadd contract float %[[M]], %c
+// STRICT: %[[M:.+]] = tail call contract float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// STRICT-NEXT: tail call contract float @llvm.experimental.constrained.fadd.f32(float %[[M]], float %c, metadata !"round.tonearest", metadata !"fpexcept.strict")
 
 // Check file-scoped FP_CONTRACT
 #pragma clang fp contract(fast)
 float fp_contract_5(float a, float b, float c) {
-  // CHECK: _Z13fp_contract_5fff
+  // COMMON: _Z13fp_contract_5fff
   // CHECK: %[[M:.+]] = fmul contract float %a, %b
   // CHECK-NEXT: fadd contract float %[[M]], %c
+  // STRICT: %[[M:.+]] = tail call contract float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.strict")
+  // STRICT-NEXT: tail call contract float @llvm.experimental.constrained.fadd.f32(float %[[M]], float %c, metadata !"round.tonearest", metadata !"fpexcept.strict")
   return a * b + c;
 }
 
 // Verify that we can handle multiple flags on the same pragma
 #pragma clang fp contract(fast) contract(off)
 float fp_contract_6(float a, float b, float c) {
-  // CHECK: _Z13fp_contract_6fff
+  // COMMON: _Z13fp_contract_6fff
   // CHECK: %[[M:.+]] = fmul float %a, %b
   // CHECK-NEXT: fadd float %[[M]], %c
+  // STRICT: %[[M:.+]] = tail call float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.strict")
+  // STRICT-NEXT: tail call float @llvm.experimental.constrained.fadd.f32(float %[[M]], float %c, metadata !"round.tonearest", metadata !"fpexcept.strict")
   return a * b + c;
 }
+
+
+#pragma clang fp contract(fast)
+float fp_contract_7(float a) {
+// COMMON: _Z13fp_contract_7f
+// CHECK: tail call contract float @llvm.sqrt.f32(float %a)
+// STRICT: tail call contract float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.strict")
+  return __builtin_sqrtf(a);
+}
+
+float fp_contract_8(float a) {
+// COMMON: _Z13fp_contract_8f
+// CHECK: tail call float @llvm.sqrt.f32(float %a)
+// STRICT: tail call float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.strict")
+#pragma clang fp contract(off)
+  return __builtin_sqrtf(a);
+}


        


More information about the cfe-commits mailing list