Skip to content

Commit 2fbda15

Browse files
committed
[EarlyCSE] De-Duplicate callsites with differing attrs
We only do this if the attributes of the two callsites are compatible (intersectable) which is probably not in fact necessary.
1 parent 2cf7c3a commit 2fbda15

File tree

4 files changed

+35
-19
lines changed

4 files changed

+35
-19
lines changed

llvm/include/llvm/IR/Instruction.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,8 @@ class Instruction : public User,
876876
/// Return true if the specified instruction is exactly identical to the
877877
/// current one. This means that all operands match and any extra information
878878
/// (e.g. load is volatile) agree.
879-
bool isIdenticalTo(const Instruction *I) const LLVM_READONLY;
879+
bool isIdenticalTo(const Instruction *I,
880+
bool IntersectAttrs = false) const LLVM_READONLY;
880881

881882
/// This is like isIdenticalTo, except that it ignores the
882883
/// SubclassOptionalData flags, which may specify conditions under which the

llvm/lib/IR/Instruction.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -862,8 +862,9 @@ bool Instruction::hasSameSpecialState(const Instruction *I2,
862862
return true;
863863
}
864864

865-
bool Instruction::isIdenticalTo(const Instruction *I) const {
866-
return isIdenticalToWhenDefined(I) &&
865+
bool Instruction::isIdenticalTo(const Instruction *I,
866+
bool IntersectAttrs) const {
867+
return isIdenticalToWhenDefined(I, IntersectAttrs) &&
867868
SubclassOptionalData == I->SubclassOptionalData;
868869
}
869870

llvm/lib/Transforms/Scalar/EarlyCSE.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ static bool isEqualImpl(SimpleValue LHS, SimpleValue RHS) {
362362

363363
if (LHSI->getOpcode() != RHSI->getOpcode())
364364
return false;
365-
if (LHSI->isIdenticalToWhenDefined(RHSI)) {
365+
if (LHSI->isIdenticalToWhenDefined(RHSI, /*IntersectAttrs=*/true)) {
366366
// Convergent calls implicitly depend on the set of threads that is
367367
// currently executing, so conservatively return false if they are in
368368
// different basic blocks.
@@ -551,7 +551,7 @@ bool DenseMapInfo<CallValue>::isEqual(CallValue LHS, CallValue RHS) {
551551
if (LHSI->isConvergent() && LHSI->getParent() != RHSI->getParent())
552552
return false;
553553

554-
return LHSI->isIdenticalTo(RHSI);
554+
return LHSI->isIdenticalTo(RHSI, /*IntersectAttrs=*/true);
555555
}
556556

557557
//===----------------------------------------------------------------------===//
@@ -1534,6 +1534,13 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
15341534
LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
15351535
continue;
15361536
}
1537+
if (auto *CB = dyn_cast<CallBase>(V)) {
1538+
bool Success = CB->tryIntersectAttributes(cast<CallBase>(&Inst));
1539+
assert(Success && "Failed to intersect attributes in callsites that "
1540+
"passed identical check");
1541+
// For NDEBUG Compile.
1542+
(void)Success;
1543+
}
15371544
combineIRFlags(Inst, V);
15381545
Inst.replaceAllUsesWith(V);
15391546
salvageKnowledge(&Inst, &AC);
@@ -1632,6 +1639,18 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
16321639
LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
16331640
continue;
16341641
}
1642+
// We probably don't need a complete itersection of attrs between
1643+
// InVal.first and Inst.
1644+
// We only CSE readonly functions that have the same memory state and
1645+
// its not clear that any non-return *callsite* attribute can create
1646+
// side-effects. Likewise this implies when checking equality of
1647+
// callsite for CSEing, we can probably ignore all non-return attrs.
1648+
bool Success = cast<CallBase>(InVal.first)
1649+
->tryIntersectAttributes(cast<CallBase>(&Inst));
1650+
assert(Success && "Failed to intersect attributes in callsites that "
1651+
"passed identical check");
1652+
// For NDEBUG Compile.
1653+
(void)Success;
16351654
if (!Inst.use_empty())
16361655
Inst.replaceAllUsesWith(InVal.first);
16371656
salvageKnowledge(&Inst, &AC);

llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ declare i8 @buz.ptr(ptr, ptr)
1010
define i8 @same_parent_combine_diff_attrs(i8 %x, i8 %y) {
1111
; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs(
1212
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
13-
; CHECK-NEXT: [[C2:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR0:[0-9]+]]
14-
; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
15-
; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C1]], i8 [[C2]])
13+
; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0:[0-9]+]]
14+
; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C1]], i8 [[C1]])
1615
; CHECK-NEXT: ret i8 [[R]]
1716
;
1817
%c1 = call i8 @baz(i8 noundef %x, i8 noundef %y) readnone
@@ -25,9 +24,8 @@ define i8 @same_parent_combine_diff_attrs(i8 %x, i8 %y) {
2524
define i8 @same_parent_combine_diff_attrs_needs_intersect(i8 %x, i8 %y) {
2625
; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_needs_intersect(
2726
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
28-
; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR0]]
29-
; CHECK-NEXT: [[C0:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
30-
; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr [[C1]])
27+
; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
28+
; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr [[C1]])
3129
; CHECK-NEXT: ret i8 [[R]]
3230
;
3331
%c1 = call nonnull ptr @baz.ptr(i8 noundef %x, i8 noundef %y) readnone
@@ -40,9 +38,8 @@ define i8 @same_parent_combine_diff_attrs_needs_intersect(i8 %x, i8 %y) {
4038
define i8 @same_parent_combine_diff_attrs_needs_intersect2(i8 %x, i8 %y) {
4139
; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_needs_intersect2(
4240
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
43-
; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1:[0-9]+]]
44-
; CHECK-NEXT: [[C0:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
45-
; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr [[C1]])
41+
; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1:[0-9]+]]
42+
; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr [[C1]])
4643
; CHECK-NEXT: ret i8 [[R]]
4744
;
4845
%c1 = call nonnull ptr @baz.ptr(i8 noundef %x, i8 noundef %y) readonly
@@ -55,9 +52,8 @@ define i8 @same_parent_combine_diff_attrs_needs_intersect2(i8 %x, i8 %y) {
5552
define i8 @same_parent_combine_diff_attrs_really_needs_intersect(i8 %x, i8 %y) {
5653
; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_really_needs_intersect(
5754
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
58-
; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1]]
59-
; CHECK-NEXT: [[C0:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
60-
; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr noundef [[C1]])
55+
; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
56+
; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr noundef [[C1]])
6157
; CHECK-NEXT: ret i8 [[R]]
6258
;
6359
%c1 = call nonnull ptr @baz.ptr(i8 noundef %x, i8 noundef %y) readonly
@@ -128,8 +124,7 @@ define i8 @diff_parent_combine_diff_attrs_preserves_return_attrs(i1 %c, i8 %x, i
128124
; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
129125
; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
130126
; CHECK: [[T]]:
131-
; CHECK-NEXT: [[C0:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1]]
132-
; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr noundef [[C1]])
127+
; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr noundef [[C1]])
133128
; CHECK-NEXT: ret i8 [[R]]
134129
; CHECK: [[F]]:
135130
; CHECK-NEXT: ret i8 9

0 commit comments

Comments
 (0)