[llvm] edf634e - [AssumeBundles] Add nonnull/align to op bundle if noundef exists

Juneyoung Lee via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 15 10:23:48 PDT 2021


Author: Juneyoung Lee
Date: 2021-03-16T10:23:42+09:00
New Revision: edf634ebc2673c2f6f878390c1f90bfd799f4a6b

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

LOG: [AssumeBundles] Add nonnull/align to op bundle if noundef exists

This is a patch to add nonnull and align to assume's operand bundle
only if noundef exists.
Since nonnull and align in fn attr have poison semantics, they should be
paired with noundef or noundef-implying attributes to be immediate UB.

Reviewed By: jdoerfert, Tyker

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

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp
    llvm/test/Transforms/Util/assume-builder-counter.ll
    llvm/test/Transforms/Util/assume-builder.ll
    llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp b/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp
index e6e527221ffe..0d3f783c3b1b 100644
--- a/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp
+++ b/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp
@@ -204,8 +204,12 @@ struct AssumeBuilderState {
     auto addAttrList = [&](AttributeList AttrList) {
       for (unsigned Idx = AttributeList::FirstArgIndex;
            Idx < AttrList.getNumAttrSets(); Idx++)
-        for (Attribute Attr : AttrList.getAttributes(Idx))
-          addAttribute(Attr, Call->getArgOperand(Idx - 1));
+        for (Attribute Attr : AttrList.getAttributes(Idx)) {
+          bool IsPoisonAttr = Attr.hasAttribute(Attribute::NonNull) ||
+                              Attr.hasAttribute(Attribute::Alignment);
+          if (!IsPoisonAttr || Call->isPassingUndefUB(Idx - 1))
+            addAttribute(Attr, Call->getArgOperand(Idx - 1));
+        }
       for (Attribute Attr : AttrList.getFnAttributes())
         addAttribute(Attr, nullptr);
     };

diff  --git a/llvm/test/Transforms/Util/assume-builder-counter.ll b/llvm/test/Transforms/Util/assume-builder-counter.ll
index deaffb1cc96e..bf9b2994a05d 100644
--- a/llvm/test/Transforms/Util/assume-builder-counter.ll
+++ b/llvm/test/Transforms/Util/assume-builder-counter.ll
@@ -1,6 +1,6 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
 ; REQUIRES: asserts
 
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
 ; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention --debug-counter=assume-builder-counter-skip=5,assume-builder-counter-count=1 -S %s | FileCheck %s --check-prefixes=COUNTER1
 ; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention --debug-counter=assume-builder-counter-skip=1,assume-builder-counter-count=3 -S %s | FileCheck %s --check-prefixes=COUNTER2
 ; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention --debug-counter=assume-builder-counter-skip=2,assume-builder-counter-count=200 -S %s | FileCheck %s --check-prefixes=COUNTER3
@@ -12,59 +12,69 @@ declare void @func_cold(i32*) cold willreturn nounwind
 declare void @func_strbool(i32*) "no-jump-tables"
 declare void @func_many(i32*) "no-jump-tables" nounwind "less-precise-fpmad" willreturn norecurse
 declare void @func_argattr(i32* align 8, i32* nonnull) nounwind
+declare void @func_argattr2(i32* noundef align 8, i32* noundef nonnull) nounwind
 declare void @may_throw()
 
 define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
 ; COUNTER1-LABEL: define {{[^@]+}}@test
-; COUNTER1-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]])
+; COUNTER1-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]]) {
 ; COUNTER1-NEXT:    call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null)
 ; COUNTER1-NEXT:    call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]])
-; COUNTER1-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]]) #5
+; COUNTER1-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]]) [[ATTR5:#.*]]
 ; COUNTER1-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]])
 ; COUNTER1-NEXT:    call void @func(i32* [[P1]], i32* [[P]])
 ; COUNTER1-NEXT:    call void @func_strbool(i32* [[P1]])
 ; COUNTER1-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
-; COUNTER1-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8) ]
 ; COUNTER1-NEXT:    call void @func_many(i32* align 8 [[P1]])
+; COUNTER1-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ]
+; COUNTER1-NEXT:    call void @func_many(i32* noundef align 8 [[P1]])
 ; COUNTER1-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
+; COUNTER1-NEXT:    call void @func_argattr2(i32* [[P2]], i32* [[P3]])
 ; COUNTER1-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
+; COUNTER1-NEXT:    call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]])
 ; COUNTER1-NEXT:    ret void
 ;
 ; COUNTER2-LABEL: define {{[^@]+}}@test
-; COUNTER2-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]])
+; COUNTER2-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]]) {
 ; COUNTER2-NEXT:    call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null)
-; COUNTER2-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12), "nonnull"(i32* [[P]]) ]
+; COUNTER2-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12) ]
 ; COUNTER2-NEXT:    call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]])
 ; COUNTER2-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
-; COUNTER2-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]]) #5
+; COUNTER2-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]]) [[ATTR5:#.*]]
 ; COUNTER2-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
 ; COUNTER2-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]])
 ; COUNTER2-NEXT:    call void @func(i32* [[P1]], i32* [[P]])
 ; COUNTER2-NEXT:    call void @func_strbool(i32* [[P1]])
 ; COUNTER2-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
 ; COUNTER2-NEXT:    call void @func_many(i32* align 8 [[P1]])
+; COUNTER2-NEXT:    call void @func_many(i32* noundef align 8 [[P1]])
 ; COUNTER2-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
+; COUNTER2-NEXT:    call void @func_argattr2(i32* [[P2]], i32* [[P3]])
 ; COUNTER2-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
+; COUNTER2-NEXT:    call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]])
 ; COUNTER2-NEXT:    ret void
 ;
 ; COUNTER3-LABEL: define {{[^@]+}}@test
-; COUNTER3-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]])
+; COUNTER3-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]]) {
 ; COUNTER3-NEXT:    call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null)
 ; COUNTER3-NEXT:    call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]])
 ; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12), "cold"() ]
-; COUNTER3-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]]) #5
+; COUNTER3-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]]) [[ATTR5:#.*]]
 ; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
 ; COUNTER3-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]])
 ; COUNTER3-NEXT:    call void @func(i32* [[P1]], i32* [[P]])
 ; COUNTER3-NEXT:    call void @func_strbool(i32* [[P1]])
 ; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ]
 ; COUNTER3-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
-; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8) ]
 ; COUNTER3-NEXT:    call void @func_many(i32* align 8 [[P1]])
-; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P2]], i64 8), "nonnull"(i32* [[P3]]) ]
+; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ]
+; COUNTER3-NEXT:    call void @func_many(i32* noundef align 8 [[P1]])
 ; COUNTER3-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
-; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "nonnull"(i32* [[P]]) ]
+; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]) ]
+; COUNTER3-NEXT:    call void @func_argattr2(i32* [[P2]], i32* [[P3]])
 ; COUNTER3-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
+; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]), "nonnull"(i32* [[P]]) ]
+; COUNTER3-NEXT:    call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]])
 ; COUNTER3-NEXT:    ret void
 ;
   call void @func(i32* nonnull dereferenceable(16) %P, i32* null)
@@ -75,7 +85,10 @@ define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
   call void @func_strbool(i32* %P1)
   call void @func(i32* dereferenceable(32) %P, i32* dereferenceable(8) %P)
   call void @func_many(i32* align 8 %P1)
+  call void @func_many(i32* align 8 noundef %P1)
   call void @func_argattr(i32* %P2, i32* %P3)
+  call void @func_argattr2(i32* %P2, i32* %P3)
   call void @func(i32* nonnull %P1, i32* nonnull %P)
+  call void @func(i32* nonnull noundef %P1, i32* nonnull noundef %P)
   ret void
 }

diff  --git a/llvm/test/Transforms/Util/assume-builder.ll b/llvm/test/Transforms/Util/assume-builder.ll
index bf56fca86b91..ea0748220f57 100644
--- a/llvm/test/Transforms/Util/assume-builder.ll
+++ b/llvm/test/Transforms/Util/assume-builder.ll
@@ -18,6 +18,7 @@ declare void @func_cold(i32*) cold willreturn nounwind
 declare void @func_strbool(i32*) "no-jump-tables"
 declare void @func_many(i32*) "no-jump-tables" nounwind "less-precise-fpmad" willreturn norecurse
 declare void @func_argattr(i32* align 8, i32* nonnull) nounwind
+declare void @func_argattr2(i32* noundef align 8, i32* noundef nonnull) nounwind
 declare void @may_throw()
 
 define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
@@ -35,12 +36,15 @@ define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
 ; BASIC-NEXT:    call void @func_strbool(i32* [[P1]])
 ; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ]
 ; BASIC-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
-; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8) ]
 ; BASIC-NEXT:    call void @func_many(i32* align 8 [[P1]])
-; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P2]], i64 8), "nonnull"(i32* [[P3]]) ]
+; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ]
+; BASIC-NEXT:    call void @func_many(i32* noundef align 8 [[P1]])
 ; BASIC-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
-; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]) ]
+; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]) ]
+; BASIC-NEXT:    call void @func_argattr2(i32* [[P2]], i32* [[P3]])
 ; BASIC-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
+; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]) ]
+; BASIC-NEXT:    call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]])
 ; BASIC-NEXT:    ret void
 ;
 ; ALL-LABEL: define {{[^@]+}}@test
@@ -57,12 +61,17 @@ define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
 ; ALL-NEXT:    call void @func_strbool(i32* [[P1]])
 ; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ]
 ; ALL-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
-; ALL-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8), "norecurse"(), "nounwind"(), "willreturn"() ]
+; ALL-NEXT:    call void @llvm.assume(i1 true) [ "norecurse"(), "nounwind"(), "willreturn"() ]
 ; ALL-NEXT:    call void @func_many(i32* align 8 [[P1]])
-; ALL-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P2]], i64 8), "nonnull"(i32* [[P3]]), "nounwind"() ]
+; ALL-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8), "norecurse"(), "nounwind"(), "willreturn"() ]
+; ALL-NEXT:    call void @func_many(i32* noundef align 8 [[P1]])
+; ALL-NEXT:    call void @llvm.assume(i1 true) [ "nounwind"() ]
 ; ALL-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
-; ALL-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]) ]
+; ALL-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]), "nounwind"() ]
+; ALL-NEXT:    call void @func_argattr2(i32* [[P2]], i32* [[P3]])
 ; ALL-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
+; ALL-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]) ]
+; ALL-NEXT:    call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]])
 ; ALL-NEXT:    ret void
 ;
 ; WITH-AC-LABEL: define {{[^@]+}}@test
@@ -79,12 +88,15 @@ define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
 ; WITH-AC-NEXT:    call void @func_strbool(i32* [[P1]])
 ; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ]
 ; WITH-AC-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
-; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8) ]
 ; WITH-AC-NEXT:    call void @func_many(i32* align 8 [[P1]])
-; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P2]], i64 8), "nonnull"(i32* [[P3]]) ]
+; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ]
+; WITH-AC-NEXT:    call void @func_many(i32* noundef align 8 [[P1]])
 ; WITH-AC-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
-; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]) ]
+; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]) ]
+; WITH-AC-NEXT:    call void @func_argattr2(i32* [[P2]], i32* [[P3]])
 ; WITH-AC-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
+; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]) ]
+; WITH-AC-NEXT:    call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]])
 ; WITH-AC-NEXT:    ret void
 ;
 ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test
@@ -101,12 +113,15 @@ define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
 ; CROSS-BLOCK-NEXT:    call void @func_strbool(i32* [[P1]])
 ; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ]
 ; CROSS-BLOCK-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
-; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8) ]
 ; CROSS-BLOCK-NEXT:    call void @func_many(i32* align 8 [[P1]])
-; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P2]], i64 8), "nonnull"(i32* [[P3]]) ]
+; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ]
+; CROSS-BLOCK-NEXT:    call void @func_many(i32* noundef align 8 [[P1]])
 ; CROSS-BLOCK-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
-; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]) ]
+; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]) ]
+; CROSS-BLOCK-NEXT:    call void @func_argattr2(i32* [[P2]], i32* [[P3]])
 ; CROSS-BLOCK-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
+; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]) ]
+; CROSS-BLOCK-NEXT:    call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]])
 ; CROSS-BLOCK-NEXT:    ret void
 ;
 ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test
@@ -121,11 +136,15 @@ define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
 ; FULL-SIMPLIFY-NEXT:    call void @func_strbool(i32* [[P1]])
 ; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ]
 ; FULL-SIMPLIFY-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
-; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8), "align"(i32* [[P2]], i64 8), "nonnull"(i32* [[P3]]) ]
 ; FULL-SIMPLIFY-NEXT:    call void @func_many(i32* align 8 [[P1]])
+; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ]
+; FULL-SIMPLIFY-NEXT:    call void @func_many(i32* noundef align 8 [[P1]])
 ; FULL-SIMPLIFY-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
-; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]) ]
+; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]) ]
+; FULL-SIMPLIFY-NEXT:    call void @func_argattr2(i32* [[P2]], i32* [[P3]])
 ; FULL-SIMPLIFY-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
+; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]) ]
+; FULL-SIMPLIFY-NEXT:    call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]])
 ; FULL-SIMPLIFY-NEXT:    ret void
 ;
   call void @func(i32* nonnull dereferenceable(16) %P, i32* null)
@@ -136,8 +155,11 @@ define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
   call void @func_strbool(i32* %P1)
   call void @func(i32* dereferenceable(32) %P, i32* dereferenceable(8) %P)
   call void @func_many(i32* align 8 %P1)
+  call void @func_many(i32* align 8 noundef %P1)
   call void @func_argattr(i32* %P2, i32* %P3)
+  call void @func_argattr2(i32* %P2, i32* %P3)
   call void @func(i32* nonnull %P1, i32* nonnull %P)
+  call void @func(i32* nonnull noundef %P1, i32* nonnull noundef %P)
   ret void
 }
 

diff  --git a/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp b/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp
index a66e365f237e..913e17f8c774 100644
--- a/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp
+++ b/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp
@@ -71,7 +71,7 @@ TEST(AssumeQueryAPI, hasAttributeInAssume) {
   EnableKnowledgeRetention.setValue(true);
   StringRef Head =
       "declare void @llvm.assume(i1)\n"
-      "declare void @func(i32*, i32*)\n"
+      "declare void @func(i32*, i32*, i32*)\n"
       "declare void @func1(i32*, i32*, i32*, i32*)\n"
       "declare void @func_many(i32*) \"no-jump-tables\" nounwind "
       "\"less-precise-fpmad\" willreturn norecurse\n"
@@ -82,14 +82,16 @@ TEST(AssumeQueryAPI, hasAttributeInAssume) {
       Tests;
   Tests.push_back(std::make_pair(
       "call void @func(i32* nonnull align 4 dereferenceable(16) %P, i32* align "
-      "8 noalias %P1)\n",
+      "8 noalias %P1, i32* align 8 noundef %P2)\n",
       [](Instruction *I) {
         IntrinsicInst *Assume = buildAssumeFromInst(I);
         Assume->insertBefore(I);
         ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(0),
                                        "(nonnull|align|dereferenceable)"));
         ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(1),
-                                       "(align)"));
+                                       "()"));
+        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(2),
+                                       "(align|noundef)"));
         ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),
                                      Attribute::AttrKind::Dereferenceable, 16));
         ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),
@@ -122,12 +124,13 @@ TEST(AssumeQueryAPI, hasAttributeInAssume) {
                                      Attribute::AttrKind::Alignment, 64));
       }));
   Tests.push_back(std::make_pair(
-      "call void @func_many(i32* align 8 %P1) cold\n", [](Instruction *I) {
+      "call void @func_many(i32* align 8 noundef %P1) cold\n", [](Instruction *I) {
         ShouldPreserveAllAttributes.setValue(true);
         IntrinsicInst *Assume = buildAssumeFromInst(I);
         Assume->insertBefore(I);
         ASSERT_TRUE(hasMatchesExactlyAttributes(
-            Assume, nullptr, "(align|nounwind|norecurse|willreturn|cold)"));
+            Assume, nullptr,
+            "(align|nounwind|norecurse|noundef|willreturn|cold)"));
         ShouldPreserveAllAttributes.setValue(false);
       }));
   Tests.push_back(
@@ -199,7 +202,7 @@ TEST(AssumeQueryAPI, hasAttributeInAssume) {
       }));
   Tests.push_back(std::make_pair(
       "call void @func(i32* nonnull align 4 dereferenceable(16) %P, i32* align "
-      "8 noalias %P1)\n",
+      "8 noalias %P1, i32* %P1)\n",
       [](Instruction *I) {
         IntrinsicInst *Assume = buildAssumeFromInst(I);
         Assume->insertBefore(I);
@@ -244,7 +247,7 @@ TEST(AssumeQueryAPI, fillMapFromAssume) {
   EnableKnowledgeRetention.setValue(true);
   StringRef Head =
       "declare void @llvm.assume(i1)\n"
-      "declare void @func(i32*, i32*)\n"
+      "declare void @func(i32*, i32*, i32*)\n"
       "declare void @func1(i32*, i32*, i32*, i32*)\n"
       "declare void @func_many(i32*) \"no-jump-tables\" nounwind "
       "\"less-precise-fpmad\" willreturn norecurse\n"
@@ -255,7 +258,7 @@ TEST(AssumeQueryAPI, fillMapFromAssume) {
       Tests;
   Tests.push_back(std::make_pair(
       "call void @func(i32* nonnull align 4 dereferenceable(16) %P, i32* align "
-      "8 noalias %P1)\n",
+      "8 noalias %P1, i32* align 8 dereferenceable(8) %P2)\n",
       [](Instruction *I) {
         IntrinsicInst *Assume = buildAssumeFromInst(I);
         Assume->insertBefore(I);
@@ -264,8 +267,10 @@ TEST(AssumeQueryAPI, fillMapFromAssume) {
         fillMapFromAssume(*Assume, Map);
         ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(0),
                                        "(nonnull|align|dereferenceable)"));
-        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(1),
+        ASSERT_FALSE(FindExactlyAttributes(Map, I->getOperand(1),
                                        "(align)"));
+        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(2),
+                                       "(align|dereferenceable)"));
         ASSERT_TRUE(MapHasRightValue(
             Map, Assume, {I->getOperand(0), Attribute::Dereferenceable}, {16, 16}));
         ASSERT_TRUE(MapHasRightValue(Map, Assume, {I->getOperand(0), Attribute::Alignment},
@@ -363,7 +368,7 @@ TEST(AssumeQueryAPI, fillMapFromAssume) {
   /// Keep this test last as it modifies the function.
   Tests.push_back(std::make_pair(
       "call void @func(i32* nonnull align 4 dereferenceable(16) %P, i32* align "
-      "8 noalias %P1)\n",
+      "8 noalias %P1, i32* %P2)\n",
       [](Instruction *I) {
         IntrinsicInst *Assume = buildAssumeFromInst(I);
         Assume->insertBefore(I);


        


More information about the llvm-commits mailing list