[llvm] r355378 - [PowerPC] fix killed/dead flag after convert x-form to d-form tranformation.

Chen Zheng via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 4 20:56:54 PST 2019


Author: shchenz
Date: Mon Mar  4 20:56:54 2019
New Revision: 355378

URL: http://llvm.org/viewvc/llvm-project?rev=355378&view=rev
Log:
[PowerPC] fix killed/dead flag after convert x-form to d-form tranformation.
Differential Revision: https://reviews.llvm.org/D58428

Added:
    llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-kill-flag.mir
Modified:
    llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp
    llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h
    llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instr-add.mir

Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp?rev=355378&r1=355377&r2=355378&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp Mon Mar  4 20:56:54 2019
@@ -2424,6 +2424,83 @@ const unsigned *PPCInstrInfo::getLoadOpc
   return OpcodesForSpill[(Subtarget.hasP9Vector()) ? 1 : 0];
 }
 
+void PPCInstrInfo::fixupIsDeadOrKill(MachineInstr &StartMI, MachineInstr &EndMI,
+                                     unsigned RegNo) const {
+  const MachineRegisterInfo &MRI =
+      StartMI.getParent()->getParent()->getRegInfo();
+  if (MRI.isSSA())
+    return;
+
+  // Instructions between [StartMI, EndMI] should be in same basic block.
+  assert((StartMI.getParent() == EndMI.getParent()) &&
+         "Instructions are not in same basic block");
+
+  bool IsKillSet = false;
+
+  auto clearOperandKillInfo = [=] (MachineInstr &MI, unsigned Index) {
+    MachineOperand &MO = MI.getOperand(Index);
+    if (MO.isReg() && MO.isUse() && MO.isKill() &&
+        getRegisterInfo().regsOverlap(MO.getReg(), RegNo))
+      MO.setIsKill(false);
+  };
+
+  // Set killed flag for EndMI.
+  // No need to do anything if EndMI defines RegNo.
+  int UseIndex =
+      EndMI.findRegisterUseOperandIdx(RegNo, false, &getRegisterInfo());
+  if (UseIndex != -1) {
+    EndMI.getOperand(UseIndex).setIsKill(true);
+    IsKillSet = true;
+    // Clear killed flag for other EndMI operands related to RegNo. In some
+    // upexpected cases, killed may be set multiple times for same register
+    // operand in same MI.
+    for (int i = 0, e = EndMI.getNumOperands(); i != e; ++i)
+      if (i != UseIndex)
+        clearOperandKillInfo(EndMI, i);
+  }
+
+  // Walking the inst in reverse order (EndMI -> StartMI].
+  MachineBasicBlock::reverse_iterator It = EndMI;
+  MachineBasicBlock::reverse_iterator E = EndMI.getParent()->rend();
+  // EndMI has been handled above, skip it here.
+  It++;
+  MachineOperand *MO = nullptr;
+  for (; It != E; ++It) {
+    // Skip insturctions which could not be a def/use of RegNo.
+    if (It->isDebugInstr() || It->isPosition())
+      continue;
+
+    // Clear killed flag for all It operands related to RegNo. In some
+    // upexpected cases, killed may be set multiple times for same register
+    // operand in same MI.
+    for (int i = 0, e = It->getNumOperands(); i != e; ++i)
+        clearOperandKillInfo(*It, i);
+
+    // If killed is not set, set killed for its last use or set dead for its def
+    // if no use found.
+    if (!IsKillSet) {
+      if ((MO = It->findRegisterUseOperand(RegNo, false, &getRegisterInfo()))) {
+        // Use found, set it killed.
+        IsKillSet = true;
+        MO->setIsKill(true);
+        continue;
+      } else if ((MO = It->findRegisterDefOperand(RegNo, false, true,
+                                                  &getRegisterInfo()))) {
+        // No use found, set dead for its def.
+        assert(&*It == &StartMI && "No new def between StartMI and EndMI.");
+        MO->setIsDead(true);
+        break;
+      }
+    }
+
+    if ((&*It) == &StartMI)
+      break;
+  }
+  // Ensure RegMo liveness is killed after EndMI.
+  assert((IsKillSet || (MO && MO->isDead())) &&
+         "RegNo should be killed or dead");
+}
+
 // If this instruction has an immediate form and one of its operands is a
 // result of a load-immediate or an add-immediate, convert it to
 // the immediate form if the constant is in range.
@@ -2440,8 +2517,9 @@ bool PPCInstrInfo::convertToImmediateFor
     return false;
   assert(ForwardingOperand < MI.getNumOperands() &&
          "The forwarding operand needs to be valid at this point");
-  bool KillFwdDefMI = !SeenIntermediateUse &&
-    MI.getOperand(ForwardingOperand).isKill();
+  bool IsForwardingOperandKilled = MI.getOperand(ForwardingOperand).isKill();
+  bool KillFwdDefMI = !SeenIntermediateUse && IsForwardingOperandKilled;
+  unsigned ForwardingOperandReg = MI.getOperand(ForwardingOperand).getReg();
   if (KilledDef && KillFwdDefMI)
     *KilledDef = DefMI;
 
@@ -2450,8 +2528,9 @@ bool PPCInstrInfo::convertToImmediateFor
   // If this is a reg+reg instruction that has a reg+imm form,
   // and one of the operands is produced by an add-immediate,
   // try to convert it.
-  if (HasImmForm && transformToImmFormFedByAdd(MI, III, ForwardingOperand,
-                                               *DefMI, KillFwdDefMI))
+  if (HasImmForm &&
+      transformToImmFormFedByAdd(MI, III, ForwardingOperand, *DefMI,
+                                 KillFwdDefMI))
     return true;
 
   if ((DefMI->getOpcode() != PPC::LI && DefMI->getOpcode() != PPC::LI8) ||
@@ -2466,7 +2545,7 @@ bool PPCInstrInfo::convertToImmediateFor
   // If this is a reg+reg instruction that has a reg+imm form,
   // and one of the operands is produced by LI, convert it now.
   if (HasImmForm)
-    return transformToImmFormFedByLI(MI, III, ForwardingOperand, SExtImm);
+    return transformToImmFormFedByLI(MI, III, ForwardingOperand, *DefMI, SExtImm);
 
   bool ReplaceWithLI = false;
   bool Is64BitLI = false;
@@ -2486,6 +2565,8 @@ bool PPCInstrInfo::convertToImmediateFor
   case PPC::CMPLDI: {
     // Doing this post-RA would require dataflow analysis to reliably find uses
     // of the CR register set by the compare.
+    // No need to fixup killed/dead flag since this transformation is only valid
+    // before RA.
     if (PostRA)
       return false;
     // If a compare-immediate is fed by an immediate and is itself an input of
@@ -2662,6 +2743,14 @@ bool PPCInstrInfo::convertToImmediateFor
     if (KilledDef && SetCR)
       *KilledDef = nullptr;
     replaceInstrWithLI(MI, LII);
+
+    // Fixup killed/dead flag after transformation.
+    // Pattern:
+    // ForwardingOperandReg = LI imm1
+    // y = op2 imm2, ForwardingOperandReg(killed)
+    if (IsForwardingOperandKilled)
+      fixupIsDeadOrKill(*DefMI, MI, ForwardingOperandReg);
+
     LLVM_DEBUG(dbgs() << "With:\n");
     LLVM_DEBUG(MI.dump());
     return true;
@@ -3169,11 +3258,10 @@ bool PPCInstrInfo::isDefMIElgibleForForw
   return isAnImmediateOperand(*ImmMO);
 }
 
-bool PPCInstrInfo::isRegElgibleForForwarding(const MachineOperand &RegMO,
-                                             const MachineInstr &DefMI,
-                                             const MachineInstr &MI,
-                                             bool KillDefMI
-                                             ) const {
+bool PPCInstrInfo::isRegElgibleForForwarding(
+    const MachineOperand &RegMO, const MachineInstr &DefMI,
+    const MachineInstr &MI, bool KillDefMI,
+    bool &IsFwdFeederRegKilled) const {
   // x = addi y, imm
   // ...
   // z = lfdx 0, x   -> z = lfd imm(y)
@@ -3193,6 +3281,8 @@ bool PPCInstrInfo::isRegElgibleForForwar
   for (; It != E; ++It) {
     if (It->modifiesRegister(Reg, &getRegisterInfo()) && (&*It) != &DefMI)
       return false;
+    else if (It->killsRegister(Reg, &getRegisterInfo()) && (&*It) != &DefMI)
+      IsFwdFeederRegKilled = true;
     // Made it to DefMI without encountering a clobber.
     if ((&*It) == &DefMI)
       break;
@@ -3264,11 +3354,9 @@ bool PPCInstrInfo::isImmElgibleForForwar
 // is the literal zero, attempt to forward the source of the add-immediate to
 // the corresponding D-Form instruction with the displacement coming from
 // the immediate being added.
-bool PPCInstrInfo::transformToImmFormFedByAdd(MachineInstr &MI,
-                                              const ImmInstrInfo &III,
-                                              unsigned OpNoForForwarding,
-                                              MachineInstr &DefMI,
-                                              bool KillDefMI) const {
+bool PPCInstrInfo::transformToImmFormFedByAdd(
+    MachineInstr &MI, const ImmInstrInfo &III, unsigned OpNoForForwarding,
+    MachineInstr &DefMI, bool KillDefMI) const {
   //         RegMO ImmMO
   //           |    |
   // x = addi reg, imm  <----- DefMI
@@ -3293,10 +3381,19 @@ bool PPCInstrInfo::transformToImmFormFed
   if (!isImmElgibleForForwarding(*ImmMO, DefMI, III, Imm))
     return false;
 
+  bool IsFwdFeederRegKilled = false;
   // Check if the RegMO can be forwarded to MI.
-  if (!isRegElgibleForForwarding(*RegMO, DefMI, MI, KillDefMI))
+  if (!isRegElgibleForForwarding(*RegMO, DefMI, MI, KillDefMI,
+                                 IsFwdFeederRegKilled))
     return false;
 
+  // Get killed info in case fixup needed after transformation.
+  unsigned ForwardKilledOperandReg = ~0U;
+  MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
+  bool PostRA = !MRI.isSSA();
+  if (PostRA && MI.getOperand(OpNoForForwarding).isKill())
+    ForwardKilledOperandReg = MI.getOperand(OpNoForForwarding).getReg();
+
   // We know that, the MI and DefMI both meet the pattern, and
   // the Imm also meet the requirement with the new Imm-form.
   // It is safe to do the transformation now.
@@ -3347,6 +3444,22 @@ bool PPCInstrInfo::transformToImmFormFed
   // Update the opcode.
   MI.setDesc(get(III.ImmOpcode));
 
+  // Fix up killed/dead flag after transformation.
+  // Pattern 1:
+  // x = ADD KilledFwdFeederReg, imm
+  // n = opn KilledFwdFeederReg(killed), regn
+  // y = XOP 0, x
+  // Pattern 2:
+  // x = ADD reg(killed), imm
+  // y = XOP 0, x
+  if (IsFwdFeederRegKilled || RegMO->isKill())
+    fixupIsDeadOrKill(DefMI, MI, RegMO->getReg());
+  // Pattern 3:
+  // ForwardKilledOperandReg = ADD reg, imm
+  // y = XOP 0, ForwardKilledOperandReg(killed)
+  if (ForwardKilledOperandReg != ~0U)
+    fixupIsDeadOrKill(DefMI, MI, ForwardKilledOperandReg);
+
   LLVM_DEBUG(dbgs() << "With:\n");
   LLVM_DEBUG(MI.dump());
 
@@ -3356,6 +3469,7 @@ bool PPCInstrInfo::transformToImmFormFed
 bool PPCInstrInfo::transformToImmFormFedByLI(MachineInstr &MI,
                                              const ImmInstrInfo &III,
                                              unsigned ConstantOpNo,
+                                             MachineInstr &DefMI,
                                              int64_t Imm) const {
   MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
   bool PostRA = !MRI.isSSA();
@@ -3394,6 +3508,11 @@ bool PPCInstrInfo::transformToImmFormFed
       return false;
   }
 
+  // Get killed info in case fixup needed after transformation.
+  unsigned ForwardKilledOperandReg = ~0U;
+  if (PostRA && MI.getOperand(ConstantOpNo).isKill())
+    ForwardKilledOperandReg = MI.getOperand(ConstantOpNo).getReg();
+
   unsigned Opc = MI.getOpcode();
   bool SpecialShift32 =
     Opc == PPC::SLW || Opc == PPC::SLWo || Opc == PPC::SRW || Opc == PPC::SRWo;
@@ -3476,6 +3595,13 @@ bool PPCInstrInfo::transformToImmFormFed
       }
     }
   }
+
+  // Fix up killed/dead flag after transformation.
+  // Pattern:
+  // ForwardKilledOperandReg = LI imm
+  // y = XOP reg, ForwardKilledOperandReg(killed)
+  if (ForwardKilledOperandReg != ~0U)
+    fixupIsDeadOrKill(DefMI, MI, ForwardKilledOperandReg);
   return true;
 }
 

Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h?rev=355378&r1=355377&r2=355378&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h Mon Mar  4 20:56:54 2019
@@ -128,12 +128,12 @@ class PPCInstrInfo : public PPCGenInstrI
   // If the inst has imm-form and one of its operand is produced by a LI,
   // put the imm into the inst directly and remove the LI if possible.
   bool transformToImmFormFedByLI(MachineInstr &MI, const ImmInstrInfo &III,
-                                 unsigned ConstantOpNo, int64_t Imm) const;
+                                 unsigned ConstantOpNo, MachineInstr &DefMI,
+                                 int64_t Imm) const;
   // If the inst has imm-form and one of its operand is produced by an
   // add-immediate, try to transform it when possible.
   bool transformToImmFormFedByAdd(MachineInstr &MI, const ImmInstrInfo &III,
-                                  unsigned ConstantOpNo,
-                                  MachineInstr &DefMI,
+                                  unsigned ConstantOpNo, MachineInstr &DefMI,
                                   bool KillDefMI) const;
   // Try to find that, if the instruction 'MI' contains any operand that
   // could be forwarded from some inst that feeds it. If yes, return the
@@ -158,8 +158,8 @@ class PPCInstrInfo : public PPCGenInstrI
                                  int64_t &Imm) const;
   bool isRegElgibleForForwarding(const MachineOperand &RegMO,
                                  const MachineInstr &DefMI,
-                                 const MachineInstr &MI,
-                                 bool KillDefMI) const;
+                                 const MachineInstr &MI, bool KillDefMI,
+                                 bool &IsFwdFeederRegKilled) const;
   const unsigned *getStoreOpcodesForSpillArray() const;
   const unsigned *getLoadOpcodesForSpillArray() const;
   virtual void anchor();
@@ -411,6 +411,18 @@ public:
 
   bool convertToImmediateForm(MachineInstr &MI,
                               MachineInstr **KilledDef = nullptr) const;
+
+  /// Fixup killed/dead flag for register \p RegNo between instructions [\p
+  /// StartMI, \p EndMI]. Some PostRA transformations may violate register
+  /// killed/dead flags semantics, this function can be called to fix up. Before
+  /// calling this function,
+  /// 1. Ensure that \p RegNo liveness is killed after instruction \p EndMI.
+  /// 2. Ensure that there is no new definition between (\p StartMI, \p EndMI)
+  ///    and possible definition for \p RegNo is \p StartMI or \p EndMI.
+  /// 3. Ensure that all instructions between [\p StartMI, \p EndMI] are in same
+  ///    basic block.
+  void fixupIsDeadOrKill(MachineInstr &StartMI, MachineInstr &EndMI,
+                         unsigned RegNo) const;
   void replaceInstrWithLI(MachineInstr &MI, const LoadImmediateInfo &LII) const;
   void replaceInstrOperandWithImm(MachineInstr &MI, unsigned OpNo,
                                   int64_t Imm) const;

Modified: llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instr-add.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instr-add.mir?rev=355378&r1=355377&r2=355378&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instr-add.mir (original)
+++ llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instr-add.mir Mon Mar  4 20:56:54 2019
@@ -27,7 +27,7 @@ body: |
     ; Following instruction $r3 also reads $x3, ADDI8 can not be erased
     ; CHECK: $x3 = ADDI8 $x5, 100, implicit-def $r3
     STW $r3, $x5, 100
-    ; CHECK: STW $r3, $x5, 100
+    ; CHECK: STW killed $r3, $x5, 100
     STFSX killed $f1, $zero8, $x3
     ; CHECK: STFS killed $f1, 100, $x5
     STD $x5, $x5, 100

Added: llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-kill-flag.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-kill-flag.mir?rev=355378&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-kill-flag.mir (added)
+++ llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-kill-flag.mir Mon Mar  4 20:56:54 2019
@@ -0,0 +1,183 @@
+# RUN: llc -mtriple=powerpc64le--linux-gnu -stop-after ppc-pre-emit-peephole %s -o - -verify-machineinstrs | FileCheck %s
+
+---
+# LI + XFORM -> DFORM, no killed/dead flag fixup.
+name: testKillPassUpLI1
+#CHECK : name : testKillPassUpLI1
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+    liveins: $x3, $f1, $x5
+    $x3 = LI8 100
+    STFSX killed $f1, $x3, $x5
+    ; CHECK: STFS killed $f1, 100, $x5
+    STD killed $x3, killed $x5, 100
+    ; CHECK: STD killed $x3, killed $x5, 100
+    BLR8 implicit $lr8, implicit $rm
+
+...
+---
+# LI + XFORM -> DFORM, fixup killed/dead flag for $x3, find no use, set def as
+# dead(LI8 is deleted).
+name : testKillPassUpLI2
+# CHECK: name: testKillPassUpLI2
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+    liveins: $x3, $f1, $x5
+    $x3 = LI8 100
+    ; CHECK-NOT: LI8
+    STFSX killed $f1, killed $x3, killed $x5
+    ; CHECK: STFS killed $f1, 100, killed $x5
+    BLR8 implicit $lr8, implicit $rm
+
+...
+---
+# LI + XFORM -> DFORM, fixup killed/dead flag for $x3, find last use, set last
+# use as killed.
+name: testKillPassUpLI3
+# CHECK: name: testKillPassUpLI3
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+    liveins: $x3, $f1, $x5
+    $x3 = LI8 100
+    STD $x3, $x5, 100
+    ; CHECK: STD killed $x3, $x5, 100
+    STFSX killed $f1, killed $x3, $x5
+    ; CHECK: STFS killed $f1, 100, $x5
+    STD killed $x5, $x5, 100
+    ; CHECK: STD killed $x5, $x5, 100
+    BLR8 implicit $lr8, implicit $rm
+
+...
+---
+# LI + OP -> LI, fixup killed/dead flag for $x3, find last use, set last use as
+# killed.
+name: testKillPassUpLI4
+# CHECK: name: testKillPassUpLI4
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+    liveins: $x3, $x5
+    $x3 = LI8 100
+    STD $x3, $x5, 100
+    ; CHECK: STD killed $x3, killed $x5, 100
+    $x5 = ADDI8 killed $x3, 200
+    ; CHECK: $x5 = LI8 300
+    STD $x5, $x5, 100
+    BLR8 implicit $lr8, implicit $rm
+
+...
+---
+# ADD + XFORM -> DFORM, fixup killed/dead flag for $x3, find no use, set def as dead
+# (ADDI8 is deleted).
+name: testKillPassUpADD1
+# CHECK: name: testKillPassUpADD1
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+    liveins: $x3, $f1, $x5
+    $x3 = ADDI8 killed $x5, 100
+    ; CHECK-NOT: ADDI8
+    STFSX killed $f1, $zero8, killed $x3
+    ; CHECK: STFS killed $f1, 100, killed $x5
+    BLR8 implicit $lr8, implicit $rm
+
+...
+---
+# ADD + XFORM -> DFORM, fixup killed/dead flag for $x3, find last use, set last
+# use as killed.
+name: testKillPassUpADD2
+# CHECK: name: testKillPassUpADD2
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+    liveins: $x3, $f1, $x5
+    $x3 = ADDI8 $x5, 100
+    STD $x3, $x5, 100
+    ; CHECK: STD killed $x3, $x5, 100
+    STFSX killed $f1, $zero8, killed $x3
+    ; CHECK: STFS killed $f1, 100, $x5
+    STD killed $x5, $x5, 100
+    ; CHECK: STD killed $x5, $x5, 100
+    BLR8 implicit $lr8, implicit $rm
+
+...
+---
+# ADD + XFORM -> DFORM, fixup killed/dead flag for register $x5, DFORM
+# instruction uses $x5 and no other kill uses, set it as killed in
+# DFORM instruction.
+name: testKillPassDownADD1
+# CHECK: name: testKillPassDownADD1
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+    liveins: $x3, $f1, $x5
+    $x3 = ADDI8 killed $x5, 100
+    ; CHECK: $x3 = ADDI8 $x5, 100
+    STFSX killed $f1, $zero8, $x3
+    ; CHECK: STFS killed $f1, 100, killed $x5
+    STD killed $x3, $x3, 100
+    ; CHECK: STD killed $x3, $x3, 100
+    BLR8 implicit $lr8, implicit $rm
+
+...
+---
+# ADD + XFORM -> DFORM, fixup killed/dead flag for register $x5, DFORM
+# instruction uses $x5 and there is one kill use, set $x5 as killed in
+# DFORM instruction and clear the other kill use killed flag.
+name: testKillPassDownADD2
+# CHECK: name: testKillPassDownADD2
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+    liveins: $x3, $f1, $x5
+    $x3 = ADDI8 $x5, 100
+    STD killed $x5, $x5, 100
+    ; CHECK: STD $x5, $x5, 100
+    STFSX killed $f1, $zero8, killed $x3
+    ; CHECK: STFS killed $f1, 100, killed $x5
+    BLR8 implicit $lr8, implicit $rm
+
+...
+---
+# ADD + XFORM -> DFORM, fixup killed/dead flag for register $x3, DFORM
+# instruction defines $x3, do nothing for killed/dead flag.
+name: testKillPassDownADD3
+# CHECK: name: testKillPassDownADD3
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+    liveins: $x3, $x5
+    $x3 = ADDI8 $x5, 100
+    $x3 = LDX $zero8, killed $x3
+    ; CHECK: $x3 = LD 100, $x5
+    STD killed $x5, $x5, 100
+    ; CHECK: STD killed $x5, $x5, 100
+    STD killed $x3, $x3, 200
+    ; CHECK: STD killed $x3, $x3, 200
+    BLR8 implicit $lr8, implicit $rm
+
+...
+---
+# ADD + XFORM -> DFORM, fixup killed/dead flag for both register $x5 and $x3,
+# DFORM instruction uses $x5 and there is one kill use, set $x5 as killed in
+# DFORM instruction and clear the other kill use killed flag. Find last use for
+# $x3, set last use as killed.
+name: testKillPassDownADD4
+# CHECK: name: testKillPassDownADD4
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+    liveins: $x3, $f1, $x5
+    $x3 = ADDI8 $x5, 100
+    STD killed $x5, $x5, 100
+    ; CHECK: STD $x5, $x5, 100
+    STD $x3, $x3, 200
+    ; CHECK: STD killed $x3, $x3, 200
+    STFSX killed $f1, $zero8, killed $x3
+    ; CHECK: STFS killed $f1, 100, killed $x5
+    BLR8 implicit $lr8, implicit $rm
+
+...




More information about the llvm-commits mailing list