]> granicus.if.org Git - llvm/commitdiff
[Hexagon] Don't kill live registers when creating mux out of tfr
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>
Fri, 16 Jun 2017 12:24:03 +0000 (12:24 +0000)
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>
Fri, 16 Jun 2017 12:24:03 +0000 (12:24 +0000)
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
test/CodeGen/Hexagon/mux-kill2.mir [new file with mode: 0644]

index a2502ce5ec34b31838bddd47c8fe2898d21dddbd..11ac5454f604323672cc74c48a2cc4cac7d9c1b4 100644 (file)
@@ -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 (file)
index 0000000..5f34097
--- /dev/null
@@ -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
+...
+