From cc350332fc3fb4fa93fe7e9a80e466fd85d23241 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Thu, 22 Jun 2017 20:43:02 +0000 Subject: [PATCH] [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 --- lib/Target/Hexagon/HexagonGenMux.cpp | 86 ++++++++----------- .../Hexagon/{mux-kill.mir => mux-kill1.mir} | 2 +- test/CodeGen/Hexagon/mux-kill2.mir | 2 +- test/CodeGen/Hexagon/mux-kill3.mir | 31 +++++++ 4 files changed, 69 insertions(+), 52 deletions(-) rename test/CodeGen/Hexagon/{mux-kill.mir => mux-kill1.mir} (84%) create mode 100644 test/CodeGen/Hexagon/mux-kill3.mir diff --git a/lib/Target/Hexagon/HexagonGenMux.cpp b/lib/Target/Hexagon/HexagonGenMux.cpp index 11ac5454f60..5abbcbba72d 100644 --- a/lib/Target/Hexagon/HexagonGenMux.cpp +++ b/lib/Target/Hexagon/HexagonGenMux.cpp @@ -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; } diff --git a/test/CodeGen/Hexagon/mux-kill.mir b/test/CodeGen/Hexagon/mux-kill1.mir similarity index 84% rename from test/CodeGen/Hexagon/mux-kill.mir rename to test/CodeGen/Hexagon/mux-kill1.mir index 6944050e3da..098620bfb4f 100644 --- a/test/CodeGen/Hexagon/mux-kill.mir +++ b/test/CodeGen/Hexagon/mux-kill1.mir @@ -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 diff --git a/test/CodeGen/Hexagon/mux-kill2.mir b/test/CodeGen/Hexagon/mux-kill2.mir index 5f34097af7c..23469f96c35 100644 --- a/test/CodeGen/Hexagon/mux-kill2.mir +++ b/test/CodeGen/Hexagon/mux-kill2.mir @@ -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 diff --git a/test/CodeGen/Hexagon/mux-kill3.mir b/test/CodeGen/Hexagon/mux-kill3.mir new file mode 100644 index 00000000000..ac4df95b274 --- /dev/null +++ b/test/CodeGen/Hexagon/mux-kill3.mir @@ -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 +... + -- 2.40.0