23#define DEBUG_TYPE "csky-isel"
24#define PASS_NAME "CSKY DAG->DAG Pattern Instruction Selection"
46 bool selectBITCAST_TO_LOHI(
SDNode *
N);
47 bool selectInlineAsm(
SDNode *
N);
52 std::vector<SDValue> &OutOps)
override;
54#include "CSKYGenDAGISel.inc"
58char CSKYDAGToDAGISel::ID = 0;
64 if (
N->isMachineOpcode()) {
71 unsigned Opcode =
N->getOpcode();
72 bool IsSelected =
false;
78 IsSelected = selectAddCarry(
N);
81 IsSelected = selectSubCarry(
N);
84 Register GP = Subtarget->getInstrInfo()->getGlobalBaseReg(*MF);
85 ReplaceNode(
N, CurDAG->getRegister(GP,
N->getValueType(0)).getNode());
92 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
94 ReplaceNode(
N, CurDAG->getMachineNode(Subtarget->hasE2() ? CSKY::ADDI32
102 IsSelected = selectBITCAST_TO_LOHI(
N);
106 IsSelected = selectInlineAsm(
N);
117bool CSKYDAGToDAGISel::selectInlineAsm(
SDNode *
N) {
118 std::vector<SDValue> AsmNodeOperands;
120 bool Changed =
false;
121 unsigned NumOps =
N->getNumOperands();
130 N->getGluedNode() ?
N->getOperand(NumOps - 1) :
SDValue(
nullptr, 0);
134 for (
unsigned i = 0, e =
N->getGluedNode() ? NumOps - 1 : NumOps; i < e;
137 AsmNodeOperands.push_back(
op);
143 Flag =
C->getZExtValue();
154 AsmNodeOperands.push_back(
op);
163 bool IsTiedToChangedOp =
false;
167 IsTiedToChangedOp = OpChanged[DefIdx];
176 AsmNodeOperands.push_back(
op);
186 if ((!IsTiedToChangedOp && (!HasRC || RC != CSKY::GPRRegClassID)) ||
190 assert((i + 2 < NumOps) &&
"Invalid number of operands in inline asm");
193 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
194 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
203 Register GPVR =
MRI.createVirtualRegister(&CSKY::GPRPairRegClass);
204 PairedReg = CurDAG->getRegister(GPVR,
MVT::i64);
207 SDNode *GU =
N->getGluedUser();
213 CurDAG->getTargetExtractSubreg(CSKY::sub32_0, dl,
MVT::i32, RegCopy);
215 CurDAG->getTargetExtractSubreg(CSKY::sub32_32, dl,
MVT::i32, RegCopy);
217 CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0, RegCopy.
getValue(1));
222 Ops.push_back(
T1.getValue(1));
223 CurDAG->UpdateNodeOperands(GU, Ops);
238 Register GPVR =
MRI.createVirtualRegister(&CSKY::GPRPairRegClass);
239 PairedReg = CurDAG->getRegister(GPVR,
MVT::i64);
240 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair,
T1.getValue(1));
249 OpChanged[OpChanged.
size() - 1] =
true;
251 if (IsTiedToChangedOp)
256 AsmNodeOperands[AsmNodeOperands.size() - 1] =
257 CurDAG->getTargetConstant(Flag, dl,
MVT::i32);
259 AsmNodeOperands.push_back(PairedReg);
266 AsmNodeOperands.push_back(Glue);
274 ReplaceNode(
N,
New.getNode());
278bool CSKYDAGToDAGISel::selectBITCAST_TO_LOHI(
SDNode *
N) {
280 auto VT =
N->getValueType(0);
281 auto V =
N->getOperand(0);
283 if (!Subtarget->hasFPUv2DoubleFloat())
286 SDValue V1 =
SDValue(CurDAG->getMachineNode(CSKY::FMFVRL_D, Dl, VT, V), 0);
291 CurDAG->RemoveDeadNode(
N);
296bool CSKYDAGToDAGISel::selectAddCarry(
SDNode *
N) {
298 auto Type0 =
N->getValueType(0);
299 auto Type1 =
N->getValueType(1);
300 auto Op0 =
N->getOperand(0);
301 auto Op1 =
N->getOperand(1);
302 auto Op2 =
N->getOperand(2);
307 auto *CA = CurDAG->getMachineNode(
308 Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1);
309 NewNode = CurDAG->getMachineNode(
310 Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1},
311 {Op0, Op1, SDValue(CA, 0)});
313 auto *CA = CurDAG->getMachineNode(
314 Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1);
315 NewNode = CurDAG->getMachineNode(
316 Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1},
317 {Op0, Op1, SDValue(CA, 0)});
319 NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::ADDC32
321 Dl, {Type0, Type1}, {Op0, Op1, Op2});
323 ReplaceNode(
N, NewNode);
339bool CSKYDAGToDAGISel::selectSubCarry(
SDNode *
N) {
341 auto Type0 =
N->getValueType(0);
342 auto Type1 =
N->getValueType(1);
343 auto Op0 =
N->getOperand(0);
344 auto Op1 =
N->getOperand(1);
345 auto Op2 =
N->getOperand(2);
350 auto *CA = CurDAG->getMachineNode(
351 Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1);
352 NewNode = CurDAG->getMachineNode(
353 Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1},
354 {Op0, Op1, SDValue(CA, 0)});
356 auto *CA = CurDAG->getMachineNode(
357 Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1);
358 NewNode = CurDAG->getMachineNode(
359 Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1},
360 {Op0, Op1, SDValue(CA, 0)});
363 NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::SUBC32
365 Dl, {Type0, Type1}, {Op0, Op1, CarryIn});
370 ReplaceUses(
SDValue(
N, 1), CarryOut);
371 CurDAG->RemoveDeadNode(
N);
379 CurDAG->getTargetConstant(CSKY::GPRPairRegClassID, dl,
MVT::i32);
380 SDValue SubReg0 = CurDAG->getTargetConstant(CSKY::sub32_0, dl,
MVT::i32);
381 SDValue SubReg1 = CurDAG->getTargetConstant(CSKY::sub32_32, dl,
MVT::i32);
382 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
383 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
386bool CSKYDAGToDAGISel::SelectInlineAsmMemoryOperand(
387 const SDValue &Op,
unsigned ConstraintID, std::vector<SDValue> &OutOps) {
388 switch (ConstraintID) {
392 OutOps.push_back(Op);
403 return new CSKYDAGToDAGISel(
TM, OptLevel);
unsigned const MachineRegisterInfo * MRI
static SDValue createGPRPairNode(SelectionDAG &DAG, SDValue V)
amdgpu AMDGPU Register Bank Select
static SDValue InvertCarryFlag(const CSKYSubtarget *Subtarget, SelectionDAG *DAG, SDLoc Dl, SDValue OldCarry)
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
FunctionPass class - This class is used to implement most global optimizations.
static unsigned getFlagWord(unsigned Kind, unsigned NumOps)
static unsigned getNumOperandRegisters(unsigned Flag)
getNumOperandRegisters - Extract the number of registers field from the inline asm operand flag.
@ Kind_RegDefEarlyClobber
static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx)
isUseOperandTiedToDef - Return true if the flag of the inline asm operand indicates it is an use oper...
static bool hasRegClassConstraint(unsigned Flag, unsigned &RC)
hasRegClassConstraint - Returns true if the flag contains a register class constraint.
static unsigned getFlagWordForMatchingOp(unsigned InputFlag, unsigned MatchedOperandNo)
getFlagWordForMatchingOp - Augment an existing flag word returned by getFlagWord with information ind...
static unsigned getKind(unsigned Flags)
static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC)
getFlagWordForRegClass - Augment an existing flag word returned by getFlagWord with the required regi...
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,...
An SDNode that represents everything that will be needed to construct a MachineInstr.
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
EVT getValueType() const
Return the ValueType of the referenced return value.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
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.
Level
Code generation optimization level.
@ ADDCARRY
Carry-using nodes for multiple precision addition and subtraction.
@ GLOBAL_OFFSET_TABLE
The address of the GOT.
@ 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.
This is an optimization pass for GlobalISel generic memory operations.
bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
FunctionPass * createCSKYISelDag(CSKYTargetMachine &TM, CodeGenOpt::Level OptLevel)