22#define DEBUG_TYPE "sparc-isel"
23#define PASS_NAME "SPARC DAG->DAG Pattern Instruction Selection"
41 SparcDAGToDAGISel() =
delete;
60 std::vector<SDValue> &OutOps)
override;
63#include "SparcGenDAGISel.inc"
66 SDNode* getGlobalBaseReg();
71char SparcDAGToDAGISel::ID = 0;
75SDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
77 return CurDAG->getRegister(GlobalBaseReg,
78 TLI->getPointerTy(CurDAG->getDataLayout()))
85 Base = CurDAG->getTargetFrameIndex(
86 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
97 if (isInt<13>(CN->getSExtValue())) {
99 dyn_cast<FrameIndexSDNode>(
Addr.getOperand(0))) {
101 Base = CurDAG->getTargetFrameIndex(
102 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
136 if (isInt<13>(CN->getSExtValue()))
141 R1 =
Addr.getOperand(0);
147 R2 = CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
163bool SparcDAGToDAGISel::tryInlineAsm(
SDNode *
N){
164 std::vector<SDValue> AsmNodeOperands;
166 bool Changed =
false;
167 unsigned NumOps =
N->getNumOperands();
182 for(
unsigned i = 0, e =
N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
184 AsmNodeOperands.push_back(
op);
189 if (
const auto *
C = dyn_cast<ConstantSDNode>(
N->getOperand(i)))
198 if (
Flag.isImmKind()) {
200 AsmNodeOperands.push_back(
op);
204 const unsigned NumRegs =
Flag.getNumOperandRegisters();
209 bool IsTiedToChangedOp =
false;
212 if (Changed &&
Flag.isUseOperandTiedToDef(DefIdx))
213 IsTiedToChangedOp = OpChanged[DefIdx];
215 if (!
Flag.isRegUseKind() && !
Flag.isRegDefKind() &&
216 !
Flag.isRegDefEarlyClobberKind())
220 const bool HasRC =
Flag.hasRegClassConstraint(RC);
221 if ((!IsTiedToChangedOp && (!HasRC || RC != SP::IntRegsRegClassID))
225 assert((i+2 < NumOps) &&
"Invalid number of operands in inline asm");
228 Register Reg0 = cast<RegisterSDNode>(V0)->getReg();
229 Register Reg1 = cast<RegisterSDNode>(V1)->getReg();
233 if (
Flag.isRegDefKind() ||
Flag.isRegDefEarlyClobberKind()) {
237 Register GPVR =
MRI.createVirtualRegister(&SP::IntPairRegClass);
238 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
241 SDNode *GU =
N->getGluedUser();
242 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::v2i32,
246 SDValue Sub0 = CurDAG->getTargetExtractSubreg(SP::sub_even, dl, MVT::i32,
248 SDValue Sub1 = CurDAG->getTargetExtractSubreg(SP::sub_odd, dl, MVT::i32,
250 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
256 Ops.push_back(
T1.getValue(1));
257 CurDAG->UpdateNodeOperands(GU, Ops);
264 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
266 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
269 CurDAG->getMachineNode(
270 TargetOpcode::REG_SEQUENCE, dl, MVT::v2i32,
272 CurDAG->getTargetConstant(SP::IntPairRegClassID, dl,
275 CurDAG->getTargetConstant(SP::sub_even, dl, MVT::i32),
277 CurDAG->getTargetConstant(SP::sub_odd, dl, MVT::i32),
283 Register GPVR =
MRI.createVirtualRegister(&SP::IntPairRegClass);
284 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
285 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair,
T1.getValue(1));
294 OpChanged[OpChanged.
size() -1 ] =
true;
296 if (IsTiedToChangedOp)
297 Flag.setMatchingOp(DefIdx);
299 Flag.setRegClass(SP::IntPairRegClassID);
301 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
304 AsmNodeOperands.push_back(PairedReg);
311 AsmNodeOperands.push_back(Glue);
315 SelectInlineAsmMemoryOperands(AsmNodeOperands,
SDLoc(
N));
318 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
320 ReplaceNode(
N,
New.getNode());
324void SparcDAGToDAGISel::Select(
SDNode *
N) {
326 if (
N->isMachineOpcode()) {
331 switch (
N->getOpcode()) {
340 ReplaceNode(
N, getGlobalBaseReg());
346 if (
N->getValueType(0) == MVT::i64)
355 TopPart =
SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
356 CurDAG->getTargetConstant(31, dl, MVT::i32)),
359 TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
361 TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart,
367 CurDAG->SelectNodeTo(
N,
Opcode, MVT::i32, DivLHS, DivRHS, TopPart);
378bool SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(
380 std::vector<SDValue> &OutOps) {
382 switch (ConstraintID) {
383 default:
return true;
384 case InlineAsm::ConstraintCode::o:
385 case InlineAsm::ConstraintCode::m:
386 if (!SelectADDRrr(
Op, Op0, Op1))
387 SelectADDRri(
Op, Op0, Op1);
391 OutOps.push_back(Op0);
392 OutOps.push_back(Op1);
400 return new SparcDAGToDAGISel(
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())
static constexpr uint32_t Opcode
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,...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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,...