[llvm] e343af7 - [SimplifyCFG][Attributes] Enabling sinking calls with differing number of attrsets
Noah Goldstein via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 2 13:15:22 PDT 2024
Author: Noah Goldstein
Date: 2024-10-02T15:15:07-05:00
New Revision: e343af777ef51c4496e7fb2689735866bc617897
URL: https://github.com/llvm/llvm-project/commit/e343af777ef51c4496e7fb2689735866bc617897
DIFF: https://github.com/llvm/llvm-project/commit/e343af777ef51c4496e7fb2689735866bc617897.diff
LOG: [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.
Closes #110896
Added:
Modified:
llvm/lib/IR/Attributes.cpp
llvm/lib/IR/Instruction.cpp
llvm/test/Transforms/SimplifyCFG/sink-cb-diff-attrs.ll
llvm/unittests/IR/AttributesTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index c5874c58c0ecae..f2ba61ae51039e 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -1800,12 +1800,10 @@ 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 IndexIt =
+ index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
+ for (unsigned Idx : IndexIt) {
auto IntersectedAS =
getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
// If any index fails to intersect, fail.
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..f73f2b20e9fea5 100644
--- a/llvm/unittests/IR/AttributesTest.cpp
+++ b/llvm/unittests/IR/AttributesTest.cpp
@@ -596,6 +596,38 @@ TEST(Attributes, SetIntersectByValAlign) {
}
}
+TEST(Attributes, ListIntersectDifferingMustPreserve) {
+ LLVMContext C;
+ 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());
+
+ 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());
+ }
+}
+
TEST(Attributes, ListIntersect) {
LLVMContext C;
AttributeList AL0;
@@ -610,11 +642,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 +729,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);
More information about the llvm-commits
mailing list