22#define DEBUG_TYPE "sparc-isel"
23#define PASS_NAME "SPARC DAG->DAG Pattern Instruction Selection"
40 SparcDAGToDAGISel() =
delete;
59 std::vector<SDValue> &OutOps)
override;
62#include "SparcGenDAGISel.inc"
65 SDNode* getGlobalBaseReg();
77char SparcDAGToDAGISelLegacy::ID = 0;
81SDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
83 return CurDAG->getRegister(GlobalBaseReg,
84 TLI->getPointerTy(CurDAG->getDataLayout()))
91 Base = CurDAG->getTargetFrameIndex(
92 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
103 if (isInt<13>(CN->getSExtValue())) {
105 dyn_cast<FrameIndexSDNode>(
Addr.getOperand(0))) {
107 Base = CurDAG->getTargetFrameIndex(
108 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
142 if (isInt<13>(CN->getSExtValue()))
147 R1 =
Addr.getOperand(0);
153 R2 = CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
169bool SparcDAGToDAGISel::tryInlineAsm(
SDNode *
N){
170 std::vector<SDValue> AsmNodeOperands;
172 bool Changed =
false;
173 unsigned NumOps =
N->getNumOperands();
188 for(
unsigned i = 0, e =
N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
190 AsmNodeOperands.push_back(
op);
195 if (
const auto *
C = dyn_cast<ConstantSDNode>(
N->getOperand(i)))
204 if (
Flag.isImmKind()) {
206 AsmNodeOperands.push_back(
op);
210 const unsigned NumRegs =
Flag.getNumOperandRegisters();
215 bool IsTiedToChangedOp =
false;
218 if (Changed &&
Flag.isUseOperandTiedToDef(DefIdx))
219 IsTiedToChangedOp = OpChanged[DefIdx];
221 if (!
Flag.isRegUseKind() && !
Flag.isRegDefKind() &&
222 !
Flag.isRegDefEarlyClobberKind())
226 const bool HasRC =
Flag.hasRegClassConstraint(RC);
227 if ((!IsTiedToChangedOp && (!HasRC || RC != SP::IntRegsRegClassID))
231 assert((i+2 < NumOps) &&
"Invalid number of operands in inline asm");
234 Register Reg0 = cast<RegisterSDNode>(V0)->getReg();
235 Register Reg1 = cast<RegisterSDNode>(V1)->getReg();
239 if (
Flag.isRegDefKind() ||
Flag.isRegDefEarlyClobberKind()) {
243 Register GPVR =
MRI.createVirtualRegister(&SP::IntPairRegClass);
244 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
247 SDNode *GU =
N->getGluedUser();
248 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::v2i32,
252 SDValue Sub0 = CurDAG->getTargetExtractSubreg(SP::sub_even, dl, MVT::i32,
254 SDValue Sub1 = CurDAG->getTargetExtractSubreg(SP::sub_odd, dl, MVT::i32,
256 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
262 Ops.push_back(
T1.getValue(1));
263 CurDAG->UpdateNodeOperands(GU, Ops);
270 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
272 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
275 CurDAG->getMachineNode(
276 TargetOpcode::REG_SEQUENCE, dl, MVT::v2i32,
278 CurDAG->getTargetConstant(SP::IntPairRegClassID, dl,
281 CurDAG->getTargetConstant(SP::sub_even, dl, MVT::i32),
283 CurDAG->getTargetConstant(SP::sub_odd, dl, MVT::i32),
289 Register GPVR =
MRI.createVirtualRegister(&SP::IntPairRegClass);
290 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
291 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair,
T1.getValue(1));
300 OpChanged[OpChanged.
size() -1 ] =
true;
302 if (IsTiedToChangedOp)
303 Flag.setMatchingOp(DefIdx);
305 Flag.setRegClass(SP::IntPairRegClassID);
307 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
310 AsmNodeOperands.push_back(PairedReg);
317 AsmNodeOperands.push_back(Glue);
321 SelectInlineAsmMemoryOperands(AsmNodeOperands,
SDLoc(
N));
324 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
326 ReplaceNode(
N,
New.getNode());
330void SparcDAGToDAGISel::Select(
SDNode *
N) {
332 if (
N->isMachineOpcode()) {
337 switch (
N->getOpcode()) {
346 ReplaceNode(
N, getGlobalBaseReg());
352 if (
N->getValueType(0) == MVT::i64)
361 TopPart =
SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
362 CurDAG->getTargetConstant(31, dl, MVT::i32)),
365 TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
367 TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart,
372 unsigned Opcode =
N->getOpcode() ==
ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
373 CurDAG->SelectNodeTo(
N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart);
384bool SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(
386 std::vector<SDValue> &OutOps) {
388 switch (ConstraintID) {
389 default:
return true;
390 case InlineAsm::ConstraintCode::o:
391 case InlineAsm::ConstraintCode::m:
392 if (!SelectADDRrr(
Op, Op0, Op1))
393 SelectADDRri(
Op, Op0, Op1);
397 OutOps.push_back(Op0);
398 OutOps.push_back(Op1);
406 return new SparcDAGToDAGISelLegacy(
TM);
unsigned const MachineRegisterInfo * MRI
amdgpu AMDGPU Register Bank Select
const char LLVMTargetMachineRef TM
#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.
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,...