Browse Source

[MachineOperand][MIR] Add isRenamable to MachineOperand.

Summary:
Add isRenamable() predicate to MachineOperand.  This predicate can be
used by machine passes after register allocation to determine whether it
is safe to rename a given register operand.  Register operands that
aren't marked as renamable may be required to be assigned their current
register to satisfy constraints that are not captured by the machine
IR (e.g. ABI or ISA constraints).

Reviewers: qcolombet, MatzeB, hfinkel

Subscribers: nemanjai, mcrosier, javed.absar, llvm-commits

Differential Revision: https://reviews.llvm.org/D39400

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320503 91177308-0d34-0410-b5e6-96231b3b80d8
Geoff Berry 7 years ago
parent
commit
3b391fe80e

+ 3 - 0
docs/MIRLangRef.rst

@@ -529,6 +529,9 @@ corresponding internal ``llvm::RegState`` representation:
    * - ``debug-use``
    * - ``debug-use``
      - ``RegState::Debug``
      - ``RegState::Debug``
 
 
+   * - ``renamable``
+     - ``RegState::Renamable``
+
 .. _subregister-indices:
 .. _subregister-indices:
 
 
 Subregister Indices
 Subregister Indices

+ 11 - 2
include/llvm/CodeGen/MachineInstrBuilder.h

@@ -25,6 +25,7 @@
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineInstrBundle.h"
 #include "llvm/CodeGen/MachineInstrBundle.h"
 #include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -48,6 +49,7 @@ namespace RegState {
     EarlyClobber   = 0x40,
     EarlyClobber   = 0x40,
     Debug          = 0x80,
     Debug          = 0x80,
     InternalRead   = 0x100,
     InternalRead   = 0x100,
+    Renamable      = 0x200,
     DefineNoRead   = Define | Undef,
     DefineNoRead   = Define | Undef,
     ImplicitDefine = Implicit | Define,
     ImplicitDefine = Implicit | Define,
     ImplicitKill   = Implicit | Kill
     ImplicitKill   = Implicit | Kill
@@ -91,7 +93,8 @@ public:
                                                flags & RegState::EarlyClobber,
                                                flags & RegState::EarlyClobber,
                                                SubReg,
                                                SubReg,
                                                flags & RegState::Debug,
                                                flags & RegState::Debug,
-                                               flags & RegState::InternalRead));
+                                               flags & RegState::InternalRead,
+                                               flags & RegState::Renamable));
     return *this;
     return *this;
   }
   }
 
 
@@ -443,6 +446,9 @@ inline unsigned getInternalReadRegState(bool B) {
 inline unsigned getDebugRegState(bool B) {
 inline unsigned getDebugRegState(bool B) {
   return B ? RegState::Debug : 0;
   return B ? RegState::Debug : 0;
 }
 }
+inline unsigned getRenamableRegState(bool B) {
+  return B ? RegState::Renamable : 0;
+}
 
 
 /// Get all register state flags from machine operand \p RegOp.
 /// Get all register state flags from machine operand \p RegOp.
 inline unsigned getRegState(const MachineOperand &RegOp) {
 inline unsigned getRegState(const MachineOperand &RegOp) {
@@ -453,7 +459,10 @@ inline unsigned getRegState(const MachineOperand &RegOp) {
          getDeadRegState(RegOp.isDead())                  |
          getDeadRegState(RegOp.isDead())                  |
          getUndefRegState(RegOp.isUndef())                |
          getUndefRegState(RegOp.isUndef())                |
          getInternalReadRegState(RegOp.isInternalRead())  |
          getInternalReadRegState(RegOp.isInternalRead())  |
-         getDebugRegState(RegOp.isDebug());
+         getDebugRegState(RegOp.isDebug())                |
+         getRenamableRegState(
+             TargetRegisterInfo::isPhysicalRegister(RegOp.getReg()) &&
+             RegOp.isRenamable());
 }
 }
 
 
 /// Helper class for constructing bundles of MachineInstrs.
 /// Helper class for constructing bundles of MachineInstrs.

+ 32 - 17
include/llvm/CodeGen/MachineOperand.h

@@ -86,24 +86,30 @@ private:
   /// before MachineInstr::tieOperands().
   /// before MachineInstr::tieOperands().
   unsigned char TiedTo : 4;
   unsigned char TiedTo : 4;
 
 
-  /// IsDef/IsImp/IsKill/IsDead flags - These are only valid for MO_Register
-  /// operands.
-
   /// IsDef - True if this is a def, false if this is a use of the register.
   /// IsDef - True if this is a def, false if this is a use of the register.
+  /// This is only valid on register operands.
   ///
   ///
   bool IsDef : 1;
   bool IsDef : 1;
 
 
   /// IsImp - True if this is an implicit def or use, false if it is explicit.
   /// IsImp - True if this is an implicit def or use, false if it is explicit.
+  /// This is only valid on register opderands.
   ///
   ///
   bool IsImp : 1;
   bool IsImp : 1;
 
 
-  /// IsKill - True if this instruction is the last use of the register on this
-  /// path through the function.  This is only valid on uses of registers.
-  bool IsKill : 1;
-
-  /// IsDead - True if this register is never used by a subsequent instruction.
-  /// This is only valid on definitions of registers.
-  bool IsDead : 1;
+  /// IsDeadOrKill
+  /// For uses: IsKill - True if this instruction is the last use of the
+  /// register on this path through the function.
+  /// For defs: IsDead - True if this register is never used by a subsequent
+  /// instruction.
+  /// This is only valid on register operands.
+  bool IsDeadOrKill : 1;
+
+  /// IsRenamable - True if this register may be renamed, i.e. it does not
+  /// generate a value that is somehow read in a way that is not represented by
+  /// the Machine IR (e.g. to meet an ABI or ISA requirement).  This is only
+  /// valid on physical register operands.  Virtual registers are assumed to
+  /// always be renamable regardless of the value of this field.
+  bool IsRenamable : 1;
 
 
   /// IsUndef - True if this register operand reads an "undef" value, i.e. the
   /// IsUndef - True if this register operand reads an "undef" value, i.e. the
   /// read value doesn't matter.  This flag can be set on both use and def
   /// read value doesn't matter.  This flag can be set on both use and def
@@ -333,12 +339,12 @@ public:
 
 
   bool isDead() const {
   bool isDead() const {
     assert(isReg() && "Wrong MachineOperand accessor");
     assert(isReg() && "Wrong MachineOperand accessor");
-    return IsDead;
+    return IsDeadOrKill & IsDef;
   }
   }
 
 
   bool isKill() const {
   bool isKill() const {
     assert(isReg() && "Wrong MachineOperand accessor");
     assert(isReg() && "Wrong MachineOperand accessor");
-    return IsKill;
+    return IsDeadOrKill & !IsDef;
   }
   }
 
 
   bool isUndef() const {
   bool isUndef() const {
@@ -346,6 +352,8 @@ public:
     return IsUndef;
     return IsUndef;
   }
   }
 
 
+  bool isRenamable() const;
+
   bool isInternalRead() const {
   bool isInternalRead() const {
     assert(isReg() && "Wrong MachineOperand accessor");
     assert(isReg() && "Wrong MachineOperand accessor");
     return IsInternalRead;
     return IsInternalRead;
@@ -418,12 +426,12 @@ public:
   void setIsKill(bool Val = true) {
   void setIsKill(bool Val = true) {
     assert(isReg() && !IsDef && "Wrong MachineOperand mutator");
     assert(isReg() && !IsDef && "Wrong MachineOperand mutator");
     assert((!Val || !isDebug()) && "Marking a debug operation as kill");
     assert((!Val || !isDebug()) && "Marking a debug operation as kill");
-    IsKill = Val;
+    IsDeadOrKill = Val;
   }
   }
 
 
   void setIsDead(bool Val = true) {
   void setIsDead(bool Val = true) {
     assert(isReg() && IsDef && "Wrong MachineOperand mutator");
     assert(isReg() && IsDef && "Wrong MachineOperand mutator");
-    IsDead = Val;
+    IsDeadOrKill = Val;
   }
   }
 
 
   void setIsUndef(bool Val = true) {
   void setIsUndef(bool Val = true) {
@@ -431,6 +439,12 @@ public:
     IsUndef = Val;
     IsUndef = Val;
   }
   }
 
 
+  void setIsRenamable(bool Val = true);
+
+  /// Set IsRenamable to true if there are no extra register allocation
+  /// requirements placed on this operand by the parent instruction's opcode.
+  void setIsRenamableIfNoExtraRegAllocReq();
+
   void setIsInternalRead(bool Val = true) {
   void setIsInternalRead(bool Val = true) {
     assert(isReg() && "Wrong MachineOperand mutator");
     assert(isReg() && "Wrong MachineOperand mutator");
     IsInternalRead = Val;
     IsInternalRead = Val;
@@ -675,14 +689,15 @@ public:
                                   bool isUndef = false,
                                   bool isUndef = false,
                                   bool isEarlyClobber = false,
                                   bool isEarlyClobber = false,
                                   unsigned SubReg = 0, bool isDebug = false,
                                   unsigned SubReg = 0, bool isDebug = false,
-                                  bool isInternalRead = false) {
+                                  bool isInternalRead = false,
+                                  bool isRenamable = false) {
     assert(!(isDead && !isDef) && "Dead flag on non-def");
     assert(!(isDead && !isDef) && "Dead flag on non-def");
     assert(!(isKill && isDef) && "Kill flag on def");
     assert(!(isKill && isDef) && "Kill flag on def");
     MachineOperand Op(MachineOperand::MO_Register);
     MachineOperand Op(MachineOperand::MO_Register);
     Op.IsDef = isDef;
     Op.IsDef = isDef;
     Op.IsImp = isImp;
     Op.IsImp = isImp;
-    Op.IsKill = isKill;
-    Op.IsDead = isDead;
+    Op.IsDeadOrKill = isKill | isDead;
+    Op.IsRenamable = isRenamable;
     Op.IsUndef = isUndef;
     Op.IsUndef = isUndef;
     Op.IsInternalRead = isInternalRead;
     Op.IsInternalRead = isInternalRead;
     Op.IsEarlyClobber = isEarlyClobber;
     Op.IsEarlyClobber = isEarlyClobber;

+ 1 - 0
lib/CodeGen/MIRParser/MILexer.cpp

@@ -208,6 +208,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
       .Case("internal", MIToken::kw_internal)
       .Case("internal", MIToken::kw_internal)
       .Case("early-clobber", MIToken::kw_early_clobber)
       .Case("early-clobber", MIToken::kw_early_clobber)
       .Case("debug-use", MIToken::kw_debug_use)
       .Case("debug-use", MIToken::kw_debug_use)
+      .Case("renamable", MIToken::kw_renamable)
       .Case("tied-def", MIToken::kw_tied_def)
       .Case("tied-def", MIToken::kw_tied_def)
       .Case("frame-setup", MIToken::kw_frame_setup)
       .Case("frame-setup", MIToken::kw_frame_setup)
       .Case("debug-location", MIToken::kw_debug_location)
       .Case("debug-location", MIToken::kw_debug_location)

+ 3 - 1
lib/CodeGen/MIRParser/MILexer.h

@@ -60,6 +60,7 @@ struct MIToken {
     kw_internal,
     kw_internal,
     kw_early_clobber,
     kw_early_clobber,
     kw_debug_use,
     kw_debug_use,
+    kw_renamable,
     kw_tied_def,
     kw_tied_def,
     kw_frame_setup,
     kw_frame_setup,
     kw_debug_location,
     kw_debug_location,
@@ -166,7 +167,8 @@ public:
     return Kind == kw_implicit || Kind == kw_implicit_define ||
     return Kind == kw_implicit || Kind == kw_implicit_define ||
            Kind == kw_def || Kind == kw_dead || Kind == kw_killed ||
            Kind == kw_def || Kind == kw_dead || Kind == kw_killed ||
            Kind == kw_undef || Kind == kw_internal ||
            Kind == kw_undef || Kind == kw_internal ||
-           Kind == kw_early_clobber || Kind == kw_debug_use;
+           Kind == kw_early_clobber || Kind == kw_debug_use ||
+           Kind == kw_renamable;
   }
   }
 
 
   bool isMemoryOperandFlag() const {
   bool isMemoryOperandFlag() const {

+ 6 - 1
lib/CodeGen/MIRParser/MIParser.cpp

@@ -1060,6 +1060,9 @@ bool MIParser::parseRegisterFlag(unsigned &Flags) {
   case MIToken::kw_debug_use:
   case MIToken::kw_debug_use:
     Flags |= RegState::Debug;
     Flags |= RegState::Debug;
     break;
     break;
+  case MIToken::kw_renamable:
+    Flags |= RegState::Renamable;
+    break;
   default:
   default:
     llvm_unreachable("The current token should be a register flag");
     llvm_unreachable("The current token should be a register flag");
   }
   }
@@ -1212,7 +1215,8 @@ bool MIParser::parseRegisterOperand(MachineOperand &Dest,
       Reg, Flags & RegState::Define, Flags & RegState::Implicit,
       Reg, Flags & RegState::Define, Flags & RegState::Implicit,
       Flags & RegState::Kill, Flags & RegState::Dead, Flags & RegState::Undef,
       Flags & RegState::Kill, Flags & RegState::Dead, Flags & RegState::Undef,
       Flags & RegState::EarlyClobber, SubReg, Flags & RegState::Debug,
       Flags & RegState::EarlyClobber, SubReg, Flags & RegState::Debug,
-      Flags & RegState::InternalRead);
+      Flags & RegState::InternalRead, Flags & RegState::Renamable);
+
   return false;
   return false;
 }
 }
 
 
@@ -1880,6 +1884,7 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest,
   case MIToken::kw_internal:
   case MIToken::kw_internal:
   case MIToken::kw_early_clobber:
   case MIToken::kw_early_clobber:
   case MIToken::kw_debug_use:
   case MIToken::kw_debug_use:
+  case MIToken::kw_renamable:
   case MIToken::underscore:
   case MIToken::underscore:
   case MIToken::NamedRegister:
   case MIToken::NamedRegister:
   case MIToken::VirtualRegister:
   case MIToken::VirtualRegister:

+ 35 - 2
lib/CodeGen/MachineOperand.cpp

@@ -90,6 +90,7 @@ void MachineOperand::setIsDef(bool Val) {
   assert((!Val || !isDebug()) && "Marking a debug operation as def");
   assert((!Val || !isDebug()) && "Marking a debug operation as def");
   if (IsDef == Val)
   if (IsDef == Val)
     return;
     return;
+  assert(!IsDeadOrKill && "Changing def/use with dead/kill set not supported");
   // MRI may keep uses and defs in different list positions.
   // MRI may keep uses and defs in different list positions.
   if (MachineFunction *MF = getMFIfAvailable(*this)) {
   if (MachineFunction *MF = getMFIfAvailable(*this)) {
     MachineRegisterInfo &MRI = MF->getRegInfo();
     MachineRegisterInfo &MRI = MF->getRegInfo();
@@ -101,6 +102,34 @@ void MachineOperand::setIsDef(bool Val) {
   IsDef = Val;
   IsDef = Val;
 }
 }
 
 
+bool MachineOperand::isRenamable() const {
+  assert(isReg() && "Wrong MachineOperand accessor");
+  assert(TargetRegisterInfo::isPhysicalRegister(getReg()) &&
+         "isRenamable should only be checked on physical registers");
+  return IsRenamable;
+}
+
+void MachineOperand::setIsRenamable(bool Val) {
+  assert(isReg() && "Wrong MachineOperand accessor");
+  assert(TargetRegisterInfo::isPhysicalRegister(getReg()) &&
+         "setIsRenamable should only be called on physical registers");
+  if (const MachineInstr *MI = getParent())
+    if ((isDef() && MI->hasExtraDefRegAllocReq()) ||
+        (isUse() && MI->hasExtraSrcRegAllocReq()))
+      assert(!Val && "isRenamable should be false for "
+                     "hasExtraDefRegAllocReq/hasExtraSrcRegAllocReq opcodes");
+  IsRenamable = Val;
+}
+
+void MachineOperand::setIsRenamableIfNoExtraRegAllocReq() {
+  if (const MachineInstr *MI = getParent())
+    if ((isDef() && MI->hasExtraDefRegAllocReq()) ||
+        (isUse() && MI->hasExtraSrcRegAllocReq()))
+      return;
+
+  setIsRenamable(true);
+}
+
 // If this operand is currently a register operand, and if this is in a
 // If this operand is currently a register operand, and if this is in a
 // function, deregister the operand from the register's use/def list.
 // function, deregister the operand from the register's use/def list.
 void MachineOperand::removeRegFromUses() {
 void MachineOperand::removeRegFromUses() {
@@ -194,13 +223,15 @@ void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp,
     RegInfo->removeRegOperandFromUseList(this);
     RegInfo->removeRegOperandFromUseList(this);
 
 
   // Change this to a register and set the reg#.
   // Change this to a register and set the reg#.
+  assert(!(isDead && !isDef) && "Dead flag on non-def");
+  assert(!(isKill && isDef) && "Kill flag on def");
   OpKind = MO_Register;
   OpKind = MO_Register;
   SmallContents.RegNo = Reg;
   SmallContents.RegNo = Reg;
   SubReg_TargetFlags = 0;
   SubReg_TargetFlags = 0;
   IsDef = isDef;
   IsDef = isDef;
   IsImp = isImp;
   IsImp = isImp;
-  IsKill = isKill;
-  IsDead = isDead;
+  IsDeadOrKill = isKill | isDead;
+  IsRenamable = false;
   IsUndef = isUndef;
   IsUndef = isUndef;
   IsInternalRead = false;
   IsInternalRead = false;
   IsEarlyClobber = false;
   IsEarlyClobber = false;
@@ -389,6 +420,8 @@ void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
       OS << "early-clobber ";
       OS << "early-clobber ";
     if (isDebug())
     if (isDebug())
       OS << "debug-use ";
       OS << "debug-use ";
+    if (TargetRegisterInfo::isPhysicalRegister(getReg()) && isRenamable())
+      OS << "renamable ";
     OS << printReg(Reg, TRI);
     OS << printReg(Reg, TRI);
     // Print the sub register.
     // Print the sub register.
     if (unsigned SubReg = getSubReg()) {
     if (unsigned SubReg = getSubReg()) {

+ 8 - 0
lib/CodeGen/MachineVerifier.cpp

@@ -1101,6 +1101,14 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
           }
           }
         }
         }
       }
       }
+      if (MO->isRenamable() &&
+          ((MO->isDef() && MI->hasExtraDefRegAllocReq()) ||
+           (MO->isUse() && MI->hasExtraSrcRegAllocReq()))) {
+        report("Illegal isRenamable setting for opcode with extra regalloc "
+               "requirements",
+               MO, MONum);
+        return;
+      }
     } else {
     } else {
       // Virtual register.
       // Virtual register.
       const TargetRegisterClass *RC = MRI->getRegClassOrNull(Reg);
       const TargetRegisterClass *RC = MRI->getRegClassOrNull(Reg);

+ 2 - 0
lib/CodeGen/RegAllocFast.cpp

@@ -699,11 +699,13 @@ bool RegAllocFast::setPhysReg(MachineInstr &MI, unsigned OpNum,
   bool Dead = MO.isDead();
   bool Dead = MO.isDead();
   if (!MO.getSubReg()) {
   if (!MO.getSubReg()) {
     MO.setReg(PhysReg);
     MO.setReg(PhysReg);
+    MO.setIsRenamableIfNoExtraRegAllocReq();
     return MO.isKill() || Dead;
     return MO.isKill() || Dead;
   }
   }
 
 
   // Handle subregister index.
   // Handle subregister index.
   MO.setReg(PhysReg ? TRI->getSubReg(PhysReg, MO.getSubReg()) : 0);
   MO.setReg(PhysReg ? TRI->getSubReg(PhysReg, MO.getSubReg()) : 0);
+  MO.setIsRenamableIfNoExtraRegAllocReq();
   MO.setSubReg(0);
   MO.setSubReg(0);
 
 
   // A kill flag implies killing the full register. Add corresponding super
   // A kill flag implies killing the full register. Add corresponding super

+ 1 - 0
lib/CodeGen/VirtRegMap.cpp

@@ -530,6 +530,7 @@ void VirtRegRewriter::rewrite() {
         // Rewrite. Note we could have used MachineOperand::substPhysReg(), but
         // Rewrite. Note we could have used MachineOperand::substPhysReg(), but
         // we need the inlining here.
         // we need the inlining here.
         MO.setReg(PhysReg);
         MO.setReg(PhysReg);
+        MO.setIsRenamableIfNoExtraRegAllocReq();
       }
       }
 
 
       // Add any missing super-register kills after rewriting the whole
       // Add any missing super-register kills after rewriting the whole

+ 13 - 4
lib/Target/ARM/ARMBaseInstrInfo.cpp

@@ -1357,25 +1357,34 @@ void ARMBaseInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const {
 
 
   MachineInstrBuilder LDM, STM;
   MachineInstrBuilder LDM, STM;
   if (isThumb1 || !MI->getOperand(1).isDead()) {
   if (isThumb1 || !MI->getOperand(1).isDead()) {
+    MachineOperand LDWb(MI->getOperand(1));
+    LDWb.setIsRenamable(false);
     LDM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2LDMIA_UPD
     LDM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2LDMIA_UPD
                                                  : isThumb1 ? ARM::tLDMIA_UPD
                                                  : isThumb1 ? ARM::tLDMIA_UPD
                                                             : ARM::LDMIA_UPD))
                                                             : ARM::LDMIA_UPD))
-              .add(MI->getOperand(1));
+              .add(LDWb);
   } else {
   } else {
     LDM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2LDMIA : ARM::LDMIA));
     LDM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2LDMIA : ARM::LDMIA));
   }
   }
 
 
   if (isThumb1 || !MI->getOperand(0).isDead()) {
   if (isThumb1 || !MI->getOperand(0).isDead()) {
+    MachineOperand STWb(MI->getOperand(0));
+    STWb.setIsRenamable(false);
     STM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2STMIA_UPD
     STM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2STMIA_UPD
                                                  : isThumb1 ? ARM::tSTMIA_UPD
                                                  : isThumb1 ? ARM::tSTMIA_UPD
                                                             : ARM::STMIA_UPD))
                                                             : ARM::STMIA_UPD))
-              .add(MI->getOperand(0));
+              .add(STWb);
   } else {
   } else {
     STM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2STMIA : ARM::STMIA));
     STM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2STMIA : ARM::STMIA));
   }
   }
 
 
-  LDM.add(MI->getOperand(3)).add(predOps(ARMCC::AL));
-  STM.add(MI->getOperand(2)).add(predOps(ARMCC::AL));
+  MachineOperand LDBase(MI->getOperand(3));
+  LDBase.setIsRenamable(false);
+  LDM.add(LDBase).add(predOps(ARMCC::AL));
+
+  MachineOperand STBase(MI->getOperand(2));
+  STBase.setIsRenamable(false);
+  STM.add(STBase).add(predOps(ARMCC::AL));
 
 
   // Sort the scratch registers into ascending order.
   // Sort the scratch registers into ascending order.
   const TargetRegisterInfo &TRI = getRegisterInfo();
   const TargetRegisterInfo &TRI = getRegisterInfo();

+ 8 - 3
lib/Target/ARM/ARMExpandPseudoInsts.cpp

@@ -606,8 +606,11 @@ void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI,
 
 
   // Transfer the destination register operand.
   // Transfer the destination register operand.
   MIB.add(MI.getOperand(OpIdx++));
   MIB.add(MI.getOperand(OpIdx++));
-  if (IsExt)
-    MIB.add(MI.getOperand(OpIdx++));
+  if (IsExt) {
+    MachineOperand VdSrc(MI.getOperand(OpIdx++));
+    VdSrc.setIsRenamable(false);
+    MIB.add(VdSrc);
+  }
 
 
   bool SrcIsKill = MI.getOperand(OpIdx).isKill();
   bool SrcIsKill = MI.getOperand(OpIdx).isKill();
   unsigned SrcReg = MI.getOperand(OpIdx++).getReg();
   unsigned SrcReg = MI.getOperand(OpIdx++).getReg();
@@ -616,7 +619,9 @@ void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI,
   MIB.addReg(D0);
   MIB.addReg(D0);
 
 
   // Copy the other source register operand.
   // Copy the other source register operand.
-  MIB.add(MI.getOperand(OpIdx++));
+  MachineOperand VmSrc(MI.getOperand(OpIdx++));
+  VmSrc.setIsRenamable(false);
+  MIB.add(VmSrc);
 
 
   // Copy the predicate operands.
   // Copy the predicate operands.
   MIB.add(MI.getOperand(OpIdx++));
   MIB.add(MI.getOperand(OpIdx++));

+ 4 - 1
lib/Target/ARM/ARMISelLowering.cpp

@@ -8974,8 +8974,11 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
 
 
   // Thumb1 post-indexed loads are really just single-register LDMs.
   // Thumb1 post-indexed loads are really just single-register LDMs.
   case ARM::tLDR_postidx: {
   case ARM::tLDR_postidx: {
+    MachineOperand Def(MI.getOperand(1));
+    if (TargetRegisterInfo::isPhysicalRegister(Def.getReg()))
+      Def.setIsRenamable(false);
     BuildMI(*BB, MI, dl, TII->get(ARM::tLDMIA_UPD))
     BuildMI(*BB, MI, dl, TII->get(ARM::tLDMIA_UPD))
-        .add(MI.getOperand(1))  // Rn_wb
+        .add(Def)  // Rn_wb
         .add(MI.getOperand(2))  // Rn
         .add(MI.getOperand(2))  // Rn
         .add(MI.getOperand(3))  // PredImm
         .add(MI.getOperand(3))  // PredImm
         .add(MI.getOperand(4))  // PredReg
         .add(MI.getOperand(4))  // PredReg

+ 2 - 2
test/CodeGen/AArch64/arm64-misched-multimmo.ll

@@ -8,11 +8,11 @@
 ; Check that no scheduling dependencies are created between the paired loads and the store during post-RA MI scheduling.
 ; Check that no scheduling dependencies are created between the paired loads and the store during post-RA MI scheduling.
 ;
 ;
 ; CHECK-LABEL: # Machine code for function foo:
 ; CHECK-LABEL: # Machine code for function foo:
-; CHECK: SU(2):   %w{{[0-9]+}}, %w{{[0-9]+}} = LDPWi
+; CHECK: SU(2):   renamable %w{{[0-9]+}}, renamable %w{{[0-9]+}} = LDPWi
 ; CHECK: Successors:
 ; CHECK: Successors:
 ; CHECK-NOT: ch SU(4)
 ; CHECK-NOT: ch SU(4)
 ; CHECK: SU(3)
 ; CHECK: SU(3)
-; CHECK: SU(4):   STRWui %wzr, %x{{[0-9]+}}
+; CHECK: SU(4):   STRWui %wzr, renamable %x{{[0-9]+}}
 define i32 @foo() {
 define i32 @foo() {
 entry:
 entry:
   %0 = load i32, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @G2, i64 0, i64 0), align 4
   %0 = load i32, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @G2, i64 0, i64 0), align 4

+ 4 - 4
test/CodeGen/AMDGPU/shrink-carry.mir

@@ -1,7 +1,7 @@
 # RUN: llc -march=amdgcn -verify-machineinstrs -start-before si-shrink-instructions -stop-before si-insert-skips -o - %s | FileCheck -check-prefix=GCN %s
 # RUN: llc -march=amdgcn -verify-machineinstrs -start-before si-shrink-instructions -stop-before si-insert-skips -o - %s | FileCheck -check-prefix=GCN %s
 
 
 # GCN-LABEL: name: subbrev{{$}}
 # GCN-LABEL: name: subbrev{{$}}
-# GCN:       V_SUBBREV_U32_e64 0, undef %vgpr0, killed %vcc, implicit %exec
+# GCN:       V_SUBBREV_U32_e64 0, undef %vgpr0, killed renamable %vcc, implicit %exec
 
 
 ---
 ---
 name:            subbrev
 name:            subbrev
@@ -25,7 +25,7 @@ body:             |
 ...
 ...
 
 
 # GCN-LABEL: name: subb{{$}}
 # GCN-LABEL: name: subb{{$}}
-# GCN:       V_SUBB_U32_e64 undef %vgpr0, 0, killed %vcc, implicit %exec
+# GCN:       V_SUBB_U32_e64 undef %vgpr0, 0, killed renamable %vcc, implicit %exec
 
 
 ---
 ---
 name:            subb
 name:            subb
@@ -49,7 +49,7 @@ body:             |
 ...
 ...
 
 
 # GCN-LABEL: name: addc{{$}}
 # GCN-LABEL: name: addc{{$}}
-# GCN:       V_ADDC_U32_e32 0, undef %vgpr0, implicit-def %vcc, implicit killed %vcc, implicit %exec
+# GCN:       V_ADDC_U32_e32 0, undef renamable %vgpr0, implicit-def %vcc, implicit killed %vcc, implicit %exec
 
 
 ---
 ---
 name:            addc
 name:            addc
@@ -73,7 +73,7 @@ body:             |
 ...
 ...
 
 
 # GCN-LABEL: name: addc2{{$}}
 # GCN-LABEL: name: addc2{{$}}
-# GCN:       V_ADDC_U32_e32 0, undef %vgpr0, implicit-def %vcc, implicit killed %vcc, implicit %exec
+# GCN:       V_ADDC_U32_e32 0, undef renamable %vgpr0, implicit-def %vcc, implicit killed %vcc, implicit %exec
 
 
 ---
 ---
 name:            addc2
 name:            addc2

+ 8 - 8
test/CodeGen/AMDGPU/splitkit.mir

@@ -37,13 +37,13 @@ body: |
 # CHECK: [[REG0:%sgpr[0-9]+]] = COPY %sgpr0
 # CHECK: [[REG0:%sgpr[0-9]+]] = COPY %sgpr0
 # CHECK: [[REG1:%sgpr[0-9]+]] = COPY %sgpr2
 # CHECK: [[REG1:%sgpr[0-9]+]] = COPY %sgpr2
 # CHECK: S_NOP 0
 # CHECK: S_NOP 0
-# CHECK: S_NOP 0, implicit [[REG0]]
-# CHECK: S_NOP 0, implicit [[REG1]]
-# CHECK: %sgpr0 = COPY [[REG0]]
-# CHECK: %sgpr2 = COPY [[REG1]]
+# CHECK: S_NOP 0, implicit renamable [[REG0]]
+# CHECK: S_NOP 0, implicit renamable [[REG1]]
+# CHECK: %sgpr0 = COPY renamable [[REG0]]
+# CHECK: %sgpr2 = COPY renamable [[REG1]]
 # CHECK: S_NOP
 # CHECK: S_NOP
-# CHECK: S_NOP 0, implicit %sgpr0
-# CHECK: S_NOP 0, implicit %sgpr2
+# CHECK: S_NOP 0, implicit renamable %sgpr0
+# CHECK: S_NOP 0, implicit renamable %sgpr2
 name: func1
 name: func1
 tracksRegLiveness: true
 tracksRegLiveness: true
 body: |
 body: |
@@ -67,8 +67,8 @@ body: |
 # Check that copy hoisting out of loops works. This mainly should not crash the
 # Check that copy hoisting out of loops works. This mainly should not crash the
 # compiler when it hoists a subreg copy sequence.
 # compiler when it hoists a subreg copy sequence.
 # CHECK-LABEL: name: splitHoist
 # CHECK-LABEL: name: splitHoist
-# CHECK: S_NOP 0, implicit-def %sgpr0
-# CHECK: S_NOP 0, implicit-def %sgpr3
+# CHECK: S_NOP 0, implicit-def renamable %sgpr0
+# CHECK: S_NOP 0, implicit-def renamable %sgpr3
 # CHECK-NEXT: SI_SPILL_S128_SAVE
 # CHECK-NEXT: SI_SPILL_S128_SAVE
 name: splitHoist
 name: splitHoist
 tracksRegLiveness: true
 tracksRegLiveness: true

+ 2 - 2
test/CodeGen/AMDGPU/stack-slot-color-sgpr-vgpr-spills.mir

@@ -9,10 +9,10 @@
 # CHECK: - { id: 1, name: '', type: spill-slot, offset: 0, size: 4, alignment: 4,
 # CHECK: - { id: 1, name: '', type: spill-slot, offset: 0, size: 4, alignment: 4,
 # CHECK-NEXT: stack-id: 1,
 # CHECK-NEXT: stack-id: 1,
 
 
-# CHECK: SI_SPILL_V32_SAVE killed %vgpr0, %stack.0, %sgpr0_sgpr1_sgpr2_sgpr3, %sgpr5, 0, implicit %exec :: (store 4 into %stack.0)
+# CHECK: SI_SPILL_V32_SAVE killed renamable %vgpr0, %stack.0, %sgpr0_sgpr1_sgpr2_sgpr3, %sgpr5, 0, implicit %exec :: (store 4 into %stack.0)
 # CHECK: %vgpr0 = SI_SPILL_V32_RESTORE %stack.0, %sgpr0_sgpr1_sgpr2_sgpr3, %sgpr5, 0, implicit %exec :: (load 4 from %stack.0)
 # CHECK: %vgpr0 = SI_SPILL_V32_RESTORE %stack.0, %sgpr0_sgpr1_sgpr2_sgpr3, %sgpr5, 0, implicit %exec :: (load 4 from %stack.0)
 
 
-# CHECK: SI_SPILL_S32_SAVE killed %sgpr6, %stack.1, implicit %exec, implicit %sgpr0_sgpr1_sgpr2_sgpr3, implicit %sgpr5, implicit-def dead %m0 :: (store 4 into %stack.1)
+# CHECK: SI_SPILL_S32_SAVE killed renamable %sgpr6, %stack.1, implicit %exec, implicit %sgpr0_sgpr1_sgpr2_sgpr3, implicit %sgpr5, implicit-def dead %m0 :: (store 4 into %stack.1)
 # CHECK: %sgpr6 = SI_SPILL_S32_RESTORE %stack.1, implicit %exec, implicit %sgpr0_sgpr1_sgpr2_sgpr3, implicit %sgpr5, implicit-def dead %m0 :: (load 4 from %stack.1)
 # CHECK: %sgpr6 = SI_SPILL_S32_RESTORE %stack.1, implicit %exec, implicit %sgpr0_sgpr1_sgpr2_sgpr3, implicit %sgpr5, implicit-def dead %m0 :: (load 4 from %stack.1)
 
 
 name: no_merge_sgpr_vgpr_spill_slot
 name: no_merge_sgpr_vgpr_spill_slot

+ 6 - 6
test/CodeGen/AMDGPU/subreg_interference.mir

@@ -12,12 +12,12 @@
 # sgpr0-sgpr3.
 # sgpr0-sgpr3.
 #
 #
 # CHECK-LABEL: func0
 # CHECK-LABEL: func0
-# CHECK: S_NOP 0, implicit-def %sgpr0
-# CHECK: S_NOP 0, implicit-def %sgpr3
-# CHECK: S_NOP 0, implicit-def %sgpr1
-# CHECK: S_NOP 0, implicit-def %sgpr2
-# CHECK: S_NOP 0, implicit %sgpr0, implicit %sgpr3
-# CHECK: S_NOP 0, implicit %sgpr1, implicit %sgpr2
+# CHECK: S_NOP 0, implicit-def renamable %sgpr0
+# CHECK: S_NOP 0, implicit-def renamable %sgpr3
+# CHECK: S_NOP 0, implicit-def renamable %sgpr1
+# CHECK: S_NOP 0, implicit-def renamable %sgpr2
+# CHECK: S_NOP 0, implicit renamable %sgpr0, implicit renamable %sgpr3
+# CHECK: S_NOP 0, implicit renamable %sgpr1, implicit renamable %sgpr2
 name: func0
 name: func0
 body: |
 body: |
   bb.0:
   bb.0:

+ 3 - 3
test/CodeGen/AMDGPU/syncscopes.ll

@@ -1,9 +1,9 @@
 ; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx803 -stop-before=si-debugger-insert-nops < %s | FileCheck --check-prefix=GCN %s
 ; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx803 -stop-before=si-debugger-insert-nops < %s | FileCheck --check-prefix=GCN %s
 
 
 ; GCN-LABEL: name: syncscopes
 ; GCN-LABEL: name: syncscopes
-; GCN: FLAT_STORE_DWORD killed %vgpr1_vgpr2, killed %vgpr0, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store syncscope("agent") seq_cst 4 into %ir.agent_out)
-; GCN: FLAT_STORE_DWORD killed %vgpr4_vgpr5, killed %vgpr3, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store syncscope("workgroup") seq_cst 4 into %ir.workgroup_out)
-; GCN: FLAT_STORE_DWORD killed %vgpr7_vgpr8, killed %vgpr6, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store syncscope("wavefront") seq_cst 4 into %ir.wavefront_out)
+; GCN: FLAT_STORE_DWORD killed renamable %vgpr1_vgpr2, killed renamable %vgpr0, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store syncscope("agent") seq_cst 4 into %ir.agent_out)
+; GCN: FLAT_STORE_DWORD killed renamable %vgpr4_vgpr5, killed renamable %vgpr3, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store syncscope("workgroup") seq_cst 4 into %ir.workgroup_out)
+; GCN: FLAT_STORE_DWORD killed renamable %vgpr7_vgpr8, killed renamable %vgpr6, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store syncscope("wavefront") seq_cst 4 into %ir.wavefront_out)
 define void @syncscopes(
 define void @syncscopes(
     i32 %agent,
     i32 %agent,
     i32 addrspace(4)* %agent_out,
     i32 addrspace(4)* %agent_out,

+ 1 - 1
test/CodeGen/Hexagon/regalloc-bad-undef.mir

@@ -153,7 +153,7 @@ body:             |
     %13 = S2_asl_r_p_acc %13, %47, %8.isub_lo
     %13 = S2_asl_r_p_acc %13, %47, %8.isub_lo
     %51 = A2_tfrpi 0
     %51 = A2_tfrpi 0
 
 
-    ; CHECK: %d2 = S2_extractup undef %d0, 6, 25
+    ; CHECK: %d2 = S2_extractup undef renamable %d0, 6, 25
     ; CHECK: %d0 = A2_tfrpi 2
     ; CHECK: %d0 = A2_tfrpi 2
     ; CHECK: %d13 = A2_tfrpi -1
     ; CHECK: %d13 = A2_tfrpi -1
     ; CHECK-NOT: undef %r4
     ; CHECK-NOT: undef %r4

+ 16 - 0
test/CodeGen/MIR/X86/renamable-register-flag.mir

@@ -0,0 +1,16 @@
+# RUN: llc -march=x86-64 -run-pass none -o - %s | FileCheck %s
+# This test ensures that the MIR parser parses the 'renamable' register flags
+# correctly.
+
+--- |
+  define void @foo() { ret void }
+...
+---
+name:            foo
+body: |
+  ; CHECK: bb.0:
+  bb.0:
+    ; CHECK: renamable %eax = IMUL32rri8 %edi, 11, implicit-def dead %eflags
+    renamable %eax = IMUL32rri8 %edi, 11, implicit-def dead %eflags
+    RETQ %eax
+...

+ 1 - 1
test/CodeGen/PowerPC/byval-agg-info.ll

@@ -13,5 +13,5 @@ entry:
 
 
 ; Make sure that the MMO on the store has no offset from the byval
 ; Make sure that the MMO on the store has no offset from the byval
 ; variable itself (we used to have mem:ST8[%v+64]).
 ; variable itself (we used to have mem:ST8[%v+64]).
-; CHECK: STD killed %x5, 176, %x1; mem:ST8[%v](align=16)
+; CHECK: STD killed renamable %x5, 176, %x1; mem:ST8[%v](align=16)
 
 

+ 2 - 2
test/CodeGen/SystemZ/regalloc-fast-invalid-kill-flag.mir

@@ -18,11 +18,11 @@ registers:
   - { id: 1, class: gr64bit }
   - { id: 1, class: gr64bit }
   - { id: 2, class: addr64bit }
   - { id: 2, class: addr64bit }
 # CHECK: %r0q = L128
 # CHECK: %r0q = L128
-# CHECK-NEXT: %r0l = COPY %r1l
+# CHECK-NEXT: %r0l = COPY renamable %r1l
 # Although R0L partially redefines R0Q, it must not mark R0Q as kill
 # Although R0L partially redefines R0Q, it must not mark R0Q as kill
 # because R1D is still live through that instruction.
 # because R1D is still live through that instruction.
 # CHECK-NOT: implicit killed %r0q
 # CHECK-NOT: implicit killed %r0q
-# CHECK-NEXT: %r2d = COPY %r1d
+# CHECK-NEXT: %r2d = COPY renamable %r1d
 # CHECK-NEXT: LARL
 # CHECK-NEXT: LARL
 body:             |
 body:             |
   bb.0:
   bb.0:

+ 1 - 1
test/CodeGen/X86/tail-merge-debugloc.ll

@@ -6,7 +6,7 @@
 ; location info.
 ; location info.
 ; 
 ; 
 ; CHECK:      [[DLOC:![0-9]+]] = !DILocation(line: 2, column: 2, scope: !{{[0-9]+}})
 ; CHECK:      [[DLOC:![0-9]+]] = !DILocation(line: 2, column: 2, scope: !{{[0-9]+}})
-; CHECK:      TEST64rr{{.*}}%rsi, %rsi, implicit-def %eflags
+; CHECK:      TEST64rr{{.*}}%rsi, renamable %rsi, implicit-def %eflags
 ; CHECK-NEXT: JNE_1{{.*}}, debug-location [[DLOC]]
 ; CHECK-NEXT: JNE_1{{.*}}, debug-location [[DLOC]]
 
 
 target triple = "x86_64-unknown-linux-gnu"
 target triple = "x86_64-unknown-linux-gnu"

+ 2 - 2
test/DebugInfo/X86/pr34545.ll

@@ -2,11 +2,11 @@
 
 
 ; CHECK: %eax = MOV32rm
 ; CHECK: %eax = MOV32rm
 ; CHECK: DBG_VALUE %eax
 ; CHECK: DBG_VALUE %eax
-; CHECK: %eax = SHL32rCL killed %eax
+; CHECK: %eax = SHL32rCL killed renamable %eax
 ; CHECK: DBG_VALUE %eax
 ; CHECK: DBG_VALUE %eax
 ; CHECK: DBG_VALUE %rsp, 0, !{{[0-9]+}}, !DIExpression(DW_OP_constu, 4, DW_OP_minus)
 ; CHECK: DBG_VALUE %rsp, 0, !{{[0-9]+}}, !DIExpression(DW_OP_constu, 4, DW_OP_minus)
 ; CHECK: DBG_VALUE %eax
 ; CHECK: DBG_VALUE %eax
-; CHECK: %eax = SHL32rCL killed %eax
+; CHECK: %eax = SHL32rCL killed renamable %eax
 ; CHECK: DBG_VALUE %eax
 ; CHECK: DBG_VALUE %eax
 ; CHECK: RETQ %eax
 ; CHECK: RETQ %eax
 
 

+ 1 - 1
test/DebugInfo/X86/sdag-salvage-add.ll

@@ -28,7 +28,7 @@
 ; CHECK-SAME:           !DIExpression(DW_OP_plus_uconst, 4096, DW_OP_stack_value)
 ; CHECK-SAME:           !DIExpression(DW_OP_plus_uconst, 4096, DW_OP_stack_value)
 ; CHECK-NEXT: DBG_VALUE debug-use %rax, debug-use %noreg, ![[S4]],
 ; CHECK-NEXT: DBG_VALUE debug-use %rax, debug-use %noreg, ![[S4]],
 ; CHECK-SAME:           !DIExpression(DW_OP_plus_uconst, 4096, DW_OP_stack_value)
 ; CHECK-SAME:           !DIExpression(DW_OP_plus_uconst, 4096, DW_OP_stack_value)
-; CHECK-NEXT: %rdi = MOV64rm killed %rax, 1, %noreg, 4096, %noreg,
+; CHECK-NEXT: %rdi = MOV64rm killed renamable %rax, 1, %noreg, 4096, %noreg,
 
 
 source_filename = "test.c"
 source_filename = "test.c"
 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"