mibintc updated this revision to Diff 349644.
mibintc added a comment.

I made a change to ActOnParenExpr to check that the parenthesized expression is 
not an lvalue before inserting the call to builtin __arithmetic_fence


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100118/new/

https://reviews.llvm.org/D100118

Files:
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Basic/TargetInfo.h
  clang/include/clang/Driver/Options.td
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Basic/TargetInfo.cpp
  clang/lib/Basic/Targets/AMDGPU.cpp
  clang/lib/Basic/Targets/AMDGPU.h
  clang/lib/Basic/Targets/PPC.cpp
  clang/lib/Basic/Targets/PPC.h
  clang/lib/Basic/Targets/SPIR.h
  clang/lib/Basic/Targets/WebAssembly.cpp
  clang/lib/Basic/Targets/WebAssembly.h
  clang/lib/Basic/Targets/X86.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/ASTUnit.cpp
  clang/lib/Frontend/CompilerInstance.cpp
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaCoroutine.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGen/arithmetic-fence-builtin.c
  clang/test/Driver/clang_f_opts.c
  clang/test/Sema/arithmetic-fence-builtin.c
  clang/tools/clang-import-test/clang-import-test.cpp

Index: clang/tools/clang-import-test/clang-import-test.cpp
===================================================================
--- clang/tools/clang-import-test/clang-import-test.cpp
+++ clang/tools/clang-import-test/clang-import-test.cpp
@@ -208,7 +208,7 @@
   TargetInfo *TI = TargetInfo::CreateTargetInfo(
       Ins->getDiagnostics(), Ins->getInvocation().TargetOpts);
   Ins->setTarget(TI);
-  Ins->getTarget().adjust(Ins->getLangOpts());
+  Ins->getTarget().adjust(Ins->getDiagnostics(), Ins->getLangOpts());
   Ins->createFileManager();
   Ins->createSourceManager(Ins->getFileManager());
   Ins->createPreprocessor(TU_Complete);
Index: clang/test/Sema/arithmetic-fence-builtin.c
===================================================================
--- /dev/null
+++ clang/test/Sema/arithmetic-fence-builtin.c
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -o - -verify -x c++ %s
+// RUN: %clang_cc1 -triple ppc64le -DPPC     -emit-llvm -o - -verify -x c++ %s
+// RUN: not %clang_cc1 -triple ppc64le -DPPC     -emit-llvm -o - -x c++ %s \
+// RUN:            -fprotect-parens 2>&1 | FileCheck -check-prefix=PPC %s
+#ifndef PPC
+int v;
+template <typename T> T addT(T a, T b) {
+  T *q = __arithmetic_fence(&a);
+  // expected-error@-1 {{operand of type 'float *' where floating, complex or a vector of such types is required ('float *' invalid)}}
+  // expected-error@-2 {{operand of type 'int *' where floating, complex or a vector of such types is required ('int *' invalid)}}
+  return __arithmetic_fence(a + b);
+  // expected-error@-1 {{operand of type 'int' where floating, complex or a vector of such types is required ('int' invalid)}}
+}
+int addit(int a, int b) {
+  float x, y;
+  typedef struct {
+    int a, b;
+  } stype;
+  stype s;
+  s = __arithmetic_fence(s);    // expected-error {{operand of type 'stype' where floating, complex or a vector of such types is required ('stype' invalid)}}
+  x = __arithmetic_fence(x, y); // expected-error {{too many arguments to function call, expected 1, have 2}}
+  // Complex is supported.
+  _Complex double cd, cd1;
+  cd = __arithmetic_fence(cd1);
+  // Vector is supported.
+  typedef float __v4hi __attribute__((__vector_size__(8)));
+  __v4hi vec1, vec2;
+  vec1 = __arithmetic_fence(vec2);
+
+  v = __arithmetic_fence(a + b); // expected-error {{operand of type 'int' where floating, complex or a vector of such types is required ('int' invalid)}}
+  float f = addT<float>(a, b);   // expected-note {{in instantiation of function template specialization 'addT<float>' requested here}}
+  int i = addT<int>(1, 2);       // expected-note {{in instantiation of function template specialization 'addT<int>' requested here}}
+  constexpr float d = 1.0 + 2.0;
+  constexpr float c = __arithmetic_fence(1.0 + 2.0);
+  // expected-error@-1 {{constexpr variable 'c' must be initialized by a constant expression}}
+  return 0;
+}
+// expected-error@+1 {{static_assert expression is not an integral constant expression}}
+static_assert( __arithmetic_fence(1.0 + 2.0), "message" );
+#else
+float addit(float a, float b) {
+  return __arithmetic_fence(a+b); // expected-error {{builtin is not supported on this target}}
+}
+#endif
+//PPC: error: option '-fprotect-parens' cannot be specified on this target
Index: clang/test/Driver/clang_f_opts.c
===================================================================
--- clang/test/Driver/clang_f_opts.c
+++ clang/test/Driver/clang_f_opts.c
@@ -1,13 +1,14 @@
 // REQUIRES: clang-driver
 
 // RUN: %clang -### -S -fasm -fblocks -fbuiltin -fno-math-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fmath-errno -fno-common -fno-pascal-strings -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fsplit-stack %s 2>&1 | FileCheck -check-prefix=CHECK-OPTIONS1 %s
-// RUN: %clang -### -S -fasm -fblocks -fbuiltin -fno-math-errno -fcommon -fpascal-strings -fno-asm -fno-blocks -fno-builtin -fmath-errno -fno-common -fno-pascal-strings -fno-show-source-location -fshort-enums %s 2>&1 | FileCheck -check-prefix=CHECK-OPTIONS2 %s
+// RUN: %clang -### -S -fasm -fblocks -fbuiltin -fno-math-errno -fcommon -fpascal-strings -fno-asm -fno-blocks -fno-builtin -fmath-errno -fno-common -fno-pascal-strings -fno-show-source-location -fshort-enums -fprotect-parens %s 2>&1 | FileCheck -check-prefix=CHECK-OPTIONS2 %s
 
 // CHECK-OPTIONS1: -fsplit-stack
 // CHECK-OPTIONS1: -fgnu-keywords
 // CHECK-OPTIONS1: -fblocks
 // CHECK-OPTIONS1: -fpascal-strings
 
+// CHECK-OPTIONS2: -fprotect-parens
 // CHECK-OPTIONS2: -fmath-errno
 // CHECK-OPTIONS2: -fno-gnu-keywords
 // CHECK-OPTIONS2: -fno-builtin
Index: clang/test/CodeGen/arithmetic-fence-builtin.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/arithmetic-fence-builtin.c
@@ -0,0 +1,50 @@
+// Test with fast math
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -DFAST \
+// RUN: -mreassociate \
+// RUN: -o - %s | FileCheck --check-prefixes CHECK,CHECKFAST %s
+//
+// Test with fast math and fprotect-parens
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -DFAST \
+// RUN: -mreassociate -fprotect-parens\
+// RUN: -o - %s | FileCheck --check-prefixes CHECK,CHECKFAST,CHECKPP %s
+//
+// Test without fast math: llvm intrinsic not created
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -fprotect-parens\
+// RUN: -o - %s | FileCheck --implicit-check-not="llvm.arithmetic.fence" %s
+//
+int v;
+int addit(float a, float b) {
+  // CHECK: define {{.*}}@addit(float %a, float %b) #0 {
+  _Complex double cd, cd1;
+  cd = __arithmetic_fence(cd1);
+  // CHECKFAST: call{{.*}} double @llvm.arithmetic.fence.f64({{.*}}real)
+  // CHECKFAST: call{{.*}} double @llvm.arithmetic.fence.f64({{.*}}imag)
+  // Vector should be supported.
+  typedef float __v2f32 __attribute__((__vector_size__(8)));
+  __v2f32 vec1, vec2;
+  vec1 = __arithmetic_fence(vec2);
+  // CHECKFAST: call{{.*}} <2 x float> @llvm.arithmetic.fence.v2f32
+
+  v = __arithmetic_fence(a + b);
+  // CHECKFAST: call{{.*}} float @llvm.arithmetic.fence.f32(float %add)
+
+  v = (a + b);
+  // CHECKPP: call{{.*}} float @llvm.arithmetic.fence.f32(float %add1)
+  return 0;
+}
+int addit1(int a, int b) {
+  // CHECK: define {{.*}}@addit1(i32 %a, i32 %b{{.*}}
+  v = (a + b);
+  // CHECK-NOT: call{{.*}} float @llvm.arithmetic.fence.int(float %add)
+  return 0;
+}
+#ifdef FAST
+#pragma float_control(precise, on)
+int subit(float a, float b, float *fp) {
+  // CHECKFAST: define {{.*}}@subit(float %a, float %b{{.*}}
+  *fp = __arithmetic_fence(a - b);
+  *fp = (a + b);
+  // CHECK-NOT: call{{.*}} float @llvm.arithmetic.fence.f32(float %add)
+  return 0;
+}
+#endif
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -4020,6 +4020,12 @@
 
 ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E) {
   assert(E && "ActOnParenExpr() missing expr");
+  QualType ExprTy = E->getType();
+  if (getLangOpts().ProtectParens && CurFPFeatures.getAllowFPReassociate() &&
+      !E->isLValue() &&
+      (ExprTy->isFloatingType() || (ExprTy->isComplexType()))) {
+    return BuildBuiltinCallExpr(R, Builtin::BI__arithmetic_fence, E);
+  }
   return new (Context) ParenExpr(L, R, E);
 }
 
@@ -6524,6 +6530,29 @@
                                ExecConfig, IsExecConfig);
 }
 
+/// BuildBuiltinCallExpr - Create a call to a builtin function specified by Id
+//  with the specified CallArgs
+ExprResult Sema::BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id,
+                                      MultiExprArg CallArgs) {
+  StringRef Name = Context.BuiltinInfo.getName(Id);
+  LookupResult R(*this, &Context.Idents.get(Name), Loc,
+                 Sema::LookupOrdinaryName);
+  LookupName(R, TUScope, /*AllowBuiltinCreation=*/true);
+
+  auto *BuiltInDecl = R.getAsSingle<FunctionDecl>();
+  assert(BuiltInDecl && "failed to find builtin declaration");
+
+  ExprResult DeclRef =
+      BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc);
+  assert(DeclRef.isUsable() && "Builtin reference cannot fail");
+
+  ExprResult Call =
+      BuildCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc);
+
+  assert(!Call.isInvalid() && "Call to builtin cannot fail!");
+  return Call;
+}
+
 /// Parse a __builtin_astype expression.
 ///
 /// __builtin_astype( value, dst type )
Index: clang/lib/Sema/SemaCoroutine.cpp
===================================================================
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -291,26 +291,6 @@
                                   cast<UnresolvedLookupExpr>(R.get()));
 }
 
-static Expr *buildBuiltinCall(Sema &S, SourceLocation Loc, Builtin::ID Id,
-                              MultiExprArg CallArgs) {
-  StringRef Name = S.Context.BuiltinInfo.getName(Id);
-  LookupResult R(S, &S.Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName);
-  S.LookupName(R, S.TUScope, /*AllowBuiltinCreation=*/true);
-
-  auto *BuiltInDecl = R.getAsSingle<FunctionDecl>();
-  assert(BuiltInDecl && "failed to find builtin declaration");
-
-  ExprResult DeclRef =
-      S.BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc);
-  assert(DeclRef.isUsable() && "Builtin reference cannot fail");
-
-  ExprResult Call =
-      S.BuildCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc);
-
-  assert(!Call.isInvalid() && "Call to builtin cannot fail!");
-  return Call.get();
-}
-
 static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType,
                                        SourceLocation Loc) {
   QualType CoroHandleType = lookupCoroutineHandleType(S, PromiseType, Loc);
@@ -327,7 +307,7 @@
   }
 
   Expr *FramePtr =
-      buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {});
+      S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {}).get();
 
   CXXScopeSpec SS;
   ExprResult FromAddr =
@@ -404,8 +384,8 @@
   // the resume call and return instruction, which would interfere with the
   // musttail call contract.
   JustAddress = S.MaybeCreateExprWithCleanups(JustAddress);
-  return buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_resume,
-                          JustAddress);
+  return S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_resume,
+                                JustAddress).get();
 }
 
 /// Build calls to await_ready, await_suspend, and await_resume for a co_await
@@ -1373,10 +1353,10 @@
     return false;
 
   Expr *FramePtr =
-      buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {});
+      S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {}).get();
 
   Expr *FrameSize =
-      buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_size, {});
+      S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_size, {}).get();
 
   // Make new call.
 
@@ -1405,7 +1385,8 @@
     return false;
 
   Expr *CoroFree =
-      buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_free, {FramePtr});
+      S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_free, {FramePtr})
+          .get();
 
   SmallVector<Expr *, 2> DeleteArgs{CoroFree};
 
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -1554,6 +1554,10 @@
     Diag(TheCall->getBeginLoc(), diag::warn_alloca)
         << TheCall->getDirectCallee();
     break;
+  case Builtin::BI__arithmetic_fence:
+    if (SemaBuiltinArithmeticFence(TheCall))
+      return ExprError();
+    break;
   case Builtin::BI__assume:
   case Builtin::BI__builtin_assume:
     if (SemaBuiltinAssume(TheCall))
@@ -6409,6 +6413,32 @@
   return false;
 }
 
+/// SemaBuiltinArithmeticFence - Handle __arithmetic_fence.
+bool Sema::SemaBuiltinArithmeticFence(CallExpr *TheCall) {
+  if (!Context.getTargetInfo().checkArithmeticFenceSupported())
+    return Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
+           << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
+  Expr *Arg = TheCall->getArg(0);
+  if (Arg->isInstantiationDependent())
+    return false;
+
+  const QualType ArgTy = TheCall->getArg(0)->getType();
+  bool IsFloating = [&]() {
+    if (const VectorType *VT = dyn_cast<VectorType>(ArgTy.getCanonicalType()))
+      return VT->getElementType().getTypePtr()->isFloatingType();
+    if (const ComplexType *CT = dyn_cast<ComplexType>(ArgTy.getCanonicalType()))
+      return CT->getElementType().getTypePtr()->isFloatingType();
+    return ArgTy->isFloatingType();
+  }();
+  if (!IsFloating)
+    return Diag(TheCall->getEndLoc(), diag::err_typecheck_expect_flt_or_vector)
+           << ArgTy;
+  if (checkArgCount(*this, TheCall, 1))
+    return true;
+  TheCall->setType(ArgTy);
+  return false;
+}
+
 /// SemaBuiltinAssume - Handle __assume (MS Extension).
 // __assume does not evaluate its arguments, and should warn if its argument
 // has side effects.
Index: clang/lib/Interpreter/Interpreter.cpp
===================================================================
--- clang/lib/Interpreter/Interpreter.cpp
+++ clang/lib/Interpreter/Interpreter.cpp
@@ -110,7 +110,7 @@
                                    "Initialization failed. "
                                    "Target is missing");
 
-  Clang->getTarget().adjust(Clang->getLangOpts());
+  Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
 
   return std::move(Clang);
 }
Index: clang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -142,7 +142,7 @@
   // Inform the target of the language options.
   // FIXME: We shouldn't need to do this, the target should be immutable once
   // created. This complexity should be lifted elsewhere.
-  getTarget().adjust(getLangOpts());
+  getTarget().adjust(getDiagnostics(), getLangOpts());
 
   // Adjust target options based on codegen options.
   getTarget().adjustTargetOptions(getCodeGenOpts(), getTargetOpts());
@@ -457,7 +457,7 @@
                                       getSourceManager(), *HeaderInfo, *this,
                                       /*IdentifierInfoLookup=*/nullptr,
                                       /*OwnsHeaderSearch=*/true, TUKind);
-  getTarget().adjust(getLangOpts());
+  getTarget().adjust(getDiagnostics(), getLangOpts());
   PP->Initialize(getTarget(), getAuxTarget());
 
   if (PPOpts.DetailedRecord)
Index: clang/lib/Frontend/ASTUnit.cpp
===================================================================
--- clang/lib/Frontend/ASTUnit.cpp
+++ clang/lib/Frontend/ASTUnit.cpp
@@ -588,7 +588,7 @@
     //
     // FIXME: We shouldn't need to do this, the target should be immutable once
     // created. This complexity should be lifted elsewhere.
-    Target->adjust(LangOpt);
+    Target->adjust(PP.getDiagnostics(), LangOpt);
 
     // Initialize the preprocessor.
     PP.Initialize(*Target);
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -2709,6 +2709,10 @@
     // If this isn't an FP option skip the claim below
     default: continue;
 
+    case options::OPT_fprotect_parens:
+    case options::OPT_fno_protect_parens:
+      break;
+
     // Options controlling individual features
     case options::OPT_fhonor_infinities:    HonorINFs = true;         break;
     case options::OPT_fno_honor_infinities: HonorINFs = false;        break;
@@ -4956,6 +4960,11 @@
                    false))
     CmdArgs.push_back("-fsplit-stack");
 
+  // -fprotect-parens=0 is default.
+  if (Args.hasFlag(options::OPT_fprotect_parens,
+                   options::OPT_fno_protect_parens, false))
+    CmdArgs.push_back("-fprotect-parens");
+
   RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs, JA);
 
   if (Arg *A = Args.getLastArg(options::OPT_fextend_args_EQ)) {
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -2833,6 +2833,33 @@
     Function *FnAssume = CGM.getIntrinsic(Intrinsic::assume);
     return RValue::get(Builder.CreateCall(FnAssume, ArgValue));
   }
+  case Builtin::BI__arithmetic_fence: {
+    // If FastMath is not selected, the builtin call is skipped.
+    CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
+    auto FMF = Builder.getFastMathFlags();
+    bool isArithmeticFenceEnabled = FMF.allowReassoc();
+    QualType ArgType = E->getArg(0)->getType();
+    if (ArgType->isComplexType()) {
+      if (isArithmeticFenceEnabled) {
+        QualType ElementType = ArgType->castAs<ComplexType>()->getElementType();
+        ComplexPairTy ComplexVal = EmitComplexExpr(E->getArg(0));
+        Value *Real = Builder.CreateArithmeticFence(ComplexVal.first,
+                                                    ConvertType(ElementType));
+        Value *Imag = Builder.CreateArithmeticFence(ComplexVal.second,
+                                                    ConvertType(ElementType));
+        return RValue::getComplex(std::make_pair(Real, Imag));
+      }
+      ComplexPairTy ComplexVal = EmitComplexExpr(E->getArg(0));
+      Value *Real = ComplexVal.first;
+      Value *Imag = ComplexVal.second;
+      return RValue::getComplex(std::make_pair(Real, Imag));
+    }
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+    if (isArithmeticFenceEnabled)
+      return RValue::get(
+          Builder.CreateArithmeticFence(ArgValue, ConvertType(ArgType)));
+    return RValue::get(ArgValue);
+  }
   case Builtin::BI__builtin_bswap16:
   case Builtin::BI__builtin_bswap32:
   case Builtin::BI__builtin_bswap64: {
Index: clang/lib/Basic/Targets/X86.h
===================================================================
--- clang/lib/Basic/Targets/X86.h
+++ clang/lib/Basic/Targets/X86.h
@@ -362,6 +362,8 @@
     }
   }
 
+  bool checkArithmeticFenceSupported() const override { return true; }
+
   CallingConv getDefaultCallingConv() const override {
     return CC_C;
   }
Index: clang/lib/Basic/Targets/WebAssembly.h
===================================================================
--- clang/lib/Basic/Targets/WebAssembly.h
+++ clang/lib/Basic/Targets/WebAssembly.h
@@ -138,7 +138,7 @@
 
   bool hasProtectedVisibility() const override { return false; }
 
-  void adjust(LangOptions &Opts) override;
+  void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
 };
 
 class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo
Index: clang/lib/Basic/Targets/WebAssembly.cpp
===================================================================
--- clang/lib/Basic/Targets/WebAssembly.cpp
+++ clang/lib/Basic/Targets/WebAssembly.cpp
@@ -234,7 +234,8 @@
                                              Builtin::FirstTSBuiltin);
 }
 
-void WebAssemblyTargetInfo::adjust(LangOptions &Opts) {
+void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags,
+                                   LangOptions &Opts) {
   // If the Atomics feature isn't available, turn off POSIXThreads and
   // ThreadModel, so that we don't predefine _REENTRANT or __STDCPP_THREADS__.
   if (!HasAtomics) {
Index: clang/lib/Basic/Targets/SPIR.h
===================================================================
--- clang/lib/Basic/Targets/SPIR.h
+++ clang/lib/Basic/Targets/SPIR.h
@@ -130,8 +130,8 @@
     AddrSpaceMap = DefaultIsGeneric ? &SPIRDefIsGenMap : &SPIRDefIsPrivMap;
   }
 
-  void adjust(LangOptions &Opts) override {
-    TargetInfo::adjust(Opts);
+  void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override {
+    TargetInfo::adjust(Diags, Opts);
     // FIXME: SYCL specification considers unannotated pointers and references
     // to be pointing to the generic address space. See section 5.9.3 of
     // SYCL 2020 specification.
Index: clang/lib/Basic/Targets/PPC.h
===================================================================
--- clang/lib/Basic/Targets/PPC.h
+++ clang/lib/Basic/Targets/PPC.h
@@ -89,7 +89,7 @@
   }
 
   // Set the language option for altivec based on our value.
-  void adjust(LangOptions &Opts) override;
+  void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
 
   // Note: GCC recognizes the following additional cpus:
   //  401, 403, 405, 405fp, 440fp, 464, 464fp, 476, 476fp, 505, 740, 801,
Index: clang/lib/Basic/Targets/PPC.cpp
===================================================================
--- clang/lib/Basic/Targets/PPC.cpp
+++ clang/lib/Basic/Targets/PPC.cpp
@@ -581,10 +581,10 @@
   Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
 }
 
-void PPCTargetInfo::adjust(LangOptions &Opts) {
+void PPCTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
   if (HasAltivec)
     Opts.AltiVec = 1;
-  TargetInfo::adjust(Opts);
+  TargetInfo::adjust(Diags, Opts);
   if (LongDoubleFormat != &llvm::APFloat::IEEEdouble())
     LongDoubleFormat = Opts.PPCIEEELongDouble
                            ? &llvm::APFloat::IEEEquad()
Index: clang/lib/Basic/Targets/AMDGPU.h
===================================================================
--- clang/lib/Basic/Targets/AMDGPU.h
+++ clang/lib/Basic/Targets/AMDGPU.h
@@ -93,7 +93,7 @@
 
   void setAddressSpaceMap(bool DefaultIsPrivate);
 
-  void adjust(LangOptions &Opts) override;
+  void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
 
   uint64_t getPointerWidthV(unsigned AddrSpace) const override {
     if (isR600(getTriple()))
Index: clang/lib/Basic/Targets/AMDGPU.cpp
===================================================================
--- clang/lib/Basic/Targets/AMDGPU.cpp
+++ clang/lib/Basic/Targets/AMDGPU.cpp
@@ -356,8 +356,8 @@
   MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
 }
 
-void AMDGPUTargetInfo::adjust(LangOptions &Opts) {
-  TargetInfo::adjust(Opts);
+void AMDGPUTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
+  TargetInfo::adjust(Diags, Opts);
   // ToDo: There are still a few places using default address space as private
   // address space in OpenCL, which needs to be cleaned up, then Opts.OpenCL
   // can be removed from the following line.
Index: clang/lib/Basic/TargetInfo.cpp
===================================================================
--- clang/lib/Basic/TargetInfo.cpp
+++ clang/lib/Basic/TargetInfo.cpp
@@ -346,7 +346,7 @@
 /// Apply changes to the target information with respect to certain
 /// language options which change the target configuration and adjust
 /// the language based on the target options where applicable.
-void TargetInfo::adjust(LangOptions &Opts) {
+void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
   if (Opts.NoBitFieldTypeAlign)
     UseBitFieldTypeAlignment = false;
 
@@ -430,6 +430,11 @@
   // its corresponding signed type.
   PaddingOnUnsignedFixedPoint |= Opts.PaddingOnUnsignedFixedPoint;
   CheckFixedPointBits();
+
+  if (Opts.ProtectParens && !checkArithmeticFenceSupported()) {
+    Diags.Report(diag::err_opt_not_valid_on_target) << "-fprotect-parens";
+    Opts.ProtectParens = false;
+  }
 }
 
 bool TargetInfo::initFeatureMap(
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -9306,6 +9306,9 @@
     }
   }
 
+  case Builtin::BI__arithmetic_fence:
+    return false;
+
   default:
     break;
   }
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -35,6 +35,7 @@
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeOrdering.h"
 #include "clang/Basic/BitmaskEnum.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/ExpressionTraits.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/OpenCLOptions.h"
@@ -5387,6 +5388,8 @@
                            Expr *ExecConfig = nullptr,
                            bool IsExecConfig = false,
                            bool AllowRecovery = false);
+  ExprResult BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id,
+                                  MultiExprArg CallArgs);
   enum class AtomicArgumentOrder { API, AST };
   ExprResult
   BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
@@ -12501,6 +12504,7 @@
 private:
   bool SemaBuiltinPrefetch(CallExpr *TheCall);
   bool SemaBuiltinAllocaWithAlign(CallExpr *TheCall);
+  bool SemaBuiltinArithmeticFence(CallExpr *TheCall);
   bool SemaBuiltinAssume(CallExpr *TheCall);
   bool SemaBuiltinAssumeAligned(CallExpr *TheCall);
   bool SemaBuiltinLongjmp(CallExpr *TheCall);
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1752,6 +1752,13 @@
             " of the target's native float-to-int conversion instructions">,
   PosFlag<SetTrue, [], "Assume that overflowing float-to-int casts are undefined (default)">>;
 
+defm protect_parens : BoolFOption<"protect-parens",
+  LangOpts<"ProtectParens">, DefaultFalse,
+  PosFlag<SetTrue, [CC1Option], 
+          "Determines whether the optimizer honors parentheses when "
+          "floating-point expressions are evaluated">,
+  NegFlag<SetFalse>>;
+
 def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
 def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;
 
@@ -4381,7 +4388,7 @@
 defm max_identifier_length : BooleanFFlag<"max-identifier-length">, Group<gfortran_Group>;
 defm module_private : BooleanFFlag<"module-private">, Group<gfortran_Group>;
 defm pack_derived : BooleanFFlag<"pack-derived">, Group<gfortran_Group>;
-defm protect_parens : BooleanFFlag<"protect-parens">, Group<gfortran_Group>;
+//defm protect_parens : BooleanFFlag<"protect-parens">, Group<gfortran_Group>;
 defm range_check : BooleanFFlag<"range-check">, Group<gfortran_Group>;
 defm real_4_real_10 : BooleanFFlag<"real-4-real-10">, Group<gfortran_Group>;
 defm real_4_real_16 : BooleanFFlag<"real-4-real-16">, Group<gfortran_Group>;
Index: clang/include/clang/Basic/TargetInfo.h
===================================================================
--- clang/include/clang/Basic/TargetInfo.h
+++ clang/include/clang/Basic/TargetInfo.h
@@ -1162,7 +1162,7 @@
   /// Apply changes to the target information with respect to certain
   /// language options which change the target configuration and adjust
   /// the language based on the target options where applicable.
-  virtual void adjust(LangOptions &Opts);
+  virtual void adjust(DiagnosticsEngine &Diags, LangOptions &Opts);
 
   /// Adjust target options based on codegen options.
   virtual void adjustTargetOptions(const CodeGenOptions &CGOpts,
@@ -1424,6 +1424,9 @@
   /// Whether the option -fextend-arguments={32,64} is supported on the target.
   virtual bool supportsExtendIntArgs() const { return false; }
 
+  /// Controls if __arithmetic_fence is supported in the targetted backend.
+  virtual bool checkArithmeticFenceSupported() const { return false; }
+
   /// Gets the default calling convention for the given target and
   /// declaration context.
   virtual CallingConv getDefaultCallingConv() const {
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -197,6 +197,8 @@
 COMPATIBLE_LANGOPT(FastMath          , 1, 0, "fast FP math optimizations, and __FAST_MATH__ predefined macro")
 COMPATIBLE_LANGOPT(FiniteMathOnly    , 1, 0, "__FINITE_MATH_ONLY__ predefined macro")
 COMPATIBLE_LANGOPT(UnsafeFPMath      , 1, 0, "Unsafe Floating Point Math")
+COMPATIBLE_LANGOPT(ProtectParens     , 1, 0, "optimizer honors parentheses "
+                   "when floating-point expressions are evaluated")
 BENIGN_LANGOPT(AllowFPReassoc    , 1, 0, "Permit Floating Point reassociation")
 BENIGN_LANGOPT(NoHonorNaNs       , 1, 0, "Permit Floating Point optimization without regard to NaN")
 BENIGN_LANGOPT(NoHonorInfs       , 1, 0, "Permit Floating Point optimization without regard to infinities")
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8476,6 +8476,9 @@
   "operand of type %0 where arithmetic or pointer type is required">;
 def err_typecheck_cond_incompatible_operands : Error<
   "incompatible operand types%diff{ ($ and $)|}0,1">;
+def err_typecheck_expect_flt_or_vector : Error<
+  "operand of type %0 where floating, complex or "
+  "a vector of such types is required (%0 invalid)">;
 def err_cast_selector_expr : Error<
   "cannot type cast @selector expression">;
 def ext_typecheck_cond_incompatible_pointers : ExtWarn<
Index: clang/include/clang/Basic/Builtins.def
===================================================================
--- clang/include/clang/Basic/Builtins.def
+++ clang/include/clang/Basic/Builtins.def
@@ -1657,6 +1657,9 @@
 BUILTIN(__builtin_ms_va_end, "vc*&", "n")
 BUILTIN(__builtin_ms_va_copy, "vc*&c*&", "n")
 
+// Arithmetic Fence: to prevent FP reordering and reassociation optimizations
+LANGBUILTIN(__arithmetic_fence, "v.", "t", ALL_LANGUAGES)
+
 #undef BUILTIN
 #undef LIBBUILTIN
 #undef LANGBUILTIN
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -1478,6 +1478,14 @@
    * ``maytrap`` The compiler avoids transformations that may raise exceptions that would not have been raised by the original code. Constant folding performed by the compiler is exempt from this option.
    * ``strict`` The compiler ensures that all transformations strictly preserve the floating point exception semantics of the original code.
 
+.. option:: -f[no-]protect-parens:
+
+   Where unsafe floating point optimizations are enabled, this option
+   determines whether the optimizer honors parentheses when floating-point
+   expressions are evaluated.  If unsafe floating point optimizations are
+   disabled, the option has no effect.  If unsafe floating point optimizations
+   are enabled, the default value is ``fno-protect-parens``.
+
 
 .. _fp-constant-eval:
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to