Follow up to r138791.
authorEvan Cheng <evan.cheng@apple.com>
Tue, 30 Aug 2011 19:09:48 +0000 (19:09 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Tue, 30 Aug 2011 19:09:48 +0000 (19:09 +0000)
Add a instruction flag: hasPostISelHook which tells the pre-RA scheduler to
call a target hook to adjust the instruction. For ARM, this is used to
adjust instructions which may be setting the 's' flag. ADC, SBC, RSB, and RSC
instructions have implicit def of CPSR (required since it now uses CPSR physical
register dependency rather than "glue"). If the carry flag is used, then the
target hook will *fill in* the optional operand with CPSR. Otherwise, the hook
will remove the CPSR implicit def from the MachineInstr.

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

12 files changed:
include/llvm/MC/MCInstrDesc.h
include/llvm/Target/Target.td
include/llvm/Target/TargetLowering.h
lib/CodeGen/SelectionDAG/InstrEmitter.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMISelLowering.h
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrThumb2.td
utils/TableGen/CodeGenInstruction.cpp
utils/TableGen/CodeGenInstruction.h
utils/TableGen/InstrInfoEmitter.cpp

index 5f5fa4c2f3a8a7fef79762e1ec493f14e031ac64..7061fcb0128404586d94e5a8d493f8e53d126599 100644 (file)
@@ -116,6 +116,7 @@ namespace MCID {
     Commutable,
     ConvertibleTo3Addr,
     UsesCustomInserter,
+    HasPostISelHook,
     Rematerializable,
     CheapAsAMove,
     ExtraSrcRegAllocReq,
@@ -476,6 +477,14 @@ public:
     return Flags & (1 << MCID::UsesCustomInserter);
   }
 
+  /// hasPostISelHook - Return true if this instruction requires *adjustment*
+  /// after instruction selection by calling a target hook. For example, this
+  /// can be used to fill in ARM 's' optional operand depending on whether
+  /// the conditional flag register is used.
+  bool hasPostISelHook() const {
+    return Flags & (1 << MCID::HasPostISelHook);
+  }
+
   /// isRematerializable - Returns true if this instruction is a candidate for
   /// remat.  This flag is deprecated, please don't use it anymore.  If this
   /// flag is set, the isReallyTriviallyReMaterializable() method is called to
index 06c22996dc77b5f40a58751e7b4022cb485b9482..b709b873f9dee25ac5e7b2ddb0b64d1c9ee6804c 100644 (file)
@@ -328,6 +328,7 @@ class Instruction {
   bit isPredicable = 0;     // Is this instruction predicable?
   bit hasDelaySlot = 0;     // Does this instruction have an delay slot?
   bit usesCustomInserter = 0; // Pseudo instr needing special help.
+  bit hasPostISelHook = 0;  // To be *adjusted* after isel by target hook.
   bit hasCtrlDep   = 0;     // Does this instruction r/w ctrl-flow chains?
   bit isNotDuplicable = 0;  // Is it unsafe to duplicate this instruction?
   bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction.
index d960d76840e9b26a8b17d48afae4b48e11b23202..b5d739a2cb7cb5410044b990d867710ee234f56f 100644 (file)
@@ -1471,6 +1471,13 @@ public:
   virtual MachineBasicBlock *
     EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
 
+  /// AdjustInstrPostInstrSelection - This method should be implemented by
+  /// targets that mark instructions with the 'hasPostISelHook' flag. These
+  /// instructions must be adjusted after instruction selection by target hooks.
+  /// e.g. To fill in optional defs for ARM 's' setting instructions.
+  virtual void
+  AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const;
+
   //===--------------------------------------------------------------------===//
   // Addressing mode description hooks (used by LSR etc).
   //
index 568f66c0398729d847838b877f8e55a84660183d..1e45ec6d11c4ca43696c4ee0bf2b41088b076536 100644 (file)
@@ -761,6 +761,10 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned,
            i != e; ++i)
         MI->addRegisterDead(IDList[i-II.getNumDefs()], TRI);
     }
+
+  // Run post-isel target hook to adjust this instruction if needed.
+  if (II.hasPostISelHook())
+    TLI->AdjustInstrPostInstrSelection(MI, Node);
 }
 
 /// EmitSpecialNode - Generate machine code for a target-independent node and
index dda018b93986a5f502fde57bbfc6f556d824e03d..7a3ea86e8c932f60b979fe90f9ea4af70d970c20 100644 (file)
@@ -177,6 +177,16 @@ TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
   return 0;
 }
 
+void TargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI,
+                                                   SDNode *Node) const {
+#ifndef NDEBUG
+  dbgs() << "If a target marks an instruction with "
+          "'hasPostISelHook', it must implement "
+          "TargetLowering::AdjustInstrPostInstrSelection!";
+#endif
+  llvm_unreachable(0);
+}
+
 //===----------------------------------------------------------------------===//
 // SelectionDAGISel code
 //===----------------------------------------------------------------------===//
index 29fb268ef439ba4e050d0b1060ae00e632ce0577..52684663af200fee44bcc2673f43dcc0ffe19300 100644 (file)
@@ -5474,6 +5474,29 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
   }
 }
 
+void ARMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI,
+                                                      SDNode *Node) const {
+  // Adjust potentially 's' setting instructions after isel, i.e. ADC, SBC,
+  // RSB, RSC. Coming out of isel, they have an implicit CPSR def, but the
+  // optional operand is not filled in. If the carry bit is used, then change
+  // the optional operand to CPSR. Otherwise, remove the CPSR implicit def.
+  const MCInstrDesc &MCID = MI->getDesc();
+  if (Node->hasAnyUseOfValue(1)) {
+    MachineOperand &MO = MI->getOperand(MCID.getNumOperands() - 2);
+    MO.setReg(ARM::CPSR);
+    MO.setIsDef(true);
+  } else {
+    for (unsigned i = MCID.getNumOperands(), e = MI->getNumOperands();
+         i != e; ++i) {
+      const MachineOperand &MO = MI->getOperand(i);
+      if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) {
+        MI->RemoveOperand(i);
+        break;
+      }
+    }
+  }
+}
+
 //===----------------------------------------------------------------------===//
 //                           ARM Optimization Hooks
 //===----------------------------------------------------------------------===//
index 4a07ebf97b549129a49ee20a67ec55955a8a78c5..92164aef00bf85ad62e8bef9224aa3c0779716b1 100644 (file)
@@ -249,6 +249,9 @@ namespace llvm {
       EmitInstrWithCustomInserter(MachineInstr *MI,
                                   MachineBasicBlock *MBB) const;
 
+    virtual void
+    AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const;
+
     SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const;
     virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
 
index f4d13577de73e765bceee9b98a350a1729ca5102..08b0954efa8e550fbd65f22f852ec420cbec7dd2 100644 (file)
@@ -1290,7 +1290,7 @@ class AI_exta_rrot_np<bits<8> opcod, string opc>
 /// AI1_adde_sube_irs - Define instructions and patterns for adde and sube.
 multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
                              string baseOpc, bit Commutable = 0> {
-  let Defs = [CPSR], Uses = [CPSR] in {
+  let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in {
   def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
                 DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
                [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm, CPSR))]>,
@@ -1378,7 +1378,7 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
 /// AI1_rsc_irs - Define instructions and patterns for rsc
 multiclass AI1_rsc_irs<bits<4> opcod, string opc, PatFrag opnode,
                        string baseOpc> {
-  let Defs = [CPSR], Uses = [CPSR] in {
+  let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in {
   def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
                 DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
                [(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn, CPSR))]>,
index 34a914723319b1faa931a0bcd36d831fc0a08162..a7652f670a908f5868d8c6450359d99c70d2bd4a 100644 (file)
@@ -1661,10 +1661,12 @@ defm t2SUBS : T2I_bin_s_irs <0b1101, "sub",
                              IIC_iALUi, IIC_iALUr, IIC_iALUsi,
                              BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
 
+let hasPostISelHook = 1 in {
 defm t2ADC  : T2I_adde_sube_irs<0b1010, "adc",
               BinOpWithFlagFrag<(ARMadde node:$LHS, node:$RHS, node:$FLAG)>, 1>;
 defm t2SBC  : T2I_adde_sube_irs<0b1011, "sbc",
               BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>>;
+}
 
 // RSB
 defm t2RSB  : T2I_rbin_irs  <0b1110, "rsb",
index b4f9d150716be48c7346d0305829e024ad952ed7..4b252774f002cd300c3ac4a52ce999f0a9f15653 100644 (file)
@@ -309,6 +309,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) {
   isReMaterializable = R->getValueAsBit("isReMaterializable");
   hasDelaySlot = R->getValueAsBit("hasDelaySlot");
   usesCustomInserter = R->getValueAsBit("usesCustomInserter");
+  hasPostISelHook = R->getValueAsBit("hasPostISelHook");
   hasCtrlDep   = R->getValueAsBit("hasCtrlDep");
   isNotDuplicable = R->getValueAsBit("isNotDuplicable");
   hasSideEffects = R->getValueAsBit("hasSideEffects");
index 8d7669aca98c0730dc2830f50985edb224745fef..468277aa96c2057007bcd780894791c1b1e9024b 100644 (file)
@@ -233,6 +233,7 @@ namespace llvm {
     bool isReMaterializable;
     bool hasDelaySlot;
     bool usesCustomInserter;
+    bool hasPostISelHook;
     bool hasCtrlDep;
     bool isNotDuplicable;
     bool hasSideEffects;
index 5ebaf174655b47673778af494940e4903a65b3fa..1cf7c90496280111aa2a67b5fe0fc5e8aa2ecf96 100644 (file)
@@ -288,6 +288,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
   if (Inst.isNotDuplicable)    OS << "|(1<<MCID::NotDuplicable)";
   if (Inst.Operands.hasOptionalDef) OS << "|(1<<MCID::HasOptionalDef)";
   if (Inst.usesCustomInserter) OS << "|(1<<MCID::UsesCustomInserter)";
+  if (Inst.hasPostISelHook)    OS << "|(1<<MCID::HasPostISelHook)";
   if (Inst.Operands.isVariadic)OS << "|(1<<MCID::Variadic)";
   if (Inst.hasSideEffects)     OS << "|(1<<MCID::UnmodeledSideEffects)";
   if (Inst.isAsCheapAsAMove)   OS << "|(1<<MCID::CheapAsAMove)";