20#define DEBUG_TYPE "sparc-isel"
21#define PASS_NAME "SPARC DAG->DAG Pattern Instruction Selection"
38 SparcDAGToDAGISel() =
delete;
56 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
58 std::vector<SDValue> &OutOps)
override;
61#include "SparcGenDAGISel.inc"
64 SDNode* getGlobalBaseReg();
76char SparcDAGToDAGISelLegacy::ID = 0;
80SDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
82 return CurDAG->getRegister(GlobalBaseReg,
83 TLI->getPointerTy(CurDAG->getDataLayout()))
87bool SparcDAGToDAGISel::SelectADDRri(
SDValue Addr,
90 Base = CurDAG->getTargetFrameIndex(
91 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
92 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
103 if (FrameIndexSDNode *FIN =
106 Base = CurDAG->getTargetFrameIndex(
107 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
111 Offset = CurDAG->getSignedTargetConstant(CN->getSExtValue(),
112 SDLoc(Addr), MVT::i32);
128 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
132bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &
R2) {
152 R2 = CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
156bool SparcDAGToDAGISel::SelectForceADDRrr(SDValue Addr, SDValue &
Base,
158 if (SelectADDRrr(Addr,
Base, Disp))
165 CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
180bool SparcDAGToDAGISel::tryInlineAsm(SDNode *
N){
181 std::vector<SDValue> AsmNodeOperands;
182 InlineAsm::Flag
Flag;
184 unsigned NumOps =
N->getNumOperands();
195 SDValue Glue =
N->getGluedNode() ?
N->getOperand(
NumOps - 1) : SDValue();
199 for(
unsigned i = 0, e =
N->getGluedNode() ?
NumOps - 1 :
NumOps; i < e; ++i) {
200 SDValue
op =
N->getOperand(i);
201 AsmNodeOperands.push_back(
op);
207 Flag = InlineAsm::Flag(
C->getZExtValue());
215 if (
Flag.isImmKind()) {
216 SDValue
op =
N->getOperand(++i);
217 AsmNodeOperands.push_back(
op);
221 const unsigned NumRegs =
Flag.getNumOperandRegisters();
226 bool IsTiedToChangedOp =
false;
230 IsTiedToChangedOp = OpChanged[DefIdx];
232 if (!
Flag.isRegUseKind() && !
Flag.isRegDefKind() &&
233 !
Flag.isRegDefEarlyClobberKind())
237 const bool HasRC =
Flag.hasRegClassConstraint(RC);
238 if ((!IsTiedToChangedOp && (!HasRC || RC != SP::IntRegsRegClassID))
242 assert((i+2 <
NumOps) &&
"Invalid number of operands in inline asm");
243 SDValue
V0 =
N->getOperand(i+1);
244 SDValue
V1 =
N->getOperand(i+2);
248 MachineRegisterInfo &MRI = MF->getRegInfo();
250 if (
Flag.isRegDefKind() ||
Flag.isRegDefEarlyClobberKind()) {
255 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
256 SDValue Chain = SDValue(
N,0);
258 SDNode *GU =
N->getGluedUser();
259 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::v2i32,
263 SDValue Sub0 = CurDAG->getTargetExtractSubreg(SP::sub_even, dl, MVT::i32,
265 SDValue Sub1 = CurDAG->getTargetExtractSubreg(SP::sub_odd, dl, MVT::i32,
267 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
269 SDValue
T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.
getValue(1));
273 Ops.push_back(
T1.getValue(1));
274 CurDAG->UpdateNodeOperands(GU,
Ops);
281 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
283 SDValue
T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
285 SDValue Pair = SDValue(
286 CurDAG->getMachineNode(
287 TargetOpcode::REG_SEQUENCE, dl, MVT::v2i32,
289 CurDAG->getTargetConstant(SP::IntPairRegClassID, dl,
292 CurDAG->getTargetConstant(SP::sub_even, dl, MVT::i32),
294 CurDAG->getTargetConstant(SP::sub_odd, dl, MVT::i32),
301 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
302 Chain = CurDAG->getCopyToReg(
T1, dl, GPVR, Pair,
T1.getValue(1));
311 OpChanged[OpChanged.
size() -1 ] =
true;
312 Flag = InlineAsm::Flag(
Flag.getKind(), 1 );
313 if (IsTiedToChangedOp)
314 Flag.setMatchingOp(DefIdx);
316 Flag.setRegClass(SP::IntPairRegClassID);
318 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
321 AsmNodeOperands.push_back(PairedReg);
328 AsmNodeOperands.push_back(Glue);
332 SelectInlineAsmMemoryOperands(AsmNodeOperands, SDLoc(
N));
334 SDValue
New = CurDAG->getNode(
N->getOpcode(), SDLoc(
N),
335 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
337 ReplaceNode(
N,
New.getNode());
341void SparcDAGToDAGISel::Select(SDNode *
N) {
343 if (
N->isMachineOpcode()) {
348 switch (
N->getOpcode()) {
356 case SPISD::GLOBAL_BASE_REG:
357 ReplaceNode(
N, getGlobalBaseReg());
363 if (
N->getValueType(0) == MVT::i64)
366 SDValue DivLHS =
N->getOperand(0);
367 SDValue DivRHS =
N->getOperand(1);
372 TopPart = SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
373 CurDAG->getTargetConstant(31, dl, MVT::i32)),
376 TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
378 TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart,
383 unsigned Opcode =
N->getOpcode() ==
ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
384 CurDAG->SelectNodeTo(
N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart);
395bool SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(
397 std::vector<SDValue> &OutOps) {
399 switch (ConstraintID) {
400 default:
return true;
401 case InlineAsm::ConstraintCode::o:
402 case InlineAsm::ConstraintCode::m:
403 if (!SelectADDRrr(
Op, Op0, Op1))
404 SelectADDRri(
Op, Op0, Op1);
408 OutOps.push_back(Op0);
409 OutOps.push_back(Op1);
417 return new SparcDAGToDAGISelLegacy(TM);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Wrapper class representing virtual and physical registers.
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
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool runOnMachineFunction(MachineFunction &mf)
void push_back(const T &Elt)
@ 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.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FunctionPass * createSparcISelDag(SparcTargetMachine &TM)
createSparcISelDag - This pass converts a legalized DAG into a SPARC-specific DAG,...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.