llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Serge Pavlov (spavloff)

<details>
<summary>Changes</summary>

The forthcoming C standard defines pragma FENV_ROUND to support constant 
rounding mode. It also requires some functions to be evaluated with such mode, 
N3096 7.6.2p4 states:

    Within the scope of an FENV_ROUND pragma establishing a mode other
    than FE_DYNAMIC ... invocations of functions indicated in the table
    below, for which macro replacement has not been suppressed (7.1.4),
    shall be evaluated according to the specified constant rounding mode
    ... . Invocations of functions for which macro replacement has been
    suppressed and invocations of functions other than those indicated
    in the table below shall not be affected by constant rounding modes
    – they are affected by (and affect) only the dynamic mode.

The way this requirement is formulated indicates that it could be implemented 
using preprocessor facility. Such implementation would require a builtin macro 
that is set in the region where pragma FENV_ROUND is in effect and reflects 
constant rounding mode.

This change introduces macro __ROUNDING_MODE__, which is a string dependent on 
the constant rounding mode:

    FE_TOWARDZERO        "_rtz"
    FE_TONEAREST         "_rte"
    FE_DOWNWARD          "_rtp"
    FE_UPWARD            "_rtn"
    FE_TONEARESTFROMZERO "_rta"
    FE_DYNAMIC           empty string

All these values except "_rta" are OpenCL rounding mode modifiers. Default 
value, when no pragma FENV_ROUND is specified, is empty string. Concatenation 
of a function name with the builtin macro can be used to obtain name of the 
function variant for particular rounding mode, like "sin_rtz", or 
"__builtin_cos_rtd". The test "macro_rounding_mode.c" added in this change 
provides an example of possible use.

The macro is implemented in the same way as FLT_EVAL_METHOD, which also depends 
on the results of semantic analysis.

---
Full diff: https://github.com/llvm/llvm-project/pull/92699.diff


5 Files Affected:

- (modified) clang/include/clang/Lex/Preprocessor.h (+12) 
- (modified) clang/lib/Lex/PPMacroExpansion.cpp (+25) 
- (modified) clang/lib/Sema/Sema.cpp (+1) 
- (modified) clang/lib/Sema/SemaAttr.cpp (+1) 
- (added) clang/test/Preprocessor/macro_rounding_mode.c (+55) 


``````````diff
diff --git a/clang/include/clang/Lex/Preprocessor.h 
b/clang/include/clang/Lex/Preprocessor.h
index c0850a8fa9f7f..295633b2e3c73 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -181,6 +181,7 @@ class Preprocessor {
   IdentifierInfo *Ident__is_target_variant_os;
   IdentifierInfo *Ident__is_target_variant_environment;
   IdentifierInfo *Ident__FLT_EVAL_METHOD__;        // __FLT_EVAL_METHOD
+  IdentifierInfo *Ident__ROUNDING_MODE__;          // __ROUNDING_MODE__
 
   // Weak, only valid (and set) while InMacroArgs is true.
   Token* ArgMacro;
@@ -201,6 +202,9 @@ class Preprocessor {
   LangOptions::FPEvalMethodKind TUFPEvalMethod =
       LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine;
 
+  LangOptions::RoundingMode CurrentRoundingMode =
+      LangOptions::RoundingMode::Dynamic;
+
   // Next __COUNTER__ value, starts at 0.
   unsigned CounterValue = 0;
 
@@ -2356,6 +2360,14 @@ class Preprocessor {
     TUFPEvalMethod = Val;
   }
 
+  LangOptions::RoundingMode getCurrentRoundingMode() const {
+    return CurrentRoundingMode;
+  }
+
+  void setCurrentRoundingMode(LangOptions::RoundingMode RM) {
+    CurrentRoundingMode = RM;
+  }
+
   /// Retrieves the module that we're currently building, if any.
   Module *getCurrentModule();
 
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp 
b/clang/lib/Lex/PPMacroExpansion.cpp
index 8af4a97d00cb8..519fbfd666375 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -344,6 +344,7 @@ void Preprocessor::RegisterBuiltinMacros() {
   Ident__COUNTER__ = RegisterBuiltinMacro(*this, "__COUNTER__");
   Ident_Pragma  = RegisterBuiltinMacro(*this, "_Pragma");
   Ident__FLT_EVAL_METHOD__ = RegisterBuiltinMacro(*this, 
"__FLT_EVAL_METHOD__");
+  Ident__ROUNDING_MODE__ = RegisterBuiltinMacro(*this, "__ROUNDING_MODE__");
 
   // C++ Standing Document Extensions.
   if (getLangOpts().CPlusPlus)
@@ -1654,6 +1655,30 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
       Diag(Tok, diag::err_illegal_use_of_flt_eval_macro);
       Diag(getLastFPEvalPragmaLocation(), diag::note_pragma_entered_here);
     }
+  } else if (II == Ident__ROUNDING_MODE__) {
+    switch (getCurrentRoundingMode()) {
+    case LangOptions::RoundingMode::TowardZero:
+      OS << "_rtz";
+      break;
+    case LangOptions::RoundingMode::NearestTiesToEven:
+      OS << "_rte";
+      break;
+    case LangOptions::RoundingMode::TowardPositive:
+      OS << "_rtp";
+      break;
+    case LangOptions::RoundingMode::TowardNegative:
+      OS << "_rtn";
+      break;
+    case LangOptions::RoundingMode::NearestTiesToAway:
+      OS << "_rta";
+      break;
+    case LangOptions::RoundingMode::Dynamic:
+      OS << "";
+      break;
+    default:
+      llvm_unreachable("unknown rounding mode");
+    }
+    Tok.setKind(tok::string_literal);
   } else if (II == Ident__COUNTER__) {
     // __COUNTER__ expands to a simple numeric value.
     OS << CounterValue++;
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index f847c49920cf3..928a7953859c9 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -2725,6 +2725,7 @@ Sema::FPFeaturesStateRAII::~FPFeaturesStateRAII() {
   S.CurFPFeatures = OldFPFeaturesState;
   S.FpPragmaStack.CurrentValue = OldOverrides;
   S.PP.setCurrentFPEvalMethod(OldFPPragmaLocation, OldEvalMethod);
+  S.PP.setCurrentRoundingMode(S.CurFPFeatures.getConstRoundingMode());
 }
 
 bool Sema::isDeclaratorFunctionLike(Declarator &D) {
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index bb44531495a56..1faa5a879f030 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -1322,6 +1322,7 @@ void Sema::ActOnPragmaFEnvRound(SourceLocation Loc, 
llvm::RoundingMode FPR) {
   NewFPFeatures.setConstRoundingModeOverride(FPR);
   FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
   CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
+  PP.setCurrentRoundingMode(FPR);
 }
 
 void Sema::setExceptionMode(SourceLocation Loc,
diff --git a/clang/test/Preprocessor/macro_rounding_mode.c 
b/clang/test/Preprocessor/macro_rounding_mode.c
new file mode 100644
index 0000000000000..a18c72db9bed2
--- /dev/null
+++ b/clang/test/Preprocessor/macro_rounding_mode.c
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -emit-llvm -triple i386-linux -Wno-unknown-pragmas %s -o - 
| FileCheck %s
+
+double sin(double);
+double sin_rte(double);
+double sin_rtz(double);
+double sin_rtp(double);
+double sin_rtn(double);
+double sin_rta(double);
+
+#define CONCAT(a, b) CONCAT_(a, b)
+#define CONCAT_(a, b) a##b
+#define ADD_ROUNDING_MODE_SUFFIX(func) CONCAT(func, __ROUNDING_MODE__)
+
+#define sin(x) ADD_ROUNDING_MODE_SUFFIX(sin)(x)
+
+double call_dyn(double x) {
+  return sin(x);
+}
+// CHECK-LABEL: define {{.*}} double @call_dyn(
+// CHECK:       call double @llvm.sin.f64(
+
+#pragma STDC FENV_ROUND FE_TOWARDZERO
+double call_tz(double x) {
+  return sin(x);
+}
+// CHECK-LABEL: define {{.*}} double @call_tz(
+// CHECK:       call double @sin_rtz(
+
+#pragma STDC FENV_ROUND FE_TONEAREST
+double call_te(double x) {
+  return sin(x);
+}
+// CHECK-LABEL: define {{.*}} double @call_te(
+// CHECK:       call double @sin_rte(
+
+#pragma STDC FENV_ROUND FE_DOWNWARD
+double call_tn(double x) {
+  return sin(x);
+}
+// CHECK-LABEL: define {{.*}} double @call_tn(
+// CHECK:       call double @sin_rtn(
+
+#pragma STDC FENV_ROUND FE_UPWARD
+double call_tp(double x) {
+  return sin(x);
+}
+// CHECK-LABEL: define {{.*}} double @call_tp(
+// CHECK:       call double @sin_rtp(
+
+#pragma STDC FENV_ROUND FE_TONEARESTFROMZERO
+double call_tea(double x) {
+  return sin(x);
+}
+// CHECK-LABEL: define {{.*}} double @call_tea(
+// CHECK:       call double @sin_rta(

``````````

</details>


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

Reply via email to