19#define DEBUG_TYPE "sparc-isel"
20#define PASS_NAME "SPARC DAG->DAG Pattern Instruction Selection"
37 SparcDAGToDAGISel() =
delete;
56 std::vector<SDValue> &OutOps)
override;
59#include "SparcGenDAGISel.inc"
62 SDNode* getGlobalBaseReg();
74char SparcDAGToDAGISelLegacy::ID = 0;
78SDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
80 return CurDAG->getRegister(GlobalBaseReg,
81 TLI->getPointerTy(CurDAG->getDataLayout()))
88 Base = CurDAG->getTargetFrameIndex(
89 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
100 if (isInt<13>(CN->getSExtValue())) {
102 dyn_cast<FrameIndexSDNode>(
Addr.getOperand(0))) {
104 Base = CurDAG->getTargetFrameIndex(
105 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
109 Offset = CurDAG->getSignedTargetConstant(CN->getSExtValue(),
139 if (isInt<13>(CN->getSExtValue()))
144 R1 =
Addr.getOperand(0);
150 R2 = CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
166bool SparcDAGToDAGISel::tryInlineAsm(
SDNode *
N){
167 std::vector<SDValue> AsmNodeOperands;
169 bool Changed =
false;
170 unsigned NumOps =
N->getNumOperands();
185 for(
unsigned i = 0, e =
N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
187 AsmNodeOperands.push_back(
op);
192 if (
const auto *
C = dyn_cast<ConstantSDNode>(
N->getOperand(i)))
201 if (
Flag.isImmKind()) {
203 AsmNodeOperands.push_back(
op);
207 const unsigned NumRegs =
Flag.getNumOperandRegisters();
212 bool IsTiedToChangedOp =
false;
215 if (Changed &&
Flag.isUseOperandTiedToDef(DefIdx))
216 IsTiedToChangedOp = OpChanged[DefIdx];
218 if (!
Flag.isRegUseKind() && !
Flag.isRegDefKind() &&
219 !
Flag.isRegDefEarlyClobberKind())
223 const bool HasRC =
Flag.hasRegClassConstraint(RC);
224 if ((!IsTiedToChangedOp && (!HasRC || RC != SP::IntRegsRegClassID))
228 assert((i+2 < NumOps) &&
"Invalid number of operands in inline asm");
231 Register Reg0 = cast<RegisterSDNode>(V0)->getReg();
232 Register Reg1 = cast<RegisterSDNode>(V1)->getReg();
236 if (
Flag.isRegDefKind() ||
Flag.isRegDefEarlyClobberKind()) {
240 Register GPVR =
MRI.createVirtualRegister(&SP::IntPairRegClass);
241 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
244 SDNode *GU =
N->getGluedUser();
245 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::v2i32,
249 SDValue Sub0 = CurDAG->getTargetExtractSubreg(SP::sub_even, dl, MVT::i32,
251 SDValue Sub1 = CurDAG->getTargetExtractSubreg(SP::sub_odd, dl, MVT::i32,
253 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
259 Ops.push_back(
T1.getValue(1));
260 CurDAG->UpdateNodeOperands(GU, Ops);
267 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
269 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
272 CurDAG->getMachineNode(
273 TargetOpcode::REG_SEQUENCE, dl, MVT::v2i32,
275 CurDAG->getTargetConstant(SP::IntPairRegClassID, dl,
278 CurDAG->getTargetConstant(SP::sub_even, dl, MVT::i32),
280 CurDAG->getTargetConstant(SP::sub_odd, dl, MVT::i32),
286 Register GPVR =
MRI.createVirtualRegister(&SP::IntPairRegClass);
287 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
288 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair,
T1.getValue(1));
297 OpChanged[OpChanged.
size() -1 ] =
true;
299 if (IsTiedToChangedOp)
300 Flag.setMatchingOp(DefIdx);
302 Flag.setRegClass(SP::IntPairRegClassID);
304 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
307 AsmNodeOperands.push_back(PairedReg);
314 AsmNodeOperands.push_back(Glue);
318 SelectInlineAsmMemoryOperands(AsmNodeOperands,
SDLoc(
N));
321 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
323 ReplaceNode(
N,
New.getNode());
327void SparcDAGToDAGISel::Select(
SDNode *
N) {
329 if (
N->isMachineOpcode()) {
334 switch (
N->getOpcode()) {
343 ReplaceNode(
N, getGlobalBaseReg());
349 if (
N->getValueType(0) == MVT::i64)
358 TopPart =
SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
359 CurDAG->getTargetConstant(31, dl, MVT::i32)),
362 TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
364 TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart,
369 unsigned Opcode =
N->getOpcode() ==
ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
370 CurDAG->SelectNodeTo(
N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart);
381bool SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(
383 std::vector<SDValue> &OutOps) {
385 switch (ConstraintID) {
386 default:
return true;
387 case InlineAsm::ConstraintCode::o:
388 case InlineAsm::ConstraintCode::m:
389 if (!SelectADDRrr(
Op, Op0, Op1))
390 SelectADDRri(
Op, Op0, Op1);
394 OutOps.push_back(Op0);
395 OutOps.push_back(Op1);
403 return new SparcDAGToDAGISelLegacy(TM);
unsigned const MachineRegisterInfo * MRI
AMDGPU Register Bank Select
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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,...