diff --git a/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp b/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp --- a/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp +++ b/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp @@ -204,8 +204,12 @@ 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 --- 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_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 @@ 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 --- a/llvm/test/Transforms/Util/assume-builder.ll +++ b/llvm/test/Transforms/Util/assume-builder.ll @@ -18,6 +18,7 @@ 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ 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 --- a/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp +++ b/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp @@ -71,7 +71,7 @@ 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 @@ 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 @@ 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 @@ })); 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 @@ 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 @@ 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 @@ 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 @@ /// 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);