Skip to content

Commit bc9986e

Browse files
committed
Reapply "[BDCE][DemandedBits] Detect dead uses of undead instructions"
This (mostly) fixes https://bugs.llvm.org/show_bug.cgi?id=39771. BDCE currently detects instructions that don't have any demanded bits and replaces their uses with zero. However, if an instruction has multiple uses, then some of the uses may be dead (have no demanded bits) even though the instruction itself is still live. This patch extends DemandedBits/BDCE to detect such uses and replace them with zero. While this will not immediately render any instructions dead, it may lead to simplifications (in the motivating case, by converting a rotate into a simple shift), break dependencies, etc. The implementation tries to strike a balance between analysis power and complexity/memory usage. Originally I wanted to track demanded bits on a per-use level, but ultimately we're only really interested in whether a use is entirely dead or not. I'm using an extra set to track which uses are dead. However, as initially all uses are dead, I'm not storing uses those user is also dead. This case is checked separately instead. The previous attempt to land this lead to miscompiles, because cases where uses were initially dead but were later found to be live during further analysis were not always correctly removed from the DeadUses set. This is fixed now and the added test case demanstrates such an instance. Differential Revision: https://reviews.llvm.org/D55563 llvm-svn: 350188
1 parent e00606a commit bc9986e

File tree

4 files changed

+92
-19
lines changed

4 files changed

+92
-19
lines changed

llvm/include/llvm/Analysis/DemandedBits.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ class DemandedBits {
5757
/// Return true if, during analysis, I could not be reached.
5858
bool isInstructionDead(Instruction *I);
5959

60+
/// Return whether this use is dead by means of not having any demanded bits.
61+
bool isUseDead(Use *U);
62+
6063
void print(raw_ostream &OS);
6164

6265
private:
@@ -75,6 +78,9 @@ class DemandedBits {
7578
// The set of visited instructions (non-integer-typed only).
7679
SmallPtrSet<Instruction*, 32> Visited;
7780
DenseMap<Instruction *, APInt> AliveBits;
81+
// Uses with no demanded bits. If the user also has no demanded bits, the use
82+
// might not be stored explicitly in this map, to save memory during analysis.
83+
SmallPtrSet<Use *, 16> DeadUses;
7884
};
7985

8086
class DemandedBitsWrapperPass : public FunctionPass {

llvm/lib/Analysis/DemandedBits.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ void DemandedBits::performAnalysis() {
314314

315315
Visited.clear();
316316
AliveBits.clear();
317+
DeadUses.clear();
317318

318319
SmallVector<Instruction*, 128> Worklist;
319320

@@ -358,7 +359,8 @@ void DemandedBits::performAnalysis() {
358359
APInt AOut;
359360
if (UserI->getType()->isIntOrIntVectorTy()) {
360361
AOut = AliveBits[UserI];
361-
LLVM_DEBUG(dbgs() << " Alive Out: " << AOut);
362+
LLVM_DEBUG(dbgs() << " Alive Out: 0x"
363+
<< Twine::utohexstr(AOut.getLimitedValue()));
362364
}
363365
LLVM_DEBUG(dbgs() << "\n");
364366

@@ -377,13 +379,20 @@ void DemandedBits::performAnalysis() {
377379
APInt AB = APInt::getAllOnesValue(BitWidth);
378380
if (UserI->getType()->isIntOrIntVectorTy() && !AOut &&
379381
!isAlwaysLive(UserI)) {
382+
// If all bits of the output are dead, then all bits of the input
383+
// are also dead.
380384
AB = APInt(BitWidth, 0);
381385
} else {
382-
// If all bits of the output are dead, then all bits of the input
383386
// Bits of each operand that are used to compute alive bits of the
384387
// output are alive, all others are dead.
385388
determineLiveOperandBits(UserI, I, OI.getOperandNo(), AOut, AB,
386389
Known, Known2);
390+
391+
// Keep track of uses which have no demanded bits.
392+
if (AB.isNullValue())
393+
DeadUses.insert(&OI);
394+
else
395+
DeadUses.erase(&OI);
387396
}
388397

389398
// If we've added to the set of alive bits (or the operand has not
@@ -426,6 +435,31 @@ bool DemandedBits::isInstructionDead(Instruction *I) {
426435
!isAlwaysLive(I);
427436
}
428437

438+
bool DemandedBits::isUseDead(Use *U) {
439+
// We only track integer uses, everything else is assumed live.
440+
if (!(*U)->getType()->isIntOrIntVectorTy())
441+
return false;
442+
443+
// Uses by always-live instructions are never dead.
444+
Instruction *UserI = cast<Instruction>(U->getUser());
445+
if (isAlwaysLive(UserI))
446+
return false;
447+
448+
performAnalysis();
449+
if (DeadUses.count(U))
450+
return true;
451+
452+
// If no output bits are demanded, no input bits are demanded and the use
453+
// is dead. These uses might not be explicitly present in the DeadUses map.
454+
if (UserI->getType()->isIntOrIntVectorTy()) {
455+
auto Found = AliveBits.find(UserI);
456+
if (Found != AliveBits.end() && Found->second.isNullValue())
457+
return true;
458+
}
459+
460+
return false;
461+
}
462+
429463
void DemandedBits::print(raw_ostream &OS) {
430464
performAnalysis();
431465
for (auto &KV : AliveBits) {

llvm/lib/Transforms/Scalar/BDCE.cpp

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,30 +96,38 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
9696
if (I.mayHaveSideEffects() && I.use_empty())
9797
continue;
9898

99-
if (I.getType()->isIntOrIntVectorTy() &&
100-
!DB.getDemandedBits(&I).getBoolValue()) {
101-
// For live instructions that have all dead bits, first make them dead by
102-
// replacing all uses with something else. Then, if they don't need to
103-
// remain live (because they have side effects, etc.) we can remove them.
104-
LLVM_DEBUG(dbgs() << "BDCE: Trivializing: " << I << " (all bits dead)\n");
99+
// Remove instructions not reached during analysis.
100+
if (DB.isInstructionDead(&I)) {
101+
salvageDebugInfo(I);
102+
Worklist.push_back(&I);
103+
I.dropAllReferences();
104+
Changed = true;
105+
continue;
106+
}
107+
108+
for (Use &U : I.operands()) {
109+
// DemandedBits only detects dead integer uses.
110+
if (!U->getType()->isIntOrIntVectorTy())
111+
continue;
112+
113+
// TODO: We could also find dead non-instruction uses, e.g. arguments.
114+
if (!isa<Instruction>(U))
115+
continue;
116+
117+
if (!DB.isUseDead(&U))
118+
continue;
119+
120+
LLVM_DEBUG(dbgs() << "BDCE: Trivializing: " << U << " (all bits dead)\n");
105121

106122
clearAssumptionsOfUsers(&I, DB);
107123

108124
// FIXME: In theory we could substitute undef here instead of zero.
109125
// This should be reconsidered once we settle on the semantics of
110126
// undef, poison, etc.
111-
Value *Zero = ConstantInt::get(I.getType(), 0);
127+
U.set(ConstantInt::get(U->getType(), 0));
112128
++NumSimplified;
113-
I.replaceNonMetadataUsesWith(Zero);
114129
Changed = true;
115130
}
116-
if (!DB.isInstructionDead(&I))
117-
continue;
118-
119-
salvageDebugInfo(I);
120-
Worklist.push_back(&I);
121-
I.dropAllReferences();
122-
Changed = true;
123131
}
124132

125133
for (Instruction *&I : Worklist) {

llvm/test/Transforms/BDCE/dead-uses.ll

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ declare <2 x i32> @llvm.fshr.v2i32(<2 x i32>, <2 x i32>, <2 x i32>)
1010
define i32 @pr39771_fshr_multi_use_instr(i32 %a) {
1111
; CHECK-LABEL: @pr39771_fshr_multi_use_instr(
1212
; CHECK-NEXT: [[X:%.*]] = or i32 [[A:%.*]], 0
13-
; CHECK-NEXT: [[B:%.*]] = tail call i32 @llvm.fshr.i32(i32 [[X]], i32 [[X]], i32 1)
13+
; CHECK-NEXT: [[B:%.*]] = tail call i32 @llvm.fshr.i32(i32 0, i32 [[X]], i32 1)
1414
; CHECK-NEXT: [[C:%.*]] = lshr i32 [[B]], 23
1515
; CHECK-NEXT: [[D:%.*]] = xor i32 [[C]], [[B]]
1616
; CHECK-NEXT: [[E:%.*]] = and i32 [[D]], 31
@@ -28,7 +28,7 @@ define i32 @pr39771_fshr_multi_use_instr(i32 %a) {
2828
define <2 x i32> @pr39771_fshr_multi_use_instr_vec(<2 x i32> %a) {
2929
; CHECK-LABEL: @pr39771_fshr_multi_use_instr_vec(
3030
; CHECK-NEXT: [[X:%.*]] = or <2 x i32> [[A:%.*]], zeroinitializer
31-
; CHECK-NEXT: [[B:%.*]] = tail call <2 x i32> @llvm.fshr.v2i32(<2 x i32> [[X]], <2 x i32> [[X]], <2 x i32> <i32 1, i32 1>)
31+
; CHECK-NEXT: [[B:%.*]] = tail call <2 x i32> @llvm.fshr.v2i32(<2 x i32> zeroinitializer, <2 x i32> [[X]], <2 x i32> <i32 1, i32 1>)
3232
; CHECK-NEXT: [[C:%.*]] = lshr <2 x i32> [[B]], <i32 23, i32 23>
3333
; CHECK-NEXT: [[D:%.*]] = xor <2 x i32> [[C]], [[B]]
3434
; CHECK-NEXT: [[E:%.*]] = and <2 x i32> [[D]], <i32 31, i32 31>
@@ -77,3 +77,28 @@ define i32 @pr39771_expanded_fshr_multi_use(i32 %a) {
7777
%e = and i32 %d, 31
7878
ret i32 %e
7979
}
80+
81+
; %b operand of %c will be dead initially, but later found live.
82+
define void @dead_use_invalidation(i32 %a) {
83+
; CHECK-LABEL: @dead_use_invalidation(
84+
; CHECK-NEXT: [[B:%.*]] = or i32 [[A:%.*]], 0
85+
; CHECK-NEXT: [[C:%.*]] = shl i32 [[B]], 31
86+
; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], 1
87+
; CHECK-NEXT: [[E:%.*]] = or i32 [[C]], 0
88+
; CHECK-NEXT: [[F:%.*]] = or i32 [[D]], 0
89+
; CHECK-NEXT: call void @dummy(i32 [[E]])
90+
; CHECK-NEXT: call void @dummy(i32 [[F]])
91+
; CHECK-NEXT: call void @dummy(i32 [[B]])
92+
; CHECK-NEXT: ret void
93+
;
94+
%b = or i32 %a, 0
95+
%c = shl i32 %b, 31
96+
%d = and i32 %c, 1
97+
%e = or i32 %c, 0
98+
%f = or i32 %d, 0
99+
call void @dummy(i32 %e)
100+
call void @dummy(i32 %f)
101+
call void @dummy(i32 %b)
102+
ret void
103+
}
104+
declare void @dummy(i32)

0 commit comments

Comments
 (0)