1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00

[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
This commit is contained in:
Juneyoung Lee 2021-03-16 09:20:49 +09:00
parent 33c1eeca58
commit 5173305fd6
4 changed files with 82 additions and 38 deletions

View File

@ -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);
};

View File

@ -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
}

View File

@ -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
}

View File

@ -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);