From 37fefc20d3a1e3934a377567d54a141f67752227 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 30 Aug 2011 19:09:48 +0000 Subject: [PATCH] Follow up to r138791. 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 --- include/llvm/MC/MCInstrDesc.h | 9 ++++++++ include/llvm/Target/Target.td | 1 + include/llvm/Target/TargetLowering.h | 7 ++++++ lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 4 ++++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 10 ++++++++ lib/Target/ARM/ARMISelLowering.cpp | 23 +++++++++++++++++++ lib/Target/ARM/ARMISelLowering.h | 3 +++ lib/Target/ARM/ARMInstrInfo.td | 4 ++-- lib/Target/ARM/ARMInstrThumb2.td | 2 ++ utils/TableGen/CodeGenInstruction.cpp | 1 + utils/TableGen/CodeGenInstruction.h | 1 + utils/TableGen/InstrInfoEmitter.cpp | 1 + 12 files changed, 64 insertions(+), 2 deletions(-) diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 5f5fa4c2f3a..7061fcb0128 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -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 diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 06c22996dc7..b709b873f9d 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -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. diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index d960d76840e..b5d739a2cb7 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -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). // diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 568f66c0398..1e45ec6d11c 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -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 diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index dda018b9398..7a3ea86e8c9 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -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 //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 29fb268ef43..52684663af2 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -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 //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index 4a07ebf97b5..92164aef00b 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -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; diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index f4d13577de7..08b0954efa8 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -1290,7 +1290,7 @@ class AI_exta_rrot_np opcod, string opc> /// AI1_adde_sube_irs - Define instructions and patterns for adde and sube. multiclass AI1_adde_sube_irs 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, @@ -1378,7 +1378,7 @@ multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode, /// AI1_rsc_irs - Define instructions and patterns for rsc multiclass AI1_rsc_irs opcod, string opc, PatFrag opnode, string baseOpc> { - let Defs = [CPSR], Uses = [CPSR] in { + let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in { def ri : AsI1, diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 34a91472331..a7652f670a9 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -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", diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index b4f9d150716..4b252774f00 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -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"); diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 8d7669aca98..468277aa96c 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -233,6 +233,7 @@ namespace llvm { bool isReMaterializable; bool hasDelaySlot; bool usesCustomInserter; + bool hasPostISelHook; bool hasCtrlDep; bool isNotDuplicable; bool hasSideEffects; diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 5ebaf174655..1cf7c904962 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -288,6 +288,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isNotDuplicable) OS << "|(1<