guiand updated this revision to Diff 274895.
guiand added a comment.
Addressed comments, added test for indirect calls
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D81678/new/
https://reviews.llvm.org/D81678
Files:
clang/include/clang/Basic/CodeGenOptions.def
clang/include/clang/Driver/CC1Options.td
clang/lib/CodeGen/CGCall.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/test/CodeGen/indirect-noundef.c
llvm/include/llvm/Bitcode/LLVMBitCodes.h
llvm/include/llvm/IR/Attributes.td
llvm/lib/AsmParser/LLLexer.cpp
llvm/lib/AsmParser/LLParser.cpp
llvm/lib/AsmParser/LLToken.h
llvm/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
llvm/lib/IR/Attributes.cpp
llvm/lib/Transforms/Utils/CodeExtractor.cpp
Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp
===================================================================
--- llvm/lib/Transforms/Utils/CodeExtractor.cpp
+++ llvm/lib/Transforms/Utils/CodeExtractor.cpp
@@ -877,6 +877,7 @@
case Attribute::NoMerge:
case Attribute::NoReturn:
case Attribute::NoSync:
+ case Attribute::NoUndef:
case Attribute::None:
case Attribute::NonNull:
case Attribute::Preallocated:
Index: llvm/lib/IR/Attributes.cpp
===================================================================
--- llvm/lib/IR/Attributes.cpp
+++ llvm/lib/IR/Attributes.cpp
@@ -443,6 +443,8 @@
return "cold";
if (hasAttribute(Attribute::ImmArg))
return "immarg";
+ if (hasAttribute(Attribute::NoUndef))
+ return "noundef";
if (hasAttribute(Attribute::ByVal)) {
std::string Result;
Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
===================================================================
--- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -731,6 +731,8 @@
return bitc::ATTR_KIND_SANITIZE_MEMTAG;
case Attribute::Preallocated:
return bitc::ATTR_KIND_PREALLOCATED;
+ case Attribute::NoUndef:
+ return bitc::ATTR_KIND_NOUNDEF;
case Attribute::EndAttrKinds:
llvm_unreachable("Can not encode end-attribute kinds marker.");
case Attribute::None:
Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp
===================================================================
--- llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1530,6 +1530,8 @@
return Attribute::SanitizeMemTag;
case bitc::ATTR_KIND_PREALLOCATED:
return Attribute::Preallocated;
+ case bitc::ATTR_KIND_NOUNDEF:
+ return Attribute::NoUndef;
}
}
Index: llvm/lib/AsmParser/LLToken.h
===================================================================
--- llvm/lib/AsmParser/LLToken.h
+++ llvm/lib/AsmParser/LLToken.h
@@ -196,6 +196,7 @@
kw_naked,
kw_nest,
kw_noalias,
+ kw_noundef,
kw_nobuiltin,
kw_nocapture,
kw_noduplicate,
Index: llvm/lib/AsmParser/LLParser.cpp
===================================================================
--- llvm/lib/AsmParser/LLParser.cpp
+++ llvm/lib/AsmParser/LLParser.cpp
@@ -1374,6 +1374,7 @@
case lltok::kw_inalloca:
case lltok::kw_nest:
case lltok::kw_noalias:
+ case lltok::kw_noundef:
case lltok::kw_nocapture:
case lltok::kw_nonnull:
case lltok::kw_returned:
@@ -1677,6 +1678,9 @@
case lltok::kw_inalloca: B.addAttribute(Attribute::InAlloca); break;
case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break;
case lltok::kw_nest: B.addAttribute(Attribute::Nest); break;
+ case lltok::kw_noundef:
+ B.addAttribute(Attribute::NoUndef);
+ break;
case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break;
case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); break;
case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break;
@@ -1774,6 +1778,9 @@
}
case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break;
case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break;
+ case lltok::kw_noundef:
+ B.addAttribute(Attribute::NoUndef);
+ break;
case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break;
case lltok::kw_signext: B.addAttribute(Attribute::SExt); break;
case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break;
Index: llvm/lib/AsmParser/LLLexer.cpp
===================================================================
--- llvm/lib/AsmParser/LLLexer.cpp
+++ llvm/lib/AsmParser/LLLexer.cpp
@@ -696,6 +696,7 @@
KEYWORD(writeonly);
KEYWORD(zeroext);
KEYWORD(immarg);
+ KEYWORD(noundef);
KEYWORD(type);
KEYWORD(opaque);
Index: llvm/include/llvm/IR/Attributes.td
===================================================================
--- llvm/include/llvm/IR/Attributes.td
+++ llvm/include/llvm/IR/Attributes.td
@@ -39,6 +39,9 @@
/// Pass structure by value.
def ByVal : TypeAttr<"byval">;
+/// Parameter or return value may not contain uninitialized or poison bits
+def NoUndef : EnumAttr<"noundef">;
+
/// Marks function as being in a cold path.
def Cold : EnumAttr<"cold">;
Index: llvm/include/llvm/Bitcode/LLVMBitCodes.h
===================================================================
--- llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -643,6 +643,7 @@
ATTR_KIND_PREALLOCATED = 65,
ATTR_KIND_NO_MERGE = 66,
ATTR_KIND_NULL_POINTER_IS_VALID = 67,
+ ATTR_KIND_NOUNDEF = 68,
};
enum ComdatSelectionKindCodes {
Index: clang/test/CodeGen/indirect-noundef.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -O0 -emit-llvm -o - %s | FileCheck %s
+
+union u1 { int val; };
+
+// CHECK: @indirect_callee_int_ptr = global i32 (i32)*
+int (*indirect_callee_int_ptr)(int);
+// CHECK: @indirect_callee_union_ptr = global i32 (i32)*
+union u1 (*indirect_callee_union_ptr)(union u1);
+
+// CHECK-LABEL: define noundef i32 @indirect_callee_int(i32 noundef %
+int indirect_callee_int(int a) { return a; }
+// CHECK-LABEL: define i32 @indirect_callee_union(i32 %
+union u1 indirect_callee_union(union u1 a) { return a; }
+
+int main() {
+ // CHECK: call noundef i32 @indirect_callee_int(i32 noundef 0)
+ indirect_callee_int(0);
+ // CHECK: call i32 @indirect_callee_union(i32 %
+ indirect_callee_union((union u1){0});
+
+ indirect_callee_int_ptr = indirect_callee_int;
+ indirect_callee_union_ptr = indirect_callee_union;
+
+ // CHECK: call noundef i32 %{{.*}}(i32 noundef 0)
+ indirect_callee_int_ptr(0);
+ // CHECK: call i32 %{{.*}}(i32 %
+ indirect_callee_union_ptr((union u1){});
+
+ return 0;
+}
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -925,6 +925,7 @@
Opts.DisableFree = Args.hasArg(OPT_disable_free);
Opts.DiscardValueNames = Args.hasArg(OPT_discard_value_names);
+ Opts.DisableNoundefArgs = Args.hasArg(OPT_disable_noundef_args);
Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls);
Opts.NoEscapingBlockTailCalls =
Args.hasArg(OPT_fno_escaping_block_tail_calls);
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -1876,6 +1876,33 @@
llvm::for_each(NBA->builtinNames(), AddNoBuiltinAttr);
}
+static bool DetermineNoUndef(QualType QTy, CodeGenTypes &Types,
+ const llvm::DataLayout &DL, const ABIArgInfo &AI) {
+ llvm::Type *Ty = Types.ConvertTypeForMem(QTy);
+ if (AI.getKind() == ABIArgInfo::Indirect)
+ return true;
+ if (AI.getKind() == ABIArgInfo::Extend)
+ return true;
+ if (!DL.typeSizeEqualsStoreSize(Ty))
+ return false;
+ if (QTy->isExtIntType())
+ return true;
+ if (QTy->isReferenceType())
+ return true;
+ if (QTy->isScalarType()) {
+ if (const ComplexType *Complex = dyn_cast<ComplexType>(QTy))
+ return DetermineNoUndef(Complex->getElementType(), Types, DL, AI);
+ return true;
+ }
+ if (const VectorType *Vector = dyn_cast<VectorType>(QTy))
+ return DetermineNoUndef(Vector->getElementType(), Types, DL, AI);
+ if (const MatrixType *Matrix = dyn_cast<MatrixType>(QTy))
+ return DetermineNoUndef(Matrix->getElementType(), Types, DL, AI);
+ if (const ArrayType *Array = dyn_cast<ArrayType>(QTy))
+ return DetermineNoUndef(Array->getElementType(), Types, DL, AI);
+ return false;
+}
+
/// Construct the IR attribute list of a function or call.
///
/// When adding an attribute, please consider where it should be handled:
@@ -2075,6 +2102,14 @@
QualType RetTy = FI.getReturnType();
const ABIArgInfo &RetAI = FI.getReturnInfo();
+ const llvm::DataLayout &DL = getDataLayout();
+
+ // Determine if the return type could be partially undef
+ if (!RetTy->isVoidType() && RetAI.getKind() != ABIArgInfo::Indirect &&
+ DetermineNoUndef(RetTy, getTypes(), DL, RetAI)) {
+ RetAttrs.addAttribute(llvm::Attribute::NoUndef);
+ }
+
switch (RetAI.getKind()) {
case ABIArgInfo::Extend:
if (RetAI.isSignExt())
@@ -2160,6 +2195,12 @@
}
}
+ // Decide whether the argument we're handling could be partially undef
+ bool ArgNoUndef = DetermineNoUndef(ParamType, getTypes(), DL, AI);
+ if (!CodeGenOpts.DisableNoundefArgs && ArgNoUndef) {
+ Attrs.addAttribute(llvm::Attribute::NoUndef);
+ }
+
// 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
// have the corresponding parameter variable. It doesn't make
// sense to do it here because parameters are so messed up.
Index: clang/include/clang/Driver/CC1Options.td
===================================================================
--- clang/include/clang/Driver/CC1Options.td
+++ clang/include/clang/Driver/CC1Options.td
@@ -509,6 +509,8 @@
HelpText<"Disable freeing of memory on exit">;
def discard_value_names : Flag<["-"], "discard-value-names">,
HelpText<"Discard value names in LLVM IR">;
+def disable_noundef_args : Flag<["-"], "disable-noundef-args">,
+ HelpText<"Disable emitting noundef attribute in LLVM IR">;
def load : Separate<["-"], "load">, MetaVarName<"<dsopath>">,
HelpText<"Load the named plugin (dynamic shared object)">;
def plugin : Separate<["-"], "plugin">, MetaVarName<"<name>">,
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -52,6 +52,7 @@
CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory.
CODEGENOPT(DiscardValueNames , 1, 0) ///< Discard Value Names from the IR (LLVMContext flag)
+CODEGENOPT(DisableNoundefArgs , 1, 0) ///< Disable emitting `noundef` attributes on IR call arguments
CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing.
CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get
///< the pristine IR generated by the
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits