22#define DEBUG_TYPE "sparc-isel"
23#define PASS_NAME "SPARC DAG->DAG Pattern Instruction Selection"
40 SparcDAGToDAGISel() =
delete;
59 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
61 std::vector<SDValue> &OutOps)
override;
64#include "SparcGenDAGISel.inc"
67 SDNode* getGlobalBaseReg();
77 ID, std::make_unique<SparcDAGToDAGISel>(tm, OptLevel)) {}
81char SparcDAGToDAGISelLegacy::ID = 0;
85SDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
87 return CurDAG->getRegister(GlobalBaseReg,
88 TLI->getPointerTy(CurDAG->getDataLayout()))
92bool SparcDAGToDAGISel::SelectADDRri(
SDValue Addr,
95 Base = CurDAG->getTargetFrameIndex(
96 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
97 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
108 if (FrameIndexSDNode *FIN =
111 Base = CurDAG->getTargetFrameIndex(
112 FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
116 Offset = CurDAG->getSignedTargetConstant(CN->getSExtValue(),
117 SDLoc(Addr), MVT::i32);
133 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
137bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &
R2) {
157 R2 = CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
161bool SparcDAGToDAGISel::SelectForceADDRrr(SDValue Addr, SDValue &
Base,
163 if (SelectADDRrr(Addr,
Base, Disp))
170 CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
185bool SparcDAGToDAGISel::tryInlineAsm(SDNode *
N){
186 std::vector<SDValue> AsmNodeOperands;
187 InlineAsm::Flag
Flag;
189 unsigned NumOps =
N->getNumOperands();
200 SDValue Glue =
N->getGluedNode() ?
N->getOperand(
NumOps - 1) : SDValue();
204 for(
unsigned i = 0, e =
N->getGluedNode() ?
NumOps - 1 :
NumOps; i < e; ++i) {
205 SDValue
op =
N->getOperand(i);
206 AsmNodeOperands.push_back(
op);
212 Flag = InlineAsm::Flag(
C->getZExtValue());
220 if (
Flag.isImmKind()) {
221 SDValue
op =
N->getOperand(++i);
222 AsmNodeOperands.push_back(
op);
226 const unsigned NumRegs =
Flag.getNumOperandRegisters();
231 bool IsTiedToChangedOp =
false;
235 IsTiedToChangedOp = OpChanged[DefIdx];
237 if (!
Flag.isRegUseKind() && !
Flag.isRegDefKind() &&
238 !
Flag.isRegDefEarlyClobberKind())
242 const bool HasRC =
Flag.hasRegClassConstraint(RC);
243 if ((!IsTiedToChangedOp && (!HasRC || RC != SP::IntRegsRegClassID))
247 assert((i+2 <
NumOps) &&
"Invalid number of operands in inline asm");
248 SDValue
V0 =
N->getOperand(i+1);
249 SDValue
V1 =
N->getOperand(i+2);
253 MachineRegisterInfo &
MRI = MF->getRegInfo();
255 if (
Flag.isRegDefKind() ||
Flag.isRegDefEarlyClobberKind()) {
260 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
261 SDValue Chain = SDValue(
N,0);
263 SDNode *GU =
N->getGluedUser();
264 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::v2i32,
268 SDValue Sub0 = CurDAG->getTargetExtractSubreg(SP::sub_even, dl, MVT::i32,
270 SDValue Sub1 = CurDAG->getTargetExtractSubreg(SP::sub_odd, dl, MVT::i32,
272 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
274 SDValue
T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.
getValue(1));
278 Ops.push_back(
T1.getValue(1));
279 CurDAG->UpdateNodeOperands(GU,
Ops);
286 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
288 SDValue
T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
290 SDValue Pair = SDValue(
291 CurDAG->getMachineNode(
292 TargetOpcode::REG_SEQUENCE, dl, MVT::v2i32,
294 CurDAG->getTargetConstant(SP::IntPairRegClassID, dl,
297 CurDAG->getTargetConstant(SP::sub_even, dl, MVT::i32),
299 CurDAG->getTargetConstant(SP::sub_odd, dl, MVT::i32),
306 PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
307 Chain = CurDAG->getCopyToReg(
T1, dl, GPVR, Pair,
T1.getValue(1));
316 OpChanged[OpChanged.
size() -1 ] =
true;
317 Flag = InlineAsm::Flag(
Flag.getKind(), 1 );
318 if (IsTiedToChangedOp)
319 Flag.setMatchingOp(DefIdx);
321 Flag.setRegClass(SP::IntPairRegClassID);
323 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
326 AsmNodeOperands.push_back(PairedReg);
333 AsmNodeOperands.push_back(Glue);
337 SelectInlineAsmMemoryOperands(AsmNodeOperands, SDLoc(
N));
339 SDValue
New = CurDAG->getNode(
N->getOpcode(), SDLoc(
N),
340 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
342 ReplaceNode(
N,
New.getNode());
346void SparcDAGToDAGISel::Select(SDNode *
N) {
348 if (
N->isMachineOpcode()) {
353 switch (
N->getOpcode()) {
361 case SPISD::GLOBAL_BASE_REG:
362 ReplaceNode(
N, getGlobalBaseReg());
368 if (
N->getValueType(0) == MVT::i64)
371 SDValue DivLHS =
N->getOperand(0);
372 SDValue DivRHS =
N->getOperand(1);
377 TopPart = SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
378 CurDAG->getTargetConstant(31, dl, MVT::i32)),
381 TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
383 TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart,
388 unsigned Opcode =
N->getOpcode() ==
ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
389 CurDAG->SelectNodeTo(
N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart);
400bool SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(
402 std::vector<SDValue> &OutOps) {
404 switch (ConstraintID) {
405 default:
return true;
406 case InlineAsm::ConstraintCode::o:
407 case InlineAsm::ConstraintCode::m:
408 if (!SelectADDRrr(
Op, Op0, Op1))
409 SelectADDRri(
Op, Op0, Op1);
413 OutOps.push_back(Op0);
414 OutOps.push_back(Op1);
428 return new SparcDAGToDAGISelLegacy(TM, OptLevel);
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)
MachineRegisterInfo & MRI
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
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
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)
SparcDAGToDAGISelPass(SparcTargetMachine &TM, CodeGenOptLevel OptLevel)
@ 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.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
DWARFExpression::Operation Op
FunctionPass * createSparcDAGToDAGISelLegacyPass(SparcTargetMachine &TM, CodeGenOptLevel OptLevel)
createSparcISelDag - This pass converts a legalized DAG into a SPARC-specific DAG,...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Implement std::hash so that hash_code can be used in STL containers.