[clang] 909a851 - [CGAtomic] Mark atomic libcall functions `nounwind`

2020-08-14 Thread Gui Andrade via cfe-commits

Author: Gui Andrade
Date: 2020-08-14T07:46:43Z
New Revision: 909a851dbffeb3637c19268e12e10fdf3dae2add

URL: 
https://github.com/llvm/llvm-project/commit/909a851dbffeb3637c19268e12e10fdf3dae2add
DIFF: 
https://github.com/llvm/llvm-project/commit/909a851dbffeb3637c19268e12e10fdf3dae2add.diff

LOG: [CGAtomic] Mark atomic libcall functions `nounwind`

These functions won't ever unwind. This is useful for MemorySanitizer
as it simplifies handling __atomic_load in particular.

Differential Revision: https://reviews.llvm.org/D85573

Added: 


Modified: 
clang/lib/CodeGen/CGAtomic.cpp
clang/test/CodeGen/atomic_ops.c

Removed: 




diff  --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index b7ada4ac7e3b..d7720a23dd72 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -307,7 +307,14 @@ static RValue emitAtomicLibcall(CodeGenFunction &CGF,
   const CGFunctionInfo &fnInfo =
 CGF.CGM.getTypes().arrangeBuiltinFunctionCall(resultType, args);
   llvm::FunctionType *fnTy = CGF.CGM.getTypes().GetFunctionType(fnInfo);
-  llvm::FunctionCallee fn = CGF.CGM.CreateRuntimeFunction(fnTy, fnName);
+  llvm::AttrBuilder fnAttrB;
+  fnAttrB.addAttribute(llvm::Attribute::NoUnwind);
+  fnAttrB.addAttribute(llvm::Attribute::WillReturn);
+  llvm::AttributeList fnAttrs = llvm::AttributeList::get(
+  CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, fnAttrB);
+
+  llvm::FunctionCallee fn =
+  CGF.CGM.CreateRuntimeFunction(fnTy, fnName, fnAttrs);
   auto callee = CGCallee::forDirect(fn);
   return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args);
 }

diff  --git a/clang/test/CodeGen/atomic_ops.c b/clang/test/CodeGen/atomic_ops.c
index c1eb1d005dba..79a1e5dba780 100644
--- a/clang/test/CodeGen/atomic_ops.c
+++ b/clang/test/CodeGen/atomic_ops.c
@@ -26,6 +26,9 @@ void foo(int x)
 
 }
 
+// LIBCALL: declare void @__atomic_load(i32, i8*, i8*, i32) 
[[LC_ATTRS:#[0-9]+]]
+// LIBCALL: declare i1 @__atomic_compare_exchange(i32, i8*, i8*, i8*, i32, 
i32) [[LC_ATTRS:#[0-9]+]]
+
 extern _Atomic _Bool b;
 
 _Bool bar() {
@@ -53,6 +56,8 @@ void baz(int y) {
   x += y;
 }
 
+// LIBCALL: declare void @__atomic_store(i32, i8*, i8*, i32) 
[[LC_ATTRS:#[0-9]+]]
+
 _Atomic(int) compound_add(_Atomic(int) in) {
 // CHECK-LABEL: @compound_add
 // CHECK: [[OLD:%.*]] = atomicrmw add i32* {{.*}}, i32 5 seq_cst
@@ -107,3 +112,5 @@ _Atomic(int) compound_mul(_Atomic(int) in) {
 
   return (in *= 5);
 }
+
+// LIBCALL: [[LC_ATTRS]] = { nounwind willreturn }



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 10264a1 - Introduce noundef attribute at call sites for stricter poison analysis

2021-03-04 Thread Gui Andrade via cfe-commits

Author: Gui Andrade
Date: 2021-03-04T12:15:12-08:00
New Revision: 10264a1b21aebf75a8102116c9648c3386e8021e

URL: 
https://github.com/llvm/llvm-project/commit/10264a1b21aebf75a8102116c9648c3386e8021e
DIFF: 
https://github.com/llvm/llvm-project/commit/10264a1b21aebf75a8102116c9648c3386e8021e.diff

LOG: Introduce noundef attribute at call sites for stricter poison analysis

This change adds a new IR noundef attribute, which denotes when a function call 
argument or return val may never contain uninitialized bits.

In MemorySanitizer, this attribute enables optimizations which decrease 
instrumented code size by up to 17% (measured with an instrumented build of 
clang) . I'll introduce the change allowing msan to take advantage of this 
information in a separate patch.

Differential Revision: https://reviews.llvm.org/D81678

Added: 
clang/test/CodeGen/attr-noundef.cpp
clang/test/CodeGen/indirect-noundef.cpp

Modified: 
clang/include/clang/Basic/CodeGenOptions.def
clang/include/clang/Driver/Options.td
clang/lib/CodeGen/CGCall.cpp
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/CodeGen/CodeGenModule.h

Removed: 




diff  --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index 50503dbe4f84..a1db1b101620 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -64,6 +64,7 @@ CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any 
lifetime markers
 CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with 
optnone at O0
 CODEGENOPT(ExperimentalStrictFloatingPoint, 1, 0) ///< Enables the new, 
experimental
   ///< strict floating point.
+CODEGENOPT(EnableNoundefAttrs, 1, 0) ///< Enable emitting `noundef` attributes 
on IR call arguments and return values
 CODEGENOPT(LegacyPassManager, 1, 0) ///< Use the legacy pass manager.
 CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
///< pass manager.

diff  --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 583d08151e1a..d4d48deb649f 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4994,6 +4994,9 @@ def code_completion_with_fixits : Flag<["-"], 
"code-completion-with-fixits">,
 def disable_free : Flag<["-"], "disable-free">,
   HelpText<"Disable freeing of memory on exit">,
   MarshallingInfoFlag>;
+def enable_noundef_analysis : Flag<["-"], "enable-noundef-analysis">, 
Group,
+  HelpText<"Enable analyzing function argument and return types for mandatory 
definedness">,
+  MarshallingInfoFlag>;
 def discard_value_names : Flag<["-"], "discard-value-names">,
   HelpText<"Discard value names in LLVM IR">,
   MarshallingInfoFlag>;

diff  --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 4ea707621b33..f5411daaa677 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1732,6 +1732,18 @@ static void 
AddAttributesFromFunctionProtoType(ASTContext &Ctx,
 FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
 }
 
+bool CodeGenModule::MayDropFunctionReturn(const ASTContext &Context,
+  QualType ReturnType) {
+  // We can't just discard the return value for a record type with a
+  // complex destructor or a non-trivially copyable type.
+  if (const RecordType *RT =
+  ReturnType.getCanonicalType()->getAs()) {
+if (const auto *ClassDecl = dyn_cast(RT->getDecl()))
+  return ClassDecl->hasTrivialDestructor();
+  }
+  return ReturnType.isTriviallyCopyableType(Context);
+}
+
 void CodeGenModule::getDefaultFunctionAttributes(StringRef Name,
  bool HasOptnone,
  bool AttrOnCallSite,
@@ -1905,6 +1917,55 @@ static void addNoBuiltinAttributes(llvm::AttrBuilder 
&FuncAttrs,
   llvm::for_each(NBA->builtinNames(), AddNoBuiltinAttr);
 }
 
+static bool DetermineNoUndef(QualType QTy, CodeGenTypes &Types,
+ const llvm::DataLayout &DL, const ABIArgInfo &AI,
+ bool CheckCoerce = true) {
+  llvm::Type *Ty = Types.ConvertTypeForMem(QTy);
+  if (AI.getKind() == ABIArgInfo::Indirect)
+return true;
+  if (AI.getKind() == ABIArgInfo::Extend)
+return true;
+  if (!DL.typeSizeEqualsStoreSize(Ty))
+// TODO: This will result in a modest amount of values not marked noundef
+// when they could be. We care about values that *invisibly* contain undef
+// bits from the perspective of LLVM IR.
+return false;
+  if (CheckCoerce && AI.canHaveCoerceToType()) {
+llvm::Type *CoerceTy = AI.getCoerceToType();
+if (llvm::TypeSize::isKnownGT(DL.getTypeSizeInBits(CoerceTy),
+