20#define DEBUG_TYPE "sparc-isel"
21#define PASS_NAME "SPARC DAG->DAG Pattern Instruction Selection"
38 SparcDAGToDAGISel() =
delete;
57 std::vector<SDValue> &OutOps)
override;
60#include "SparcGenDAGISel.inc"
63 SDNode* getGlobalBaseReg();
75char SparcDAGToDAGISelLegacy::ID = 0;
79SDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
81 return CurDAG->getRegister(GlobalBaseReg,
82 TLI->getPointerTy(CurDAG->getDataLayout()))
89 Base = CurDAG->getTargetFrameIndex(
90 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
101 if (isInt<13>(CN->getSExtValue())) {
103 dyn_cast<FrameIndexSDNode>(
Addr.getOperand(0))) {
105 Base = CurDAG->getTargetFrameIndex(
106 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
110 Offset = CurDAG->getSignedTargetConstant(CN->getSExtValue(),
115 if (
Addr.getOperand(0).getOpcode() == SPISD::Lo) {
120 if (
Addr.getOperand(1).getOpcode() == SPISD::Lo) {
140 if (isInt<13>(CN->getSExtValue()))
142 if (
Addr.getOperand(0).getOpcode() == SPISD::Lo ||
143 Addr.getOperand(1).getOpcode() == SPISD::Lo)
145 R1 =
Addr.getOperand(0);
151 R2 = CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
167bool SparcDAGToDAGISel::tryInlineAsm(
SDNode *
N){
168 std::vector<SDValue> AsmNodeOperands;
170 bool Changed =
false;
171 unsigned NumOps =
N->getNumOperands();
186 for(
unsigned i = 0, e =
N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
188 AsmNodeOperands.push_back(
op);
193 if (
const auto *
C = dyn_cast<ConstantSDNode>(
N->getOperand(i)))
202 if (
Flag.isImmKind()) {
204 AsmNodeOperands.push_back(
op);
208 const unsigned NumRegs =
Flag.getNumOperandRegisters();
213 bool IsTiedToChangedOp =
false;
216 if (Changed &&
Flag.isUseOperandTiedToDef(DefIdx))
217 IsTiedToChangedOp = OpChanged[DefIdx];
219 if (!
Flag.isRegUseKind() && !
Flag.isRegDefKind() &&
220 !
Flag.isRegDefEarlyClobberKind())
224 const bool HasRC =
Flag.hasRegClassConstraint(RC);
225 if ((!IsTiedToChangedOp && (!HasRC || RC != SP::IntRegsRegClassID))
229 assert((i+2 < NumOps) &&
"Invalid number of operands in inline asm");
232 Register Reg0 = cast<RegisterSDNode>(V0)->getReg();
233 Register Reg1 = cast<RegisterSDNode>(V1)->getReg();
237 if (
Flag.isRegDefKind() ||
Flag.isRegDefEarlyClobberKind()) {
241 Register GPVR =
MRI.createVirtualRegister(&SP::IntPairRegClass);
242 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
245 SDNode *GU =
N->getGluedUser();
246 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::v2i32,
250 SDValue Sub0 = CurDAG->getTargetExtractSubreg(SP::sub_even, dl, MVT::i32,
252 SDValue Sub1 = CurDAG->getTargetExtractSubreg(SP::sub_odd, dl, MVT::i32,
254 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
260 Ops.push_back(
T1.getValue(1));
261 CurDAG->UpdateNodeOperands(GU, Ops);
268 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
270 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
273 CurDAG->getMachineNode(
274 TargetOpcode::REG_SEQUENCE, dl, MVT::v2i32,
276 CurDAG->getTargetConstant(SP::IntPairRegClassID, dl,
279 CurDAG->getTargetConstant(SP::sub_even, dl, MVT::i32),
281 CurDAG->getTargetConstant(SP::sub_odd, dl, MVT::i32),
287 Register GPVR =
MRI.createVirtualRegister(&SP::IntPairRegClass);
288 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
289 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair,
T1.getValue(1));
298 OpChanged[OpChanged.
size() -1 ] =
true;
300 if (IsTiedToChangedOp)
301 Flag.setMatchingOp(DefIdx);
303 Flag.setRegClass(SP::IntPairRegClassID);
305 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
308 AsmNodeOperands.push_back(PairedReg);
315 AsmNodeOperands.push_back(Glue);
319 SelectInlineAsmMemoryOperands(AsmNodeOperands,
SDLoc(
N));
322 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
324 ReplaceNode(
N,
New.getNode());
328void SparcDAGToDAGISel::Select(
SDNode *
N) {
330 if (
N->isMachineOpcode()) {
335 switch (
N->getOpcode()) {
343 case SPISD::GLOBAL_BASE_REG:
344 ReplaceNode(
N, getGlobalBaseReg());
350 if (
N->getValueType(0) == MVT::i64)
359 TopPart =
SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
360 CurDAG->getTargetConstant(31, dl, MVT::i32)),
363 TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
365 TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart,
370 unsigned Opcode =
N->getOpcode() ==
ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
371 CurDAG->SelectNodeTo(
N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart);
382bool SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(
384 std::vector<SDValue> &OutOps) {
386 switch (ConstraintID) {
387 default:
return true;
388 case InlineAsm::ConstraintCode::o:
389 case InlineAsm::ConstraintCode::m:
390 if (!SelectADDRrr(
Op, Op0, Op1))
391 SelectADDRri(
Op, Op0, Op1);
395 OutOps.push_back(Op0);
396 OutOps.push_back(Op1);
404 return new SparcDAGToDAGISelLegacy(TM);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
op_iterator op_end() const
op_iterator op_begin() const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
virtual bool runOnMachineFunction(MachineFunction &mf)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ ADD
Simple integer binary arithmetic operators.
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ INLINEASM
INLINEASM - Represents an inline asm block.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createSparcISelDag(SparcTargetMachine &TM)
createSparcISelDag - This pass converts a legalized DAG into a SPARC-specific DAG,...