llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-codegen

Author: Serge Pavlov (spavloff)

<details>
<summary>Changes</summary>

This pragma is introduced by forthcoming C2x standard and can be used to set 
particular rounding mode without need to call 'fesetmode' or accessing control 
mode registers directly. Previously this pragma was implemented in clang 
partially, only for the purpose of using in constant expressions and making 
tests.

This change implements the pragma according to the standard draft. It sets up 
dynamic rounding mode in the compound statement where the pragma acts. This is 
inevitable for targets that set rounding mode by changing some control 
register. Targets that support static rounding mode encoded in instructions can 
have more efficient implementation, it is not implemented in this change.

The implementation uses intrinsic functions 'get_rounding' and 'set_rounding' 
to save/restore dynamic rounding mode. In some cases using functions that 
operate entire set of control modes or even FP environment may give more 
efficient implementation. This optimization is not a part of this change.

---

Patch is 33.34 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/89617.diff


11 Files Affected:

- (modified) clang/include/clang/AST/Stmt.h (+9) 
- (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (-3) 
- (modified) clang/include/clang/Basic/LangOptions.h (+6) 
- (modified) clang/lib/CodeGen/CGStmt.cpp (+56) 
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+3) 
- (modified) clang/lib/Parse/ParsePragma.cpp (-3) 
- (modified) clang/test/CodeGen/complex-strictfp.c (+39-21) 
- (modified) clang/test/CodeGen/math-errno.c (+1-1) 
- (modified) clang/test/CodeGen/pragma-fenv_access.c (+39-6) 
- (added) clang/test/CodeGen/pragma-fenv_round.c (+160) 
- (modified) clang/test/Parser/pragma-fenv_round.c (-1) 


``````````diff
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 1b9c9231047717..0ee9c13df75e41 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -1663,6 +1663,15 @@ class CompoundStmt final
     return *getTrailingObjects<FPOptionsOverride>();
   }
 
+  /// Get FPOptions inside this statement. They may differ from the outer
+  /// options due to pragmas.
+  /// \param CurFPOptions FPOptions outside this statement.
+  FPOptions getNewFPOptions(FPOptions CurFPOptions) const {
+    return hasStoredFPFeatures()
+               ? getStoredFPFeatures().applyOverrides(CurFPOptions)
+               : CurFPOptions;
+  }
+
   using body_iterator = Stmt **;
   using body_range = llvm::iterator_range<body_iterator>;
 
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index bb9ca2a50cc06c..cbda8975717d2e 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1255,9 +1255,6 @@ def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in 
STDC namespace">,
 // The C standard 7.6.1p2 says "The [FENV_ACCESS] pragma shall occur either
 // outside external declarations or preceding all explicit declarations and
 // statements inside a compound statement.
-def warn_stdc_fenv_round_not_supported :
-   Warning<"pragma STDC FENV_ROUND is not supported">,
-   InGroup<UnknownPragmas>;
 def warn_stdc_unknown_rounding_mode : Warning<
   "invalid or unsupported rounding mode in '#pragma STDC FENV_ROUND' - 
ignored">,
   InGroup<IgnoredPragmas>;
diff --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index 24b109e32cdd3e..2ec642e25ddcc6 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -834,6 +834,12 @@ class FPOptions {
            getAllowFEnvAccess();
   }
 
+  /// Checks if the rounding mode is unknown at compile-time.
+  bool isRoundingModeDynamic() const {
+    return (getConstRoundingMode() == RoundingMode::Dynamic) &&
+      (getAllowFEnvAccess() || getRoundingMath());
+  }
+
   RoundingMode getRoundingMode() const {
     RoundingMode RM = getConstRoundingMode();
     if (RM == RoundingMode::Dynamic) {
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 576fe2f7a2d46f..4fbc906afaeed5 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -486,6 +486,56 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S,
   return true;
 }
 
+namespace {
+/// Cleanup action that restores floating-point control modes upon leaving
+/// a scope.
+struct FPControlModesCleanup final : EHScopeStack::Cleanup {
+  llvm::Value *PreviousModes;
+  FPControlModesCleanup(llvm::Value *M) : PreviousModes(M) {}
+  void Emit(CodeGenFunction &CGF, Flags flags) override {
+    CGF.Builder.CreateIntrinsic(llvm::Intrinsic::set_rounding, {},
+                                {PreviousModes});
+  }
+};
+} // namespace
+
+void CodeGenFunction::emitSetFPControlModes(FPOptions NewFP) {
+  if (NewFP == CurFPFeatures)
+    return;
+
+  // For now only rounding mode is handled.
+
+  // If the new rounding mode is unknown in compile-time, it means that the
+  // compound statement contains `#pragma STDC FENV_ACCESS ON`. In this case 
all
+  // manipulations on FP environment, including setting and restoring control
+  // modes are made by the user.
+  if (NewFP.isRoundingModeDynamic())
+    return;
+
+  llvm::RoundingMode OldConstRM = CurFPFeatures.getConstRoundingMode();
+  llvm::RoundingMode NewConstRM = NewFP.getConstRoundingMode();
+  if (OldConstRM == NewConstRM)
+    return;
+
+  llvm::RoundingMode OldRM = CurFPFeatures.getRoundingMode();
+  if (OldRM == NewConstRM)
+    return;
+
+  llvm::Value *PreviousRM = nullptr;
+  if (CurFPFeatures.isRoundingModeDynamic()) {
+    llvm::Function *FGetRound = 
CGM.getIntrinsic(llvm::Intrinsic::get_rounding);
+    PreviousRM = Builder.CreateCall(FGetRound);
+  } else {
+    PreviousRM = llvm::ConstantInt::get(Int32Ty, static_cast<uint64_t>(OldRM));
+  }
+
+  llvm::RoundingMode NewRM = NewFP.getRoundingMode();
+  Builder.CreateIntrinsic(
+      llvm::Intrinsic::set_rounding, {},
+      llvm::ConstantInt::get(Int32Ty, static_cast<uint64_t>(NewRM)));
+  EHStack.pushCleanup<FPControlModesCleanup>(NormalAndEHCleanup, PreviousRM);
+}
+
 /// EmitCompoundStmt - Emit a compound statement {..} node.  If GetLast is 
true,
 /// this captures the expression result of the last sub-statement and returns 
it
 /// (for use by the statement expression extension).
@@ -509,6 +559,12 @@ CodeGenFunction::EmitCompoundStmtWithoutScope(const 
CompoundStmt &S,
   assert((!GetLast || (GetLast && ExprResult)) &&
          "If GetLast is true then the CompoundStmt must have a 
StmtExprResult");
 
+  // Optionally set up the new FP environment, if the compound statement
+  // contains a pragma that modifies it.
+  FPOptions NewFP = S.getNewFPOptions(CurFPFeatures);
+  emitSetFPControlModes(NewFP);
+  CGFPOptionsRAII SavedFPFeatues(*this, NewFP);
+
   Address RetAlloca = Address::invalid();
 
   for (auto *CurStmt : S.body()) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.h 
b/clang/lib/CodeGen/CodeGenFunction.h
index c49e9fd00c8d3e..4964a1c6c0c5fb 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3323,6 +3323,9 @@ class CodeGenFunction : public CodeGenTypeCache {
   /// Get the record field index as represented in debug info.
   unsigned getDebugInfoFIndex(const RecordDecl *Rec, unsigned FieldIndex);
 
+  /// Optionally emit code that sets required floating-point control modes and
+  /// creates corresponding cleanup action.
+  void emitSetFPControlModes(FPOptions NewFP);
 
   
//===--------------------------------------------------------------------===//
   //                            Declaration Emission
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 3979f75b6020db..56b15bda975a9a 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -3461,9 +3461,6 @@ void 
PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
     return;
   }
 
-  // Until the pragma is fully implemented, issue a warning.
-  PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
-
   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
                               1);
   Toks[0].startToken();
diff --git a/clang/test/CodeGen/complex-strictfp.c 
b/clang/test/CodeGen/complex-strictfp.c
index b0c84d5eebe725..e1f5405b921978 100644
--- a/clang/test/CodeGen/complex-strictfp.c
+++ b/clang/test/CodeGen/complex-strictfp.c
@@ -17,16 +17,18 @@ double D;
 
 // CHECK-LABEL: @test3a(
 // CHECK-NEXT:  entry:
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 2) #[[ATTR3:[0-9]+]]
 // CHECK-NEXT:    [[TMP0:%.*]] = load double, ptr @D, align 8
 // CHECK-NEXT:    [[CF_REAL:%.*]] = load float, ptr @cf, align 4
 // CHECK-NEXT:    [[CF_IMAG:%.*]] = load float, ptr getelementptr inbounds ({ 
float, float }, ptr @cf, i32 0, i32 1), align 4
-// CHECK-NEXT:    [[CONV:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_REAL]], metadata 
!"fpexcept.strict") #[[ATTR2:[0-9]+]]
-// CHECK-NEXT:    [[CONV1:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_IMAG]], metadata 
!"fpexcept.strict") #[[ATTR2]]
-// CHECK-NEXT:    [[ADD_R:%.*]] = call double 
@llvm.experimental.constrained.fadd.f64(double [[CONV]], double [[TMP0]], 
metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
-// CHECK-NEXT:    [[CONV2:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double [[ADD_R]], metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
-// CHECK-NEXT:    [[CONV3:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double [[CONV1]], metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    [[CONV:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_REAL]], metadata 
!"fpexcept.strict") #[[ATTR3]]
+// CHECK-NEXT:    [[CONV1:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_IMAG]], metadata 
!"fpexcept.strict") #[[ATTR3]]
+// CHECK-NEXT:    [[ADD_R:%.*]] = call double 
@llvm.experimental.constrained.fadd.f64(double [[CONV]], double [[TMP0]], 
metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR3]]
+// CHECK-NEXT:    [[CONV2:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double [[ADD_R]], metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR3]]
+// CHECK-NEXT:    [[CONV3:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double [[CONV1]], metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    store float [[CONV2]], ptr @cf, align 4
 // CHECK-NEXT:    store float [[CONV3]], ptr getelementptr inbounds ({ float, 
float }, ptr @cf, i32 0, i32 1), align 4
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 1) #[[ATTR3]]
 // CHECK-NEXT:    ret void
 //
 void test3a(void) {
@@ -35,13 +37,15 @@ void test3a(void) {
 
 // CHECK-LABEL: @test3b(
 // CHECK-NEXT:  entry:
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 2) #[[ATTR3]]
 // CHECK-NEXT:    [[CF_REAL:%.*]] = load float, ptr @cf, align 4
 // CHECK-NEXT:    [[CF_IMAG:%.*]] = load float, ptr getelementptr inbounds ({ 
float, float }, ptr @cf, i32 0, i32 1), align 4
-// CHECK-NEXT:    [[CONV:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_REAL]], metadata 
!"fpexcept.strict") #[[ATTR2]]
-// CHECK-NEXT:    [[CONV1:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_IMAG]], metadata 
!"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    [[CONV:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_REAL]], metadata 
!"fpexcept.strict") #[[ATTR3]]
+// CHECK-NEXT:    [[CONV1:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_IMAG]], metadata 
!"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    [[TMP0:%.*]] = load double, ptr @D, align 8
-// CHECK-NEXT:    [[ADD_R:%.*]] = call double 
@llvm.experimental.constrained.fadd.f64(double [[TMP0]], double [[CONV]], 
metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    [[ADD_R:%.*]] = call double 
@llvm.experimental.constrained.fadd.f64(double [[TMP0]], double [[CONV]], 
metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    store double [[ADD_R]], ptr @D, align 8
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 1) #[[ATTR3]]
 // CHECK-NEXT:    ret void
 //
 void test3b(void) {
@@ -50,19 +54,21 @@ void test3b(void) {
 
 // CHECK-LABEL: @test3c(
 // CHECK-NEXT:  entry:
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 2) #[[ATTR3]]
 // CHECK-NEXT:    [[G1_REAL:%.*]] = load double, ptr @g1, align 8
 // CHECK-NEXT:    [[G1_IMAG:%.*]] = load double, ptr getelementptr inbounds ({ 
double, double }, ptr @g1, i32 0, i32 1), align 8
 // CHECK-NEXT:    [[CF_REAL:%.*]] = load float, ptr @cf, align 4
 // CHECK-NEXT:    [[CF_IMAG:%.*]] = load float, ptr getelementptr inbounds ({ 
float, float }, ptr @cf, i32 0, i32 1), align 4
-// CHECK-NEXT:    [[CONV:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_REAL]], metadata 
!"fpexcept.strict") #[[ATTR2]]
-// CHECK-NEXT:    [[CONV1:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_IMAG]], metadata 
!"fpexcept.strict") #[[ATTR2]]
-// CHECK-NEXT:    [[CALL:%.*]] = call { double, double } @__divdc3(double 
noundef [[CONV]], double noundef [[CONV1]], double noundef [[G1_REAL]], double 
noundef [[G1_IMAG]]) #[[ATTR3:[0-9]+]]
+// CHECK-NEXT:    [[CONV:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_REAL]], metadata 
!"fpexcept.strict") #[[ATTR3]]
+// CHECK-NEXT:    [[CONV1:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float [[CF_IMAG]], metadata 
!"fpexcept.strict") #[[ATTR3]]
+// CHECK-NEXT:    [[CALL:%.*]] = call { double, double } @__divdc3(double 
noundef [[CONV]], double noundef [[CONV1]], double noundef [[G1_REAL]], double 
noundef [[G1_IMAG]]) #[[ATTR4:[0-9]+]]
 // CHECK-NEXT:    [[TMP0:%.*]] = extractvalue { double, double } [[CALL]], 0
 // CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { double, double } [[CALL]], 1
-// CHECK-NEXT:    [[CONV2:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP0]], metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
-// CHECK-NEXT:    [[CONV3:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP1]], metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    [[CONV2:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP0]], metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR3]]
+// CHECK-NEXT:    [[CONV3:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP1]], metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    store float [[CONV2]], ptr @cf, align 4
 // CHECK-NEXT:    store float [[CONV3]], ptr getelementptr inbounds ({ float, 
float }, ptr @cf, i32 0, i32 1), align 4
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 1) #[[ATTR3]]
 // CHECK-NEXT:    ret void
 //
 void test3c(void) {
@@ -71,12 +77,14 @@ void test3c(void) {
 
 // CHECK-LABEL: @test3d(
 // CHECK-NEXT:  entry:
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 2) #[[ATTR3]]
 // CHECK-NEXT:    [[G1_REAL:%.*]] = load double, ptr @g1, align 8
 // CHECK-NEXT:    [[G1_IMAG:%.*]] = load double, ptr getelementptr inbounds ({ 
double, double }, ptr @g1, i32 0, i32 1), align 8
 // CHECK-NEXT:    [[TMP0:%.*]] = load double, ptr @D, align 8
-// CHECK-NEXT:    [[ADD_R:%.*]] = call double 
@llvm.experimental.constrained.fadd.f64(double [[G1_REAL]], double [[TMP0]], 
metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    [[ADD_R:%.*]] = call double 
@llvm.experimental.constrained.fadd.f64(double [[G1_REAL]], double [[TMP0]], 
metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    store double [[ADD_R]], ptr @g1, align 8
 // CHECK-NEXT:    store double [[G1_IMAG]], ptr getelementptr inbounds ({ 
double, double }, ptr @g1, i32 0, i32 1), align 8
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 1) #[[ATTR3]]
 // CHECK-NEXT:    ret void
 //
 void test3d(void) {
@@ -85,12 +93,14 @@ void test3d(void) {
 
 // CHECK-LABEL: @test3e(
 // CHECK-NEXT:  entry:
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 2) #[[ATTR3]]
 // CHECK-NEXT:    [[TMP0:%.*]] = load double, ptr @D, align 8
 // CHECK-NEXT:    [[G1_REAL:%.*]] = load double, ptr @g1, align 8
 // CHECK-NEXT:    [[G1_IMAG:%.*]] = load double, ptr getelementptr inbounds ({ 
double, double }, ptr @g1, i32 0, i32 1), align 8
-// CHECK-NEXT:    [[ADD_R:%.*]] = call double 
@llvm.experimental.constrained.fadd.f64(double [[TMP0]], double [[G1_REAL]], 
metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    [[ADD_R:%.*]] = call double 
@llvm.experimental.constrained.fadd.f64(double [[TMP0]], double [[G1_REAL]], 
metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    store double [[ADD_R]], ptr @g1, align 8
 // CHECK-NEXT:    store double [[G1_IMAG]], ptr getelementptr inbounds ({ 
double, double }, ptr @g1, i32 0, i32 1), align 8
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 1) #[[ATTR3]]
 // CHECK-NEXT:    ret void
 //
 void test3e(void) {
@@ -99,8 +109,10 @@ void test3e(void) {
 
 // CHECK-LABEL: @t1(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[CONV:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double 4.000000e+00, metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 2) #[[ATTR3]]
+// CHECK-NEXT:    [[CONV:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double 4.000000e+00, metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    store float [[CONV]], ptr @cf, align 4
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 1) #[[ATTR3]]
 // CHECK-NEXT:    ret void
 //
 void t1(void) {
@@ -109,8 +121,10 @@ void t1(void) {
 
 // CHECK-LABEL: @t2(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[CONV:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double 4.000000e+00, metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 2) #[[ATTR3]]
+// CHECK-NEXT:    [[CONV:%.*]] = call float 
@llvm.experimental.constrained.fptrunc.f32.f64(double 4.000000e+00, metadata 
!"round.upward", metadata !"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    store float [[CONV]], ptr getelementptr inbounds ({ float, 
float }, ptr @cf, i32 0, i32 1), align 4
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 1) #[[ATTR3]]
 // CHECK-NEXT:    ret void
 //
 void t2(void) {
@@ -120,16 +134,18 @@ void t2(void) {
 // CHECK-LABEL: @t91(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[C:%.*]] = alloca [0 x i8], align 1
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 2) #[[ATTR3]]
 // CHECK-NEXT:    br i1 false, label [[COND_TRUE:%.*]], label 
[[COND_FALSE:%.*]]
 // CHECK:       cond.true:
-// CHECK-NEXT:    [[CONV:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float 2.000000e+00, metadata 
!"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    [[CONV:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float 2.000000e+00, metadata 
!"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    br label [[COND_END:%.*]]
 // CHECK:       cond.false:
-// CHECK-NEXT:    [[CONV1:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float 2.000000e+00, metadata 
!"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    [[CONV1:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float 2.000000e+00, metadata 
!"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    br label [[COND_END]]
 // CHECK:       cond.end:
 // CHECK-NEXT:    [[COND_R:%.*]] = phi double [ [[CONV]], [[COND_TRUE]] ], [ 
[[CONV1]], [[COND_FALSE]] ]
 // CHECK-NEXT:    [[COND_I:%.*]] = phi double [ 0.000000e+00, [[COND_TRUE]] ], 
[ 0.000000e+00, [[COND_FALSE]] ]
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 1) #[[ATTR3]]
 // CHECK-NEXT:    ret void
 //
 void t91(void) {
@@ -142,16 +158,18 @@ void t91(void) {
 // CHECK-LABEL: @t92(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[C:%.*]] = alloca [0 x i8], align 1
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 2) #[[ATTR3]]
 // CHECK-NEXT:    br i1 false, label [[COND_TRUE:%.*]], label 
[[COND_FALSE:%.*]]
 // CHECK:       cond.true:
-// CHECK-NEXT:    [[CONV:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float 2.000000e+00, metadata 
!"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    [[CONV:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float 2.000000e+00, metadata 
!"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    br label [[COND_END:%.*]]
 // CHECK:       cond.false:
-// CHECK-NEXT:    [[CONV1:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float 2.000000e+00, metadata 
!"fpexcept.strict") #[[ATTR2]]
+// CHECK-NEXT:    [[CONV1:%.*]] = call double 
@llvm.experimental.constrained.fpext.f64.f32(float 2.000000e+00, metadata 
!"fpexcept.strict") #[[ATTR3]]
 // CHECK-NEXT:    br label [[COND_END]]
 // CHECK:       cond.end:
 // CHECK-NEXT:    [[COND_R:%.*]] = phi double [ [[CONV]], [[COND_TRUE]] ], [ 
[[CONV1]], [[COND_FALSE]] ]
 // CHECK-NEXT:    [[COND_I:%.*]] = phi double [ 0.000000e+00, [[COND_TRUE]] ], 
[ 0.000000e+00, [[COND_FALSE]] ]
+// CHECK-NEXT:    call void @llvm.set.rounding(i32 1) #[[ATTR3]]
 // CHECK-NEXT:    ret void
 //
 void t92(void) {
diff --git a/clang/test/CodeGen/math-errno.c b/clang/test/CodeGen/math-errno.c
index b5354e47e26b77..b8da81b585fa53 100644
--- a/clang/test/CodeGen/math-errno.c
+++ b/clang/test/CodeGen/math-errno.c
@@ -27,7 +27,7 @@ float f1(float x) {
 // CHECK: tail call float @sqrtf(float noundef {{.*}}) #[[ATTR4_O2:[0-9]+]]
 
 // FAST-LABEL: define {{.*}} nofpclass(nan inf) float @f1
-// FAST: call fast nofpclass(nan inf) float @sqrtf(float noundef nofpclass(nan 
inf) {{.*}}) #[[ATTR3_FAST:[0-9]+]]
+// FAST: call nofpclass(nan inf) float @sqrtf(float noundef nofpclass(nan inf) 
{{.*}}) #[[ATTR3_FAST:[0-9]+]]
 
 // NOOPT-LABEL: define {{.*}} float @f1
 // NOOPT...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/89617
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to