[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-18 Thread Gui Andrade via Phabricator via cfe-commits
guiand closed this revision.
guiand added a comment.

Merged in https://reviews.llvm.org/rG780528d9da707b15849d6c9711cc3ab19f6c7f00


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-18 Thread Gui Andrade via Phabricator via cfe-commits
guiand reopened this revision.
guiand added a comment.
This revision is now accepted and ready to land.

Sorry, closed this mistakenly!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-23 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 279949.
guiand added a comment.

Adds additional constraints on `noundef`: Not a `nullptr_t`, not a member 
pointer, and not coerced to a type of larger size. Disabled emitting in return 
position for non-C++ languages (or inside extern "C").

@rsmith, I just didn't address your comment about being conservative with 
black-holeing C++ functions returning undef. At least for msan purposes this 
shouldn't be a *too* much of a problem, but of course this attribute is for 
general use by LLVM passes. I'm just wondering what kind of tradeoff we want to 
make here, I suppose.


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -x c++ -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
@@ -924,6 +924,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,54 @@
   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 (DL.getTypeSizeInBits(CoerceTy) > DL.getTypeSizeInBits(Ty))
+  // If we're coercing to a type with a greater size than the canonical one,
+  // we're introducing new undef bits.
+  // Coercing to a type of smaller or equal size is ok, as we know that
+  // there's no internal padding (typeSizeEqualsStoreSize).
+  return false;
+  }
+  if (QTy->isExtIntType())
+return true;
+  if (QTy->isReferenceType())
+return true;
+  if (QTy->isNullPtrType())
+return false;
+  if (QTy->isMemberPointerType())
+// TODO: Some member pointers are `noundef`, but it depends on the ABI. For
+// now, never mark them.
+return false;
+  if (QTy->isScalarType()) {
+if (const ComplexType *Complex = dyn_cast(QTy))
+  return DetermineNoUndef(Complex->getElementType(), Types, DL, AI, false);
+return true;
+  }
+  if (const VectorType *Vector = dyn_cast(QTy))
+return DetermineNoUndef(Vector->getElementType(), Types, DL, AI, false);
+  if (const MatrixType *Matrix = dyn_cast(QTy))
+return DetermineNoUndef(Matrix->getElementType(), Types, DL, AI, false);
+  if (const ArrayType *Array = dyn_cast(

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-23 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

Just saw your comment about tests as well. The idea was to have all tests 
ported over as part of a separate commit (I linked it in the main patch 
description) and then only to push either commit once both are ready to land.

To make it easier to be sure this specific feature is working correctly, I can 
port over some of those tests to this patch for review purposes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-07-25 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 280588.
guiand added a comment.

Update tests to reflect more strict noundef rules


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

Files:
  clang/test/ARCMT/objcmt-instancetype.m
  clang/test/ARCMT/objcmt-instancetype.m.result
  clang/test/ARCMT/objcmt-numeric-literals.m
  clang/test/ARCMT/objcmt-numeric-literals.m.result
  clang/test/CXX/except/except.spec/p14-ir.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
  clang/test/CXX/modules-ts/codegen-basics.cppm
  clang/test/CXX/special/class.copy/p3.cpp
  clang/test/CodeGen/2004-02-13-Memset.c
  clang/test/CodeGen/2004-06-17-UnorderedCompares.c
  clang/test/CodeGen/2006-05-19-SingleEltReturn.c
  clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
  clang/test/CodeGen/2009-02-13-zerosize-union-field.c
  clang/test/CodeGen/2009-05-04-EnumInreg.c
  clang/test/CodeGen/64bit-swiftcall.c
  clang/test/CodeGen/aapcs-align.cpp
  clang/test/CodeGen/aapcs-bitfield.c
  clang/test/CodeGen/aapcs64-align.cpp
  clang/test/CodeGen/aarch64-args.cpp
  clang/test/CodeGen/aarch64-bf16-getset-intrinsics.c
  clang/test/CodeGen/aarch64-byval-temp.c
  clang/test/CodeGen/aarch64-neon-3v.c
  clang/test/CodeGen/aarch64-neon-across.c
  clang/test/CodeGen/aarch64-neon-dot-product.c
  clang/test/CodeGen/aarch64-neon-extract.c
  clang/test/CodeGen/aarch64-neon-fcvt-intrinsics.c
  clang/test/CodeGen/aarch64-neon-fma.c
  clang/test/CodeGen/aarch64-neon-fp16fml.c
  clang/test/CodeGen/aarch64-neon-ldst-one.c
  clang/test/CodeGen/aarch64-neon-scalar-copy.c
  clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
  clang/test/CodeGen/aarch64-neon-tbl.c
  clang/test/CodeGen/aarch64-neon-vcombine.c
  clang/test/CodeGen/aarch64-neon-vget-hilo.c
  clang/test/CodeGen/aarch64-neon-vget.c
  clang/test/CodeGen/aarch64-poly128.c
  clang/test/CodeGen/aarch64-poly64.c
  clang/test/CodeGen/aarch64-varargs.c
  clang/test/CodeGen/address-space-avr.c
  clang/test/CodeGen/address-space-field1.c
  clang/test/CodeGen/address-space.c
  clang/test/CodeGen/aggregate-assign-call.c
  clang/test/CodeGen/aix-return.c
  clang/test/CodeGen/aix-struct-arg.c
  clang/test/CodeGen/aix-vaargs.c
  clang/test/CodeGen/alias.c
  clang/test/CodeGen/align_value.cpp
  clang/test/CodeGen/alloc-align-attr.c
  clang/test/CodeGen/arc/arguments.c
  clang/test/CodeGen/arm-aapcs-vfp.c
  clang/test/CodeGen/arm-abi-vector.c
  clang/test/CodeGen/arm-arguments.c
  clang/test/CodeGen/arm-bf16-params-returns.c
  clang/test/CodeGen/arm-byval-align.c
  clang/test/CodeGen/arm-cmse-attr.c
  clang/test/CodeGen/arm-cmse-call.c
  clang/test/CodeGen/arm-float-helpers.c
  clang/test/CodeGen/arm-fp16-arguments.c
  clang/test/CodeGen/arm-homogenous.c
  clang/test/CodeGen/arm-mangle-bf16.cpp
  clang/test/CodeGen/arm-mve-intrinsics/vld24.c
  clang/test/CodeGen/arm-neon-directed-rounding.c
  clang/test/CodeGen/arm-neon-dot-product.c
  clang/test/CodeGen/arm-neon-fma.c
  clang/test/CodeGen/arm-neon-numeric-maxmin.c
  clang/test/CodeGen/arm-neon-vcvtX.c
  clang/test/CodeGen/arm-swiftcall.c
  clang/test/CodeGen/arm-varargs.c
  clang/test/CodeGen/arm-vector-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments2.cpp
  clang/test/CodeGen/arm64-aapcs-arguments.c
  clang/test/CodeGen/arm64-abi-vector.c
  clang/test/CodeGen/arm64-arguments.c
  clang/test/CodeGen/arm64-microsoft-arguments.cpp
  clang/test/CodeGen/arm64-microsoft-intrinsics.c
  clang/test/CodeGen/arm64_32-vaarg.c
  clang/test/CodeGen/arm64_32.c
  clang/test/CodeGen/arm64_vcopy.c
  clang/test/CodeGen/arm64_vdupq_n_f64.c
  clang/test/CodeGen/arm_neon_intrinsics.c
  clang/test/CodeGen/armv7k-abi.c
  clang/test/CodeGen/asm-label.c
  clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c
  clang/test/CodeGen/atomic-arm64.c
  clang/test/CodeGen/atomic-ops-libcall.c
  clang/test/CodeGen/atomic-ops.c
  clang/test/CodeGen/atomic_ops.c
  clang/test/CodeGen/atomics-inlining.c
  clang/test/CodeGen/attr-func-def.c
  clang/test/CodeGen/attr-naked.c
  clang/test/CodeGen/attr-no-tail.c
  clang/test/CodeGen/attr-nomerge.cpp
  clang/test/CodeGen/attr-optnone.c
  clang/test/CodeGen/attr-target-mv-func-ptrs.c
  clang/test/CodeGen/attr-target-mv-va-args.c
  clang/test/CodeGen/attr-target-mv.c
  clang/test/CodeGen/attr-x86-interrupt.c
  clang/test/CodeGen/attributes.c
  clang/test/CodeGen/available-externally-hidden.cpp
  clang/test/CodeGen/available-externally-suppress.c
  clang/test/CodeGen/avx2-builtins.c
  clang/test/CodeGen/avx512-reduceMinMaxIntrin.c
  clang/test/CodeGen/big-atomic-ops.c
  clang/test/CodeGen/bittest-intrin.c
  clang/test/CodeGen/blocks.c
  clang/test/CodeGen/bool-convert.c
  clang/test/CodeGen/builtin-align-array.c
  clang/test/CodeGen/builtin-align.c
  clang/test/CodeGen/builtin-assume-aligned.c
  clang/test/CodeGen/builtin-attributes.c
  clang/test/CodeGen/builtin-memfns.c
  clang/test/CodeGen/builtin-sqrt.

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-25 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 280622.
guiand added a comment.

Added an across-the-board test with several different interesting cases. 
@rsmith, I'm not sure how to test things like VTables/VTTs, since afaik the way 
they would be exposed to function attributes would be if a struct is being 
passed by value. But in that case, we currently never emit noundef.


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -x c++ -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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -x c++ -S -emit-llvm %s -o - | FileCheck %s
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK: define i32 @{{.*}}ret_trivial
+// CHECK: define void @{{.*}}pass_trivial{{.*}}(i32 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge ret_huge() { return {}; }
+void pass_huge(Huge h) {}
+// CHECK: define void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef byval
+} // namespace check_structs
+
+// Passing unions by value
+// No unions may be marked noundef
+
+namespace check_unions {
+union Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK: define i32 @{{.*}}ret_trivial
+// CHECK: define void @{{.*}}pass_trivial{{.*}}(i32 %
+
+union NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+} // namespace check_unions
+
+// Passing `this` pointers
+// `this` pointer must always be defined
+
+namespace check_this {
+struct Object {
+  int data[];
+
+  Object() {
+this->data[0] = 0;
+  }
+  int getData() {
+return this->data[0];
+  }
+  Object *getThis() {
+return this;
+  }
+};
+
+void use_object() {
+  Object obj;
+  obj.getData();
+  obj.getThis();
+}
+// CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*}}getData{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef %"struct.check_this::Object"* @{{.*}}Object{{.*}}getThis{{.*}}(%"struct.check_this::Object"* noundef %
+} // namespace check_this
+
+// Passing vector types
+
+namespace check_vecs {
+typedef int __attribute__((vector_size(12))) i32x3;
+i32x3 ret_vec() {
+  return {};
+}
+void pass_vec(i32x3 v) {
+}
+
+// CHECK: define noundef <3 x i32> @{{.*}}ret_vec{{.*}}()
+// CHECK: define void @{{.*}}pass_vec{{.*}}(<3 x i32> noundef %
+} // namespace check_vec

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-28 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 281311.
guiand added a comment.

Incorporate C++'s more conservative checks for omitted return values


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -x c++ -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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -x c++ -S -emit-llvm %s -o - | FileCheck %s
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK: define i32 @{{.*}}ret_trivial
+// CHECK: define void @{{.*}}pass_trivial{{.*}}(i32 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge ret_huge() { return {}; }
+void pass_huge(Huge h) {}
+// CHECK: define void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef byval
+} // namespace check_structs
+
+// Passing unions by value
+// No unions may be marked noundef
+
+namespace check_unions {
+union Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK: define i32 @{{.*}}ret_trivial
+// CHECK: define void @{{.*}}pass_trivial{{.*}}(i32 %
+
+union NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+} // namespace check_unions
+
+// Passing `this` pointers
+// `this` pointer must always be defined
+
+namespace check_this {
+struct Object {
+  int data[];
+
+  Object() {
+this->data[0] = 0;
+  }
+  int getData() {
+return this->data[0];
+  }
+  Object *getThis() {
+return this;
+  }
+};
+
+void use_object() {
+  Object obj;
+  obj.getData();
+  obj.getThis();
+}
+// CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*}}getData{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef %"struct.check_this::Object"* @{{.*}}Object{{.*}}getThis{{.*}}(%"struct.check_this::Object"* noundef %
+} // namespace check_this
+
+// Passing vector types
+
+namespace check_vecs {
+typedef int __attribute__((vector_size(12))) i32x3;
+i32x3 ret_vec() {
+  return {};
+}
+void pass_vec(i32x3 v) {
+}
+
+// CHECK: define noundef <3 x i32> @{{.*}}ret_vec{{.*}}()
+// CHECK: define void @{{.*}}pass_vec{{.*}}(<3 x i32> noundef %
+} // namespace check_vecs
+
+// Passing exotic types
+// Function/Array pointers, Function member / Data member pointers, nullptr_t, ExtInt types
+
+namespace check_e

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-28 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 281323.
guiand edited the summary of this revision.
guiand added a comment.

Fixes regression; allows emitting noundef for non-FunctionDecls as well.


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -x c++ -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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -x c++ -S -emit-llvm %s -o - | FileCheck %s
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK: define i32 @{{.*}}ret_trivial
+// CHECK: define void @{{.*}}pass_trivial{{.*}}(i32 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge ret_huge() { return {}; }
+void pass_huge(Huge h) {}
+// CHECK: define void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef byval
+} // namespace check_structs
+
+// Passing unions by value
+// No unions may be marked noundef
+
+namespace check_unions {
+union Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK: define i32 @{{.*}}ret_trivial
+// CHECK: define void @{{.*}}pass_trivial{{.*}}(i32 %
+
+union NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+} // namespace check_unions
+
+// Passing `this` pointers
+// `this` pointer must always be defined
+
+namespace check_this {
+struct Object {
+  int data[];
+
+  Object() {
+this->data[0] = 0;
+  }
+  int getData() {
+return this->data[0];
+  }
+  Object *getThis() {
+return this;
+  }
+};
+
+void use_object() {
+  Object obj;
+  obj.getData();
+  obj.getThis();
+}
+// CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*}}getData{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef %"struct.check_this::Object"* @{{.*}}Object{{.*}}getThis{{.*}}(%"struct.check_this::Object"* noundef %
+} // namespace check_this
+
+// Passing vector types
+
+namespace check_vecs {
+typedef int __attribute__((vector_size(12))) i32x3;
+i32x3 ret_vec() {
+  return {};
+}
+void pass_vec(i32x3 v) {
+}
+
+// CHECK: define noundef <3 x i32> @{{.*}}ret_vec{{.*}}()
+// CHECK: define void @{{.*}}pass_vec{{.*}}(<3 x i32> noundef %
+} // namespace check_vecs
+
+// Passing exotic types
+// Function/Array pointers, Function member / Data member pointe

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-29 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 281345.
guiand added a comment.

Fix typo in MayDropFunctionReturn


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -x c++ -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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -x c++ -S -emit-llvm %s -o - | FileCheck %s
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK: define i32 @{{.*}}ret_trivial
+// CHECK: define void @{{.*}}pass_trivial{{.*}}(i32 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge ret_huge() { return {}; }
+void pass_huge(Huge h) {}
+// CHECK: define void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef byval
+} // namespace check_structs
+
+// Passing unions by value
+// No unions may be marked noundef
+
+namespace check_unions {
+union Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK: define i32 @{{.*}}ret_trivial
+// CHECK: define void @{{.*}}pass_trivial{{.*}}(i32 %
+
+union NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+} // namespace check_unions
+
+// Passing `this` pointers
+// `this` pointer must always be defined
+
+namespace check_this {
+struct Object {
+  int data[];
+
+  Object() {
+this->data[0] = 0;
+  }
+  int getData() {
+return this->data[0];
+  }
+  Object *getThis() {
+return this;
+  }
+};
+
+void use_object() {
+  Object obj;
+  obj.getData();
+  obj.getThis();
+}
+// CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*}}getData{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef %"struct.check_this::Object"* @{{.*}}Object{{.*}}getThis{{.*}}(%"struct.check_this::Object"* noundef %
+} // namespace check_this
+
+// Passing vector types
+
+namespace check_vecs {
+typedef int __attribute__((vector_size(12))) i32x3;
+i32x3 ret_vec() {
+  return {};
+}
+void pass_vec(i32x3 v) {
+}
+
+// CHECK: define noundef <3 x i32> @{{.*}}ret_vec{{.*}}()
+// CHECK: define void @{{.*}}pass_vec{{.*}}(<3 x i32> noundef %
+} // namespace check_vecs
+
+// Passing exotic types
+// Function/Array pointers, Function member / Data member pointers, nullptr_t, ExtInt types
+
+namespace check_exotic {
+struct Object {
+  int mfu

[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-07-29 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 281452.
guiand added a comment.

All tests up to date. Of particular note are the `ppc-*mmintrin.c` tests, which 
seemed to drastically change upon rerunning the test autogen script.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

Files:
  clang/test/ARCMT/objcmt-instancetype.m
  clang/test/ARCMT/objcmt-instancetype.m.result
  clang/test/ARCMT/objcmt-numeric-literals.m
  clang/test/ARCMT/objcmt-numeric-literals.m.result
  clang/test/CXX/except/except.spec/p14-ir.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
  clang/test/CXX/modules-ts/codegen-basics.cppm
  clang/test/CXX/special/class.copy/p3.cpp
  clang/test/CodeGen/2004-02-13-Memset.c
  clang/test/CodeGen/2004-06-17-UnorderedCompares.c
  clang/test/CodeGen/2006-05-19-SingleEltReturn.c
  clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
  clang/test/CodeGen/2009-02-13-zerosize-union-field.c
  clang/test/CodeGen/2009-05-04-EnumInreg.c
  clang/test/CodeGen/64bit-swiftcall.c
  clang/test/CodeGen/aapcs-align.cpp
  clang/test/CodeGen/aapcs-bitfield.c
  clang/test/CodeGen/aapcs64-align.cpp
  clang/test/CodeGen/aarch64-args.cpp
  clang/test/CodeGen/aarch64-bf16-getset-intrinsics.c
  clang/test/CodeGen/aarch64-byval-temp.c
  clang/test/CodeGen/aarch64-neon-3v.c
  clang/test/CodeGen/aarch64-neon-across.c
  clang/test/CodeGen/aarch64-neon-dot-product.c
  clang/test/CodeGen/aarch64-neon-extract.c
  clang/test/CodeGen/aarch64-neon-fcvt-intrinsics.c
  clang/test/CodeGen/aarch64-neon-fma.c
  clang/test/CodeGen/aarch64-neon-fp16fml.c
  clang/test/CodeGen/aarch64-neon-ldst-one.c
  clang/test/CodeGen/aarch64-neon-scalar-copy.c
  clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
  clang/test/CodeGen/aarch64-neon-tbl.c
  clang/test/CodeGen/aarch64-neon-vcombine.c
  clang/test/CodeGen/aarch64-neon-vget-hilo.c
  clang/test/CodeGen/aarch64-neon-vget.c
  clang/test/CodeGen/aarch64-poly128.c
  clang/test/CodeGen/aarch64-poly64.c
  clang/test/CodeGen/aarch64-varargs.c
  clang/test/CodeGen/address-space-avr.c
  clang/test/CodeGen/address-space-field1.c
  clang/test/CodeGen/address-space.c
  clang/test/CodeGen/aggregate-assign-call.c
  clang/test/CodeGen/aix-return.c
  clang/test/CodeGen/aix-struct-arg.c
  clang/test/CodeGen/aix-vaargs.c
  clang/test/CodeGen/alias.c
  clang/test/CodeGen/align_value.cpp
  clang/test/CodeGen/alloc-align-attr.c
  clang/test/CodeGen/arc/arguments.c
  clang/test/CodeGen/arm-aapcs-vfp.c
  clang/test/CodeGen/arm-abi-vector.c
  clang/test/CodeGen/arm-arguments.c
  clang/test/CodeGen/arm-bf16-params-returns.c
  clang/test/CodeGen/arm-byval-align.c
  clang/test/CodeGen/arm-cmse-attr.c
  clang/test/CodeGen/arm-cmse-call.c
  clang/test/CodeGen/arm-float-helpers.c
  clang/test/CodeGen/arm-fp16-arguments.c
  clang/test/CodeGen/arm-homogenous.c
  clang/test/CodeGen/arm-mangle-bf16.cpp
  clang/test/CodeGen/arm-mve-intrinsics/vld24.c
  clang/test/CodeGen/arm-neon-directed-rounding.c
  clang/test/CodeGen/arm-neon-dot-product.c
  clang/test/CodeGen/arm-neon-fma.c
  clang/test/CodeGen/arm-neon-numeric-maxmin.c
  clang/test/CodeGen/arm-neon-vcvtX.c
  clang/test/CodeGen/arm-swiftcall.c
  clang/test/CodeGen/arm-varargs.c
  clang/test/CodeGen/arm-vector-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments2.cpp
  clang/test/CodeGen/arm64-aapcs-arguments.c
  clang/test/CodeGen/arm64-abi-vector.c
  clang/test/CodeGen/arm64-arguments.c
  clang/test/CodeGen/arm64-microsoft-arguments.cpp
  clang/test/CodeGen/arm64-microsoft-intrinsics.c
  clang/test/CodeGen/arm64_32-vaarg.c
  clang/test/CodeGen/arm64_32.c
  clang/test/CodeGen/arm64_vcopy.c
  clang/test/CodeGen/arm64_vdupq_n_f64.c
  clang/test/CodeGen/arm_neon_intrinsics.c
  clang/test/CodeGen/armv7k-abi.c
  clang/test/CodeGen/asm-label.c
  clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c
  clang/test/CodeGen/atomic-arm64.c
  clang/test/CodeGen/atomic-ops-libcall.c
  clang/test/CodeGen/atomic-ops.c
  clang/test/CodeGen/atomic_ops.c
  clang/test/CodeGen/atomics-inlining.c
  clang/test/CodeGen/attr-func-def.c
  clang/test/CodeGen/attr-naked.c
  clang/test/CodeGen/attr-no-tail.c
  clang/test/CodeGen/attr-nomerge.cpp
  clang/test/CodeGen/attr-optnone.c
  clang/test/CodeGen/attr-target-mv-func-ptrs.c
  clang/test/CodeGen/attr-target-mv-va-args.c
  clang/test/CodeGen/attr-target-mv.c
  clang/test/CodeGen/attr-x86-interrupt.c
  clang/test/CodeGen/attributes.c
  clang/test/CodeGen/available-externally-hidden.cpp
  clang/test/CodeGen/available-externally-suppress.c
  clang/test/CodeGen/avx2-builtins.c
  clang/test/CodeGen/avx512-reduceMinMaxIntrin.c
  clang/test/CodeGen/big-atomic-ops.c
  clang/test/CodeGen/bittest-intrin.c
  clang/test/CodeGen/blocks.c
  clang/test/CodeGen/bool-convert.c
  clang/test/CodeGen/builtin-align-array.c
  clang/test/CodeGen/builtin-align.c
  clang/test/CodeGen/builtin-assume-aligned.c
  clang/test/C

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-29 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 281676.
guiand added a comment.

Addressed comments


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -x c++ -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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,163 @@
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -x c++ -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -x c++ -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
+// RUN: %clang_cc1 -triple aarch64-gnu-linux -x c++ -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: define i32 @{{.*}}ret_trivial
+// CHECK-AARCH: define i64 @{{.*}}ret_trivial
+// CHECK-INTEL: define void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: define void @{{.*}}pass_trivial{{.*}}(i64 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define {{(dso_local)?}}void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge ret_huge() { return {}; }
+void pass_huge(Huge h) {}
+// CHECK: define void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef
+} // namespace check_structs
+
+// Passing unions by value
+// No unions may be marked noundef
+
+namespace check_unions {
+union Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: define i32 @{{.*}}ret_trivial
+// CHECK-AARCH: define i64 @{{.*}}ret_trivial
+// CHECK-INTEL: define void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: define void @{{.*}}pass_trivial{{.*}}(i64 %
+
+union NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+} // namespace check_unions
+
+// Passing `this` pointers
+// `this` pointer must always be defined
+
+namespace check_this {
+struct Object {
+  int data[];
+
+  Object() {
+this->data[0] = 0;
+  }
+  int getData() {
+return this->data[0];
+  }
+  Object *getThis() {
+return this;
+  }
+};
+
+void use_object() {
+  Object obj;
+  obj.getData();
+  obj.getThis();
+}
+// CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*}}getData{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef %"struct.check_this::Object"* @{{.*}}Object{{.*}}getThis{{.*}}(%"struc

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-29 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 281679.
guiand added a comment.

Updated comment on disable-noundef-args option


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -x c++ -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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,163 @@
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -x c++ -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -x c++ -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
+// RUN: %clang_cc1 -triple aarch64-gnu-linux -x c++ -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: define i32 @{{.*}}ret_trivial
+// CHECK-AARCH: define i64 @{{.*}}ret_trivial
+// CHECK-INTEL: define void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: define void @{{.*}}pass_trivial{{.*}}(i64 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define {{(dso_local)?}}void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge ret_huge() { return {}; }
+void pass_huge(Huge h) {}
+// CHECK: define void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef
+} // namespace check_structs
+
+// Passing unions by value
+// No unions may be marked noundef
+
+namespace check_unions {
+union Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: define i32 @{{.*}}ret_trivial
+// CHECK-AARCH: define i64 @{{.*}}ret_trivial
+// CHECK-INTEL: define void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: define void @{{.*}}pass_trivial{{.*}}(i64 %
+
+union NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+} // namespace check_unions
+
+// Passing `this` pointers
+// `this` pointer must always be defined
+
+namespace check_this {
+struct Object {
+  int data[];
+
+  Object() {
+this->data[0] = 0;
+  }
+  int getData() {
+return this->data[0];
+  }
+  Object *getThis() {
+return this;
+  }
+};
+
+void use_object() {
+  Object obj;
+  obj.getData();
+  obj.getThis();
+}
+// CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*}}getData{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef %"struct.check_this::Object"* @{{.*}}Objec

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-29 Thread Gui Andrade via Phabricator via cfe-commits
guiand marked 5 inline comments as done.
guiand added inline comments.



Comment at: clang/lib/CodeGen/CGCall.cpp:2148-2150
+} else if (const VarDecl *VDecl = dyn_cast(TargetDecl)) {
+  // Function pointer
+  HasStrictReturn &= !VDecl->isExternC();

rsmith wrote:
> `TargetDecl` (the callee of a function call) should never be a variable. You 
> shouldn't need this check.
I tried replacing the body of this if statement with an assertion to make sure, 
and the assertion fires.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678

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


[PATCH] D81703: [Clang] Don't leave Expr::Classification fields uninitialized in default constructor

2020-06-11 Thread Gui Andrade via Phabricator via cfe-commits
guiand created this revision.
guiand added a reviewer: rsmith.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
guiand edited the summary of this revision.

This changes `Expr::Classification::{Kind, Modifiable}` fields so that they are 
initialized as `Unknown` rather than left uninitialized. This way, if the 
default `Classification` is accidentally used, Clang will fire an assertion.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D81703

Files:
  clang/include/clang/AST/Expr.h
  clang/lib/AST/ExprClassification.cpp


Index: clang/lib/AST/ExprClassification.cpp
===
--- clang/lib/AST/ExprClassification.cpp
+++ clang/lib/AST/ExprClassification.cpp
@@ -65,6 +65,8 @@
   case Cl::CL_ArrayTemporary:
   case Cl::CL_ObjCMessageRValue:
   case Cl::CL_PRValue: assert(getValueKind() == VK_RValue); break;
+  case Cl::CL_Unknown:
+llvm_unreachable("Tried to classify unknown class!");
   }
 
   Cl::ModifiableType modifiable = Cl::CM_Untested;
@@ -678,6 +680,7 @@
   case Cl::CL_ArrayTemporary: return LV_ArrayTemporary;
   case Cl::CL_ObjCMessageRValue: return LV_InvalidMessageExpression;
   case Cl::CL_PRValue: return LV_InvalidExpression;
+  case Cl::CL_Unknown: break;
   }
   llvm_unreachable("Unhandled kind");
 }
@@ -701,6 +704,7 @@
   case Cl::CL_PRValue:
 return VC.getModifiable() == Cl::CM_LValueCast ?
   MLV_LValueCast : MLV_InvalidExpression;
+  case Cl::CL_Unknown: break;
   }
   assert(VC.getKind() == Cl::CL_LValue && "Unhandled kind");
   switch (VC.getModifiable()) {
@@ -716,6 +720,7 @@
   case Cl::CM_ConstAddrSpace: return MLV_ConstAddrSpace;
   case Cl::CM_ArrayType: return MLV_ArrayType;
   case Cl::CM_IncompleteType: return MLV_IncompleteType;
+  case Cl::CM_Unknown: break;
   }
   llvm_unreachable("Unhandled modifiable type");
 }
Index: clang/include/clang/AST/Expr.h
===
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -326,7 +326,8 @@
   CL_ClassTemporary, // A temporary of class type, or subobject thereof.
   CL_ArrayTemporary, // A temporary of array type.
   CL_ObjCMessageRValue, // ObjC message is an rvalue
-  CL_PRValue // A prvalue for any other reason, of any other type
+  CL_PRValue, // A prvalue for any other reason, of any other type
+  CL_Unknown // Null enumeration
 };
 /// The results of modification testing.
 enum ModifiableType {
@@ -340,14 +341,15 @@
   CM_ConstQualifiedField,
   CM_ConstAddrSpace,
   CM_ArrayType,
-  CM_IncompleteType
+  CM_IncompleteType,
+  CM_Unknown // Null enumeration
 };
 
   private:
 friend class Expr;
 
-unsigned short Kind;
-unsigned short Modifiable;
+unsigned short Kind = CL_Unknown;
+unsigned short Modifiable = CM_Unknown;
 
 explicit Classification(Kinds k, ModifiableType m)
   : Kind(k), Modifiable(m)


Index: clang/lib/AST/ExprClassification.cpp
===
--- clang/lib/AST/ExprClassification.cpp
+++ clang/lib/AST/ExprClassification.cpp
@@ -65,6 +65,8 @@
   case Cl::CL_ArrayTemporary:
   case Cl::CL_ObjCMessageRValue:
   case Cl::CL_PRValue: assert(getValueKind() == VK_RValue); break;
+  case Cl::CL_Unknown:
+llvm_unreachable("Tried to classify unknown class!");
   }
 
   Cl::ModifiableType modifiable = Cl::CM_Untested;
@@ -678,6 +680,7 @@
   case Cl::CL_ArrayTemporary: return LV_ArrayTemporary;
   case Cl::CL_ObjCMessageRValue: return LV_InvalidMessageExpression;
   case Cl::CL_PRValue: return LV_InvalidExpression;
+  case Cl::CL_Unknown: break;
   }
   llvm_unreachable("Unhandled kind");
 }
@@ -701,6 +704,7 @@
   case Cl::CL_PRValue:
 return VC.getModifiable() == Cl::CM_LValueCast ?
   MLV_LValueCast : MLV_InvalidExpression;
+  case Cl::CL_Unknown: break;
   }
   assert(VC.getKind() == Cl::CL_LValue && "Unhandled kind");
   switch (VC.getModifiable()) {
@@ -716,6 +720,7 @@
   case Cl::CM_ConstAddrSpace: return MLV_ConstAddrSpace;
   case Cl::CM_ArrayType: return MLV_ArrayType;
   case Cl::CM_IncompleteType: return MLV_IncompleteType;
+  case Cl::CM_Unknown: break;
   }
   llvm_unreachable("Unhandled modifiable type");
 }
Index: clang/include/clang/AST/Expr.h
===
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -326,7 +326,8 @@
   CL_ClassTemporary, // A temporary of class type, or subobject thereof.
   CL_ArrayTemporary, // A temporary of array type.
   CL_ObjCMessageRValue, // ObjC message is an rvalue
-  CL_PRValue // A prvalue for any other reason, of any other type
+  CL_PRValue, // A prvalue for any other reason, of any other type
+  CL_Unknown // Null enumeration
 };
 /// The results of modification testing.
 enum ModifiableType {
@@ -340,14 +341,15 @@
   CM_C

[PATCH] D81678: Introduce partialinit attribute at call sites for stricter poison analysis

2020-06-12 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

As it stands, this attribute is applied whether or not msan is enabled, 
specifically because we think it can be useful in other contexts.

As for the negativity of this attribute, it's true that it would be more 
intuitive to have it be something like `fullinit` instead. I did it this way 
because passing arguments which are `partialinit` is orders of magnitude less 
common than the inverse. So this avoids polluting most generated code with a 
new attribute.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D81678: Introduce partialinit attribute at call sites for stricter poison analysis

2020-06-12 Thread Gui Andrade via Phabricator via cfe-commits
guiand added inline comments.



Comment at: clang/include/clang/AST/Type.h:2139-2141
+  /// Check if this type has only two possible values, and so may be lowered to
+  /// a bool.
+  bool hasBooleanRepresentation() const;

rsmith wrote:
> This seems like a CodeGen-specific concern; I'm not sure this makes sense as 
> a query on the Type.
Makes sense, I can move it.



Comment at: clang/lib/AST/Type.cpp:2752-2753
+
+  if (const EnumType *ET = getAs())
+return ET->getDecl()->getIntegerType()->isBooleanType();
+

rsmith wrote:
> Under `-fstrict-enums` in C++, `enum E { a = 0, b = 1 };` has only two 
> distinct valid values. Should we consider that case?
I factored this code out of CGExpr.cpp, as it looked like this function 
governed whether `i1` values were lifted to `i8` (to meet the requirements of 
`bool`). I wanted to avoid struct `bool` members being marked `partialinit`. Do 
you think that would be a worthwhile separate change?



Comment at: clang/lib/CodeGen/CGRecordLayoutBuilder.cpp:679
 
+void CGRecordLowering::determineMemberPartialInit() {
+  auto hasTailPadding = [&](QualType FieldTypePtr) {

rsmith wrote:
> We already have support for C++'s `__has_unique_object_representations` 
> (`ASTContext::hasUniqueObjectRepresentations`), which does something very 
> similar to this. Do we need both? (Are there cases where this is 
> intentionally diverging from `__has_unique_object_representations`?)
For the purposes of this commit, I think I can change the decisions made in 
CGRecordLayoutBuilder to defer to `ASTContext::hasUniqueObjectRepresentations`. 
In an upcoming change though, I'd like to determine exactly what *kind* of 
padding is present in the field, most importantly between basic field padding 
and bitfield/union padding. The reasoning is as follows:

- Union padding (e.g. `union { i32 a; i8 b; }`) is completely erased from the 
outgoing LLVM type, as it's lowered to a `{ i32 }`; same thing goes for 
bitfield tail padding.
- On the other hand, field padding (e.g. in `struct { i8 a; i16 b; }`) is 
preserved in the lowered LLVM type `{ i8, i16 }`.

This means that under certain CGCall conventions, if we only observe field 
padding, we can get away with not using `partialinit`.
- If we're flattening a struct (without coercion) that contains no "lost" 
padding, then each function argument will be a fully initialized field of the 
struct.
- Same thing goes if we're returning an uncoerced LLVM type such as `{ i8, i16 
}`: each individual field is still present and fully initialized.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D81678: Introduce partialinit attribute at call sites for stricter poison analysis

2020-06-17 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

In D81678#2097081 , @aqjune wrote:

> To minimize diff, what about additionally introducing a function-level 
> attribute such as `args_frozen` stating that all arguments are frozen. (e.g 
> `define void @f(i32 x, i32 y) args_frozen`)?


I like this idea, and I think it will vastly reduce the tests diff. I'll try to 
update this patch with a positive `frozen` arg attribute and `args_frozen` 
function attribute ASAP.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D81678: Introduce partialinit attribute at call sites for stricter poison analysis

2020-06-18 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

Adding the function attribute turns out to have other challenges. Specifically, 
we don't want to have transforms remove a `frozen` from a parameter and then 
have to go through and update all the other parameters. This might happen if 
the function is marked with `frozen_args`; something like `ArgumentPromotion`, 
which usually removes attributes, would have to be aware of it.

I spoke with Evgenii about having a "magic" function attribute that's only 
really exposed at the bitcode/text level. It would get converted to/from the 
individual parameter `frozen`s so that transforms don't need to know or care 
that it exists. `frozen_args` would only serve as a sort of compression keyword 
in the bitcode/text IR. He wasn't thrilled with the idea but suggested I get 
peoples' thoughts on it.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-02 Thread Gui Andrade via Phabricator via cfe-commits
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 : 

[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-07-06 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 275771.
guiand added a comment.

Another wave of test updates


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

Files:
  clang/test/ARCMT/objcmt-instancetype.m
  clang/test/ARCMT/objcmt-instancetype.m.result
  clang/test/ARCMT/objcmt-numeric-literals.m
  clang/test/ARCMT/objcmt-numeric-literals.m.result
  clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c
  clang/test/AST/gen_ast_dump_json_test.py
  clang/test/ASTMerge/unnamed_fields/test.cpp
  clang/test/Analysis/casts.c
  clang/test/Analysis/inlining/DynDispatchBifurcate.m
  clang/test/Analysis/inlining/InlineObjCClassMethod.m
  clang/test/Analysis/misc-ps-region-store.m
  clang/test/Analysis/missing-bind-temporary.cpp
  clang/test/Analysis/silence-checkers-and-packages-core-all.cpp
  clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
  clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
  clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp
  clang/test/CXX/drs/dr0xx.cpp
  clang/test/CXX/except/except.spec/p14-ir.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
  clang/test/CXX/modules-ts/codegen-basics.cppm
  clang/test/CXX/special/class.copy/p3.cpp
  clang/test/CodeGen/2004-02-13-Memset.c
  clang/test/CodeGen/2004-06-17-UnorderedCompares.c
  clang/test/CodeGen/2006-05-19-SingleEltReturn.c
  clang/test/CodeGen/2007-02-25-C-DotDotDot.c
  clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
  clang/test/CodeGen/2008-03-05-syncPtr.c
  clang/test/CodeGen/2008-07-29-override-alias-decl.c
  clang/test/CodeGen/2008-07-30-implicit-initialization.c
  clang/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c
  clang/test/CodeGen/2009-02-13-zerosize-union-field.c
  clang/test/CodeGen/2009-05-04-EnumInreg.c
  clang/test/CodeGen/2009-09-24-SqrtErrno.c
  clang/test/CodeGen/3dnow-builtins.c
  clang/test/CodeGen/64bit-swiftcall.c
  clang/test/CodeGen/PR3589-freestanding-libcalls.c
  clang/test/CodeGen/_Bool-conversion.c
  clang/test/CodeGen/aapcs-align.cpp
  clang/test/CodeGen/aapcs-bitfield.c
  clang/test/CodeGen/aapcs64-align.cpp
  clang/test/CodeGen/aarch64-args.cpp
  clang/test/CodeGen/aarch64-bf16-getset-intrinsics.c
  clang/test/CodeGen/aarch64-byval-temp.c
  clang/test/CodeGen/aarch64-neon-3v.c
  clang/test/CodeGen/aarch64-neon-across.c
  clang/test/CodeGen/aarch64-neon-dot-product.c
  clang/test/CodeGen/aarch64-neon-extract.c
  clang/test/CodeGen/aarch64-neon-fcvt-intrinsics.c
  clang/test/CodeGen/aarch64-neon-fma.c
  clang/test/CodeGen/aarch64-neon-fp16fml.c
  clang/test/CodeGen/aarch64-neon-ldst-one.c
  clang/test/CodeGen/aarch64-neon-scalar-copy.c
  clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
  clang/test/CodeGen/aarch64-neon-tbl.c
  clang/test/CodeGen/aarch64-neon-vcombine.c
  clang/test/CodeGen/aarch64-neon-vget-hilo.c
  clang/test/CodeGen/aarch64-neon-vget.c
  clang/test/CodeGen/aarch64-poly128.c
  clang/test/CodeGen/aarch64-poly64.c
  clang/test/CodeGen/aarch64-varargs-ms.c
  clang/test/CodeGen/aarch64-varargs.c
  clang/test/CodeGen/address-space-avr.c
  clang/test/CodeGen/address-space-field1.c
  clang/test/CodeGen/address-space.c
  clang/test/CodeGen/aggregate-assign-call.c
  clang/test/CodeGen/aix-return.c
  clang/test/CodeGen/aix-struct-arg.c
  clang/test/CodeGen/aix-vaargs.c
  clang/test/CodeGen/alias.c
  clang/test/CodeGen/align-param.c
  clang/test/CodeGen/align_value.cpp
  clang/test/CodeGen/alloc-align-attr.c
  clang/test/CodeGen/arc/arguments.c
  clang/test/CodeGen/arc/struct-align.c
  clang/test/CodeGen/arm-aapcs-vfp.c
  clang/test/CodeGen/arm-abi-vector.c
  clang/test/CodeGen/arm-arguments.c
  clang/test/CodeGen/arm-bf16-params-returns.c
  clang/test/CodeGen/arm-byval-align.c
  clang/test/CodeGen/arm-cmse-attr.c
  clang/test/CodeGen/arm-cmse-call.c
  clang/test/CodeGen/arm-float-helpers.c
  clang/test/CodeGen/arm-fp16-arguments.c
  clang/test/CodeGen/arm-homogenous.c
  clang/test/CodeGen/arm-mangle-bf16.cpp
  clang/test/CodeGen/arm-mve-intrinsics/vld24.c
  clang/test/CodeGen/arm-neon-directed-rounding.c
  clang/test/CodeGen/arm-neon-dot-product.c
  clang/test/CodeGen/arm-neon-fma.c
  clang/test/CodeGen/arm-neon-numeric-maxmin.c
  clang/test/CodeGen/arm-neon-vcvtX.c
  clang/test/CodeGen/arm-pcs.c
  clang/test/CodeGen/arm-swiftcall.c
  clang/test/CodeGen/arm-varargs.c
  clang/test/CodeGen/arm-vector-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments2.cpp
  clang/test/CodeGen/arm64-aapcs-arguments.c
  clang/test/CodeGen/arm64-abi-vector.c
  clang/test/CodeGen/arm64-arguments.c
  clang/test/CodeGen/arm64-microsoft-arguments.cpp
  clang/test/CodeGen/arm64-microsoft-intrinsics.c
  clang/test/CodeGen/arm64-mte.c
  clang/test/CodeGen/arm64_32-vaarg.c
  clang/test/CodeGen/arm64_32.c
  clang/

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-08 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 276487.
guiand added a comment.

Per @nikic's suggestion, I isolated the LLVM side of the changes to a separate 
revision D83412 , which should be good to go.


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

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(QTy))
+  return DetermineNoUndef(Complex->getElementType(), Types, DL, AI);
+return true;
+  }
+  if (const VectorType *Vector = dyn_cast(QTy))
+return DetermineNoUndef(Vector->getElementType(), Types, DL, AI);
+  if (const MatrixType *Matrix = dyn_cast(QTy))
+return DetermineNoUndef(Matrix->getElementType(), Types, DL, AI);
+  if (const ArrayType *Array = dyn_cast(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/

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-07-14 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.
Herald added a subscriber: dang.

Is anything still pending here (besides the tests, of course)?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-07-15 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 277992.
guiand added a comment.

Update tests again


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

Files:
  clang/test/ARCMT/objcmt-instancetype.m
  clang/test/ARCMT/objcmt-instancetype.m.result
  clang/test/ARCMT/objcmt-numeric-literals.m
  clang/test/ARCMT/objcmt-numeric-literals.m.result
  clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c
  clang/test/AST/gen_ast_dump_json_test.py
  clang/test/ASTMerge/unnamed_fields/test.cpp
  clang/test/Analysis/casts.c
  clang/test/Analysis/inlining/DynDispatchBifurcate.m
  clang/test/Analysis/inlining/InlineObjCClassMethod.m
  clang/test/Analysis/misc-ps-region-store.m
  clang/test/Analysis/missing-bind-temporary.cpp
  clang/test/Analysis/silence-checkers-and-packages-core-all.cpp
  clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
  clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
  clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp
  clang/test/CXX/drs/dr0xx.cpp
  clang/test/CXX/except/except.spec/p14-ir.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
  clang/test/CXX/modules-ts/codegen-basics.cppm
  clang/test/CXX/special/class.copy/p3.cpp
  clang/test/CodeGen/2004-02-13-Memset.c
  clang/test/CodeGen/2004-06-17-UnorderedCompares.c
  clang/test/CodeGen/2006-05-19-SingleEltReturn.c
  clang/test/CodeGen/2007-02-25-C-DotDotDot.c
  clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
  clang/test/CodeGen/2008-03-05-syncPtr.c
  clang/test/CodeGen/2008-07-29-override-alias-decl.c
  clang/test/CodeGen/2008-07-30-implicit-initialization.c
  clang/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c
  clang/test/CodeGen/2009-02-13-zerosize-union-field.c
  clang/test/CodeGen/2009-05-04-EnumInreg.c
  clang/test/CodeGen/2009-09-24-SqrtErrno.c
  clang/test/CodeGen/3dnow-builtins.c
  clang/test/CodeGen/64bit-swiftcall.c
  clang/test/CodeGen/PR3589-freestanding-libcalls.c
  clang/test/CodeGen/_Bool-conversion.c
  clang/test/CodeGen/aapcs-align.cpp
  clang/test/CodeGen/aapcs-bitfield.c
  clang/test/CodeGen/aapcs64-align.cpp
  clang/test/CodeGen/aarch64-args.cpp
  clang/test/CodeGen/aarch64-bf16-getset-intrinsics.c
  clang/test/CodeGen/aarch64-byval-temp.c
  clang/test/CodeGen/aarch64-neon-3v.c
  clang/test/CodeGen/aarch64-neon-across.c
  clang/test/CodeGen/aarch64-neon-dot-product.c
  clang/test/CodeGen/aarch64-neon-extract.c
  clang/test/CodeGen/aarch64-neon-fcvt-intrinsics.c
  clang/test/CodeGen/aarch64-neon-fma.c
  clang/test/CodeGen/aarch64-neon-fp16fml.c
  clang/test/CodeGen/aarch64-neon-ldst-one.c
  clang/test/CodeGen/aarch64-neon-scalar-copy.c
  clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
  clang/test/CodeGen/aarch64-neon-tbl.c
  clang/test/CodeGen/aarch64-neon-vcombine.c
  clang/test/CodeGen/aarch64-neon-vget-hilo.c
  clang/test/CodeGen/aarch64-neon-vget.c
  clang/test/CodeGen/aarch64-poly128.c
  clang/test/CodeGen/aarch64-poly64.c
  clang/test/CodeGen/aarch64-varargs-ms.c
  clang/test/CodeGen/aarch64-varargs.c
  clang/test/CodeGen/address-space-avr.c
  clang/test/CodeGen/address-space-field1.c
  clang/test/CodeGen/address-space.c
  clang/test/CodeGen/aggregate-assign-call.c
  clang/test/CodeGen/aix-return.c
  clang/test/CodeGen/aix-struct-arg.c
  clang/test/CodeGen/aix-vaargs.c
  clang/test/CodeGen/alias.c
  clang/test/CodeGen/align-param.c
  clang/test/CodeGen/align_value.cpp
  clang/test/CodeGen/alloc-align-attr.c
  clang/test/CodeGen/arc/arguments.c
  clang/test/CodeGen/arc/struct-align.c
  clang/test/CodeGen/arm-aapcs-vfp.c
  clang/test/CodeGen/arm-abi-vector.c
  clang/test/CodeGen/arm-arguments.c
  clang/test/CodeGen/arm-bf16-params-returns.c
  clang/test/CodeGen/arm-byval-align.c
  clang/test/CodeGen/arm-cmse-attr.c
  clang/test/CodeGen/arm-cmse-call.c
  clang/test/CodeGen/arm-float-helpers.c
  clang/test/CodeGen/arm-fp16-arguments.c
  clang/test/CodeGen/arm-homogenous.c
  clang/test/CodeGen/arm-mangle-bf16.cpp
  clang/test/CodeGen/arm-mve-intrinsics/vld24.c
  clang/test/CodeGen/arm-neon-directed-rounding.c
  clang/test/CodeGen/arm-neon-dot-product.c
  clang/test/CodeGen/arm-neon-fma.c
  clang/test/CodeGen/arm-neon-numeric-maxmin.c
  clang/test/CodeGen/arm-neon-vcvtX.c
  clang/test/CodeGen/arm-pcs.c
  clang/test/CodeGen/arm-swiftcall.c
  clang/test/CodeGen/arm-varargs.c
  clang/test/CodeGen/arm-vector-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments2.cpp
  clang/test/CodeGen/arm64-aapcs-arguments.c
  clang/test/CodeGen/arm64-abi-vector.c
  clang/test/CodeGen/arm64-arguments.c
  clang/test/CodeGen/arm64-microsoft-arguments.cpp
  clang/test/CodeGen/arm64-microsoft-intrinsics.c
  clang/test/CodeGen/arm64-mte.c
  clang/test/CodeGen/arm64_32-vaarg.c
  clang/test/CodeGen/arm64_32.c
  clang/test/CodeG

[PATCH] D81678: Introduce partialinit attribute at call sites for stricter poison analysis

2020-06-18 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

In an email conversation with @rsmith and @eugenis, they raised the issue that 
it's not necessarily wrong to pass aggregate types by value, even when some 
fields are uninit.

A relevant excerpt from Richard:

> In addition to the union case, there's another strange case for passing class 
> types: in C++17 onwards, this example:
> 
> void f(S s);
>  void g() { f(S()); }
> 
> ... results in the parameter to f being constructed in place, rather than by 
> calling the copy constructor. (The same happens for a call to "f({})" in 
> C++11 onwards; it's just a lot more common in C++17.) So it is not the case 
> in general that f cannot be called with a partially-uninitialized S object. 
> :-(

From this, it's probably best for now not to mark aggregate types `frozen`. 
There's potentially some means to have the compiler prove aggregates must be 
frozen, but it's best to land frozen scalars first. And for the purposes of 
msan at least, scalars can account for the majority of the optimizations coming 
out of frozen.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D81678: Introduce frozen attribute at call sites for stricter poison analysis

2020-06-20 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 272213.
guiand retitled this revision from "Introduce partialinit attribute at call 
sites for stricter poison analysis" to "Introduce frozen attribute at call 
sites for stricter poison analysis".
guiand edited the summary of this revision.
guiand added a comment.
Herald added subscribers: sstefan1, phosek, dmgreen, mstorsjo, arphaman, 
dylanmckay, dschuff, emaste.
Herald added a reviewer: jdoerfert.

Reversing the meaning of the attribute to `frozen` and having the code not 
apply it to records removed pretty much all the logical changes in the code.

I took Juneyoung's suggestion and added a new cc1 flag, -disable-frozen-args 
(doesn't apply to return position, only argument position `frozen` attributes), 
and applied that to some 150 particularly problematic tests. Thousands of other 
tests were programatically and manually changed to include the new attribute.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678

Files:
  clang/include/clang/AST/Type.h
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Driver/CC1Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/ARCMT/objcmt-instancetype.m
  clang/test/ARCMT/objcmt-instancetype.m.result
  clang/test/ARCMT/objcmt-numeric-literals.m
  clang/test/ARCMT/objcmt-numeric-literals.m.result
  clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c
  clang/test/ASTMerge/unnamed_fields/test.cpp
  clang/test/Analysis/casts.c
  clang/test/Analysis/inlining/DynDispatchBifurcate.m
  clang/test/Analysis/inlining/InlineObjCClassMethod.m
  clang/test/Analysis/misc-ps-region-store.m
  clang/test/Analysis/missing-bind-temporary.cpp
  clang/test/Analysis/silence-checkers-and-packages-core-all.cpp
  clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
  clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
  clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp
  clang/test/CXX/drs/dr0xx.cpp
  clang/test/CXX/except/except.spec/p14-ir.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
  clang/test/CXX/modules-ts/codegen-basics.cppm
  clang/test/CXX/special/class.copy/p3.cpp
  clang/test/CodeGen/2004-02-13-Memset.c
  clang/test/CodeGen/2004-06-17-UnorderedCompares.c
  clang/test/CodeGen/2006-05-19-SingleEltReturn.c
  clang/test/CodeGen/2007-02-25-C-DotDotDot.c
  clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
  clang/test/CodeGen/2008-03-05-syncPtr.c
  clang/test/CodeGen/2008-07-29-override-alias-decl.c
  clang/test/CodeGen/2008-07-30-implicit-initialization.c
  clang/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c
  clang/test/CodeGen/2009-02-13-zerosize-union-field.c
  clang/test/CodeGen/2009-05-04-EnumInreg.c
  clang/test/CodeGen/2009-09-24-SqrtErrno.c
  clang/test/CodeGen/3dnow-builtins.c
  clang/test/CodeGen/64bit-swiftcall.c
  clang/test/CodeGen/PR3589-freestanding-libcalls.c
  clang/test/CodeGen/_Bool-conversion.c
  clang/test/CodeGen/aapcs-align.cpp
  clang/test/CodeGen/aapcs64-align.cpp
  clang/test/CodeGen/aarch64-args.cpp
  clang/test/CodeGen/aarch64-byval-temp.c
  clang/test/CodeGen/aarch64-neon-3v.c
  clang/test/CodeGen/aarch64-neon-across.c
  clang/test/CodeGen/aarch64-neon-dot-product.c
  clang/test/CodeGen/aarch64-neon-extract.c
  clang/test/CodeGen/aarch64-neon-fcvt-intrinsics.c
  clang/test/CodeGen/aarch64-neon-fma.c
  clang/test/CodeGen/aarch64-neon-ldst-one.c
  clang/test/CodeGen/aarch64-neon-scalar-copy.c
  clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
  clang/test/CodeGen/aarch64-neon-tbl.c
  clang/test/CodeGen/aarch64-neon-vcombine.c
  clang/test/CodeGen/aarch64-neon-vget-hilo.c
  clang/test/CodeGen/aarch64-neon-vget.c
  clang/test/CodeGen/aarch64-poly128.c
  clang/test/CodeGen/aarch64-poly64.c
  clang/test/CodeGen/aarch64-varargs-ms.c
  clang/test/CodeGen/aarch64-varargs.c
  clang/test/CodeGen/address-space-avr.c
  clang/test/CodeGen/address-space-field1.c
  clang/test/CodeGen/address-space.c
  clang/test/CodeGen/aggregate-assign-call.c
  clang/test/CodeGen/aix-return.c
  clang/test/CodeGen/aix-struct-arg.c
  clang/test/CodeGen/aix-vaargs.c
  clang/test/CodeGen/alias.c
  clang/test/CodeGen/align-param.c
  clang/test/CodeGen/align_value.cpp
  clang/test/CodeGen/alloc-align-attr.c
  clang/test/CodeGen/arc/arguments.c
  clang/test/CodeGen/arc/struct-align.c
  clang/test/CodeGen/arm-aapcs-vfp.c
  clang/test/CodeGen/arm-abi-vector.c
  clang/test/CodeGen/arm-arguments.c
  clang/test/CodeGen/arm-bf16-params-returns.c
  clang/test/CodeGen/arm-byval-align.c
  clang/test/CodeGen/arm-cmse-attr.c
  clang/test/CodeGen/arm-cmse-call.c
  clang/test/CodeGen/arm-float-helpers.c
  clang/test/CodeGen/arm-fp16-arguments.c
  clang/test/CodeGen/arm-homogenous.c
  clang/test/CodeGen/arm-mangle-bf16.cpp

[PATCH] D81678: Introduce frozen attribute at call sites for stricter poison analysis

2020-06-22 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 272489.
guiand added a comment.

I've updated this patch to only include the actual implementation of `frozen`, 
for easier review.


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
  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
@@ -929,6 +929,7 @@
   case Attribute::StrictFP:
   case Attribute::UWTable:
   case Attribute::NoCfCheck:
+  case Attribute::Frozen:
 break;
   }
 
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::Frozen))
+return "frozen";
 
   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::Frozen:
+return bitc::ATTR_KIND_FROZEN;
   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
@@ -1532,6 +1532,8 @@
 return Attribute::SanitizeMemTag;
   case bitc::ATTR_KIND_PREALLOCATED:
 return Attribute::Preallocated;
+  case bitc::ATTR_KIND_FROZEN:
+return Attribute::Frozen;
   }
 }
 
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_frozen,
   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_frozen:
 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_frozen:
+  B.addAttribute(Attribute::Frozen);
+  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_frozen:
+  B.addAttribute(Attribute::Frozen);
+  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(frozen);
 
   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 unini

[PATCH] D81678: Introduce frozen attribute at call sites for stricter poison analysis

2020-06-22 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

@jdoerfert I've separated out changes to the language reference to 
https://reviews.llvm.org/D82316 as you suggested. I kept the name `frozen` for 
now while we reach a consensus regarding its final name.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D81678: Introduce frozen attribute at call sites for stricter poison analysis

2020-06-22 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

I've added the test change to yet another diff, which you can find here: 
https://reviews.llvm.org/D82317


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D82317: [Clang/Test]: Update tests where `frozen` attribute is necessary

2020-06-22 Thread Gui Andrade via Phabricator via cfe-commits
guiand created this revision.
Herald added subscribers: cfe-commits, sstefan1, phosek, kerbowa, luismarques, 
apazos, sameer.abuasal, pzheng, s.egerton, lenary, dmgreen, Jim, mstorsjo, 
jocewei, PkmX, jfb, arphaman, the_o, brucehoult, MartinMosbeck, rogfer01, 
atanasyan, edward-jones, zzheng, jrtc27, niosHD, sabuasal, simoncook, 
johnrusso, rbar, asb, fedor.sergeev, kbarton, aheejin, sbc100, nhaehnle, 
jvesely, nemanjai, dylanmckay, jyknight, dschuff, emaste.
Herald added a reviewer: jdoerfert.
Herald added a reviewer: jdoerfert.
Herald added a project: clang.
guiand added a parent revision: D81678: Introduce frozen attribute at call 
sites for stricter poison analysis.
Herald added a subscriber: wuzish.

The `frozen` attribute generally applies to all scalar function
arguments and return values. In the interest of having Clang's
test suite reflect its codegen, it has been updated to include
the new attribute.

Most tests were updated programatically, although some
required more manual intervention, usually due to regexps or
other complications in parsing. Some tests were too burdensome
to update immediately, and to these were applied a cc1 flag to
mask emitting `frozen` attributes in argument position.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D82317

Files:
  clang/test/ARCMT/objcmt-instancetype.m
  clang/test/ARCMT/objcmt-instancetype.m.result
  clang/test/ARCMT/objcmt-numeric-literals.m
  clang/test/ARCMT/objcmt-numeric-literals.m.result
  clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c
  clang/test/ASTMerge/unnamed_fields/test.cpp
  clang/test/Analysis/casts.c
  clang/test/Analysis/inlining/DynDispatchBifurcate.m
  clang/test/Analysis/inlining/InlineObjCClassMethod.m
  clang/test/Analysis/misc-ps-region-store.m
  clang/test/Analysis/missing-bind-temporary.cpp
  clang/test/Analysis/silence-checkers-and-packages-core-all.cpp
  clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
  clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
  clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp
  clang/test/CXX/drs/dr0xx.cpp
  clang/test/CXX/except/except.spec/p14-ir.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
  clang/test/CXX/modules-ts/codegen-basics.cppm
  clang/test/CXX/special/class.copy/p3.cpp
  clang/test/CodeGen/2004-02-13-Memset.c
  clang/test/CodeGen/2004-06-17-UnorderedCompares.c
  clang/test/CodeGen/2006-05-19-SingleEltReturn.c
  clang/test/CodeGen/2007-02-25-C-DotDotDot.c
  clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
  clang/test/CodeGen/2008-03-05-syncPtr.c
  clang/test/CodeGen/2008-07-29-override-alias-decl.c
  clang/test/CodeGen/2008-07-30-implicit-initialization.c
  clang/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c
  clang/test/CodeGen/2009-02-13-zerosize-union-field.c
  clang/test/CodeGen/2009-05-04-EnumInreg.c
  clang/test/CodeGen/2009-09-24-SqrtErrno.c
  clang/test/CodeGen/3dnow-builtins.c
  clang/test/CodeGen/64bit-swiftcall.c
  clang/test/CodeGen/PR3589-freestanding-libcalls.c
  clang/test/CodeGen/_Bool-conversion.c
  clang/test/CodeGen/aapcs-align.cpp
  clang/test/CodeGen/aapcs64-align.cpp
  clang/test/CodeGen/aarch64-args.cpp
  clang/test/CodeGen/aarch64-byval-temp.c
  clang/test/CodeGen/aarch64-neon-3v.c
  clang/test/CodeGen/aarch64-neon-across.c
  clang/test/CodeGen/aarch64-neon-dot-product.c
  clang/test/CodeGen/aarch64-neon-extract.c
  clang/test/CodeGen/aarch64-neon-fcvt-intrinsics.c
  clang/test/CodeGen/aarch64-neon-fma.c
  clang/test/CodeGen/aarch64-neon-ldst-one.c
  clang/test/CodeGen/aarch64-neon-scalar-copy.c
  clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
  clang/test/CodeGen/aarch64-neon-tbl.c
  clang/test/CodeGen/aarch64-neon-vcombine.c
  clang/test/CodeGen/aarch64-neon-vget-hilo.c
  clang/test/CodeGen/aarch64-neon-vget.c
  clang/test/CodeGen/aarch64-poly128.c
  clang/test/CodeGen/aarch64-poly64.c
  clang/test/CodeGen/aarch64-varargs-ms.c
  clang/test/CodeGen/aarch64-varargs.c
  clang/test/CodeGen/address-space-avr.c
  clang/test/CodeGen/address-space-field1.c
  clang/test/CodeGen/address-space.c
  clang/test/CodeGen/aggregate-assign-call.c
  clang/test/CodeGen/aix-return.c
  clang/test/CodeGen/aix-struct-arg.c
  clang/test/CodeGen/aix-vaargs.c
  clang/test/CodeGen/alias.c
  clang/test/CodeGen/align-param.c
  clang/test/CodeGen/align_value.cpp
  clang/test/CodeGen/alloc-align-attr.c
  clang/test/CodeGen/arc/arguments.c
  clang/test/CodeGen/arc/struct-align.c
  clang/test/CodeGen/arm-aapcs-vfp.c
  clang/test/CodeGen/arm-abi-vector.c
  clang/test/CodeGen/arm-arguments.c
  clang/test/CodeGen/arm-bf16-params-returns.c
  clang/test/CodeGen/arm-byval-align.c
  clang/test/CodeGen/arm-cmse-attr.c
  clang/test/CodeGen/arm-cmse-call.c
  clang/test/CodeGen/arm-float-helpers.c
  clang/test/CodeGen/arm-fp16-arguments.c
  clang/test/CodeGen/arm-homogenous

[PATCH] D81678: Introduce frozen attribute at call sites for stricter poison analysis

2020-06-23 Thread Gui Andrade via Phabricator via cfe-commits
guiand marked 2 inline comments as done.
guiand added inline comments.



Comment at: clang/include/clang/Driver/CC1Options.td:507
+def disable_frozen_args : Flag<["-"], "disable-frozen-args">,
+  HelpText<"Disable emitting frozen attribute in LLVM IR">;
 def load : Separate<["-"], "load">, MetaVarName<"">,

jdoerfert wrote:
> Do we want a second flag for return values or one to disable everything? 
> Having the ability to disable it partially seems odd.
The attribute is supposed to be a stopgap while not all the tests are up to 
date. It turns out that the return values are much less complicated to update 
the call operands, so a flag for disabling return position attributes wasn't 
necessary.



Comment at: clang/lib/CodeGen/CGCall.cpp:4095
+}
+  }
   call->setCallingConv(getRuntimeCC());

jdoerfert wrote:
> Why would we do this? Function attributes are valid at the call site, no need 
> to copy them.
Do you mean that for some definition: `define @foo(i32 frozen %a, i32 frozen 
%b)`, it's valid to issue a call instruction like `call @foo(i32 %a, i32 %b)` 
and its operands will be correctly identified as `frozen`? That's the kind of 
behavior I was seeing and I wasn't sure if it was an error.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D82398: [MSAN] Handle x86 {round,min,max}sd intrinsics

2020-06-23 Thread Gui Andrade via Phabricator via cfe-commits
guiand created this revision.
guiand added a reviewer: eugenis.
Herald added subscribers: llvm-commits, cfe-commits, hiraditya.
Herald added projects: clang, LLVM.
guiand updated this revision to Diff 272776.
guiand added a comment.

Ran clang-format


These need special handling over the simple vector intrinsics as they behave 
more like a shuffle operation: taking the top half of the vector from one 
input, and the bottom half separately. Previously, these were being handled as 
though all bits of all operands were combined.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D82398

Files:
  clang/test/CodeGen/msan-intrinsics.c
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp


Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3054,6 +3054,32 @@
 SOC.Done(&I);
   }
 
+  // Instrument _mm_*_sd intrinsics
+  void handleUnarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *LowShadow =
+IRB.CreateExtractElement(Second, IRB.getInt32(0), "_lo_a");
+Value *Shadow = IRB.CreateInsertElement(First, LowShadow, IRB.getInt32(0));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
+  void handleBinarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *LowA = IRB.CreateExtractElement(First, IRB.getInt32(0), "_lo_a");
+Value *LowB = IRB.CreateExtractElement(Second, IRB.getInt32(0), "_lo_b");
+Value *LowShadow = IRB.CreateOr(LowA, LowB);
+Value *Shadow = IRB.CreateInsertElement(Second, LowShadow, 
IRB.getInt32(0));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
   void visitIntrinsicInst(IntrinsicInst &I) {
 switch (I.getIntrinsicID()) {
 case Intrinsic::lifetime_start:
@@ -3293,6 +3319,13 @@
   handlePclmulIntrinsic(I);
   break;
 
+case Intrinsic::x86_sse41_round_sd:
+  handleUnarySdIntrinsic(I);
+  break;
+case Intrinsic::x86_sse2_max_sd:
+case Intrinsic::x86_sse2_min_sd:
+  handleBinarySdIntrinsic(I);
+  break;
 case Intrinsic::is_constant:
   // The result of llvm.is.constant() is always defined.
   setShadow(&I, getCleanShadow(&I));
Index: clang/test/CodeGen/msan-intrinsics.c
===
--- /dev/null
+++ clang/test/CodeGen/msan-intrinsics.c
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -fsanitize=memory -triple x86_64-linux-gnu -emit-llvm %s 
-O3 -o - | FileCheck %s
+
+typedef double double2 __attribute__((vector_size(16)));
+
+__attribute__((target("sse4.1")))
+double2
+RoundSD(double theta, double top) {
+  // CHECK: [[IN_SHADOW1:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  // CHECK: [[IN_SHADOW2:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  double2 vec;
+  double2 unused;
+  unused[1] = top;
+  vec[0] = theta;
+  return __builtin_ia32_roundsd(unused, vec, 1);
+  // CHECK: [[TMP_SHADOW:%.+]] = insertelement <2 x i64> undef, i64 
[[IN_SHADOW2]], i32 1
+  // CHECK: [[OUT_SHADOW:%.+]] = insertelement <2 x i64> [[TMP_SHADOW]], i64 
[[IN_SHADOW1]], i32 0
+
+  // CHECK-NOT: call void @msan_warning
+  // CHECK: call <2 x double> @llvm.x86.sse41.round.sd
+  // CHECK: store <2 x i64> [[OUT_SHADOW]], {{.*}} @__msan_retval_tls
+  // CHECK: ret <2 x double>
+}
+
+__attribute__((target("sse2"))) double MinSD(double t1, double t2) {
+  // CHECK: [[IN_SHADOW1:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  // CHECK: [[IN_SHADOW2:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  // CHECK: [[COMB_SHADOW:%[0-9]+]] = or i64 [[IN_SHADOW2]], [[IN_SHADOW1]]
+  double2 first;
+  double2 second;
+  first[0] = t1;
+  second[0] = t2;
+  double min = __builtin_ia32_minsd(first, second)[0];
+  // CHECK-NOT: call void @msan_warning
+  // CHECK: call <2 x double> @llvm.x86.sse2.min.sd
+  return min;
+  // CHECK: store i64 [[COMB_SHADOW]], {{.*}} @__msan_retval_tls
+  // CHECK: ret double
+}
\ No newline at end of file


Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3054,6 +3054,32 @@
 SOC.Done(&I);
   }
 
+  // Instrument _mm_*_sd intrinsics
+  void handleUnarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *LowShadow =
+IRB.CreateExtractElement(Second, IRB.getInt32(0), "_lo_a");
+Value *Shadow = IRB.CreateInsertElement(First, LowShadow, IRB.getInt32(0));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
+  void handleBinarySdIntrinsic(Intrinsic

[PATCH] D82398: [MSAN] Handle x86 {round,min,max}sd intrinsics

2020-06-23 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 272776.
guiand added a comment.

Ran clang-format


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82398

Files:
  clang/test/CodeGen/msan-intrinsics.c
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp


Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3054,6 +3054,32 @@
 SOC.Done(&I);
   }
 
+  // Instrument _mm_*_sd intrinsics
+  void handleUnarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *LowShadow =
+IRB.CreateExtractElement(Second, IRB.getInt32(0), "_lo_a");
+Value *Shadow = IRB.CreateInsertElement(First, LowShadow, IRB.getInt32(0));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
+  void handleBinarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *LowA = IRB.CreateExtractElement(First, IRB.getInt32(0), "_lo_a");
+Value *LowB = IRB.CreateExtractElement(Second, IRB.getInt32(0), "_lo_b");
+Value *LowShadow = IRB.CreateOr(LowA, LowB);
+Value *Shadow = IRB.CreateInsertElement(Second, LowShadow, 
IRB.getInt32(0));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
   void visitIntrinsicInst(IntrinsicInst &I) {
 switch (I.getIntrinsicID()) {
 case Intrinsic::lifetime_start:
@@ -3293,6 +3319,13 @@
   handlePclmulIntrinsic(I);
   break;
 
+case Intrinsic::x86_sse41_round_sd:
+  handleUnarySdIntrinsic(I);
+  break;
+case Intrinsic::x86_sse2_max_sd:
+case Intrinsic::x86_sse2_min_sd:
+  handleBinarySdIntrinsic(I);
+  break;
 case Intrinsic::is_constant:
   // The result of llvm.is.constant() is always defined.
   setShadow(&I, getCleanShadow(&I));
Index: clang/test/CodeGen/msan-intrinsics.c
===
--- /dev/null
+++ clang/test/CodeGen/msan-intrinsics.c
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -fsanitize=memory -triple x86_64-linux-gnu -emit-llvm %s 
-O3 -o - | FileCheck %s
+
+typedef double double2 __attribute__((vector_size(16)));
+
+__attribute__((target("sse4.1")))
+double2
+RoundSD(double theta, double top) {
+  // CHECK: [[IN_SHADOW1:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  // CHECK: [[IN_SHADOW2:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  double2 vec;
+  double2 unused;
+  unused[1] = top;
+  vec[0] = theta;
+  return __builtin_ia32_roundsd(unused, vec, 1);
+  // CHECK: [[TMP_SHADOW:%.+]] = insertelement <2 x i64> undef, i64 
[[IN_SHADOW2]], i32 1
+  // CHECK: [[OUT_SHADOW:%.+]] = insertelement <2 x i64> [[TMP_SHADOW]], i64 
[[IN_SHADOW1]], i32 0
+
+  // CHECK-NOT: call void @msan_warning
+  // CHECK: call <2 x double> @llvm.x86.sse41.round.sd
+  // CHECK: store <2 x i64> [[OUT_SHADOW]], {{.*}} @__msan_retval_tls
+  // CHECK: ret <2 x double>
+}
+
+__attribute__((target("sse2"))) double MinSD(double t1, double t2) {
+  // CHECK: [[IN_SHADOW1:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  // CHECK: [[IN_SHADOW2:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  // CHECK: [[COMB_SHADOW:%[0-9]+]] = or i64 [[IN_SHADOW2]], [[IN_SHADOW1]]
+  double2 first;
+  double2 second;
+  first[0] = t1;
+  second[0] = t2;
+  double min = __builtin_ia32_minsd(first, second)[0];
+  // CHECK-NOT: call void @msan_warning
+  // CHECK: call <2 x double> @llvm.x86.sse2.min.sd
+  return min;
+  // CHECK: store i64 [[COMB_SHADOW]], {{.*}} @__msan_retval_tls
+  // CHECK: ret double
+}
\ No newline at end of file


Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3054,6 +3054,32 @@
 SOC.Done(&I);
   }
 
+  // Instrument _mm_*_sd intrinsics
+  void handleUnarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *LowShadow =
+IRB.CreateExtractElement(Second, IRB.getInt32(0), "_lo_a");
+Value *Shadow = IRB.CreateInsertElement(First, LowShadow, IRB.getInt32(0));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
+  void handleBinarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *LowA = IRB.CreateExtractElement(First, IRB.getInt32(0), "_lo_a");
+Value *LowB = IRB.CreateExtractElement(Second, IRB.getInt32(0), "_lo_b");
+Value *LowShadow = IRB.CreateOr(LowA, LowB);
+Value *Shadow = IRB.CreateInsertElement(Second, LowSha

[PATCH] D82398: [MSAN] Handle x86 {round,min,max}sd intrinsics

2020-06-23 Thread Gui Andrade via Phabricator via cfe-commits
guiand marked an inline comment as done.
guiand added inline comments.



Comment at: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp:3077
+Value *LowShadow = IRB.CreateOr(LowA, LowB);
+Value *Shadow = IRB.CreateInsertElement(Second, LowShadow, 
IRB.getInt32(0));
+

eugenis wrote:
> You probably want to insert in First, not Second.
> 
> Is the generated code any better if you OR the vectors, and then shuffle to 
> put the top element of First into the top element of the output? That's what 
> LLVM generates if I express this logic in C.
> 
> 
The codegen is basically identical either way, but if you'd like I can still 
upload a patch to change these into shufflevector instructions.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82398



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


[PATCH] D82398: [MSAN] Handle x86 {round,min,max}sd intrinsics

2020-06-23 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 272842.
guiand added a comment.

Use shufflevector, move test over to IR


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82398

Files:
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
  llvm/test/Instrumentation/MemorySanitizer/vector_sd.ll

Index: llvm/test/Instrumentation/MemorySanitizer/vector_sd.ll
===
--- /dev/null
+++ llvm/test/Instrumentation/MemorySanitizer/vector_sd.ll
@@ -0,0 +1,48 @@
+; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck  \
+; RUN: %s
+; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
+; REQUIRES: x86-registered-target
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare <2 x double> @llvm.x86.sse41.round.sd(<2 x double>, <2 x double>, i32) nounwind readnone
+declare <2 x double> @llvm.x86.sse2.min.sd(<2 x double>, <2 x double>) nounwind readnone
+
+define <2 x double> @test_sse_round_sd(double %lowval, double %hival) sanitize_memory {
+entry:
+  ; CHECK: [[HIVAL_SHADOW:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  ; CHECK: [[LOWVAL_SHADOW:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  ; CHECK: [[OP2VEC_SHADOW:%.+]] = insertelement <2 x i64> , i64 [[LOWVAL_SHADOW]], i32 0
+  %op2vec = insertelement <2 x double> undef, double %lowval, i32 0
+  ; CHECK: [[OP1VEC_SHADOW:%.+]] = insertelement <2 x i64> , i64 [[HIVAL_SHADOW]], i32 1
+  %op1vec = insertelement <2 x double> undef, double %hival, i32 1
+  ; CHECK: [[OUT_SHADOW:%.+]] = shufflevector <2 x i64> [[OP1VEC_SHADOW]], <2 x i64> [[OP2VEC_SHADOW]], <2 x i32>  
+  ; CHECK-NOT: call void @msan_warning
+  ; CHECK: call <2 x double> @llvm.x86.sse41.round.sd
+  %0 = tail call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %op1vec, <2 x double> %op2vec, i32 0)
+  ; CHECK: store <2 x i64> [[OUT_SHADOW]], {{.*}} @__msan_retval_tls
+  ; CHECK: ret <2 x double>
+  ret <2 x double> %0
+}
+
+define <2 x double> @test_sse_min_sd(double %lowval0, double %lowval1, double %hival) sanitize_memory {
+entry:
+  ; CHECK: [[LOWVAL1_SHADOW:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  ; CHECK: [[HIVAL_SHADOW:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  ; CHECK: [[LOWVAL0_SHADOW:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  ; CHECK: [[OP2_SHADOW:%.+]] = insertelement <2 x i64> , i64 [[LOWVAL0_SHADOW]], i32 0
+  %op2vec = insertelement <2 x double> undef, double %lowval0, i32 0
+  ; CHECK: [[HIVEC_SHADOW:%.+]] = insertelement <2 x i64> , i64 [[HIVAL_SHADOW]], i32 1
+  %hivec = insertelement <2 x double> undef, double %hival, i32 1
+  ; CHECK: [[OP1_SHADOW:%.+]] = insertelement <2 x i64> [[HIVEC_SHADOW]], i64 [[LOWVAL1_SHADOW]], i32 0
+  %op1vec = insertelement <2 x double> %hivec, double %lowval1, i32 0
+  ; CHECK: [[OR_SHADOW:%.+]] = or <2 x i64> [[OP1_SHADOW]], [[OP2_SHADOW]]
+  ; CHECK: [[OUT_SHADOW_VEC:%.+]] = shufflevector <2 x i64> [[OP1_SHADOW]], <2 x i64> [[OR_SHADOW]], <2 x i32>  
+  ; CHECK-NOT: call void @msan_warning
+  ; CHECK: call <2 x double> @llvm.x86.sse2.min.sd
+  %0 = tail call <2 x double> @llvm.x86.sse2.min.sd(<2 x double> %op1vec, <2 x double> %op2vec)
+  ; CHECK: store <2 x i64> [[OUT_SHADOW_VEC]], {{.*}} @__msan_retval_tls
+  ; CHECK: ret <2 x double>
+  ret <2 x double> %0
+}
Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3054,6 +3054,32 @@
 SOC.Done(&I);
   }
 
+  // Instrument _mm_*_sd intrinsics
+  void handleUnarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+// High word of first operand, low word of second
+Value *Shadow =
+IRB.CreateShuffleVector(First, Second, llvm::ArrayRef({2, 1}));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
+  void handleBinarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *OrShadow = IRB.CreateOr(First, Second);
+// High word of first operand, low word of both OR'd together
+Value *Shadow =
+IRB.CreateShuffleVector(First, OrShadow, llvm::ArrayRef({2, 1}));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
   void visitIntrinsicInst(IntrinsicInst &I) {
 switch (I.getIntrinsicID()) {
 case Intrinsic::lifetime_start:
@@ -3293,6 +3319,24 @@
   handlePclmulIntrinsic(I);
   break;
 
+case Intrinsic::x86_sse41_round_sd:
+  handleUnarySdIntrinsic(I);
+  break;
+case Intrinsic::x86_sse2_max_sd:
+case Intrinsic:

[PATCH] D82398: [MSAN] Handle x86 {round,min,max}sd intrinsics

2020-06-23 Thread Gui Andrade via Phabricator via cfe-commits
guiand marked 4 inline comments as done.
guiand added inline comments.



Comment at: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp:3331
+  // case Intrinsic::x86_avx512_mask_sub_sd_round:
+  // case Intrinsic::x86_avx512_mask_mul_sd_round:
+  // case Intrinsic::x86_avx512_mask_div_sd_round:

eugenis wrote:
> Unrelated change.
Whoops!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82398



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


[PATCH] D82398: [MSAN] Handle x86 {round,min,max}sd intrinsics

2020-06-23 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 272855.
guiand added a comment.

Addressed comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82398

Files:
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
  llvm/test/Instrumentation/MemorySanitizer/vector_sd.ll


Index: llvm/test/Instrumentation/MemorySanitizer/vector_sd.ll
===
--- /dev/null
+++ llvm/test/Instrumentation/MemorySanitizer/vector_sd.ll
@@ -0,0 +1,37 @@
+; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck  
\
+; RUN: %s
+; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
+; REQUIRES: x86-registered-target
+
+target datalayout = 
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare <2 x double> @llvm.x86.sse41.round.sd(<2 x double>, <2 x double>, i32) 
nounwind readnone
+declare <2 x double> @llvm.x86.sse2.min.sd(<2 x double>, <2 x double>) 
nounwind readnone
+
+define <2 x double> @test_sse_round_sd(<2 x double> %op1, <2 x double> %op2) 
sanitize_memory {
+entry:
+  ; CHECK: [[OP2_SHADOW:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  ; CHECK: [[OP1_SHADOW:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  ; CHECK: [[OUT_SHADOW:%.+]] = shufflevector <2 x i64> [[OP1_SHADOW]], <2 x 
i64> [[OP2_SHADOW]], <2 x i32>  
+  ; CHECK-NOT: call void @msan_warning
+  ; CHECK: call <2 x double> @llvm.x86.sse41.round.sd
+  %0 = tail call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %op1, <2 x 
double> %op2, i32 0)
+  ; CHECK: store <2 x i64> [[OUT_SHADOW]], {{.*}} @__msan_retval_tls
+  ; CHECK: ret <2 x double>
+  ret <2 x double> %0
+}
+
+define <2 x double> @test_sse_min_sd(<2 x double> %op1, <2 x double> %op2) 
sanitize_memory {
+entry:
+  ; CHECK: [[OP2_SHADOW:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  ; CHECK: [[OP1_SHADOW:%[0-9]+]] = load {{.*}} @__msan_param_tls
+  ; CHECK: [[OR_SHADOW:%.+]] = or <2 x i64> [[OP1_SHADOW]], [[OP2_SHADOW]]
+  ; CHECK: [[OUT_SHADOW_VEC:%.+]] = shufflevector <2 x i64> [[OP1_SHADOW]], <2 
x i64> [[OR_SHADOW]], <2 x i32>  
+  ; CHECK-NOT: call void @msan_warning
+  ; CHECK: call <2 x double> @llvm.x86.sse2.min.sd
+  %0 = tail call <2 x double> @llvm.x86.sse2.min.sd(<2 x double> %op1, <2 x 
double> %op2)
+  ; CHECK: store <2 x i64> [[OUT_SHADOW_VEC]], {{.*}} @__msan_retval_tls
+  ; CHECK: ret <2 x double>
+  ret <2 x double> %0
+}
Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3054,6 +3054,32 @@
 SOC.Done(&I);
   }
 
+  // Instrument _mm_*_sd intrinsics
+  void handleUnarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+// High word of first operand, low word of second
+Value *Shadow =
+IRB.CreateShuffleVector(First, Second, llvm::makeArrayRef({2, 
1}));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
+  void handleBinarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *OrShadow = IRB.CreateOr(First, Second);
+// High word of first operand, low word of both OR'd together
+Value *Shadow = IRB.CreateShuffleVector(First, OrShadow,
+llvm::makeArrayRef({2, 1}));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
   void visitIntrinsicInst(IntrinsicInst &I) {
 switch (I.getIntrinsicID()) {
 case Intrinsic::lifetime_start:
@@ -3293,6 +3319,14 @@
   handlePclmulIntrinsic(I);
   break;
 
+case Intrinsic::x86_sse41_round_sd:
+  handleUnarySdIntrinsic(I);
+  break;
+case Intrinsic::x86_sse2_max_sd:
+case Intrinsic::x86_sse2_min_sd:
+  handleBinarySdIntrinsic(I);
+  break;
+
 case Intrinsic::is_constant:
   // The result of llvm.is.constant() is always defined.
   setShadow(&I, getCleanShadow(&I));


Index: llvm/test/Instrumentation/MemorySanitizer/vector_sd.ll
===
--- /dev/null
+++ llvm/test/Instrumentation/MemorySanitizer/vector_sd.ll
@@ -0,0 +1,37 @@
+; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck  \
+; RUN: %s
+; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
+; REQUIRES: x86-registered-target
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare <2 x double> @llvm.x86.ss

[PATCH] D81678: Introduce frozen attribute at call sites for stricter poison analysis

2020-06-25 Thread Gui Andrade via Phabricator via cfe-commits
guiand marked an inline comment as done.
guiand added inline comments.



Comment at: clang/lib/CodeGen/CGCall.cpp:2082
+  const Type *RetTyPtr = RetTy.getTypePtr();
+  if (!RetTy->isVoidType() && !RetTyPtr->isRecordType() &&
+  RetAI.getKind() != ABIArgInfo::Indirect) {

rsmith wrote:
> Other types that we should think about from a padding perspective:
> 
>  * `nullptr_t` (which has the same size and alignment as `void*` but is all 
> padding)
>  * 80-bit `long double` and `_Complex long double` (I don't know whether we 
> guarantee to initialize the 6 padding bytes)
>  * member pointers might contain padding under some ABI rules -- under the MS 
> ABI, you get a struct containing N pointers followed by M ints, which could 
> have 4 bytes of tail padding on 64-bit targets
>  * vector types with tail padding (eg, a vector of 3 `char`s is sometimes 
> passed as an `i32` with one byte `undef`)
>  * matrix types (presumably the same concerns as for vector types apply here)
>  * maybe Obj-C object types?
>  * `_ExtInt` types (eg, returning an `_ExtInt(65)` initialized to 0 produces 
> an `{i64, i64}` containing 7 bytes of `undef`)
> 
> It would be safer to list exactly those types for which we know this 
> assumption is correct rather than assuming that it's correct by default -- I 
> think more than half of the `Type` subclasses for concrete canonical types 
> can have undef bits in their IR representation.
This is a good point, and I think there was some nuance that I had previously 
included in determining this for records (since removed) that I didn't think to 
include in CGCall.cpp.

I think one particular check, `llvm::DataLayout::typeSizeEqualsStoreSize`, 
handles a lot of these cases:
- `long double`
- oddly-sized vectors
- `_ExtInt` types

I don't know if the `matrix` type has internal padding (like structs) but if 
not it would cover that as well.  
I believe that the struct with padding wouldn't be an issue as we're excluding 
record types here.  
And I'd have to take a closer look at `nullptr_t` to see how it behaves here.

~~~

But if I'd like to build an exhaustive list of types I think will work 
correctly with a check like this:
- scalars
- floating point numbers
- pointers

I think I'd need also need an inner `typeSizeEqualsStoreSize` check on the base 
type of vectors/complex numbers.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-06-25 Thread Gui Andrade via Phabricator via cfe-commits
guiand marked an inline comment as done.
guiand added inline comments.



Comment at: clang/lib/CodeGen/CGCall.cpp:2082
+  const Type *RetTyPtr = RetTy.getTypePtr();
+  if (!RetTy->isVoidType() && !RetTyPtr->isRecordType() &&
+  RetAI.getKind() != ABIArgInfo::Indirect) {

guiand wrote:
> rsmith wrote:
> > Other types that we should think about from a padding perspective:
> > 
> >  * `nullptr_t` (which has the same size and alignment as `void*` but is all 
> > padding)
> >  * 80-bit `long double` and `_Complex long double` (I don't know whether we 
> > guarantee to initialize the 6 padding bytes)
> >  * member pointers might contain padding under some ABI rules -- under the 
> > MS ABI, you get a struct containing N pointers followed by M ints, which 
> > could have 4 bytes of tail padding on 64-bit targets
> >  * vector types with tail padding (eg, a vector of 3 `char`s is sometimes 
> > passed as an `i32` with one byte `undef`)
> >  * matrix types (presumably the same concerns as for vector types apply 
> > here)
> >  * maybe Obj-C object types?
> >  * `_ExtInt` types (eg, returning an `_ExtInt(65)` initialized to 0 
> > produces an `{i64, i64}` containing 7 bytes of `undef`)
> > 
> > It would be safer to list exactly those types for which we know this 
> > assumption is correct rather than assuming that it's correct by default -- 
> > I think more than half of the `Type` subclasses for concrete canonical 
> > types can have undef bits in their IR representation.
> This is a good point, and I think there was some nuance that I had previously 
> included in determining this for records (since removed) that I didn't think 
> to include in CGCall.cpp.
> 
> I think one particular check, `llvm::DataLayout::typeSizeEqualsStoreSize`, 
> handles a lot of these cases:
> - `long double`
> - oddly-sized vectors
> - `_ExtInt` types
> 
> I don't know if the `matrix` type has internal padding (like structs) but if 
> not it would cover that as well.  
> I believe that the struct with padding wouldn't be an issue as we're 
> excluding record types here.  
> And I'd have to take a closer look at `nullptr_t` to see how it behaves here.
> 
> ~~~
> 
> But if I'd like to build an exhaustive list of types I think will work 
> correctly with a check like this:
> - scalars
> - floating point numbers
> - pointers
> 
> I think I'd need also need an inner `typeSizeEqualsStoreSize` check on the 
> base type of vectors/complex numbers.
> nullptr_t (which has the same size and alignment as void* but is all padding)

From what I can gather looking at the IR of `test/CodeGenCXX/nullptr.cpp`, it 
looks like `nullptr_t` arguments and return values are represented as normal 
`i8*` types but given the special value `null`. From this it seems like we can 
mark them `noundef` without worry?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-06-25 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 273456.
guiand retitled this revision from "Introduce frozen attribute at call sites 
for stricter poison analysis" to "Introduce noundef attribute at call sites for 
stricter poison analysis".
guiand edited the summary of this revision.
guiand added a comment.

Renamed to noundef, added additional checks before determining attribute


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
  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
@@ -929,6 +929,7 @@
   case Attribute::StrictFP:
   case Attribute::UWTable:
   case Attribute::NoCfCheck:
+  case Attribute::NoUndef:
 break;
   }
 
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
@@ -1532,6 +1532,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
==

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-06-26 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 273558.
guiand added a comment.

Made DetermineNoUndef more robust


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
  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
@@ -929,6 +929,7 @@
   case Attribute::StrictFP:
   case Attribute::UWTable:
   case Attribute::NoCfCheck:
+  case Attribute::NoUndef:
 break;
   }
 
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
@@ -1532,6 +1532,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<"no

[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-06-26 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 273570.
guiand retitled this revision from "[Clang/Test]: Update tests where `frozen` 
attribute is necessary" to "[Clang/Test]: Update tests where `noundef` 
attribute is necessary".
guiand edited the summary of this revision.
guiand added a comment.
Herald added subscribers: aaron.ballman, ormris, mgrang.
Herald added a reviewer: sscalpone.

Updated almost all tests to rename frozen->noundef. Still needs rebase to master


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

Files:
  clang/test/ARCMT/objcmt-instancetype.m
  clang/test/ARCMT/objcmt-instancetype.m.result
  clang/test/ARCMT/objcmt-numeric-literals.m
  clang/test/ARCMT/objcmt-numeric-literals.m.result
  clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c
  clang/test/ASTMerge/unnamed_fields/test.cpp
  clang/test/Analysis/casts.c
  clang/test/Analysis/inlining/DynDispatchBifurcate.m
  clang/test/Analysis/inlining/InlineObjCClassMethod.m
  clang/test/Analysis/misc-ps-region-store.m
  clang/test/Analysis/missing-bind-temporary.cpp
  clang/test/Analysis/silence-checkers-and-packages-core-all.cpp
  clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
  clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
  clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp
  clang/test/CXX/drs/dr0xx.cpp
  clang/test/CXX/except/except.spec/p14-ir.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
  clang/test/CXX/modules-ts/codegen-basics.cppm
  clang/test/CXX/special/class.copy/p3.cpp
  clang/test/CodeGen/2004-02-13-Memset.c
  clang/test/CodeGen/2004-06-17-UnorderedCompares.c
  clang/test/CodeGen/2006-05-19-SingleEltReturn.c
  clang/test/CodeGen/2007-02-25-C-DotDotDot.c
  clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
  clang/test/CodeGen/2008-03-05-syncPtr.c
  clang/test/CodeGen/2008-07-29-override-alias-decl.c
  clang/test/CodeGen/2008-07-30-implicit-initialization.c
  clang/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c
  clang/test/CodeGen/2009-02-13-zerosize-union-field.c
  clang/test/CodeGen/2009-05-04-EnumInreg.c
  clang/test/CodeGen/2009-09-24-SqrtErrno.c
  clang/test/CodeGen/3dnow-builtins.c
  clang/test/CodeGen/64bit-swiftcall.c
  clang/test/CodeGen/PR3589-freestanding-libcalls.c
  clang/test/CodeGen/_Bool-conversion.c
  clang/test/CodeGen/aapcs-align.cpp
  clang/test/CodeGen/aapcs64-align.cpp
  clang/test/CodeGen/aarch64-args.cpp
  clang/test/CodeGen/aarch64-byval-temp.c
  clang/test/CodeGen/aarch64-neon-3v.c
  clang/test/CodeGen/aarch64-neon-across.c
  clang/test/CodeGen/aarch64-neon-dot-product.c
  clang/test/CodeGen/aarch64-neon-extract.c
  clang/test/CodeGen/aarch64-neon-fcvt-intrinsics.c
  clang/test/CodeGen/aarch64-neon-fma.c
  clang/test/CodeGen/aarch64-neon-ldst-one.c
  clang/test/CodeGen/aarch64-neon-scalar-copy.c
  clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
  clang/test/CodeGen/aarch64-neon-tbl.c
  clang/test/CodeGen/aarch64-neon-vcombine.c
  clang/test/CodeGen/aarch64-neon-vget-hilo.c
  clang/test/CodeGen/aarch64-neon-vget.c
  clang/test/CodeGen/aarch64-poly128.c
  clang/test/CodeGen/aarch64-poly64.c
  clang/test/CodeGen/aarch64-varargs-ms.c
  clang/test/CodeGen/aarch64-varargs.c
  clang/test/CodeGen/address-space-avr.c
  clang/test/CodeGen/address-space-field1.c
  clang/test/CodeGen/address-space.c
  clang/test/CodeGen/aggregate-assign-call.c
  clang/test/CodeGen/aix-return.c
  clang/test/CodeGen/aix-struct-arg.c
  clang/test/CodeGen/aix-vaargs.c
  clang/test/CodeGen/alias.c
  clang/test/CodeGen/align-param.c
  clang/test/CodeGen/align_value.cpp
  clang/test/CodeGen/alloc-align-attr.c
  clang/test/CodeGen/arc/arguments.c
  clang/test/CodeGen/arc/struct-align.c
  clang/test/CodeGen/arm-aapcs-vfp.c
  clang/test/CodeGen/arm-abi-vector.c
  clang/test/CodeGen/arm-arguments.c
  clang/test/CodeGen/arm-bf16-params-returns.c
  clang/test/CodeGen/arm-byval-align.c
  clang/test/CodeGen/arm-cmse-attr.c
  clang/test/CodeGen/arm-cmse-call.c
  clang/test/CodeGen/arm-float-helpers.c
  clang/test/CodeGen/arm-fp16-arguments.c
  clang/test/CodeGen/arm-homogenous.c
  clang/test/CodeGen/arm-mangle-bf16.cpp
  clang/test/CodeGen/arm-neon-directed-rounding.c
  clang/test/CodeGen/arm-neon-dot-product.c
  clang/test/CodeGen/arm-neon-fma.c
  clang/test/CodeGen/arm-neon-numeric-maxmin.c
  clang/test/CodeGen/arm-neon-vcvtX.c
  clang/test/CodeGen/arm-pcs.c
  clang/test/CodeGen/arm-swiftcall.c
  clang/test/CodeGen/arm-varargs.c
  clang/test/CodeGen/arm-vector-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments2.cpp
  clang/test/CodeGen/arm64-aapcs-arguments.c
  clang/test/CodeGen/arm64-abi-vector.c
  clang/test/CodeGen/arm64-arguments.c
  clang/test/CodeGen/arm64-microsoft-arguments.cpp
  clang/test/CodeGen/ar

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-06-26 Thread Gui Andrade via Phabricator via cfe-commits
guiand marked an inline comment as done.
guiand added inline comments.



Comment at: clang/lib/CodeGen/CGCall.cpp:2082
+  const Type *RetTyPtr = RetTy.getTypePtr();
+  if (!RetTy->isVoidType() && !RetTyPtr->isRecordType() &&
+  RetAI.getKind() != ABIArgInfo::Indirect) {

guiand wrote:
> guiand wrote:
> > rsmith wrote:
> > > Other types that we should think about from a padding perspective:
> > > 
> > >  * `nullptr_t` (which has the same size and alignment as `void*` but is 
> > > all padding)
> > >  * 80-bit `long double` and `_Complex long double` (I don't know whether 
> > > we guarantee to initialize the 6 padding bytes)
> > >  * member pointers might contain padding under some ABI rules -- under 
> > > the MS ABI, you get a struct containing N pointers followed by M ints, 
> > > which could have 4 bytes of tail padding on 64-bit targets
> > >  * vector types with tail padding (eg, a vector of 3 `char`s is sometimes 
> > > passed as an `i32` with one byte `undef`)
> > >  * matrix types (presumably the same concerns as for vector types apply 
> > > here)
> > >  * maybe Obj-C object types?
> > >  * `_ExtInt` types (eg, returning an `_ExtInt(65)` initialized to 0 
> > > produces an `{i64, i64}` containing 7 bytes of `undef`)
> > > 
> > > It would be safer to list exactly those types for which we know this 
> > > assumption is correct rather than assuming that it's correct by default 
> > > -- I think more than half of the `Type` subclasses for concrete canonical 
> > > types can have undef bits in their IR representation.
> > This is a good point, and I think there was some nuance that I had 
> > previously included in determining this for records (since removed) that I 
> > didn't think to include in CGCall.cpp.
> > 
> > I think one particular check, `llvm::DataLayout::typeSizeEqualsStoreSize`, 
> > handles a lot of these cases:
> > - `long double`
> > - oddly-sized vectors
> > - `_ExtInt` types
> > 
> > I don't know if the `matrix` type has internal padding (like structs) but 
> > if not it would cover that as well.  
> > I believe that the struct with padding wouldn't be an issue as we're 
> > excluding record types here.  
> > And I'd have to take a closer look at `nullptr_t` to see how it behaves 
> > here.
> > 
> > ~~~
> > 
> > But if I'd like to build an exhaustive list of types I think will work 
> > correctly with a check like this:
> > - scalars
> > - floating point numbers
> > - pointers
> > 
> > I think I'd need also need an inner `typeSizeEqualsStoreSize` check on the 
> > base type of vectors/complex numbers.
> > nullptr_t (which has the same size and alignment as void* but is all 
> > padding)
> 
> From what I can gather looking at the IR of `test/CodeGenCXX/nullptr.cpp`, it 
> looks like `nullptr_t` arguments and return values are represented as normal 
> `i8*` types but given the special value `null`. From this it seems like we 
> can mark them `noundef` without worry?
Actually I've been thinking more about these cases, and they should only really 
be a problem if clang coerces them away from their native types to something 
larger.

For example, if clang emits `i33` that's not a problem, as potential padding 
belonging to `i33` can be always be determined by looking at the data layout.
But if it emits `{ i32, i32 }` or `i64` or something similar, it's introducing 
new hidden/erased padding and so we can't mark it `noundef`.
Same thing goes for `long double`: if it's emitted as `x86_fp80` that's no 
problem.

There's been some confusion wrt this in the LangRef patch as well. I think what 
we really want is an attribute that indicates the presence of undef bits *not 
inherent to the IR type*. So (for the sake of argument, we're not handling 
structs right now) `struct { char; short }` emitted as `{ i8, i16 } noundef` is 
fine, but emitting it as `i64` is a problem.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D82398: [MSAN] Handle x86 {round,min,max}sd intrinsics

2020-06-26 Thread Gui Andrade via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
guiand marked an inline comment as done.
Closed by commit rGeae84b41fe8e: [MSAN] Handle x86 {round,min,max}sd intrinsics 
(authored by guiand).

Changed prior to commit:
  https://reviews.llvm.org/D82398?vs=272855&id=273883#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82398

Files:
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp


Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3046,6 +3046,32 @@
 SOC.Done(&I);
   }
 
+  // Instrument _mm_*_sd intrinsics
+  void handleUnarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+// High word of first operand, low word of second
+Value *Shadow =
+IRB.CreateShuffleVector(First, Second, llvm::makeArrayRef({2, 
1}));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
+  void handleBinarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *OrShadow = IRB.CreateOr(First, Second);
+// High word of first operand, low word of both OR'd together
+Value *Shadow = IRB.CreateShuffleVector(First, OrShadow,
+llvm::makeArrayRef({2, 1}));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
   void visitIntrinsicInst(IntrinsicInst &I) {
 switch (I.getIntrinsicID()) {
 case Intrinsic::lifetime_start:
@@ -3285,6 +3311,14 @@
   handlePclmulIntrinsic(I);
   break;
 
+case Intrinsic::x86_sse41_round_sd:
+  handleUnarySdIntrinsic(I);
+  break;
+case Intrinsic::x86_sse2_max_sd:
+case Intrinsic::x86_sse2_min_sd:
+  handleBinarySdIntrinsic(I);
+  break;
+
 case Intrinsic::is_constant:
   // The result of llvm.is.constant() is always defined.
   setShadow(&I, getCleanShadow(&I));


Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3046,6 +3046,32 @@
 SOC.Done(&I);
   }
 
+  // Instrument _mm_*_sd intrinsics
+  void handleUnarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+// High word of first operand, low word of second
+Value *Shadow =
+IRB.CreateShuffleVector(First, Second, llvm::makeArrayRef({2, 1}));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
+  void handleBinarySdIntrinsic(IntrinsicInst &I) {
+IRBuilder<> IRB(&I);
+Value *First = getShadow(&I, 0);
+Value *Second = getShadow(&I, 1);
+Value *OrShadow = IRB.CreateOr(First, Second);
+// High word of first operand, low word of both OR'd together
+Value *Shadow = IRB.CreateShuffleVector(First, OrShadow,
+llvm::makeArrayRef({2, 1}));
+
+setShadow(&I, Shadow);
+setOriginForNaryOp(I);
+  }
+
   void visitIntrinsicInst(IntrinsicInst &I) {
 switch (I.getIntrinsicID()) {
 case Intrinsic::lifetime_start:
@@ -3285,6 +3311,14 @@
   handlePclmulIntrinsic(I);
   break;
 
+case Intrinsic::x86_sse41_round_sd:
+  handleUnarySdIntrinsic(I);
+  break;
+case Intrinsic::x86_sse2_max_sd:
+case Intrinsic::x86_sse2_min_sd:
+  handleBinarySdIntrinsic(I);
+  break;
+
 case Intrinsic::is_constant:
   // The result of llvm.is.constant() is always defined.
   setShadow(&I, getCleanShadow(&I));
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-06-29 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

I've run across an issue when bootstrapping clang, that manifests itself in the 
following code when compiled with optimizations:

  #include 
  
  float my_exp2(float a) {
  return pow(2.0, a);
  }

With this code, the call to `pow` is lifted to a `exp2`, and then the resulting 
call causes `llvm::verifyFunction` to fail. The error is that attributes are 
present past the end of the argument list.
I'm thinking that whatever code does the lifting here fails to remove the 
attribute list corresponding to the `2.0` parameter here.

Could anyone point me to where I might need to make a change for that?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678



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


[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-07-30 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

@jdoerfert what would the procedure be for reviewing these test changes / 
getting this landed with the noundef patch?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

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


[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-08-01 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 282328.
guiand added a comment.

Rebased; all tests passing again. Removed the change to the `ppc-*mmintrin.c` 
tests, instead I just use the -disable-noundef-args flag`. Cleaned up typos.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

Files:
  clang/test/ARCMT/objcmt-instancetype.m
  clang/test/ARCMT/objcmt-instancetype.m.result
  clang/test/ARCMT/objcmt-numeric-literals.m
  clang/test/ARCMT/objcmt-numeric-literals.m.result
  clang/test/CXX/except/except.spec/p14-ir.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
  clang/test/CXX/modules-ts/codegen-basics.cppm
  clang/test/CXX/special/class.copy/p3.cpp
  clang/test/CodeGen/2006-05-19-SingleEltReturn.c
  clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
  clang/test/CodeGen/2009-02-13-zerosize-union-field.c
  clang/test/CodeGen/2009-05-04-EnumInreg.c
  clang/test/CodeGen/64bit-swiftcall.c
  clang/test/CodeGen/aapcs-align.cpp
  clang/test/CodeGen/aapcs-bitfield.c
  clang/test/CodeGen/aapcs64-align.cpp
  clang/test/CodeGen/aarch64-args.cpp
  clang/test/CodeGen/aarch64-bf16-getset-intrinsics.c
  clang/test/CodeGen/aarch64-byval-temp.c
  clang/test/CodeGen/aarch64-neon-3v.c
  clang/test/CodeGen/aarch64-neon-across.c
  clang/test/CodeGen/aarch64-neon-dot-product.c
  clang/test/CodeGen/aarch64-neon-extract.c
  clang/test/CodeGen/aarch64-neon-fcvt-intrinsics.c
  clang/test/CodeGen/aarch64-neon-fma.c
  clang/test/CodeGen/aarch64-neon-fp16fml.c
  clang/test/CodeGen/aarch64-neon-ldst-one.c
  clang/test/CodeGen/aarch64-neon-scalar-copy.c
  clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
  clang/test/CodeGen/aarch64-neon-tbl.c
  clang/test/CodeGen/aarch64-neon-vcombine.c
  clang/test/CodeGen/aarch64-neon-vget-hilo.c
  clang/test/CodeGen/aarch64-neon-vget.c
  clang/test/CodeGen/aarch64-poly128.c
  clang/test/CodeGen/aarch64-poly64.c
  clang/test/CodeGen/aarch64-varargs.c
  clang/test/CodeGen/address-space-avr.c
  clang/test/CodeGen/address-space-field1.c
  clang/test/CodeGen/address-space.c
  clang/test/CodeGen/aggregate-assign-call.c
  clang/test/CodeGen/aix-return.c
  clang/test/CodeGen/aix-struct-arg.c
  clang/test/CodeGen/aix-vaargs.c
  clang/test/CodeGen/alias.c
  clang/test/CodeGen/align_value.cpp
  clang/test/CodeGen/alloc-align-attr.c
  clang/test/CodeGen/arc/arguments.c
  clang/test/CodeGen/arm-aapcs-vfp.c
  clang/test/CodeGen/arm-abi-vector.c
  clang/test/CodeGen/arm-arguments.c
  clang/test/CodeGen/arm-bf16-params-returns.c
  clang/test/CodeGen/arm-byval-align.c
  clang/test/CodeGen/arm-cmse-attr.c
  clang/test/CodeGen/arm-cmse-call.c
  clang/test/CodeGen/arm-float-helpers.c
  clang/test/CodeGen/arm-fp16-arguments.c
  clang/test/CodeGen/arm-homogenous.c
  clang/test/CodeGen/arm-mangle-bf16.cpp
  clang/test/CodeGen/arm-mve-intrinsics/vld24.c
  clang/test/CodeGen/arm-neon-directed-rounding.c
  clang/test/CodeGen/arm-neon-dot-product.c
  clang/test/CodeGen/arm-neon-fma.c
  clang/test/CodeGen/arm-neon-numeric-maxmin.c
  clang/test/CodeGen/arm-neon-vcvtX.c
  clang/test/CodeGen/arm-swiftcall.c
  clang/test/CodeGen/arm-varargs.c
  clang/test/CodeGen/arm-vector-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments.c
  clang/test/CodeGen/arm-vfp16-arguments2.cpp
  clang/test/CodeGen/arm64-aapcs-arguments.c
  clang/test/CodeGen/arm64-abi-vector.c
  clang/test/CodeGen/arm64-arguments.c
  clang/test/CodeGen/arm64-microsoft-arguments.cpp
  clang/test/CodeGen/arm64_32-vaarg.c
  clang/test/CodeGen/arm64_32.c
  clang/test/CodeGen/arm64_vcopy.c
  clang/test/CodeGen/arm64_vdupq_n_f64.c
  clang/test/CodeGen/armv7k-abi.c
  clang/test/CodeGen/asm-label.c
  clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c
  clang/test/CodeGen/atomic-arm64.c
  clang/test/CodeGen/atomic-ops-libcall.c
  clang/test/CodeGen/atomic-ops.c
  clang/test/CodeGen/atomic_ops.c
  clang/test/CodeGen/atomics-inlining.c
  clang/test/CodeGen/attr-func-def.c
  clang/test/CodeGen/attr-naked.c
  clang/test/CodeGen/attr-no-tail.c
  clang/test/CodeGen/attr-nomerge.cpp
  clang/test/CodeGen/attr-target-mv-func-ptrs.c
  clang/test/CodeGen/attr-target-mv-va-args.c
  clang/test/CodeGen/attr-target-mv.c
  clang/test/CodeGen/attr-x86-interrupt.c
  clang/test/CodeGen/attributes.c
  clang/test/CodeGen/available-externally-hidden.cpp
  clang/test/CodeGen/available-externally-suppress.c
  clang/test/CodeGen/avx2-builtins.c
  clang/test/CodeGen/avx512-reduceMinMaxIntrin.c
  clang/test/CodeGen/big-atomic-ops.c
  clang/test/CodeGen/bittest-intrin.c
  clang/test/CodeGen/blocks.c
  clang/test/CodeGen/bool-convert.c
  clang/test/CodeGen/builtin-align-array.c
  clang/test/CodeGen/builtin-align.c
  clang/test/CodeGen/builtin-assume-aligned.c
  clang/test/CodeGen/builtin-attributes.c
  clang/test/CodeGen/builtin-memfns.c
  clang/test/CodeGen/builtin-sqrt.c
  clang/test/CodeGen/builtins-arm.c
  clang/test/CodeGen/builtins-memcpy-inline.c
  clang/test/CodeGen/builtins-ms

[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-08-07 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

In D82317#2200789 , @rjmccall wrote:

> Are you seriously adding an attribute to literally every argument and return 
> value?  Why is this the right representation?

This adds an attribute to every argument and return value where the language 
rules denote it cannot be undef (which is ideally in most places, but 
definitely not everywhere). In a previous incarnation of this idea, the 
attribute was called `partialinit`, and had the inverse meaning -- the idea 
being that it would be a less invasive change because it is more common for 
these values to be fully defined (@rsmith at some point noted that in C, return 
values in general may be undef, which would complicate that a bit, but anyway 
was the idea). `partialinit` was scrapped as pretty much everybody agreed it 
wasn't ideal to have a negative attribute: the presence of `partialinit` 
meaning "proceed as normal", and its absence denoting a different behavior.

As for being an attribute, that was the level of granularity we had decided on. 
The alternative I suppose would be to some form of metadata.

As for being enabled by default, the idea was that transformation maintainers 
could get to using the attribute right away. This might be a good place to 
compromise.

And as for applying them to all the tests (rather than suppressing the 
attribute by default or something along those lines), we figured it would be 
best to keep the tests reflecting the actual common-case codegen. If `noundef` 
was on and showing up everywhere, the idea was to have the tests reflect that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

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


[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-08-07 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

In D82317#2200809 , @jrtc27 wrote:

> At the very least, make whatever script you used to update these public, as I 
> don't want to have to recreate it from scratch when merging this in. I had 
> enough "fun" with the LLD mass-renaming (UpperCamel -> lowerCamel) and that 
> was _with_ a supposedly-working script (it didn't quite do the right thing 
> and I seem to recall there being two refactoring commits, only one of which 
> had a script); I do not want a repeat of that experience.

That's totally fair, and I can try and prepare a more polished version of the 
script I was using to get started with these changes. But the script isn't 
perfect, unfortunately, and follows roughly the 80-20 rule. The tests aren't 
written in a regular language so there are lots of places where manual 
intervention was necessary.

Sadly I think you're right in that this will cause headaches for downstream 
forks. Maybe this is another good reason to have `noundef` turned off by 
default, at least for now.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

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


[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-08-07 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

Most of the discussion has been in https://reviews.llvm.org/D81678 
(implementing the attribute in clang) and https://reviews.llvm.org/D82316 
(adding the attribute to langref).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

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


[PATCH] D85559: [MSAN] Reintroduce libatomic load/store instrumentation

2020-08-07 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 284076.
guiand edited the summary of this revision.
guiand added a reviewer: rsmith.
guiand added a comment.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Simplified by returning to the old implementation, but having libatomic calls 
made nounwind (so we never see them as invokes).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85559

Files:
  clang/lib/CodeGen/CGAtomic.cpp
  compiler-rt/test/msan/libatomic_load_exceptions.cpp
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp


Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3505,7 +3505,13 @@
 IRB.CreateExtractElement(makeAddAcquireOrderingTable(IRB), Ordering);
 CB.setArgOperand(3, NewOrdering);
 
-IRBuilder<> NextIRB(CB.getNextNode());
+Instruction *InsPoint = CB.getNextNode();
+if (!InsPoint) {
+  llvm::errs() << "MSAN -- cannot instrument libatomic call with no "
+  "successor. Ignoring!\n";
+  return;
+}
+IRBuilder<> NextIRB(InsPoint);
 NextIRB.SetCurrentDebugLocation(CB.getDebugLoc());
 
 Value *SrcShadowPtr, *SrcOriginPtr;
Index: compiler-rt/test/msan/libatomic_load_exceptions.cpp
===
--- /dev/null
+++ compiler-rt/test/msan/libatomic_load_exceptions.cpp
@@ -0,0 +1,36 @@
+// RUN: %clangxx_msan -fexceptions -fsanitize-memory-track-origins=2 -latomic 
-O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK 
--check-prefix=CHECK-SHADOW
+
+// PPC has no libatomic
+// UNSUPPORTED: powerpc64-target-arch
+// UNSUPPORTED: powerpc64le-target-arch
+
+#include 
+#include 
+
+typedef struct __attribute((packed)) {
+  uint8_t val[3];
+} i24;
+
+void copy(i24 *dst, i24 *src);
+
+int main() {
+  i24 uninit;
+  i24 init = {0};
+
+  __msan_check_mem_is_initialized(&init, 3);
+  copy(&init, &uninit);
+  __msan_check_mem_is_initialized(&init, 3);
+}
+
+void copy(i24 *dst, i24 *src) {
+  try {
+__atomic_load(src, dst, __ATOMIC_RELAXED);
+  } catch (...) {
+  }
+}
+
+// CHECK: MemorySanitizer: use-of-uninitialized-value
+// CHECK: #0 {{0x[a-f0-9]+}} in 
main{{.*}}libatomic_load_exceptions.cpp:[[@LINE-10]]
+
+// CHECK-SHADOW: Uninitialized value was stored to memory at
+// CHECK-SHADOW: #0 {{0x[a-f0-9]+}} in 
copy{{.*}}libatomic_load_exceptions.cpp:[[@LINE-8]]
Index: clang/lib/CodeGen/CGAtomic.cpp
===
--- clang/lib/CodeGen/CGAtomic.cpp
+++ clang/lib/CodeGen/CGAtomic.cpp
@@ -307,7 +307,12 @@
   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::AttributeList fnAttrs;
+  fnAttrs = fnAttrs.addAttribute(CGF.getLLVMContext(),
+ llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoUnwind);
+  llvm::FunctionCallee fn =
+  CGF.CGM.CreateRuntimeFunction(fnTy, fnName, fnAttrs);
   auto callee = CGCallee::forDirect(fn);
   return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args);
 }


Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3505,7 +3505,13 @@
 IRB.CreateExtractElement(makeAddAcquireOrderingTable(IRB), Ordering);
 CB.setArgOperand(3, NewOrdering);
 
-IRBuilder<> NextIRB(CB.getNextNode());
+Instruction *InsPoint = CB.getNextNode();
+if (!InsPoint) {
+  llvm::errs() << "MSAN -- cannot instrument libatomic call with no "
+  "successor. Ignoring!\n";
+  return;
+}
+IRBuilder<> NextIRB(InsPoint);
 NextIRB.SetCurrentDebugLocation(CB.getDebugLoc());
 
 Value *SrcShadowPtr, *SrcOriginPtr;
Index: compiler-rt/test/msan/libatomic_load_exceptions.cpp
===
--- /dev/null
+++ compiler-rt/test/msan/libatomic_load_exceptions.cpp
@@ -0,0 +1,36 @@
+// RUN: %clangxx_msan -fexceptions -fsanitize-memory-track-origins=2 -latomic -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SHADOW
+
+// PPC has no libatomic
+// UNSUPPORTED: powerpc64-target-arch
+// UNSUPPORTED: powerpc64le-target-arch
+
+#include 
+#include 
+
+typedef struct __attribute((packed)) {
+  uint8_t val[3];
+} i24;
+
+void copy(i24 *dst, i24 *src);
+
+int main() {
+  i24 uninit;
+  i24 init = {0};
+
+  __msan_check_me

[PATCH] D85559: [MSAN] Reintroduce libatomic load/store instrumentation

2020-08-07 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 284079.
guiand added a comment.

Rebased on master


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85559

Files:
  clang/lib/CodeGen/CGAtomic.cpp
  compiler-rt/test/msan/libatomic_load_exceptions.cpp
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp


Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3505,7 +3505,13 @@
 IRB.CreateExtractElement(makeAddAcquireOrderingTable(IRB), Ordering);
 CB.setArgOperand(3, NewOrdering);
 
-IRBuilder<> NextIRB(CB.getNextNode());
+Instruction *InsPoint = CB.getNextNode();
+if (!InsPoint) {
+  llvm::errs() << "MSAN -- cannot instrument libatomic call with no "
+  "successor. Ignoring!\n";
+  return;
+}
+IRBuilder<> NextIRB(InsPoint);
 NextIRB.SetCurrentDebugLocation(CB.getDebugLoc());
 
 Value *SrcShadowPtr, *SrcOriginPtr;
Index: compiler-rt/test/msan/libatomic_load_exceptions.cpp
===
--- /dev/null
+++ compiler-rt/test/msan/libatomic_load_exceptions.cpp
@@ -0,0 +1,36 @@
+// RUN: %clangxx_msan -fexceptions -fsanitize-memory-track-origins=2 -latomic 
-O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK 
--check-prefix=CHECK-SHADOW
+
+// PPC has no libatomic
+// UNSUPPORTED: powerpc64-target-arch
+// UNSUPPORTED: powerpc64le-target-arch
+
+#include 
+#include 
+
+typedef struct __attribute((packed)) {
+  uint8_t val[3];
+} i24;
+
+void copy(i24 *dst, i24 *src);
+
+int main() {
+  i24 uninit;
+  i24 init = {0};
+
+  __msan_check_mem_is_initialized(&init, 3);
+  copy(&init, &uninit);
+  __msan_check_mem_is_initialized(&init, 3);
+}
+
+void copy(i24 *dst, i24 *src) {
+  try {
+__atomic_load(src, dst, __ATOMIC_RELAXED);
+  } catch (...) {
+  }
+}
+
+// CHECK: MemorySanitizer: use-of-uninitialized-value
+// CHECK: #0 {{0x[a-f0-9]+}} in 
main{{.*}}libatomic_load_exceptions.cpp:[[@LINE-10]]
+
+// CHECK-SHADOW: Uninitialized value was stored to memory at
+// CHECK-SHADOW: #0 {{0x[a-f0-9]+}} in 
copy{{.*}}libatomic_load_exceptions.cpp:[[@LINE-8]]
Index: clang/lib/CodeGen/CGAtomic.cpp
===
--- clang/lib/CodeGen/CGAtomic.cpp
+++ clang/lib/CodeGen/CGAtomic.cpp
@@ -307,7 +307,12 @@
   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::AttributeList fnAttrs;
+  fnAttrs = fnAttrs.addAttribute(CGF.getLLVMContext(),
+ llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoUnwind);
+  llvm::FunctionCallee fn =
+  CGF.CGM.CreateRuntimeFunction(fnTy, fnName, fnAttrs);
   auto callee = CGCallee::forDirect(fn);
   return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args);
 }


Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -3505,7 +3505,13 @@
 IRB.CreateExtractElement(makeAddAcquireOrderingTable(IRB), Ordering);
 CB.setArgOperand(3, NewOrdering);
 
-IRBuilder<> NextIRB(CB.getNextNode());
+Instruction *InsPoint = CB.getNextNode();
+if (!InsPoint) {
+  llvm::errs() << "MSAN -- cannot instrument libatomic call with no "
+  "successor. Ignoring!\n";
+  return;
+}
+IRBuilder<> NextIRB(InsPoint);
 NextIRB.SetCurrentDebugLocation(CB.getDebugLoc());
 
 Value *SrcShadowPtr, *SrcOriginPtr;
Index: compiler-rt/test/msan/libatomic_load_exceptions.cpp
===
--- /dev/null
+++ compiler-rt/test/msan/libatomic_load_exceptions.cpp
@@ -0,0 +1,36 @@
+// RUN: %clangxx_msan -fexceptions -fsanitize-memory-track-origins=2 -latomic -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SHADOW
+
+// PPC has no libatomic
+// UNSUPPORTED: powerpc64-target-arch
+// UNSUPPORTED: powerpc64le-target-arch
+
+#include 
+#include 
+
+typedef struct __attribute((packed)) {
+  uint8_t val[3];
+} i24;
+
+void copy(i24 *dst, i24 *src);
+
+int main() {
+  i24 uninit;
+  i24 init = {0};
+
+  __msan_check_mem_is_initialized(&init, 3);
+  copy(&init, &uninit);
+  __msan_check_mem_is_initialized(&init, 3);
+}
+
+void copy(i24 *dst, i24 *src) {
+  try {
+__atomic_load(src, dst, __ATOMIC_RELAXED);
+  } catch (...) {
+  }
+}
+
+// CHECK: MemorySanitizer: use-of-

[PATCH] D85559: [MSAN] Reintroduce libatomic load/store instrumentation

2020-08-07 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 284080.
guiand added a comment.

Rebased on master (again)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85559

Files:
  clang/lib/CodeGen/CGAtomic.cpp
  compiler-rt/test/msan/libatomic.c
  compiler-rt/test/msan/libatomic_load_exceptions.cpp
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
  llvm/test/Instrumentation/MemorySanitizer/libatomic.ll

Index: llvm/test/Instrumentation/MemorySanitizer/libatomic.ll
===
--- /dev/null
+++ llvm/test/Instrumentation/MemorySanitizer/libatomic.ll
@@ -0,0 +1,69 @@
+; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck %s
+; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S -passes=msan 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-ORIGIN
+; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @__atomic_load(i64, i8*, i8*, i32)
+declare void @__atomic_store(i64, i8*, i8*, i32)
+
+define i24 @odd_sized_load(i24* %ptr) sanitize_memory {
+; CHECK: @odd_sized_load(i24* {{.*}}[[PTR:%.+]])
+; CHECK: [[VAL_PTR:%.*]] = alloca i24, align 1
+; CHECK-ORIGIN: @__msan_set_alloca_origin
+; CHECK: [[VAL_PTR_I8:%.*]] = bitcast i24* [[VAL_PTR]] to i8*
+; CHECK: [[PTR_I8:%.*]] = bitcast i24* [[PTR]] to i8*
+; CHECK: call void @__atomic_load(i64 3, i8* [[PTR_I8]], i8* [[VAL_PTR_I8]], i32 2)
+
+; CHECK: ptrtoint i8* [[PTR_I8]]
+; CHECK: xor
+; CHECK: [[SPTR_I8:%.*]] = inttoptr
+; CHECK-ORIGIN: add
+; CHECK-ORIGIN: and
+; CHECK-ORIGIN: [[OPTR:%.*]] = inttoptr
+
+; CHECK: ptrtoint i8* [[VAL_PTR_I8]]
+; CHECK: xor
+; CHECK: [[VAL_SPTR_I8:%.*]] = inttoptr
+; CHECK-ORIGIN: add
+; CHECK-ORIGIN: and
+; CHECK-ORIGIN: [[VAL_OPTR:%.*]] = inttoptr
+
+; CHECK: call void @llvm.memcpy{{.*}}(i8* align 1 [[VAL_SPTR_I8]], i8* align 1 [[SPTR_I8]], i64 3
+
+; CHECK-ORIGIN: [[ARG_ORIGIN:%.*]] = load i32, i32* [[OPTR]]
+; CHECK-ORIGIN: [[VAL_ORIGIN:%.*]] = call i32 @__msan_chain_origin(i32 [[ARG_ORIGIN]])
+; CHECK-ORIGIN: call void @__msan_set_origin(i8* [[VAL_PTR_I8]], i64 3, i32 [[VAL_ORIGIN]])
+
+; CHECK: [[VAL:%.*]] = load i24, i24* [[VAL_PTR]]
+; CHECK: ret i24 [[VAL]]
+  %val_ptr = alloca i24, align 1
+  %val_ptr_i8 = bitcast i24* %val_ptr to i8*
+  %ptr_i8 = bitcast i24* %ptr to i8*
+  call void @__atomic_load(i64 3, i8* %ptr_i8, i8* %val_ptr_i8, i32 0)
+  %val = load i24, i24* %val_ptr
+  ret i24 %val
+}
+
+define void @odd_sized_store(i24* %ptr, i24 %val) sanitize_memory {
+; CHECK: @odd_sized_store(i24* {{.*}}[[PTR:%.+]], i24 {{.*}}[[VAL:%.+]])
+; CHECK: [[VAL_PTR:%.*]] = alloca i24, align 1
+; CHECK: store i24 [[VAL]], i24* [[VAL_PTR]]
+; CHECK: [[VAL_PTR_I8:%.*]] = bitcast i24* [[VAL_PTR]] to i8*
+; CHECK: [[PTR_I8:%.*]] = bitcast i24* [[PTR]] to i8*
+
+; CHECK: ptrtoint i8* [[PTR_I8]]
+; CHECK: xor
+; CHECK: [[SPTR_I8:%.*]] = inttoptr
+; CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[SPTR_I8]], i8 0, i64 3
+
+; CHECK: call void @__atomic_store(i64 3, i8* [[VAL_PTR_I8]], i8* [[PTR_I8]], i32 3)
+; CHECK: ret void
+  %val_ptr = alloca i24, align 1
+  store i24 %val, i24* %val_ptr
+  %val_ptr_i8 = bitcast i24* %val_ptr to i8*
+  %ptr_i8 = bitcast i24* %ptr to i8*
+  call void @__atomic_store(i64 3, i8* %val_ptr_i8, i8* %ptr_i8, i32 0)
+  ret void
+}
+
Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -573,6 +573,9 @@
   /// uninitialized value and returns an updated origin id encoding this info.
   FunctionCallee MsanChainOriginFn;
 
+  /// Run-time helper that paints an origin over a region.
+  FunctionCallee MsanSetOriginFn;
+
   /// MSan runtime replacements for memmove, memcpy and memset.
   FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
 
@@ -851,6 +854,9 @@
   // instrumentation.
   MsanChainOriginFn = M.getOrInsertFunction(
 "__msan_chain_origin", IRB.getInt32Ty(), IRB.getInt32Ty());
+  MsanSetOriginFn =
+  M.getOrInsertFunction("__msan_set_origin", IRB.getVoidTy(),
+IRB.getInt8PtrTy(), IntptrTy, IRB.getInt32Ty());
   MemmoveFn = M.getOrInsertFunction(
 "__msan_memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
 IRB.getInt8PtrTy(), IntptrTy);
@@ -1818,6 +1824,24 @@
 llvm_unreachable("Unknown ordering");
   }
 
+  Value *makeAddReleaseOrderingTable(IRBuilder<> &IRB) {
+constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
+uint32_t OrderingTable[NumOrderings] = {};
+
+OrderingTable[(int)AtomicOrderingCABI::relaxed] =
+OrderingTable[(int)Atomi

[PATCH] D85573: [CGAtomic] Mark atomic libcall functions `nounwind`

2020-08-07 Thread Gui Andrade via Phabricator via cfe-commits
guiand created this revision.
guiand added reviewers: rsmith, eugenis.
Herald added subscribers: cfe-commits, jfb.
Herald added a project: clang.
guiand requested review of this revision.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D85573

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


Index: clang/test/CodeGen/atomic_ops.c
===
--- clang/test/CodeGen/atomic_ops.c
+++ clang/test/CodeGen/atomic_ops.c
@@ -26,6 +26,9 @@
 
 }
 
+// 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 @@
   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 @@
 
   return (in *= 5);
 }
+
+// LIBCALL: [[LC_ATTRS]] = { nounwind }
Index: clang/lib/CodeGen/CGAtomic.cpp
===
--- clang/lib/CodeGen/CGAtomic.cpp
+++ clang/lib/CodeGen/CGAtomic.cpp
@@ -307,7 +307,12 @@
   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::AttributeList fnAttrs;
+  fnAttrs = fnAttrs.addAttribute(CGF.getLLVMContext(),
+ llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoUnwind);
+  llvm::FunctionCallee fn =
+  CGF.CGM.CreateRuntimeFunction(fnTy, fnName, fnAttrs);
   auto callee = CGCallee::forDirect(fn);
   return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args);
 }


Index: clang/test/CodeGen/atomic_ops.c
===
--- clang/test/CodeGen/atomic_ops.c
+++ clang/test/CodeGen/atomic_ops.c
@@ -26,6 +26,9 @@
 
 }
 
+// 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 @@
   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 @@
 
   return (in *= 5);
 }
+
+// LIBCALL: [[LC_ATTRS]] = { nounwind }
Index: clang/lib/CodeGen/CGAtomic.cpp
===
--- clang/lib/CodeGen/CGAtomic.cpp
+++ clang/lib/CodeGen/CGAtomic.cpp
@@ -307,7 +307,12 @@
   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::AttributeList fnAttrs;
+  fnAttrs = fnAttrs.addAttribute(CGF.getLLVMContext(),
+ llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoUnwind);
+  llvm::FunctionCallee fn =
+  CGF.CGM.CreateRuntimeFunction(fnTy, fnName, fnAttrs);
   auto callee = CGCallee::forDirect(fn);
   return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args);
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D85559: [MSAN] Reintroduce libatomic load/store instrumentation

2020-08-07 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 284102.
guiand removed a reviewer: rsmith.
guiand added a comment.

Separated out the frontend change. Addressed other comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85559

Files:
  compiler-rt/test/msan/libatomic.c
  compiler-rt/test/msan/libatomic_load_exceptions.cpp
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
  llvm/test/Instrumentation/MemorySanitizer/libatomic.ll

Index: llvm/test/Instrumentation/MemorySanitizer/libatomic.ll
===
--- /dev/null
+++ llvm/test/Instrumentation/MemorySanitizer/libatomic.ll
@@ -0,0 +1,69 @@
+; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck %s
+; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S -passes=msan 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-ORIGIN
+; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @__atomic_load(i64, i8*, i8*, i32)
+declare void @__atomic_store(i64, i8*, i8*, i32)
+
+define i24 @odd_sized_load(i24* %ptr) sanitize_memory {
+; CHECK: @odd_sized_load(i24* {{.*}}[[PTR:%.+]])
+; CHECK: [[VAL_PTR:%.*]] = alloca i24, align 1
+; CHECK-ORIGIN: @__msan_set_alloca_origin
+; CHECK: [[VAL_PTR_I8:%.*]] = bitcast i24* [[VAL_PTR]] to i8*
+; CHECK: [[PTR_I8:%.*]] = bitcast i24* [[PTR]] to i8*
+; CHECK: call void @__atomic_load(i64 3, i8* [[PTR_I8]], i8* [[VAL_PTR_I8]], i32 2)
+
+; CHECK: ptrtoint i8* [[PTR_I8]]
+; CHECK: xor
+; CHECK: [[SPTR_I8:%.*]] = inttoptr
+; CHECK-ORIGIN: add
+; CHECK-ORIGIN: and
+; CHECK-ORIGIN: [[OPTR:%.*]] = inttoptr
+
+; CHECK: ptrtoint i8* [[VAL_PTR_I8]]
+; CHECK: xor
+; CHECK: [[VAL_SPTR_I8:%.*]] = inttoptr
+; CHECK-ORIGIN: add
+; CHECK-ORIGIN: and
+; CHECK-ORIGIN: [[VAL_OPTR:%.*]] = inttoptr
+
+; CHECK: call void @llvm.memcpy{{.*}}(i8* align 1 [[VAL_SPTR_I8]], i8* align 1 [[SPTR_I8]], i64 3
+
+; CHECK-ORIGIN: [[ARG_ORIGIN:%.*]] = load i32, i32* [[OPTR]]
+; CHECK-ORIGIN: [[VAL_ORIGIN:%.*]] = call i32 @__msan_chain_origin(i32 [[ARG_ORIGIN]])
+; CHECK-ORIGIN: call void @__msan_set_origin(i8* [[VAL_PTR_I8]], i64 3, i32 [[VAL_ORIGIN]])
+
+; CHECK: [[VAL:%.*]] = load i24, i24* [[VAL_PTR]]
+; CHECK: ret i24 [[VAL]]
+  %val_ptr = alloca i24, align 1
+  %val_ptr_i8 = bitcast i24* %val_ptr to i8*
+  %ptr_i8 = bitcast i24* %ptr to i8*
+  call void @__atomic_load(i64 3, i8* %ptr_i8, i8* %val_ptr_i8, i32 0)
+  %val = load i24, i24* %val_ptr
+  ret i24 %val
+}
+
+define void @odd_sized_store(i24* %ptr, i24 %val) sanitize_memory {
+; CHECK: @odd_sized_store(i24* {{.*}}[[PTR:%.+]], i24 {{.*}}[[VAL:%.+]])
+; CHECK: [[VAL_PTR:%.*]] = alloca i24, align 1
+; CHECK: store i24 [[VAL]], i24* [[VAL_PTR]]
+; CHECK: [[VAL_PTR_I8:%.*]] = bitcast i24* [[VAL_PTR]] to i8*
+; CHECK: [[PTR_I8:%.*]] = bitcast i24* [[PTR]] to i8*
+
+; CHECK: ptrtoint i8* [[PTR_I8]]
+; CHECK: xor
+; CHECK: [[SPTR_I8:%.*]] = inttoptr
+; CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[SPTR_I8]], i8 0, i64 3
+
+; CHECK: call void @__atomic_store(i64 3, i8* [[VAL_PTR_I8]], i8* [[PTR_I8]], i32 3)
+; CHECK: ret void
+  %val_ptr = alloca i24, align 1
+  store i24 %val, i24* %val_ptr
+  %val_ptr_i8 = bitcast i24* %val_ptr to i8*
+  %ptr_i8 = bitcast i24* %ptr to i8*
+  call void @__atomic_store(i64 3, i8* %val_ptr_i8, i8* %ptr_i8, i32 0)
+  ret void
+}
+
Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -573,6 +573,9 @@
   /// uninitialized value and returns an updated origin id encoding this info.
   FunctionCallee MsanChainOriginFn;
 
+  /// Run-time helper that paints an origin over a region.
+  FunctionCallee MsanSetOriginFn;
+
   /// MSan runtime replacements for memmove, memcpy and memset.
   FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
 
@@ -851,6 +854,9 @@
   // instrumentation.
   MsanChainOriginFn = M.getOrInsertFunction(
 "__msan_chain_origin", IRB.getInt32Ty(), IRB.getInt32Ty());
+  MsanSetOriginFn =
+  M.getOrInsertFunction("__msan_set_origin", IRB.getVoidTy(),
+IRB.getInt8PtrTy(), IntptrTy, IRB.getInt32Ty());
   MemmoveFn = M.getOrInsertFunction(
 "__msan_memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
 IRB.getInt8PtrTy(), IntptrTy);
@@ -1818,6 +1824,24 @@
 llvm_unreachable("Unknown ordering");
   }
 
+  Value *makeAddReleaseOrderingTable(IRBuilder<> &IRB) {
+constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
+uint32_t OrderingTable[NumOrderings] = {};
+
+OrderingTable[(int)AtomicOrderingCABI::relaxed

[PATCH] D85559: [MSAN] Reintroduce libatomic load/store instrumentation

2020-08-07 Thread Gui Andrade via Phabricator via cfe-commits
guiand marked 2 inline comments as done.
guiand added inline comments.



Comment at: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp:3513
+assert(InsPoint);
+if (!InsPoint) {
+  return;

TODO: Remove this redudant call


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85559

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


[PATCH] D85573: [CGAtomic] Mark atomic libcall functions `nounwind`

2020-08-10 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

I don't think we can necessarily guarantee `argmemonly/readonly/writeonly`, 
particularly since these library calls can take a lock somewhere inside. I'll 
definitely add `nocapture` and `willreturn` though.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85573

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


[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-08-11 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

After discussing with @eugenis, for the meantime it might be best to do the 
following:

- Change the masking attribute to be `-fdisable-noundef-analysis` (name 
notwithstanding), and have it completely turn off all `noundef`s
- Change the llvm-lit configuration to use the new codegen flag for all the 
tests by default
- Have `noundef` emitted in the frontend by default (when the codegen flag 
isn't present)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

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


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-08-11 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 284907.
guiand added a comment.
Herald added a subscriber: delcypher.

To try to alleviate the tests issue, @eugenis and I discussed that it might be 
best to take it slow. So now this patch will mask off emitting the attribute on 
clang tests by default.


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp
  clang/test/lit.cfg.py
  llvm/utils/lit/lit/llvm/config.py
  llvm/utils/update_cc_test_checks.py

Index: llvm/utils/update_cc_test_checks.py
===
--- llvm/utils/update_cc_test_checks.py
+++ llvm/utils/update_cc_test_checks.py
@@ -28,9 +28,9 @@
 from UpdateTestChecks import common
 
 SUBST = {
-'%clang': [],
-'%clang_cc1': ['-cc1'],
-'%clangxx': ['--driver-mode=g++'],
+'%clang': ['-fdisable-noundef-analysis'],
+'%clang_cc1': ['-cc1', '-fdisable-noundef-analysis'],
+'%clangxx': ['--driver-mode=g++', '-fdisable-noundef-analysis'],
 }
 
 def get_line2spell_and_mangled(args, clang_args):
@@ -161,8 +161,8 @@
   try:
 builtin_include_dir = subprocess.check_output(
   [args.clang, '-print-file-name=include']).decode().strip()
-SUBST['%clang_cc1'] = ['-cc1', '-internal-isystem', builtin_include_dir,
-   '-nostdsysteminc']
+SUBST['%clang_cc1'] += ['-internal-isystem', builtin_include_dir,
+'-nostdsysteminc']
   except subprocess.CalledProcessError:
 common.warn('Could not determine clang builtins directory, some tests '
 'might not update correctly.')
Index: llvm/utils/lit/lit/llvm/config.py
===
--- llvm/utils/lit/lit/llvm/config.py
+++ llvm/utils/lit/lit/llvm/config.py
@@ -412,7 +412,7 @@
 ToolSubst('%clang_analyze_cc1', command='%clang_cc1', extra_args=['-analyze', '%analyze', '-setup-static-analyzer']+additional_flags),
 ToolSubst('%clang_cc1', command=self.config.clang, extra_args=['-cc1', '-internal-isystem', builtin_include_dir, '-nostdsysteminc']+additional_flags),
 ToolSubst('%clang_cpp', command=self.config.clang, extra_args=['--driver-mode=cpp']+additional_flags),
-ToolSubst('%clang_cl', command=self.config.clang, extra_args=['--driver-mode=cl']+additional_flags),
+ToolSubst('%clang_cl', command=self.config.clang, extra_args=['--driver-mode=cl']),
 ToolSubst('%clangxx', command=self.config.clang, extra_args=['--driver-mode=g++']+additional_flags),
 ToolSubst('%clang_bin', command=self.config.clang),
 ]
Index: clang/test/lit.cfg.py
===
--- clang/test/lit.cfg.py
+++ clang/test/lit.cfg.py
@@ -41,7 +41,7 @@
 
 llvm_config.use_default_substitutions()
 
-llvm_config.use_clang()
+llvm_config.use_clang(additional_flags=['-fdisable-noundef-analysis'])
 
 config.substitutions.append(
 ('%src_include_dir', config.clang_src_dir + '/include'))
Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_bin -cc1 -x c++ -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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,163 @@
+// RUN: %clang_bin -cc1 -triple x86_64-g

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-08-11 Thread Gui Andrade via Phabricator via cfe-commits
guiand requested review of this revision.
guiand added a comment.

I think I'd like someone to take a look at the `llvm-lit` changes to see if 
this makes sense as an approach


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678

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


[PATCH] D85573: [CGAtomic] Mark atomic libcall functions `nounwind`

2020-08-11 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 284922.
guiand added a comment.

Added `willreturn`. I think `nocapture` is probably best left to a future 
change since it's more invasive -- it would require keeping tabs of which 
arguments to each function is a pointer arg.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85573

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


Index: clang/test/CodeGen/atomic_ops.c
===
--- clang/test/CodeGen/atomic_ops.c
+++ clang/test/CodeGen/atomic_ops.c
@@ -26,6 +26,9 @@
 
 }
 
+// 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 @@
   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 @@
 
   return (in *= 5);
 }
+
+// LIBCALL: [[LC_ATTRS]] = { nounwind willreturn }
Index: clang/lib/CodeGen/CGAtomic.cpp
===
--- clang/lib/CodeGen/CGAtomic.cpp
+++ clang/lib/CodeGen/CGAtomic.cpp
@@ -307,7 +307,14 @@
   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);
 }


Index: clang/test/CodeGen/atomic_ops.c
===
--- clang/test/CodeGen/atomic_ops.c
+++ clang/test/CodeGen/atomic_ops.c
@@ -26,6 +26,9 @@
 
 }
 
+// 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 @@
   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 @@
 
   return (in *= 5);
 }
+
+// LIBCALL: [[LC_ATTRS]] = { nounwind willreturn }
Index: clang/lib/CodeGen/CGAtomic.cpp
===
--- clang/lib/CodeGen/CGAtomic.cpp
+++ clang/lib/CodeGen/CGAtomic.cpp
@@ -307,7 +307,14 @@
   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);
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2020-08-12 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 284931.
guiand added a comment.

Made the compiler flag non-public


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp
  clang/test/lit.cfg.py
  llvm/utils/update_cc_test_checks.py

Index: llvm/utils/update_cc_test_checks.py
===
--- llvm/utils/update_cc_test_checks.py
+++ llvm/utils/update_cc_test_checks.py
@@ -28,9 +28,9 @@
 from UpdateTestChecks import common
 
 SUBST = {
-'%clang': [],
-'%clang_cc1': ['-cc1'],
-'%clangxx': ['--driver-mode=g++'],
+'%clang': ['-Xclang -disable-noundef-analysis'],
+'%clang_cc1': ['-cc1', '-disable-noundef-analysis'],
+'%clangxx': ['--driver-mode=g++', '-disable-noundef-analysis'],
 }
 
 def get_line2spell_and_mangled(args, clang_args):
@@ -161,8 +161,8 @@
   try:
 builtin_include_dir = subprocess.check_output(
   [args.clang, '-print-file-name=include']).decode().strip()
-SUBST['%clang_cc1'] = ['-cc1', '-internal-isystem', builtin_include_dir,
-   '-nostdsysteminc']
+SUBST['%clang_cc1'] += ['-internal-isystem', builtin_include_dir,
+'-nostdsysteminc']
   except subprocess.CalledProcessError:
 common.warn('Could not determine clang builtins directory, some tests '
 'might not update correctly.')
Index: clang/test/lit.cfg.py
===
--- clang/test/lit.cfg.py
+++ clang/test/lit.cfg.py
@@ -41,7 +41,8 @@
 
 llvm_config.use_default_substitutions()
 
-llvm_config.use_clang()
+llvm_config.use_clang(cc_additional_flags=['-Xclang -disable-noundef-analysis'],
+  cc1_additional_flags=['-disable-noundef-analysis'])
 
 config.substitutions.append(
 ('%src_include_dir', config.clang_src_dir + '/include'))
Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_bin -cc1 -x c++ -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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,163 @@
+// RUN: %clang_bin -cc1 -triple x86_64-gnu-linux -x c++ -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
+// RUN: %clang_bin -cc1 -triple x86_64-gnu-linux -x c++ -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
+// RUN: %clang_bin -cc1 -triple aarch64-gnu-linux -x c++ -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: define i32 @{{.*}}ret_trivial
+// CHECK-AARCH: define i64 @{{.*}}ret_trivial
+// CHECK-INTEL: define void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: define void @{{.*}}pass_trivial{{.*}}(i64 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: define {{(dso_local)?}}void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret align 4 %
+// CHECK: define void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge 

[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-08-12 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

In D82317#2212145 , @jdoerfert wrote:

> TBH, I don't see how this solves any problem. It just makes it a problem for 
> someone in the future... (FWIW, I say this being in full support of `noundef`)

That's true. At the same time, it might allow us to have a more baby-steps 
approach: be able to use the attribute now, update tests in their own time, and 
hopefully amortize the effect on downstream forks as @jrtc27 mentioned.

But the work for updating the tests is done now, in this patch, and as time 
goes on more and more of this work will need to be duplicated as the tests 
change every day.

There's one other option here, which has been mentioned a few times but I'll 
flesh it out for the purposes of discussion.

- Instead of updating the default test configuration to use 
`-disable-noundef-analysis`, we update every failing test (due to noundef) to 
use that flag in the RUN lines. This unblocks the clang noundef change.
- Then I can split up this patch into many smaller patches, probably organized 
by subfolder of `clang/test`, and these smaller patches would remove the 
`-disable-noundef-analysis` flags and add in the relevant `noundef` attributes.
- Test authors which don't want theirs changed could voice that they want to 
just keep the masking flag for their files.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

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


[PATCH] D85573: [CGAtomic] Mark atomic libcall functions `nounwind`

2020-08-14 Thread Gui Andrade via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG909a851dbffe: [CGAtomic] Mark atomic libcall functions 
`nounwind` (authored by guiand).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85573

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


Index: clang/test/CodeGen/atomic_ops.c
===
--- clang/test/CodeGen/atomic_ops.c
+++ clang/test/CodeGen/atomic_ops.c
@@ -26,6 +26,9 @@
 
 }
 
+// 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 @@
   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 @@
 
   return (in *= 5);
 }
+
+// LIBCALL: [[LC_ATTRS]] = { nounwind willreturn }
Index: clang/lib/CodeGen/CGAtomic.cpp
===
--- clang/lib/CodeGen/CGAtomic.cpp
+++ clang/lib/CodeGen/CGAtomic.cpp
@@ -307,7 +307,14 @@
   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);
 }


Index: clang/test/CodeGen/atomic_ops.c
===
--- clang/test/CodeGen/atomic_ops.c
+++ clang/test/CodeGen/atomic_ops.c
@@ -26,6 +26,9 @@
 
 }
 
+// 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 @@
   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 @@
 
   return (in *= 5);
 }
+
+// LIBCALL: [[LC_ATTRS]] = { nounwind willreturn }
Index: clang/lib/CodeGen/CGAtomic.cpp
===
--- clang/lib/CodeGen/CGAtomic.cpp
+++ clang/lib/CodeGen/CGAtomic.cpp
@@ -307,7 +307,14 @@
   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);
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D85559: [MSAN] Reintroduce libatomic load/store instrumentation

2020-08-14 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 285572.
guiand added a comment.

Addressed comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85559

Files:
  compiler-rt/test/msan/libatomic.c
  compiler-rt/test/msan/libatomic_load_exceptions.cpp
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
  llvm/test/Instrumentation/MemorySanitizer/libatomic.ll

Index: llvm/test/Instrumentation/MemorySanitizer/libatomic.ll
===
--- /dev/null
+++ llvm/test/Instrumentation/MemorySanitizer/libatomic.ll
@@ -0,0 +1,69 @@
+; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck %s
+; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S -passes=msan 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-ORIGIN
+; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @__atomic_load(i64, i8*, i8*, i32)
+declare void @__atomic_store(i64, i8*, i8*, i32)
+
+define i24 @odd_sized_load(i24* %ptr) sanitize_memory {
+; CHECK: @odd_sized_load(i24* {{.*}}[[PTR:%.+]])
+; CHECK: [[VAL_PTR:%.*]] = alloca i24, align 1
+; CHECK-ORIGIN: @__msan_set_alloca_origin
+; CHECK: [[VAL_PTR_I8:%.*]] = bitcast i24* [[VAL_PTR]] to i8*
+; CHECK: [[PTR_I8:%.*]] = bitcast i24* [[PTR]] to i8*
+; CHECK: call void @__atomic_load(i64 3, i8* [[PTR_I8]], i8* [[VAL_PTR_I8]], i32 2)
+
+; CHECK: ptrtoint i8* [[PTR_I8]]
+; CHECK: xor
+; CHECK: [[SPTR_I8:%.*]] = inttoptr
+; CHECK-ORIGIN: add
+; CHECK-ORIGIN: and
+; CHECK-ORIGIN: [[OPTR:%.*]] = inttoptr
+
+; CHECK: ptrtoint i8* [[VAL_PTR_I8]]
+; CHECK: xor
+; CHECK: [[VAL_SPTR_I8:%.*]] = inttoptr
+; CHECK-ORIGIN: add
+; CHECK-ORIGIN: and
+; CHECK-ORIGIN: [[VAL_OPTR:%.*]] = inttoptr
+
+; CHECK: call void @llvm.memcpy{{.*}}(i8* align 1 [[VAL_SPTR_I8]], i8* align 1 [[SPTR_I8]], i64 3
+
+; CHECK-ORIGIN: [[ARG_ORIGIN:%.*]] = load i32, i32* [[OPTR]]
+; CHECK-ORIGIN: [[VAL_ORIGIN:%.*]] = call i32 @__msan_chain_origin(i32 [[ARG_ORIGIN]])
+; CHECK-ORIGIN: call void @__msan_set_origin(i8* [[VAL_PTR_I8]], i64 3, i32 [[VAL_ORIGIN]])
+
+; CHECK: [[VAL:%.*]] = load i24, i24* [[VAL_PTR]]
+; CHECK: ret i24 [[VAL]]
+  %val_ptr = alloca i24, align 1
+  %val_ptr_i8 = bitcast i24* %val_ptr to i8*
+  %ptr_i8 = bitcast i24* %ptr to i8*
+  call void @__atomic_load(i64 3, i8* %ptr_i8, i8* %val_ptr_i8, i32 0)
+  %val = load i24, i24* %val_ptr
+  ret i24 %val
+}
+
+define void @odd_sized_store(i24* %ptr, i24 %val) sanitize_memory {
+; CHECK: @odd_sized_store(i24* {{.*}}[[PTR:%.+]], i24 {{.*}}[[VAL:%.+]])
+; CHECK: [[VAL_PTR:%.*]] = alloca i24, align 1
+; CHECK: store i24 [[VAL]], i24* [[VAL_PTR]]
+; CHECK: [[VAL_PTR_I8:%.*]] = bitcast i24* [[VAL_PTR]] to i8*
+; CHECK: [[PTR_I8:%.*]] = bitcast i24* [[PTR]] to i8*
+
+; CHECK: ptrtoint i8* [[PTR_I8]]
+; CHECK: xor
+; CHECK: [[SPTR_I8:%.*]] = inttoptr
+; CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[SPTR_I8]], i8 0, i64 3
+
+; CHECK: call void @__atomic_store(i64 3, i8* [[VAL_PTR_I8]], i8* [[PTR_I8]], i32 3)
+; CHECK: ret void
+  %val_ptr = alloca i24, align 1
+  store i24 %val, i24* %val_ptr
+  %val_ptr_i8 = bitcast i24* %val_ptr to i8*
+  %ptr_i8 = bitcast i24* %ptr to i8*
+  call void @__atomic_store(i64 3, i8* %val_ptr_i8, i8* %ptr_i8, i32 0)
+  ret void
+}
+
Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -573,6 +573,9 @@
   /// uninitialized value and returns an updated origin id encoding this info.
   FunctionCallee MsanChainOriginFn;
 
+  /// Run-time helper that paints an origin over a region.
+  FunctionCallee MsanSetOriginFn;
+
   /// MSan runtime replacements for memmove, memcpy and memset.
   FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
 
@@ -851,6 +854,9 @@
   // instrumentation.
   MsanChainOriginFn = M.getOrInsertFunction(
 "__msan_chain_origin", IRB.getInt32Ty(), IRB.getInt32Ty());
+  MsanSetOriginFn =
+  M.getOrInsertFunction("__msan_set_origin", IRB.getVoidTy(),
+IRB.getInt8PtrTy(), IntptrTy, IRB.getInt32Ty());
   MemmoveFn = M.getOrInsertFunction(
 "__msan_memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
 IRB.getInt8PtrTy(), IntptrTy);
@@ -1818,6 +1824,24 @@
 llvm_unreachable("Unknown ordering");
   }
 
+  Value *makeAddReleaseOrderingTable(IRBuilder<> &IRB) {
+constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
+uint32_t OrderingTable[NumOrderings] = {};
+
+OrderingTable[(int)AtomicOrderingCABI::relaxed] =
+OrderingTable[(int)AtomicOrderingCABI::release] =
+(

[PATCH] D85559: [MSAN] Reintroduce libatomic load/store instrumentation

2020-08-14 Thread Gui Andrade via Phabricator via cfe-commits
guiand added inline comments.



Comment at: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp:3573
+  case LibFunc_atomic_load:
+if (!isa(CB)) {
+  llvm::errs() << "MSAN -- cannot instrument invoke of libatomic load."

eugenis wrote:
> Probably need the same check for atomic_store.
Although it would be good for consistency I don't think it's strictly needed 
since with `atomic_store` we don't need to use `getNextNode()`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85559

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


[PATCH] D85559: [MSAN] Reintroduce libatomic load/store instrumentation

2020-08-14 Thread Gui Andrade via Phabricator via cfe-commits
guiand closed this revision.
guiand added a comment.

Committed as 97de0188dd5d845ff90c8ac779a2ea09688b17df 



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85559

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


[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2020-08-24 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.
Herald added a subscriber: wenlei.

@rjmccall We've discussed several different possibilities here. Does any of 
them strike you as a good step forward here?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

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


[PATCH] D85788: [Clang test] Update to allow passing extra default clang arguments in use_clang

2020-12-09 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

This whole thing is a little unfortunate, but maybe a better substitution would 
be leaving `%clang` as referring to the pure clang binary, with default 
arguments. Then we can have a `%clang_cc` which may only be used for a standard 
C compiler invocation.

Returning to the main issue, adding a default argument to `%clang` breaks a 
number of tests. Generally these tests change the compiler mode such that a C 
compiler argument makes no sense. Consider `%clang -cc1`: this gets expanded to 
`clang -Xclang -disable-noundef-analysis -cc1`, which IIRC causes an error.
This isn't a problem with something like `%clang_cc`, because a C compiler flag 
would always be valid for that expansion.

IMO it's better to just one-and-done programatically add `-Xclang 
-disable-noundef-analysis` to all the tests' RUN lines. That way there are no 
hidden flags.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85788

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


[PATCH] D85788: [Clang test] Update to allow passing extra default clang arguments in use_clang

2020-10-16 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

Did we decide that we wanted this change then? I remember there being 
discussion around whether it's the right approach.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85788

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


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2021-02-05 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

Changing the mechanism to explicit opt-in seems like a good idea, and bypasses 
the test issues.

If everyone agrees about proceeding with this, I can fix up this patch within 
the next couple days and we can hopefully wrap this up!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678

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


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2021-02-11 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 322899.
guiand added a comment.

Updated to use -enable-noundef-analysis


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang -cc1 -x c++ -triple x86_64-unknown-unknown -O0 -emit-llvm -enable-noundef-analysis -o - %s | FileCheck %s
+
+union u1 {
+  int val;
+};
+
+// CHECK: @indirect_callee_int_ptr = [[GLOBAL:(dso_local )?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: [[DEFINE:define( dso_local)?]] noundef i32 @{{.*}}indirect_callee_int{{.*}}(i32 noundef %
+int indirect_callee_int(int a) { return a; }
+// CHECK: [[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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,162 @@
+// RUN: %clang -cc1 -triple x86_64-gnu-linux -x c++ -S -emit-llvm -enable-noundef-analysis %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
+// RUN: %clang -cc1 -triple aarch64-gnu-linux -x c++ -S -emit-llvm -enable-noundef-analysis %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: [[DEFINE:define( dso_local)?]] i32 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEFINE:define( dso_local)?]] i64 @{{.*}}ret_trivial
+// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge ret_huge() { return {}; }
+void pass_huge(Huge h) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef
+} // namespace check_structs
+
+// Passing unions by value
+// No unions may be marked noundef
+
+namespace check_unions {
+union Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: [[DEFINE]] i32 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEFINE]] i64 @{{.*}}ret_trivial
+// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
+
+union NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+} // namespace check_unions
+
+// Passing `this` pointers
+// `this` pointer must always be defined
+
+namespace check_this {
+struct Object {
+  int data[];
+
+  Object() {
+this->data[0] = 0;
+  }
+  int getData() {
+return this->data[0];
+  }
+  Object *getThis() {
+return this;
+  }
+};
+
+void use_object() {
+  Object obj;
+  obj.getData();
+  obj.getThis();
+}
+// CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*}}getData{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr nou

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2021-03-02 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

For sure. I'll upload a rebased patch shortly and give it another day or so for 
people to look, and then push if there aren't any issues.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81678

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


[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2021-03-04 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 328055.
guiand added a comment.

Reupload patch to trigger build


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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang -cc1 -x c++ -triple x86_64-unknown-unknown -O0 -emit-llvm -enable-noundef-analysis -o - %s | FileCheck %s
+
+union u1 {
+  int val;
+};
+
+// CHECK: @indirect_callee_int_ptr = [[GLOBAL:(dso_local )?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: [[DEFINE:define( dso_local)?]] noundef i32 @{{.*}}indirect_callee_int{{.*}}(i32 noundef %
+int indirect_callee_int(int a) { return a; }
+// CHECK: [[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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,162 @@
+// RUN: %clang -cc1 -triple x86_64-gnu-linux -x c++ -S -emit-llvm -enable-noundef-analysis %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
+// RUN: %clang -cc1 -triple aarch64-gnu-linux -x c++ -S -emit-llvm -enable-noundef-analysis %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: [[DEFINE:define( dso_local)?]] i32 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEFINE:define( dso_local)?]] i64 @{{.*}}ret_trivial
+// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge ret_huge() { return {}; }
+void pass_huge(Huge h) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef
+} // namespace check_structs
+
+// Passing unions by value
+// No unions may be marked noundef
+
+namespace check_unions {
+union Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: [[DEFINE]] i32 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEFINE]] i64 @{{.*}}ret_trivial
+// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
+
+union NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+} // namespace check_unions
+
+// Passing `this` pointers
+// `this` pointer must always be defined
+
+namespace check_this {
+struct Object {
+  int data[];
+
+  Object() {
+this->data[0] = 0;
+  }
+  int getData() {
+return this->data[0];
+  }
+  Object *getThis() {
+return this;
+  }
+};
+
+void use_object() {
+  Object obj;
+  obj.getData();
+  obj.getThis();
+}
+// CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*}}getData{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef %"s

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2021-03-04 Thread Gui Andrade via Phabricator via cfe-commits
guiand updated this revision to Diff 328060.

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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang -cc1 -x c++ -triple x86_64-unknown-unknown -O0 -emit-llvm -enable-noundef-analysis -o - %s | FileCheck %s
+
+union u1 {
+  int val;
+};
+
+// CHECK: @indirect_callee_int_ptr = [[GLOBAL:(dso_local )?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: [[DEFINE:define( dso_local)?]] noundef i32 @{{.*}}indirect_callee_int{{.*}}(i32 noundef %
+int indirect_callee_int(int a) { return a; }
+// CHECK: [[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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,162 @@
+// RUN: %clang -cc1 -triple x86_64-gnu-linux -x c++ -S -emit-llvm -enable-noundef-analysis %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
+// RUN: %clang -cc1 -triple aarch64-gnu-linux -x c++ -S -emit-llvm -enable-noundef-analysis %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: [[DEFINE:define( dso_local)?]] i32 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEFINE:define( dso_local)?]] i64 @{{.*}}ret_trivial
+// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge ret_huge() { return {}; }
+void pass_huge(Huge h) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef
+} // namespace check_structs
+
+// Passing unions by value
+// No unions may be marked noundef
+
+namespace check_unions {
+union Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: [[DEFINE]] i32 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEFINE]] i64 @{{.*}}ret_trivial
+// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
+
+union NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+} // namespace check_unions
+
+// Passing `this` pointers
+// `this` pointer must always be defined
+
+namespace check_this {
+struct Object {
+  int data[];
+
+  Object() {
+this->data[0] = 0;
+  }
+  int getData() {
+return this->data[0];
+  }
+  Object *getThis() {
+return this;
+  }
+};
+
+void use_object() {
+  Object obj;
+  obj.getData();
+  obj.getThis();
+}
+// CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*}}getData{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef %"struct.check_this::Object"* @{{.*}}Object{{.*}}getThis{{.*}

[PATCH] D81678: Introduce noundef attribute at call sites for stricter poison analysis

2021-03-05 Thread Gui Andrade via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG10264a1b21ae: Introduce noundef attribute at call sites for 
stricter poison analysis (authored by guiand).

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/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/indirect-noundef.cpp

Index: clang/test/CodeGen/indirect-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/indirect-noundef.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang -cc1 -x c++ -triple x86_64-unknown-unknown -O0 -emit-llvm -enable-noundef-analysis -o - %s | FileCheck %s
+
+union u1 {
+  int val;
+};
+
+// CHECK: @indirect_callee_int_ptr = [[GLOBAL:(dso_local )?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: [[DEFINE:define( dso_local)?]] noundef i32 @{{.*}}indirect_callee_int{{.*}}(i32 noundef %
+int indirect_callee_int(int a) { return a; }
+// CHECK: [[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/test/CodeGen/attr-noundef.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -0,0 +1,162 @@
+// RUN: %clang -cc1 -triple x86_64-gnu-linux -x c++ -S -emit-llvm -enable-noundef-analysis %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
+// RUN: %clang -cc1 -triple aarch64-gnu-linux -x c++ -S -emit-llvm -enable-noundef-analysis %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH
+
+// Passing structs by value
+// TODO: No structs may currently be marked noundef
+
+namespace check_structs {
+struct Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: [[DEFINE:define( dso_local)?]] i32 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEFINE:define( dso_local)?]] i64 @{{.*}}ret_trivial
+// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
+
+struct NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+
+struct Huge {
+  int a[1024];
+};
+Huge ret_huge() { return {}; }
+void pass_huge(Huge h) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef
+} // namespace check_structs
+
+// Passing unions by value
+// No unions may be marked noundef
+
+namespace check_unions {
+union Trivial {
+  int a;
+};
+Trivial ret_trivial() { return {}; }
+void pass_trivial(Trivial e) {}
+// CHECK-INTEL: [[DEFINE]] i32 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEFINE]] i64 @{{.*}}ret_trivial
+// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
+
+union NoCopy {
+  int a;
+  NoCopy(NoCopy &) = delete;
+};
+NoCopy ret_nocopy() { return {}; }
+void pass_nocopy(NoCopy e) {}
+// CHECK: [[DEFINE]] void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEFINE]] void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+} // namespace check_unions
+
+// Passing `this` pointers
+// `this` pointer must always be defined
+
+namespace check_this {
+struct Object {
+  int data[];
+
+  Object() {
+this->data[0] = 0;
+  }
+  int getData() {
+return this->data[0];
+  }
+  Object *getThis() {
+return this;
+  }
+};
+
+void use_object() {
+  Object obj;
+  obj.getData();
+  obj.getThis();
+}
+// CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(%"struct.check_this::Object"* noundef %
+// CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*

[PATCH] D85788: [Clang test] Update to allow passing extra default clang arguments in use_clang

2021-03-05 Thread Gui Andrade via Phabricator via cfe-commits
guiand abandoned this revision.
guiand added a comment.

We decided to go with a positive flag for enabling noundef, so I'm closing this.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D85788

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


[PATCH] D82317: [Clang/Test]: Update tests where `noundef` attribute is necessary

2021-04-06 Thread Gui Andrade via Phabricator via cfe-commits
guiand added a comment.

Sorry, I must've missed this. @aqjune, if you'd be willing to take on this 
change, that would be amazing (I haven't got much time to update these patches 
lately).

We can make these changes incrementally, too; say, one test subfolder at a 
time. Each patch could add the noundef enable option, and then once all the 
tests are ready we can batch remove the flag.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82317

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