Revert the earlier change that removed the M_REMATERIALIZABLE machine
instruction flag, and use the flag along with a virtual member function
hook for targets to override if there are instructions that are only
trivially rematerializable with specific operands (i.e. constant pool
loads).


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37728 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index 339b391..8fa73a7 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/include/llvm/Target/TargetInstrInfo.h
@@ -78,6 +78,10 @@
 // controls execution. It may be set to 'always'.
 const unsigned M_PREDICABLE = 1 << 12;
 
+// M_REMATERIALIZIBLE - Set if this instruction can be trivally re-materialized
+// at any time, e.g. constant generation, load from constant pool.
+const unsigned M_REMATERIALIZIBLE = 1 << 13;
+
 // M_CLOBBERS_PRED - Set if this instruction may clobbers the condition code
 // register and / or registers that are used to predicate instructions.
 const unsigned M_CLOBBERS_PRED = 1 << 14;
@@ -268,6 +272,28 @@
     return get(Opcode).Flags & M_NOT_DUPLICABLE;
   }
 
+  /// isTriviallyReMaterializable - Return true if the instruction is trivially
+  /// rematerializable, meaning it has no side effects and requires no operands
+  /// that aren't always available.
+  bool isTriviallyReMaterializable(MachineInstr *MI) const {
+    return (MI->getInstrDescriptor()->Flags & M_REMATERIALIZIBLE) &&
+           isReallyTriviallyReMaterializable(MI);
+  }
+
+protected:
+  /// isReallyTriviallyReMaterializable - For instructions with opcodes for
+  /// which the M_REMATERIALIZABLE flag is set, this function tests whether the
+  /// instruction itself is actually trivially rematerializable, considering
+  /// its operands.  This is used for targets that have instructions that are
+  /// only trivially rematerializable for specific uses.  This predicate must
+  /// return false if the instruction has any side effects other than
+  /// producing a value, or if it requres any address registers that are not
+  /// always available.
+  virtual bool isReallyTriviallyReMaterializable(MachineInstr *MI) const {
+    return true;
+  }
+
+public:
   /// getOperandConstraint - Returns the value of the specific constraint if
   /// it is set. Returns -1 if it is not set.
   int getOperandConstraint(MachineOpCode Opcode, unsigned OpNum,
@@ -301,16 +327,6 @@
     return 0;
   }
 
-  /// isTriviallyReMaterializable - If the specified machine instruction can
-  /// be trivally re-materialized  at any time, e.g. constant generation or
-  /// loads from constant pools. If not, return false.  This predicate must
-  /// return false if the instruction has any side effects other than
-  /// producing the value from the load, or if it requres any address
-  /// registers that are not always available.
-  virtual bool isTriviallyReMaterializable(MachineInstr *MI) const {
-    return false;
-  }
-
   /// convertToThreeAddress - This method must be implemented by targets that
   /// set the M_CONVERTIBLE_TO_3_ADDR flag.  When this flag is set, the target
   /// may be able to convert a two-address instruction into one or moretrue
diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp
index a1e0258..1370fab 100644
--- a/lib/Target/ARM/ARMInstrInfo.cpp
+++ b/lib/Target/ARM/ARMInstrInfo.cpp
@@ -130,20 +130,6 @@
   return 0;
 }
 
-bool ARMInstrInfo::isTriviallyReMaterializable(MachineInstr *MI) const {
-  switch (MI->getOpcode()) {
-  default: break;
-  case ARM::LDRcp:
-  case ARM::MOVi:
-  case ARM::MVNi:
-  case ARM::MOVi2pieces:
-  case ARM::tLDRcp:
-    // These instructions are always trivially rematerializable.
-    return true;
-  }
-  return false;
-}
-
 static unsigned getUnindexedOpcode(unsigned Opc) {
   switch (Opc) {
   default: break;
diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h
index 8e6a2fd..5b406cb 100644
--- a/lib/Target/ARM/ARMInstrInfo.h
+++ b/lib/Target/ARM/ARMInstrInfo.h
@@ -87,7 +87,6 @@
                            unsigned &SrcReg, unsigned &DstReg) const;
   virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const;
   virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const;
-  virtual bool isTriviallyReMaterializable(MachineInstr *MI) const;
   
   virtual MachineInstr *convertToThreeAddress(MachineFunction::iterator &MFI,
                                               MachineBasicBlock::iterator &MBBI,
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index deeb236..db6814c 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -677,6 +677,7 @@
                [(set GPR:$dst, (load addrmode2:$addr))]>;
 
 // Special LDR for loads from non-pc-relative constpools.
+let isReMaterializable = 1 in
 def LDRcp : AI2<(ops GPR:$dst, addrmode2:$addr),
                  "ldr", " $dst, $addr", []>;
 
@@ -810,6 +811,7 @@
 def MOVs : AI1<(ops GPR:$dst, so_reg:$src),
                 "mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>;
 
+let isReMaterializable = 1 in
 def MOVi : AI1<(ops GPR:$dst, so_imm:$src),
                 "mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>;
 
@@ -917,6 +919,7 @@
                 "mvn", " $dst, $src", [(set GPR:$dst, (not GPR:$src))]>;
 def  MVNs  : AI<(ops GPR:$dst, so_reg:$src),
                 "mvn", " $dst, $src", [(set GPR:$dst, (not so_reg:$src))]>;
+let isReMaterializable = 1 in
 def  MVNi  : AI<(ops GPR:$dst, so_imm:$imm),
                 "mvn", " $dst, $imm", [(set GPR:$dst, so_imm_not:$imm)]>;
 
@@ -1187,6 +1190,7 @@
 // Large immediate handling.
 
 // Two piece so_imms.
+let isReMaterializable = 1 in
 def MOVi2pieces : AI1x2<(ops GPR:$dst, so_imm2part:$src),
                          "mov", " $dst, $src",
                          [(set GPR:$dst, so_imm2part:$src)]>;
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index de71410..996b635 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -267,6 +267,7 @@
                   [(set GPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>;
 
 // Special LDR for loads from non-pc-relative constpools.
+let isReMaterializable = 1 in
 def tLDRcp  : TIs<(ops GPR:$dst, i32imm:$addr),
                   "ldr $dst, $addr", []>;
 } // isLoad
diff --git a/lib/Target/Target.td b/lib/Target/Target.td
index 2258199..43e3af8 100644
--- a/lib/Target/Target.td
+++ b/lib/Target/Target.td
@@ -186,6 +186,7 @@
   bit isConvertibleToThreeAddress = 0;  // Can this 2-addr instruction promote?
   bit isCommutable = 0;     // Is this 3 operand instruction commutable?
   bit isTerminator = 0;     // Is this part of the terminator for a basic block?
+  bit isReMaterializable = 0; // Is this instruction re-materializable?
   bit isPredicable = 0;     // Is this instruction predicable?
   bit hasDelaySlot = 0;     // Does this instruction have an delay slot?
   bit usesCustomDAGSchedInserter = 0; // Pseudo instr needing special help.
diff --git a/lib/Target/X86/X86InstrFPStack.td b/lib/Target/X86/X86InstrFPStack.td
index 48b216a..848d370 100644
--- a/lib/Target/X86/X86InstrFPStack.td
+++ b/lib/Target/X86/X86InstrFPStack.td
@@ -413,10 +413,12 @@
 def FXCH    : FPI<0xC8, AddRegFrm, (ops RST:$op), "fxch $op">, D9;
 
 // Floating point constant loads.
+let isReMaterializable = 1 in {
 def FpLD0 : FpI<(ops RFP:$dst), ZeroArgFP,
                 [(set RFP:$dst, fp64imm0)]>;
 def FpLD1 : FpI<(ops RFP:$dst), ZeroArgFP,
                 [(set RFP:$dst, fp64imm1)]>;
+}
 
 def FLD0 : FPI<0xEE, RawFrm, (ops), "fldz">, D9;
 def FLD1 : FPI<0xE8, RawFrm, (ops), "fld1">, D9;
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 0e02ef0..9959490 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -112,20 +112,9 @@
 }
 
 
-bool X86InstrInfo::isTriviallyReMaterializable(MachineInstr *MI) const {
+bool X86InstrInfo::isReallyTriviallyReMaterializable(MachineInstr *MI) const {
   switch (MI->getOpcode()) {
   default: break;
-  case X86::FpLD0:
-  case X86::FpLD1:
-  case X86::MOV8ri:
-  case X86::MOV16ri:
-  case X86::MOV32ri:
-  case X86::MMX_V_SET0:
-  case X86::MMX_V_SETALLONES:
-  case X86::V_SET0:
-  case X86::V_SETALLONES:
-    // These instructions are always trivially rematerializable.
-    return true;
   case X86::MOV8rm:
   case X86::MOV16rm:
   case X86::MOV16_rm:
@@ -146,7 +135,9 @@
            MI->getOperand(2).getImmedValue() == 1 &&
            MI->getOperand(3).getReg() == 0;
   }
-  return false;
+  // All other instructions marked M_REMATERIALIZABLE are always trivially
+  // rematerializable.
+  return true;
 }
 
 /// convertToThreeAddress - This method must be implemented by targets that
diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h
index f3d571a..ec30cc7 100644
--- a/lib/Target/X86/X86InstrInfo.h
+++ b/lib/Target/X86/X86InstrInfo.h
@@ -239,7 +239,7 @@
                    unsigned& destReg) const;
   unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const;
   unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const;
-  bool isTriviallyReMaterializable(MachineInstr *MI) const;
+  bool isReallyTriviallyReMaterializable(MachineInstr *MI) const;
   
   /// convertToThreeAddress - This method must be implemented by targets that
   /// set the M_CONVERTIBLE_TO_3_ADDR flag.  When this flag is set, the target
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index a221c42..f8eac7e 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -617,6 +617,7 @@
                 "mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
 def MOV32rr : I<0x89, MRMDestReg, (ops GR32:$dst, GR32:$src),
                 "mov{l} {$src, $dst|$dst, $src}", []>;
+let isReMaterializable = 1 in {
 def MOV8ri  : Ii8 <0xB0, AddRegFrm, (ops GR8 :$dst, i8imm :$src),
                    "mov{b} {$src, $dst|$dst, $src}",
                    [(set GR8:$dst, imm:$src)]>;
@@ -626,6 +627,7 @@
 def MOV32ri : Ii32<0xB8, AddRegFrm, (ops GR32:$dst, i32imm:$src),
                    "mov{l} {$src, $dst|$dst, $src}",
                    [(set GR32:$dst, imm:$src)]>;
+}
 def MOV8mi  : Ii8 <0xC6, MRM0m, (ops i8mem :$dst, i8imm :$src),
                    "mov{b} {$src, $dst|$dst, $src}",
                    [(store (i8 imm:$src), addr:$dst)]>;
diff --git a/lib/Target/X86/X86InstrMMX.td b/lib/Target/X86/X86InstrMMX.td
index cc22f4f..897d8f2 100644
--- a/lib/Target/X86/X86InstrMMX.td
+++ b/lib/Target/X86/X86InstrMMX.td
@@ -503,12 +503,14 @@
 
 // Alias instructions that map zero vector to pxor.
 // FIXME: remove when we can teach regalloc that xor reg, reg is ok.
-def MMX_V_SET0       : MMXI<0xEF, MRMInitReg, (ops VR64:$dst),
-                            "pxor $dst, $dst",
-                            [(set VR64:$dst, (v1i64 immAllZerosV))]>;
-def MMX_V_SETALLONES : MMXI<0x76, MRMInitReg, (ops VR64:$dst),
-                            "pcmpeqd $dst, $dst",
-                            [(set VR64:$dst, (v1i64 immAllOnesV))]>;
+let isReMaterializable = 1 in {
+  def MMX_V_SET0       : MMXI<0xEF, MRMInitReg, (ops VR64:$dst),
+                              "pxor $dst, $dst",
+                              [(set VR64:$dst, (v1i64 immAllZerosV))]>;
+  def MMX_V_SETALLONES : MMXI<0x76, MRMInitReg, (ops VR64:$dst),
+                              "pcmpeqd $dst, $dst",
+                              [(set VR64:$dst, (v1i64 immAllOnesV))]>;
+}
 
 //===----------------------------------------------------------------------===//
 // Non-Instruction Patterns
diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td
index 78574ee..d604091 100644
--- a/lib/Target/X86/X86InstrSSE.td
+++ b/lib/Target/X86/X86InstrSSE.td
@@ -762,6 +762,7 @@
 
 // Alias instructions that map zero vector to pxor / xorp* for sse.
 // FIXME: remove when we can teach regalloc that xor reg, reg is ok.
+let isReMaterializable = 1 in
 def V_SET0 : PSI<0x57, MRMInitReg, (ops VR128:$dst),
                  "xorps $dst, $dst",
                  [(set VR128:$dst, (v4f32 immAllZerosV))]>;
@@ -1821,9 +1822,10 @@
 
 // Alias instructions that map zero vector to pxor / xorp* for sse.
 // FIXME: remove when we can teach regalloc that xor reg, reg is ok.
-def V_SETALLONES : PDI<0x76, MRMInitReg, (ops VR128:$dst),
-                       "pcmpeqd $dst, $dst",
-                       [(set VR128:$dst, (v2f64 immAllOnesV))]>;
+let isReMaterializable = 1 in
+  def V_SETALLONES : PDI<0x76, MRMInitReg, (ops VR128:$dst),
+                         "pcmpeqd $dst, $dst",
+                         [(set VR128:$dst, (v2f64 immAllOnesV))]>;
 
 // FR64 to 128-bit vector conversion.
 def MOVSD2PDrr : SDI<0x10, MRMSrcReg, (ops VR128:$dst, FR64:$src),
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index 4f76de8..54d9b3f 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -91,6 +91,7 @@
     bool isConvertibleToThreeAddress;
     bool isCommutable;
     bool isTerminator;
+    bool isReMaterializable;
     bool hasDelaySlot;
     bool usesCustomDAGSchedInserter;
     bool hasVariableNumberOfOperands;
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index b02c423..c54ecd0 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -365,6 +365,7 @@
   isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
   isCommutable = R->getValueAsBit("isCommutable");
   isTerminator = R->getValueAsBit("isTerminator");
+  isReMaterializable = R->getValueAsBit("isReMaterializable");
   hasDelaySlot = R->getValueAsBit("hasDelaySlot");
   usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter");
   hasCtrlDep   = R->getValueAsBit("hasCtrlDep");
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index bf027dd..af01e4c 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -240,6 +240,7 @@
   if (Inst.isConvertibleToThreeAddress) OS << "|M_CONVERTIBLE_TO_3_ADDR";
   if (Inst.isCommutable) OS << "|M_COMMUTABLE";
   if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG";
+  if (Inst.isReMaterializable) OS << "|M_REMATERIALIZIBLE";
   if (Inst.clobbersPred) OS << "|M_CLOBBERS_PRED";
   if (Inst.isNotDuplicable) OS << "|M_NOT_DUPLICABLE";
   if (Inst.usesCustomDAGSchedInserter)