Skip to content

Commit 0741dec

Browse files
committed
[Attributor][FIX] Handle droppable uses when replacing values
Since we use the fact that some uses are droppable in the Attributor we need to handle them explicitly when we replace uses. As an example, an assumed dead value can have live droppable users. In those we cannot replace the value simply by an undef. Instead, we either drop the uses (via `dropDroppableUses`) or keep them as they are. In this patch we do both, depending on the situation. For values that are dead but not necessarily removed we keep droppable uses around because they contain information we might be able to use later. For values that are removed we drop droppable uses explicitly to avoid replacement with undef.
1 parent ea7f17e commit 0741dec

File tree

5 files changed

+19
-10
lines changed

5 files changed

+19
-10
lines changed

llvm/include/llvm/Transforms/IPO/Attributor.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -875,11 +875,14 @@ struct Attributor {
875875
}
876876

877877
/// Helper function to replace all uses of \p V with \p NV. Return true if
878-
/// there is any change.
879-
bool changeValueAfterManifest(Value &V, Value &NV) {
878+
/// there is any change. The flag \p ChangeDroppable indicates if dropppable
879+
/// uses should be changed too.
880+
bool changeValueAfterManifest(Value &V, Value &NV,
881+
bool ChangeDroppable = true) {
880882
bool Changed = false;
881883
for (auto &U : V.uses())
882-
Changed |= changeUseAfterManifest(U, NV);
884+
if (ChangeDroppable || !U.getUser()->isDroppable())
885+
Changed |= changeUseAfterManifest(U, NV);
883886

884887
return Changed;
885888
}

llvm/lib/Transforms/IPO/Attributor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,7 @@ ChangeStatus Attributor::run() {
11691169

11701170
for (auto &V : ToBeDeletedInsts) {
11711171
if (Instruction *I = dyn_cast_or_null<Instruction>(V)) {
1172+
I->dropDroppableUses();
11721173
CGModifiedFunctions.insert(I->getFunction());
11731174
if (!I->getType()->isVoidTy())
11741175
I->replaceAllUsesWith(UndefValue::get(I->getType()));

llvm/lib/Transforms/IPO/AttributorAttributes.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2675,8 +2675,11 @@ struct AAIsDeadFloating : public AAIsDeadValueImpl {
26752675
if (C.hasValue() && C.getValue())
26762676
return ChangeStatus::UNCHANGED;
26772677

2678+
// Replace the value with undef as it is dead but keep droppable uses around
2679+
// as they provide information we don't want to give up on just yet.
26782680
UndefValue &UV = *UndefValue::get(V.getType());
2679-
bool AnyChange = A.changeValueAfterManifest(V, UV);
2681+
bool AnyChange =
2682+
A.changeValueAfterManifest(V, UV, /* ChangeDropppable */ false);
26802683
return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
26812684
}
26822685

@@ -2703,8 +2706,10 @@ struct AAIsDeadArgument : public AAIsDeadFloating {
27032706
if (A.registerFunctionSignatureRewrite(
27042707
Arg, /* ReplacementTypes */ {},
27052708
Attributor::ArgumentReplacementInfo::CalleeRepairCBTy{},
2706-
Attributor::ArgumentReplacementInfo::ACSRepairCBTy{}))
2709+
Attributor::ArgumentReplacementInfo::ACSRepairCBTy{})) {
2710+
Arg.dropDroppableUses();
27072711
return ChangeStatus::CHANGED;
2712+
}
27082713
return Changed;
27092714
}
27102715

llvm/test/Transforms/Attributor/dereferenceable-1.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -623,19 +623,19 @@ define void @nonnull_assume_pos(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) {
623623
;
624624
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@nonnull_assume_pos
625625
; IS__TUNIT_OPM-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(101) [[ARG1:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(31) [[ARG2:%.*]], i8* nocapture nofree nonnull readnone [[ARG3:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(42) [[ARG4:%.*]])
626-
; IS__TUNIT_OPM-NEXT: call void @llvm.assume(i1 true) #6 [ "nonnull"(i8* undef), "dereferenceable"(i8* undef, i64 1), "dereferenceable"(i8* undef, i64 2), "dereferenceable"(i8* undef, i64 101), "dereferenceable_or_null"(i8* undef, i64 31), "dereferenceable_or_null"(i8* undef, i64 42) ]
626+
; IS__TUNIT_OPM-NEXT: call void @llvm.assume(i1 true) #6 [ "nonnull"(i8* [[ARG3]]), "dereferenceable"(i8* [[ARG1]], i64 1), "dereferenceable"(i8* [[ARG1]], i64 2), "dereferenceable"(i8* [[ARG1]], i64 101), "dereferenceable_or_null"(i8* [[ARG2]], i64 31), "dereferenceable_or_null"(i8* [[ARG4]], i64 42) ]
627627
; IS__TUNIT_OPM-NEXT: call void @unknown()
628628
; IS__TUNIT_OPM-NEXT: ret void
629629
;
630630
; IS________NPM-LABEL: define {{[^@]+}}@nonnull_assume_pos
631631
; IS________NPM-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(101) [[ARG1:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(31) [[ARG2:%.*]], i8* nocapture nofree nonnull readnone [[ARG3:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(42) [[ARG4:%.*]])
632-
; IS________NPM-NEXT: call void @llvm.assume(i1 true) #7 [ "nonnull"(i8* undef), "dereferenceable"(i8* undef, i64 1), "dereferenceable"(i8* undef, i64 2), "dereferenceable"(i8* undef, i64 101), "dereferenceable_or_null"(i8* undef, i64 31), "dereferenceable_or_null"(i8* undef, i64 42) ]
632+
; IS________NPM-NEXT: call void @llvm.assume(i1 true) #7 [ "nonnull"(i8* [[ARG3]]), "dereferenceable"(i8* [[ARG1]], i64 1), "dereferenceable"(i8* [[ARG1]], i64 2), "dereferenceable"(i8* [[ARG1]], i64 101), "dereferenceable_or_null"(i8* [[ARG2]], i64 31), "dereferenceable_or_null"(i8* [[ARG4]], i64 42) ]
633633
; IS________NPM-NEXT: call void @unknown()
634634
; IS________NPM-NEXT: ret void
635635
;
636636
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@nonnull_assume_pos
637637
; IS__CGSCC_OPM-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(101) [[ARG1:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(31) [[ARG2:%.*]], i8* nocapture nofree nonnull readnone [[ARG3:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(42) [[ARG4:%.*]])
638-
; IS__CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #8 [ "nonnull"(i8* undef), "dereferenceable"(i8* undef, i64 1), "dereferenceable"(i8* undef, i64 2), "dereferenceable"(i8* undef, i64 101), "dereferenceable_or_null"(i8* undef, i64 31), "dereferenceable_or_null"(i8* undef, i64 42) ]
638+
; IS__CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #8 [ "nonnull"(i8* [[ARG3]]), "dereferenceable"(i8* [[ARG1]], i64 1), "dereferenceable"(i8* [[ARG1]], i64 2), "dereferenceable"(i8* [[ARG1]], i64 101), "dereferenceable_or_null"(i8* [[ARG2]], i64 31), "dereferenceable_or_null"(i8* [[ARG4]], i64 42) ]
639639
; IS__CGSCC_OPM-NEXT: call void @unknown()
640640
; IS__CGSCC_OPM-NEXT: ret void
641641
;
@@ -653,7 +653,7 @@ define void @nonnull_assume_neg(i8* %arg1, i8* %arg2, i8* %arg3) {
653653
; CHECK-LABEL: define {{[^@]+}}@nonnull_assume_neg
654654
; CHECK-SAME: (i8* nocapture nofree readnone [[ARG1:%.*]], i8* nocapture nofree readnone [[ARG2:%.*]], i8* nocapture nofree readnone [[ARG3:%.*]])
655655
; CHECK-NEXT: call void @unknown()
656-
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i8* undef, i64 101), "dereferenceable"(i8* undef, i64 -2), "dereferenceable_or_null"(i8* undef, i64 31) ]
656+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i8* [[ARG1]], i64 101), "dereferenceable"(i8* [[ARG2]], i64 -2), "dereferenceable_or_null"(i8* [[ARG3]], i64 31) ]
657657
; CHECK-NEXT: ret void
658658
;
659659
call void @unknown()

llvm/test/Transforms/Attributor/nonnull.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ declare void @llvm.assume(i1)
185185
define i8* @test10(i8* %a, i64 %n) {
186186
; CHECK-LABEL: define {{[^@]+}}@test10
187187
; CHECK-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]])
188-
; CHECK-NEXT: call void @llvm.assume(i1 undef)
188+
; CHECK-NEXT: call void @llvm.assume(i1 true)
189189
; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 [[N]]
190190
; CHECK-NEXT: ret i8* [[B]]
191191
;

0 commit comments

Comments
 (0)