[llvm] [SimplifyCFG][Attributes] Enabling sinking calls with differing number of attrsets (PR #110896)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 2 11:53:33 PDT 2024
https://github.com/goldsteinn updated https://github.com/llvm/llvm-project/pull/110896
>From 7567bda03b4f391a188633adef9248637f844b63 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Wed, 2 Oct 2024 11:34:55 -0500
Subject: [PATCH 1/4] [SimplifyCFG] Add tests for sinking calls with differing
number of attrs; NFC
---
.../SimplifyCFG/sink-cb-diff-attrs.ll | 98 +++++++++++++++----
1 file changed, 79 insertions(+), 19 deletions(-)
diff --git a/llvm/test/Transforms/SimplifyCFG/sink-cb-diff-attrs.ll b/llvm/test/Transforms/SimplifyCFG/sink-cb-diff-attrs.ll
index 1998055ca75f2e..f5f414cc88711c 100644
--- a/llvm/test/Transforms/SimplifyCFG/sink-cb-diff-attrs.ll
+++ b/llvm/test/Transforms/SimplifyCFG/sink-cb-diff-attrs.ll
@@ -1,10 +1,69 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt < %s -passes='simplifycfg<sink-common-insts>' -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
+declare ptr @foo0()
declare ptr @foo(ptr %p, i64 %x)
declare ptr @foo2(ptr %p, ptr %p2, i64 %x)
declare void @side.effect()
+define ptr @test_sink_no_args_oneside(i1 %c) {
+; CHECK-LABEL: define {{[^@]+}}@test_sink_no_args_oneside
+; CHECK-SAME: (i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK: if:
+; CHECK-NEXT: call void @side.effect()
+; CHECK-NEXT: [[R:%.*]] = call ptr @foo0()
+; CHECK-NEXT: br label [[END:%.*]]
+; CHECK: else:
+; CHECK-NEXT: [[R2:%.*]] = call ptr @foo0() #[[ATTR0:[0-9]+]]
+; CHECK-NEXT: br label [[END]]
+; CHECK: end:
+; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
+; CHECK-NEXT: ret ptr [[PR]]
+;
+ br i1 %c, label %if, label %else
+if:
+ call void @side.effect()
+ %r = call ptr @foo0()
+ br label %end
+
+else:
+ %r2 = call ptr @foo0() readonly
+ br label %end
+end:
+ %pr = phi ptr [ %r, %if], [%r2, %else]
+ ret ptr %pr
+}
+
+define ptr @test_sink_no_args_oneside_fail(i1 %c) {
+; CHECK-LABEL: define {{[^@]+}}@test_sink_no_args_oneside_fail
+; CHECK-SAME: (i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK: if:
+; CHECK-NEXT: call void @side.effect()
+; CHECK-NEXT: [[R:%.*]] = call ptr @foo0()
+; CHECK-NEXT: br label [[END:%.*]]
+; CHECK: else:
+; CHECK-NEXT: [[R2:%.*]] = call ptr @foo0() #[[ATTR1:[0-9]+]]
+; CHECK-NEXT: br label [[END]]
+; CHECK: end:
+; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
+; CHECK-NEXT: ret ptr [[PR]]
+;
+ br i1 %c, label %if, label %else
+if:
+ call void @side.effect()
+ %r = call ptr @foo0()
+ br label %end
+
+else:
+ %r2 = call ptr @foo0() readonly alwaysinline
+ br label %end
+end:
+ %pr = phi ptr [ %r, %if], [%r2, %else]
+ ret ptr %pr
+}
+
define ptr @test_sink_int_attrs(i1 %c, ptr %p, ptr %p2, i64 %x) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_int_attrs
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], ptr [[P2:%.*]], i64 [[X:%.*]]) {
@@ -13,7 +72,7 @@ define ptr @test_sink_int_attrs(i1 %c, ptr %p, ptr %p2, i64 %x) {
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
-; CHECK-NEXT: [[R2:%.*]] = call ptr @foo2(ptr align 32 dereferenceable_or_null(100) [[P]], ptr align 32 dereferenceable(50) [[P2]], i64 range(i64 10, 100000) [[X]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT: [[R2:%.*]] = call ptr @foo2(ptr align 32 dereferenceable_or_null(100) [[P]], ptr align 32 dereferenceable(50) [[P2]], i64 range(i64 10, 100000) [[X]]) #[[ATTR2:[0-9]+]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
@@ -38,7 +97,7 @@ define ptr @test_sink_int_attrs2(i1 %c, ptr %p, i64 %x) {
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
-; CHECK-NEXT: [[R2:%.*]] = call ptr @foo(ptr dereferenceable(50) [[P]], i64 range(i64 10, 1000) [[X]]) #[[ATTR1:[0-9]+]]
+; CHECK-NEXT: [[R2:%.*]] = call ptr @foo(ptr dereferenceable(50) [[P]], i64 range(i64 10, 1000) [[X]]) #[[ATTR0]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
@@ -63,7 +122,7 @@ define ptr @test_sink_bool_attrs2(i1 %c, ptr %p, i64 %x) {
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
-; CHECK-NEXT: [[R2:%.*]] = call noundef ptr @foo(ptr nonnull [[P]], i64 noundef [[X]]) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT: [[R2:%.*]] = call noundef ptr @foo(ptr nonnull [[P]], i64 noundef [[X]]) #[[ATTR3:[0-9]+]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
@@ -88,7 +147,7 @@ define ptr @test_sink_bool_attrs3(i1 %c, ptr %p, i64 %x) {
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
-; CHECK-NEXT: [[R2:%.*]] = call nonnull ptr @foo(ptr [[P]], i64 noundef [[X]]) #[[ATTR3:[0-9]+]]
+; CHECK-NEXT: [[R2:%.*]] = call nonnull ptr @foo(ptr [[P]], i64 noundef [[X]]) #[[ATTR4:[0-9]+]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
@@ -111,10 +170,10 @@ define ptr @test_sink_bool_attrs_fail_non_droppable(i1 %c, ptr %p, i64 %x) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
-; CHECK-NEXT: [[R:%.*]] = call nonnull ptr @foo(ptr noundef readonly [[P]], i64 noundef [[X]]) #[[ATTR4:[0-9]+]]
+; CHECK-NEXT: [[R:%.*]] = call nonnull ptr @foo(ptr noundef readonly [[P]], i64 noundef [[X]]) #[[ATTR5:[0-9]+]]
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: else:
-; CHECK-NEXT: [[R2:%.*]] = call noundef nonnull ptr @foo(ptr nonnull writeonly [[P]], i64 noundef [[X]]) #[[ATTR5:[0-9]+]]
+; CHECK-NEXT: [[R2:%.*]] = call noundef nonnull ptr @foo(ptr nonnull writeonly [[P]], i64 noundef [[X]]) #[[ATTR6:[0-9]+]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
@@ -140,10 +199,10 @@ define ptr @test_sink_bool_attrs_fail_non_droppable2(i1 %c, ptr %p, i64 %x) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
-; CHECK-NEXT: [[R:%.*]] = call nonnull ptr @foo(ptr noundef readonly [[P]], i64 noundef [[X]]) #[[ATTR6:[0-9]+]]
+; CHECK-NEXT: [[R:%.*]] = call nonnull ptr @foo(ptr noundef readonly [[P]], i64 noundef [[X]]) #[[ATTR7:[0-9]+]]
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: else:
-; CHECK-NEXT: [[R2:%.*]] = call noundef nonnull ptr @foo(ptr nonnull writeonly byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR5]]
+; CHECK-NEXT: [[R2:%.*]] = call noundef nonnull ptr @foo(ptr nonnull writeonly byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR6]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
@@ -169,10 +228,10 @@ define ptr @test_sink_bool_attrs_fail_non_droppable3(i1 %c, ptr %p, i64 %x) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
-; CHECK-NEXT: [[R:%.*]] = call nonnull ptr @foo(ptr noundef readonly byval(i32) [[P]], i64 noundef [[X]]) #[[ATTR6]]
+; CHECK-NEXT: [[R:%.*]] = call nonnull ptr @foo(ptr noundef readonly byval(i32) [[P]], i64 noundef [[X]]) #[[ATTR7]]
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: else:
-; CHECK-NEXT: [[R2:%.*]] = call noundef nonnull ptr @foo(ptr nonnull writeonly byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR7:[0-9]+]]
+; CHECK-NEXT: [[R2:%.*]] = call noundef nonnull ptr @foo(ptr nonnull writeonly byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR8:[0-9]+]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
@@ -200,7 +259,7 @@ define ptr @test_sink_bool_attrs4(i1 %c, ptr %p, i64 %x) {
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
-; CHECK-NEXT: [[R2:%.*]] = call nonnull ptr @foo(ptr byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR7]]
+; CHECK-NEXT: [[R2:%.*]] = call nonnull ptr @foo(ptr byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR8]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
@@ -218,12 +277,13 @@ end:
}
;.
-; CHECK: attributes #[[ATTR0]] = { memory(readwrite) }
-; CHECK: attributes #[[ATTR1]] = { memory(read) }
-; CHECK: attributes #[[ATTR2]] = { mustprogress nocallback nofree willreturn }
-; CHECK: attributes #[[ATTR3]] = { alwaysinline nosync willreturn }
-; CHECK: attributes #[[ATTR4]] = { alwaysinline cold nocallback nofree nosync willreturn }
-; CHECK: attributes #[[ATTR5]] = { nosync willreturn }
-; CHECK: attributes #[[ATTR6]] = { cold nocallback nofree nosync willreturn }
-; CHECK: attributes #[[ATTR7]] = { nosync }
+; CHECK: attributes #[[ATTR0]] = { memory(read) }
+; CHECK: attributes #[[ATTR1]] = { alwaysinline memory(read) }
+; CHECK: attributes #[[ATTR2]] = { memory(readwrite) }
+; CHECK: attributes #[[ATTR3]] = { mustprogress nocallback nofree willreturn }
+; CHECK: attributes #[[ATTR4]] = { alwaysinline nosync willreturn }
+; CHECK: attributes #[[ATTR5]] = { alwaysinline cold nocallback nofree nosync willreturn }
+; CHECK: attributes #[[ATTR6]] = { nosync willreturn }
+; CHECK: attributes #[[ATTR7]] = { cold nocallback nofree nosync willreturn }
+; CHECK: attributes #[[ATTR8]] = { nosync }
;.
>From b15106ce5f0a4d25dc7412dd78744cefa0f01768 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Wed, 2 Oct 2024 11:35:03 -0500
Subject: [PATCH 2/4] [SimplifyCFG][Attributes] Enabling sinking calls with
differing number of attrsets
Prior impl would fail if the number of attribute sets on the two calls
wasn't the same which is unnecessary as long as we aren't throwing
away and must-preserve attrs.
---
llvm/lib/IR/Attributes.cpp | 21 ++++++++++++------
llvm/lib/IR/Instruction.cpp | 3 ++-
.../SimplifyCFG/sink-cb-diff-attrs.ll | 22 ++++++++-----------
llvm/unittests/IR/AttributesTest.cpp | 21 +++++++++++++++---
4 files changed, 43 insertions(+), 24 deletions(-)
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index c5874c58c0ecae..9f0f2d983dd74c 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -1800,14 +1801,20 @@ AttributeList::intersectWith(LLVMContext &C, AttributeList Other) const {
if (*this == Other)
return *this;
- // At least for now, only intersect lists with same number of params.
- if (getNumAttrSets() != Other.getNumAttrSets())
- return std::nullopt;
-
SmallVector<std::pair<unsigned, AttributeSet>> IntersectedAttrs;
- for (unsigned Idx : indexes()) {
- auto IntersectedAS =
- getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
+ SmallSet<unsigned, 8> AllIndexes{};
+ AllIndexes.insert(indexes().begin(), indexes().end());
+ AllIndexes.insert(Other.indexes().begin(), Other.indexes().end());
+
+ for (unsigned Idx : AllIndexes) {
+ AttributeSet ThisSet = {};
+ AttributeSet OtherSet = {};
+ if (hasAttributesAtIndex(Idx))
+ ThisSet = getAttributes(Idx);
+ if (Other.hasAttributesAtIndex(Idx))
+ OtherSet = Other.getAttributes(Idx);
+
+ auto IntersectedAS = ThisSet.intersectWith(C, OtherSet);
// If any index fails to intersect, fail.
if (!IntersectedAS)
return std::nullopt;
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index b84e62d2e43b7e..eec751078698b2 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -875,7 +875,8 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I,
// If both instructions have no operands, they are identical.
if (getNumOperands() == 0 && I->getNumOperands() == 0)
- return this->hasSameSpecialState(I);
+ return this->hasSameSpecialState(I, /*IgnoreAlignment=*/false,
+ IntersectAttrs);
// We have two instructions of identical opcode and #operands. Check to see
// if all operands are the same.
diff --git a/llvm/test/Transforms/SimplifyCFG/sink-cb-diff-attrs.ll b/llvm/test/Transforms/SimplifyCFG/sink-cb-diff-attrs.ll
index f5f414cc88711c..fe9d87080dd111 100644
--- a/llvm/test/Transforms/SimplifyCFG/sink-cb-diff-attrs.ll
+++ b/llvm/test/Transforms/SimplifyCFG/sink-cb-diff-attrs.ll
@@ -9,17 +9,13 @@ declare void @side.effect()
define ptr @test_sink_no_args_oneside(i1 %c) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_no_args_oneside
; CHECK-SAME: (i1 [[C:%.*]]) {
-; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[END:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
-; CHECK-NEXT: [[R:%.*]] = call ptr @foo0()
-; CHECK-NEXT: br label [[END:%.*]]
-; CHECK: else:
-; CHECK-NEXT: [[R2:%.*]] = call ptr @foo0() #[[ATTR0:[0-9]+]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
-; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
-; CHECK-NEXT: ret ptr [[PR]]
+; CHECK-NEXT: [[R2:%.*]] = call ptr @foo0()
+; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
if:
@@ -44,7 +40,7 @@ define ptr @test_sink_no_args_oneside_fail(i1 %c) {
; CHECK-NEXT: [[R:%.*]] = call ptr @foo0()
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: else:
-; CHECK-NEXT: [[R2:%.*]] = call ptr @foo0() #[[ATTR1:[0-9]+]]
+; CHECK-NEXT: [[R2:%.*]] = call ptr @foo0() #[[ATTR0:[0-9]+]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
@@ -72,7 +68,7 @@ define ptr @test_sink_int_attrs(i1 %c, ptr %p, ptr %p2, i64 %x) {
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
-; CHECK-NEXT: [[R2:%.*]] = call ptr @foo2(ptr align 32 dereferenceable_or_null(100) [[P]], ptr align 32 dereferenceable(50) [[P2]], i64 range(i64 10, 100000) [[X]]) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT: [[R2:%.*]] = call ptr @foo2(ptr align 32 dereferenceable_or_null(100) [[P]], ptr align 32 dereferenceable(50) [[P2]], i64 range(i64 10, 100000) [[X]]) #[[ATTR1:[0-9]+]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
@@ -97,7 +93,7 @@ define ptr @test_sink_int_attrs2(i1 %c, ptr %p, i64 %x) {
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
-; CHECK-NEXT: [[R2:%.*]] = call ptr @foo(ptr dereferenceable(50) [[P]], i64 range(i64 10, 1000) [[X]]) #[[ATTR0]]
+; CHECK-NEXT: [[R2:%.*]] = call ptr @foo(ptr dereferenceable(50) [[P]], i64 range(i64 10, 1000) [[X]]) #[[ATTR2:[0-9]+]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
@@ -277,9 +273,9 @@ end:
}
;.
-; CHECK: attributes #[[ATTR0]] = { memory(read) }
-; CHECK: attributes #[[ATTR1]] = { alwaysinline memory(read) }
-; CHECK: attributes #[[ATTR2]] = { memory(readwrite) }
+; CHECK: attributes #[[ATTR0]] = { alwaysinline memory(read) }
+; CHECK: attributes #[[ATTR1]] = { memory(readwrite) }
+; CHECK: attributes #[[ATTR2]] = { memory(read) }
; CHECK: attributes #[[ATTR3]] = { mustprogress nocallback nofree willreturn }
; CHECK: attributes #[[ATTR4]] = { alwaysinline nosync willreturn }
; CHECK: attributes #[[ATTR5]] = { alwaysinline cold nocallback nofree nosync willreturn }
diff --git a/llvm/unittests/IR/AttributesTest.cpp b/llvm/unittests/IR/AttributesTest.cpp
index 0fdb5a9c5a6886..316d7db924d05f 100644
--- a/llvm/unittests/IR/AttributesTest.cpp
+++ b/llvm/unittests/IR/AttributesTest.cpp
@@ -610,11 +610,16 @@ TEST(Attributes, ListIntersect) {
AL0 = AL0.addParamAttribute(C, 1, Attribute::NoUndef);
Res = AL0.intersectWith(C, AL1);
- ASSERT_FALSE(Res.has_value());
+ ASSERT_TRUE(Res.has_value());
+ ASSERT_TRUE(Res->hasRetAttr(Attribute::NoUndef));
+ ASSERT_FALSE(Res->hasParamAttr(1, Attribute::NoUndef));
AL1 = AL1.addParamAttribute(C, 2, Attribute::NoUndef);
Res = AL0.intersectWith(C, AL1);
- ASSERT_FALSE(Res.has_value());
+ ASSERT_TRUE(Res.has_value());
+ ASSERT_TRUE(Res->hasRetAttr(Attribute::NoUndef));
+ ASSERT_FALSE(Res->hasParamAttr(1, Attribute::NoUndef));
+ ASSERT_FALSE(Res->hasParamAttr(2, Attribute::NoUndef));
AL0 = AL0.addParamAttribute(C, 2, Attribute::NoUndef);
AL1 = AL1.addParamAttribute(C, 1, Attribute::NoUndef);
@@ -692,7 +697,17 @@ TEST(Attributes, ListIntersect) {
AL1 = AL1.addParamAttribute(C, 3, Attribute::ReadNone);
Res = AL0.intersectWith(C, AL1);
- ASSERT_FALSE(Res.has_value());
+ ASSERT_TRUE(Res.has_value());
+ ASSERT_TRUE(Res.has_value());
+ ASSERT_TRUE(Res->hasFnAttr(Attribute::AlwaysInline));
+ ASSERT_TRUE(Res->hasFnAttr(Attribute::ReadOnly));
+ ASSERT_TRUE(Res->hasRetAttr(Attribute::NoUndef));
+ ASSERT_FALSE(Res->hasRetAttr(Attribute::NonNull));
+ ASSERT_TRUE(Res->hasParamAttr(1, Attribute::NoUndef));
+ ASSERT_TRUE(Res->hasParamAttr(2, Attribute::NoUndef));
+ ASSERT_FALSE(Res->hasParamAttr(2, Attribute::NonNull));
+ ASSERT_FALSE(Res->hasParamAttr(2, Attribute::ReadNone));
+ ASSERT_FALSE(Res->hasParamAttr(3, Attribute::ReadNone));
AL0 = AL0.addParamAttribute(C, 3, Attribute::ReadNone);
Res = AL0.intersectWith(C, AL1);
>From ebc4a921d493c86da8401fe92b5db4ef420113e1 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Wed, 2 Oct 2024 13:01:45 -0500
Subject: [PATCH 3/4] Cleaner + Another Test
---
llvm/lib/IR/Attributes.cpp | 18 +++++-------------
llvm/unittests/IR/AttributesTest.cpp | 26 ++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 9f0f2d983dd74c..63dfdacbcd169c 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -1802,19 +1802,11 @@ AttributeList::intersectWith(LLVMContext &C, AttributeList Other) const {
return *this;
SmallVector<std::pair<unsigned, AttributeSet>> IntersectedAttrs;
- SmallSet<unsigned, 8> AllIndexes{};
- AllIndexes.insert(indexes().begin(), indexes().end());
- AllIndexes.insert(Other.indexes().begin(), Other.indexes().end());
-
- for (unsigned Idx : AllIndexes) {
- AttributeSet ThisSet = {};
- AttributeSet OtherSet = {};
- if (hasAttributesAtIndex(Idx))
- ThisSet = getAttributes(Idx);
- if (Other.hasAttributesAtIndex(Idx))
- OtherSet = Other.getAttributes(Idx);
-
- auto IntersectedAS = ThisSet.intersectWith(C, OtherSet);
+ auto IndexIt = index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
+ for (unsigned Idx : IndexIt) {
+ fprintf(stderr, "Checking Idx: %u\n", Idx);
+ auto IntersectedAS =
+ getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
// If any index fails to intersect, fail.
if (!IntersectedAS)
return std::nullopt;
diff --git a/llvm/unittests/IR/AttributesTest.cpp b/llvm/unittests/IR/AttributesTest.cpp
index 316d7db924d05f..a627bddd64a3e3 100644
--- a/llvm/unittests/IR/AttributesTest.cpp
+++ b/llvm/unittests/IR/AttributesTest.cpp
@@ -596,6 +596,32 @@ TEST(Attributes, SetIntersectByValAlign) {
}
}
+TEST(Attributes, ListIntersectDifferingMustPreserve) {
+ LLVMContext C;
+ fprintf(stderr, "Starting Test!\n");
+ std::optional<AttributeList> Res;
+ {
+ AttributeList AL0;
+ AttributeList AL1;
+ AL1 = AL1.addFnAttribute(C, Attribute::ReadOnly);
+ AL0 = AL0.addParamAttribute(C, 0, Attribute::SExt);
+ Res = AL0.intersectWith(C, AL1);
+ ASSERT_FALSE(Res.has_value());
+ Res = AL1.intersectWith(C, AL0);
+ ASSERT_FALSE(Res.has_value());
+ }
+ {
+ AttributeList AL0;
+ AttributeList AL1;
+ AL1 = AL1.addFnAttribute(C, Attribute::AlwaysInline);
+ AL0 = AL0.addParamAttribute(C, 0, Attribute::ReadOnly);
+ Res = AL0.intersectWith(C, AL1);
+ ASSERT_FALSE(Res.has_value());
+ Res = AL1.intersectWith(C, AL0);
+ ASSERT_FALSE(Res.has_value());
+ }
+}
+
TEST(Attributes, ListIntersect) {
LLVMContext C;
AttributeList AL0;
>From bdbc0eeb4f7567ea0e907d7d050cd9a1dc54e65a Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Wed, 2 Oct 2024 13:53:18 -0500
Subject: [PATCH 4/4] Fix fmt + 1 more test
---
llvm/lib/IR/Attributes.cpp | 4 ++--
llvm/unittests/IR/AttributesTest.cpp | 8 +++++++-
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 63dfdacbcd169c..0fe213e95e50a9 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -1802,9 +1802,9 @@ AttributeList::intersectWith(LLVMContext &C, AttributeList Other) const {
return *this;
SmallVector<std::pair<unsigned, AttributeSet>> IntersectedAttrs;
- auto IndexIt = index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
+ auto IndexIt =
+ index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
for (unsigned Idx : IndexIt) {
- fprintf(stderr, "Checking Idx: %u\n", Idx);
auto IntersectedAS =
getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
// If any index fails to intersect, fail.
diff --git a/llvm/unittests/IR/AttributesTest.cpp b/llvm/unittests/IR/AttributesTest.cpp
index a627bddd64a3e3..f73f2b20e9fea5 100644
--- a/llvm/unittests/IR/AttributesTest.cpp
+++ b/llvm/unittests/IR/AttributesTest.cpp
@@ -598,7 +598,6 @@ TEST(Attributes, SetIntersectByValAlign) {
TEST(Attributes, ListIntersectDifferingMustPreserve) {
LLVMContext C;
- fprintf(stderr, "Starting Test!\n");
std::optional<AttributeList> Res;
{
AttributeList AL0;
@@ -619,6 +618,13 @@ TEST(Attributes, ListIntersectDifferingMustPreserve) {
ASSERT_FALSE(Res.has_value());
Res = AL1.intersectWith(C, AL0);
ASSERT_FALSE(Res.has_value());
+
+ AL0 = AL0.addFnAttribute(C, Attribute::AlwaysInline);
+ AL1 = AL1.addParamAttribute(C, 1, Attribute::SExt);
+ Res = AL0.intersectWith(C, AL1);
+ ASSERT_FALSE(Res.has_value());
+ Res = AL1.intersectWith(C, AL0);
+ ASSERT_FALSE(Res.has_value());
}
}
More information about the llvm-commits
mailing list