[Hexagon] Use LivePhysRegs to fix up kills in HexagonGenMux

Remove the previous, manual shuffling of the kill flags. 


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306054 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Krzysztof Parzyszek 2017-06-22 20:43:02 +00:00
parent 7eb15c6d33
commit cc350332fc
4 changed files with 69 additions and 52 deletions

View File

@ -28,6 +28,7 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@ -295,15 +296,12 @@ bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) {
unsigned SR1 = Src1->isReg() ? Src1->getReg() : 0;
unsigned SR2 = Src2->isReg() ? Src2->getReg() : 0;
bool Failure = false, CanUp = true, CanDown = true;
bool Used1 = false, Used2 = false;
for (unsigned X = MinX+1; X < MaxX; X++) {
const DefUseInfo &DU = DUM.lookup(X);
if (DU.Defs[PR] || DU.Defs[DR] || DU.Uses[DR]) {
Failure = true;
break;
}
Used1 |= DU.Uses[SR1];
Used2 |= DU.Uses[SR2];
if (CanDown && DU.Defs[SR1])
CanDown = false;
if (CanUp && DU.Defs[SR2])
@ -317,64 +315,52 @@ bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) {
// Prefer "down", since this will move the MUX farther away from the
// predicate definition.
MachineBasicBlock::iterator At = CanDown ? Def2 : Def1;
if (CanDown) {
// If the MUX is placed "down", we need to make sure that there aren't
// any kills of the source registers between the two defs.
if (Used1 || Used2) {
auto ResetKill = [this] (unsigned Reg, MachineInstr &MI) -> bool {
if (MachineOperand *Op = MI.findRegisterUseOperand(Reg, true, HRI)) {
Op->setIsKill(false);
return true;
}
return false;
};
bool KilledSR1 = false, KilledSR2 = false;
for (MachineInstr &MJ : make_range(std::next(It1), It2)) {
if (SR1)
KilledSR1 |= ResetKill(SR1, MJ);
if (SR2)
KilledSR2 |= ResetKill(SR1, MJ);
}
// If any of the source registers were killed in this range, transfer
// the kills to the source operands: they will me "moved" to the
// resulting MUX and their parent instructions will be deleted.
if (KilledSR1) {
assert(Src1->isReg());
Src1->setIsKill(true);
}
if (KilledSR2) {
assert(Src2->isReg());
Src2->setIsKill(true);
}
}
} else {
// If the MUX is placed "up", it shouldn't kill any source registers
// that are still used afterwards. We can reset the kill flags directly
// on the operands, because the source instructions will be erased.
if (Used1 && Src1->isReg())
Src1->setIsKill(false);
if (Used2 && Src2->isReg())
Src2->setIsKill(false);
}
ML.push_back(MuxInfo(At, DR, PR, SrcT, SrcF, Def1, Def2));
}
for (unsigned I = 0, N = ML.size(); I < N; ++I) {
MuxInfo &MX = ML[I];
MachineBasicBlock &B = *MX.At->getParent();
DebugLoc DL = MX.At->getDebugLoc();
for (MuxInfo &MX : ML) {
unsigned MxOpc = getMuxOpcode(*MX.SrcT, *MX.SrcF);
if (!MxOpc)
continue;
BuildMI(B, MX.At, DL, HII->get(MxOpc), MX.DefR)
.addReg(MX.PredR)
.add(*MX.SrcT)
.add(*MX.SrcF);
MachineBasicBlock &B = *MX.At->getParent();
const DebugLoc &DL = B.findDebugLoc(MX.At);
auto NewMux = BuildMI(B, MX.At, DL, HII->get(MxOpc), MX.DefR)
.addReg(MX.PredR)
.add(*MX.SrcT)
.add(*MX.SrcF);
NewMux->clearKillInfo();
B.erase(MX.Def1);
B.erase(MX.Def2);
Changed = true;
}
// Fix up kill flags.
LivePhysRegs LPR(*HRI);
LPR.addLiveOuts(B);
auto IsLive = [&LPR,this] (unsigned Reg) -> bool {
for (MCSubRegIterator S(Reg, HRI, true); S.isValid(); ++S)
if (LPR.contains(*S))
return true;
return false;
};
for (auto I = B.rbegin(), E = B.rend(); I != E; ++I) {
if (I->isDebugValue())
continue;
// This isn't 100% accurate, but it's safe.
// It won't detect (as a kill) a case like this
// r0 = add r0, 1 <-- r0 should be "killed"
// ... = r0
for (MachineOperand &Op : I->operands()) {
if (!Op.isReg() || !Op.isUse())
continue;
assert(Op.getSubReg() == 0 && "Should have physical registers only");
bool Live = IsLive(Op.getReg());
Op.setIsKill(!Live);
}
LPR.stepBackward(*I);
}
return Changed;
}

View File

@ -1,5 +1,5 @@
# RUN: llc -march=hexagon -run-pass hexagon-gen-mux -o - %s -verify-machineinstrs | FileCheck %s
# CHECK: %r2 = C2_mux %p0, %r0, %r1
# CHECK: %r2 = C2_mux killed %p0, killed %r0, %r1
---
name: fred
tracksRegLiveness: true

View File

@ -1,6 +1,6 @@
# RUN: llc -march=hexagon -run-pass hexagon-gen-mux -o - -verify-machineinstrs %s | FileCheck %s
# CHECK: %r1 = C2_muxri %p0, 123, %r0
# CHECK: %r2 = C2_muxir %p0, killed %r0, 321
# CHECK: %r2 = C2_muxir killed %p0, killed %r0, 321
---
name: fred
tracksRegLiveness: true

View File

@ -0,0 +1,31 @@
# RUN: llc -march=hexagon -run-pass hexagon-gen-mux -o - %s -verify-machineinstrs | FileCheck %s
# Make sure this verifies correctly.
# CHECK: PS_jmpret killed %r31, implicit-def %pc
---
name: fred
tracksRegLiveness: true
body: |
bb.0:
liveins: %d0, %d1, %d2, %d3
%p0 = C2_cmpeqi killed %r4, 128
%d4 = A2_tfrpi 0
%r3 = A2_tfrsi 0
%r4 = A2_tfrsi 0
%r7 = A2_tfrt %p0, %r0
%p1 = C2_cmpeqp %d0, killed %d4
%r8 = A2_tfrt %p0, killed %r0
%r9 = A2_tfrt %p0, killed %r1
%r7 = A2_tfrf %p0, %r3, implicit killed %r7
%r9 = A2_tfrf %p0, killed %r3, implicit killed %r9
%r8 = C2_cmoveif killed %p0, 1, implicit killed %r8
%d0 = A4_combineri killed %r4, 0
%r2 = A2_tfrt %p1, killed %r7, implicit killed %r2
%r3 = A2_tfr killed %r9
%r2 = A2_tfrf killed %p1, killed %r8, implicit killed %r2
S2_storerd_io killed %r6, 0, killed %d1
S2_storerd_io killed %r5, 0, killed %d0
PS_jmpret %r31, implicit-def %pc
...