Allow <undef> flags on def operands as well as uses.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Tue, 4 Oct 2011 21:49:33 +0000 (21:49 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Tue, 4 Oct 2011 21:49:33 +0000 (21:49 +0000)
The <undef> flag says that a MachineOperand doesn't read its register,
or doesn't depend on the previous value of its register.

A full register def never depends on the previous register value.  A
partial register def may depend on the previous value if it is intended
to update part of a register.

For example:

  %vreg10:dsub_0<def,undef> = COPY %vreg1
  %vreg10:dsub_1<def> = COPY %vreg2

The first copy instruction defines the full %vreg10 register with the
bits not covered by dsub_0 defined as <undef>.  It is not considered a
read of %vreg10.

The second copy modifies part of %vreg10 while preserving the rest.  It
has an implicit read of %vreg10.

This patch adds a MachineOperand::readsReg() method to determine if an
operand reads its register.

Previously, this was modelled by adding a full-register <imp-def>
operand to the instruction.  This approach makes it possible to
determine directly from a MachineOperand if it reads its register.  No
scanning of MI operands is required.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141124 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/MachineOperand.h
lib/CodeGen/LiveIntervalAnalysis.cpp

index fdef574be932af2215289522773c503222f85b99..5440a636a4a54e098686e5570bf40f6aa7b71fc8 100644 (file)
@@ -83,8 +83,23 @@ private:
   /// This is only valid on definitions of registers.
   bool IsDead : 1;
 
-  /// IsUndef - True if this is a register def / use of "undef", i.e. register
-  /// defined by an IMPLICIT_DEF. This is only valid on registers.
+  /// 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
+  /// operands.  On a sub-register def operand, it refers to the part of the
+  /// register that isn't written.  On a full-register def operand, it is a
+  /// noop.  See readsReg().
+  ///
+  /// This is only valid on registers.
+  ///
+  /// Note that an instruction may have multiple <undef> operands referring to
+  /// the same register.  In that case, the instruction may depend on those
+  /// operands reading the same dont-care value.  For example:
+  ///
+  ///   %vreg1<def> = XOR %vreg2<undef>, %vreg2<undef>
+  ///
+  /// Any register can be used for %vreg2, and its value doesn't matter, but
+  /// the two operands must be the same register.
+  ///
   bool IsUndef : 1;
 
   /// IsEarlyClobber - True if this MO_Register 'def' operand is written to
@@ -253,6 +268,15 @@ public:
     return IsDebug;
   }
 
+  /// readsReg - Returns true if this operand reads the previous value of its
+  /// register.  A use operand with the <undef> flag set doesn't read its
+  /// register.  A sub-register def implicitly reads the other parts of the
+  /// register being redefined unless the <undef> flag is set.
+  bool readsReg() const {
+    assert(isReg() && "Wrong MachineOperand accessor");
+    return !isUndef() && (isUse() || getSubReg());
+  }
+
   /// getNextOperandForReg - Return the next MachineOperand in the function that
   /// uses or defines this register.
   MachineOperand *getNextOperandForReg() const {
index cacbd0a61b686d65bb67e2c94d7edb004dec0ace..3d95827226a0e95d6208de6f0f01155f67f909c3 100644 (file)
@@ -304,8 +304,15 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
 
     // Make sure the first definition is not a partial redefinition. Add an
     // <imp-def> of the full register.
-    if (MO.getSubReg())
+    if (MO.getSubReg()) {
       mi->addRegisterDefined(interval.reg);
+      // Mark all defs of interval.reg on this instruction as reading <undef>.
+      for (unsigned i = MOIdx, e = mi->getNumOperands(); i != e; ++i) {
+        MachineOperand &MO2 = mi->getOperand(i);
+        if (MO2.isReg() && MO2.getReg() == interval.reg && MO2.getSubReg())
+          MO2.setIsUndef();
+      }
+    }
 
     MachineInstr *CopyMI = NULL;
     if (mi->isCopyLike()) {