From c86dcc6411c6905c880c129641036db915adbd65 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Fri, 16 Jun 2017 12:24:03 +0000 Subject: [PATCH] [Hexagon] Don't kill live registers when creating mux out of tfr The second part of r305300: when placing the mux at the later location, make sure that it won't use any register that was killed between the two original instructions. Remove any such kills and transfer them to the mux. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305553 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Hexagon/HexagonGenMux.cpp | 32 +++++++++++++++++++++++++++- test/CodeGen/Hexagon/mux-kill2.mir | 17 +++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/Hexagon/mux-kill2.mir diff --git a/lib/Target/Hexagon/HexagonGenMux.cpp b/lib/Target/Hexagon/HexagonGenMux.cpp index a2502ce5ec3..11ac5454f60 100644 --- a/lib/Target/Hexagon/HexagonGenMux.cpp +++ b/lib/Target/Hexagon/HexagonGenMux.cpp @@ -317,7 +317,37 @@ 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 (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. diff --git a/test/CodeGen/Hexagon/mux-kill2.mir b/test/CodeGen/Hexagon/mux-kill2.mir new file mode 100644 index 00000000000..5f34097af7c --- /dev/null +++ b/test/CodeGen/Hexagon/mux-kill2.mir @@ -0,0 +1,17 @@ +# 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 +--- +name: fred +tracksRegLiveness: true + +body: | + bb.0: + liveins: %r0, %p0 + + %r2 = A2_tfrt %p0, %r0 + %r1 = C2_cmoveit %p0, 123 + %r1 = A2_tfrf %p0, killed %r0, implicit killed %r1 + %r2 = C2_cmoveif killed %p0, 321, implicit killed %r2 +... + -- 2.50.1