Skip to content

Commit cb5a48b

Browse files
committed
[Codegen] Remove dead flags on Physical Defs in machine cse
We may leave behind incorrect dead flags on instructions that are CSE'd. Make sure we remove the dead flags on physical registers to prevent other incorrect code motion. Differential Revision: https://reviews.llvm.org/D58115 llvm-svn: 354443
1 parent 30d3408 commit cb5a48b

File tree

2 files changed

+127
-19
lines changed

2 files changed

+127
-19
lines changed

llvm/lib/CodeGen/MachineCSE.cpp

+24-19
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ namespace {
9494
ScopedHashTable<MachineInstr *, unsigned, MachineInstrExpressionTrait,
9595
AllocatorTy>;
9696
using ScopeType = ScopedHTType::ScopeTy;
97+
using PhysDefVector = SmallVector<std::pair<unsigned, unsigned>, 2>;
9798

9899
unsigned LookAheadLimit = 0;
99100
DenseMap<MachineBasicBlock *, ScopeType *> ScopeMap;
@@ -108,13 +109,11 @@ namespace {
108109
MachineBasicBlock::const_iterator E) const;
109110
bool hasLivePhysRegDefUses(const MachineInstr *MI,
110111
const MachineBasicBlock *MBB,
111-
SmallSet<unsigned,8> &PhysRefs,
112-
SmallVectorImpl<unsigned> &PhysDefs,
113-
bool &PhysUseDef) const;
112+
SmallSet<unsigned, 8> &PhysRefs,
113+
PhysDefVector &PhysDefs, bool &PhysUseDef) const;
114114
bool PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
115-
SmallSet<unsigned,8> &PhysRefs,
116-
SmallVectorImpl<unsigned> &PhysDefs,
117-
bool &NonLocal) const;
115+
SmallSet<unsigned, 8> &PhysRefs,
116+
PhysDefVector &PhysDefs, bool &NonLocal) const;
118117
bool isCSECandidate(MachineInstr *MI);
119118
bool isProfitableToCSE(unsigned CSReg, unsigned Reg,
120119
MachineInstr *CSMI, MachineInstr *MI);
@@ -255,9 +254,9 @@ static bool isCallerPreservedOrConstPhysReg(unsigned Reg,
255254
/// instruction does not uses a physical register.
256255
bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
257256
const MachineBasicBlock *MBB,
258-
SmallSet<unsigned,8> &PhysRefs,
259-
SmallVectorImpl<unsigned> &PhysDefs,
260-
bool &PhysUseDef) const{
257+
SmallSet<unsigned, 8> &PhysRefs,
258+
PhysDefVector &PhysDefs,
259+
bool &PhysUseDef) const {
261260
// First, add all uses to PhysRefs.
262261
for (const MachineOperand &MO : MI->operands()) {
263262
if (!MO.isReg() || MO.isDef())
@@ -277,7 +276,8 @@ bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
277276
// (which currently contains only uses), set the PhysUseDef flag.
278277
PhysUseDef = false;
279278
MachineBasicBlock::const_iterator I = MI; I = std::next(I);
280-
for (const MachineOperand &MO : MI->operands()) {
279+
for (const auto &MOP : llvm::enumerate(MI->operands())) {
280+
const MachineOperand &MO = MOP.value();
281281
if (!MO.isReg() || !MO.isDef())
282282
continue;
283283
unsigned Reg = MO.getReg();
@@ -292,20 +292,21 @@ bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
292292
// common since this pass is run before livevariables. We can scan
293293
// forward a few instructions and check if it is obviously dead.
294294
if (!MO.isDead() && !isPhysDefTriviallyDead(Reg, I, MBB->end()))
295-
PhysDefs.push_back(Reg);
295+
PhysDefs.push_back(std::make_pair(MOP.index(), Reg));
296296
}
297297

298298
// Finally, add all defs to PhysRefs as well.
299299
for (unsigned i = 0, e = PhysDefs.size(); i != e; ++i)
300-
for (MCRegAliasIterator AI(PhysDefs[i], TRI, true); AI.isValid(); ++AI)
300+
for (MCRegAliasIterator AI(PhysDefs[i].second, TRI, true); AI.isValid();
301+
++AI)
301302
PhysRefs.insert(*AI);
302303

303304
return !PhysRefs.empty();
304305
}
305306

306307
bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
307-
SmallSet<unsigned,8> &PhysRefs,
308-
SmallVectorImpl<unsigned> &PhysDefs,
308+
SmallSet<unsigned, 8> &PhysRefs,
309+
PhysDefVector &PhysDefs,
309310
bool &NonLocal) const {
310311
// For now conservatively returns false if the common subexpression is
311312
// not in the same basic block as the given instruction. The only exception
@@ -319,7 +320,8 @@ bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
319320
return false;
320321

321322
for (unsigned i = 0, e = PhysDefs.size(); i != e; ++i) {
322-
if (MRI->isAllocatable(PhysDefs[i]) || MRI->isReserved(PhysDefs[i]))
323+
if (MRI->isAllocatable(PhysDefs[i].second) ||
324+
MRI->isReserved(PhysDefs[i].second))
323325
// Avoid extending live range of physical registers if they are
324326
//allocatable or reserved.
325327
return false;
@@ -535,7 +537,7 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
535537
// It's also not safe if the instruction uses physical registers.
536538
bool CrossMBBPhysDef = false;
537539
SmallSet<unsigned, 8> PhysRefs;
538-
SmallVector<unsigned, 2> PhysDefs;
540+
PhysDefVector PhysDefs;
539541
bool PhysUseDef = false;
540542
if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs,
541543
PhysDefs, PhysUseDef)) {
@@ -634,6 +636,9 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
634636
// we should make sure it is not dead at CSMI.
635637
for (unsigned ImplicitDefToUpdate : ImplicitDefsToUpdate)
636638
CSMI->getOperand(ImplicitDefToUpdate).setIsDead(false);
639+
for (auto PhysDef : PhysDefs)
640+
if (!MI->getOperand(PhysDef.first).isDead())
641+
CSMI->getOperand(PhysDef.first).setIsDead(false);
637642

638643
// Go through implicit defs of CSMI and MI, and clear the kill flags on
639644
// their uses in all the instructions between CSMI and MI.
@@ -662,9 +667,9 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
662667
// Add physical register defs now coming in from a predecessor to MBB
663668
// livein list.
664669
while (!PhysDefs.empty()) {
665-
unsigned LiveIn = PhysDefs.pop_back_val();
666-
if (!MBB->isLiveIn(LiveIn))
667-
MBB->addLiveIn(LiveIn);
670+
auto LiveIn = PhysDefs.pop_back_val();
671+
if (!MBB->isLiveIn(LiveIn.second))
672+
MBB->addLiveIn(LiveIn.second);
668673
}
669674
++NumCrossBBCSEs;
670675
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# RUN: llc -mtriple thumbv6m-arm-none-eabi -run-pass=machine-cse -verify-machineinstrs -o - %s | FileCheck %s
2+
3+
--- |
4+
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
5+
target triple = "thumbv6m-arm-none-eabi"
6+
7+
define i32 @funca(i64 %l1) {
8+
entry:
9+
%l2 = icmp ult i64 %l1, -177673816660004267
10+
%l3 = add i64 %l1, 401100203
11+
%rem.i = select i1 %l2, i64 %l1, i64 %l3
12+
%conv = trunc i64 %rem.i to i32
13+
ret i32 %conv
14+
}
15+
16+
define i32 @funcb(i64 %l1) { ret i32 0 }
17+
18+
...
19+
---
20+
name: funca
21+
tracksRegLiveness: true
22+
liveins:
23+
- { reg: '$r0', virtual-reg: '%0' }
24+
- { reg: '$r1', virtual-reg: '%1' }
25+
constants:
26+
- id: 0
27+
value: i32 401100203
28+
alignment: 4
29+
isTargetSpecific: false
30+
- id: 1
31+
value: i32 41367909
32+
alignment: 4
33+
isTargetSpecific: false
34+
body: |
35+
bb.0.entry:
36+
successors: %bb.1(0x40000000), %bb.2(0x40000000)
37+
liveins: $r0, $r1
38+
39+
%1:tgpr = COPY $r1
40+
%0:tgpr = COPY $r0
41+
%2:tgpr = tLDRpci %const.0, 14, $noreg :: (load 4 from constant-pool)
42+
%3:tgpr, dead $cpsr = tADDrr %0, %2, 14, $noreg
43+
%4:tgpr = tLDRpci %const.1, 14, $noreg :: (load 4 from constant-pool)
44+
%5:tgpr, $cpsr = tADDrr %0, %2, 14, $noreg
45+
%6:tgpr, $cpsr = tADC %1, killed %4, 14, $noreg, implicit $cpsr
46+
tBcc %bb.2, 3, $cpsr
47+
48+
bb.1.entry:
49+
successors: %bb.2(0x80000000)
50+
51+
bb.2.entry:
52+
%7:tgpr = PHI %3, %bb.1, %0, %bb.0
53+
$r0 = COPY %7
54+
tBX_RET 14, $noreg, implicit $r0
55+
56+
# CHECK-LABEL: name: funca
57+
# cpsr def must not be dead
58+
# CHECK: %3:tgpr, $cpsr = tADDrr %0, %2
59+
# CHECK-NOT: %5:tgpr, $cpsr = tADDrr %0, %2
60+
61+
...
62+
---
63+
name: funcb
64+
tracksRegLiveness: true
65+
liveins:
66+
- { reg: '$r0', virtual-reg: '%0' }
67+
- { reg: '$r1', virtual-reg: '%1' }
68+
constants:
69+
- id: 0
70+
value: i32 401100203
71+
alignment: 4
72+
isTargetSpecific: false
73+
- id: 1
74+
value: i32 41367909
75+
alignment: 4
76+
isTargetSpecific: false
77+
body: |
78+
bb.0:
79+
successors: %bb.1(0x40000000), %bb.2(0x40000000)
80+
liveins: $r0, $r1
81+
82+
%1:tgpr = COPY $r1
83+
%0:tgpr = COPY $r0
84+
%2:tgpr = tLDRpci %const.0, 14, $noreg :: (load 4 from constant-pool)
85+
%3:tgpr, dead $cpsr = tADDrr %0, %2, 14, $noreg
86+
%4:tgpr = tLDRpci %const.1, 14, $noreg :: (load 4 from constant-pool)
87+
%5:tgpr, dead $cpsr = tADDrr %0, %2, 14, $noreg
88+
%6:tgpr, $cpsr = tADDrr %1, killed %4, 14, $noreg
89+
tBcc %bb.2, 3, $cpsr
90+
91+
bb.1:
92+
successors: %bb.2(0x80000000)
93+
94+
bb.2:
95+
%7:tgpr = PHI %3, %bb.1, %0, %bb.0
96+
$r0 = COPY %7
97+
tBX_RET 14, $noreg, implicit $r0
98+
99+
# CHECK-LABEL: name: funcb
100+
# cpsr def should be dead
101+
# CHECK: %3:tgpr, dead $cpsr = tADDrr %0, %2
102+
# CHECK-NOT: %5:tgpr, dead $cpsr = tADDrr %0, %2
103+
...

0 commit comments

Comments
 (0)