23 #define DEBUG_TYPE "csky-isel"
33 return "CSKY DAG->DAG Pattern Instruction Selection";
46 bool selectBITCAST_TO_LOHI(
SDNode *
N);
47 bool selectInlineAsm(
SDNode *
N);
51 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
unsigned ConstraintID,
52 std::vector<SDValue> &OutOps)
override;
54 #include "CSKYGenDAGISel.inc"
60 if (
N->isMachineOpcode()) {
67 unsigned Opcode =
N->getOpcode();
68 bool IsSelected =
false;
74 IsSelected = selectAddCarry(
N);
77 IsSelected = selectSubCarry(
N);
80 Register GP = Subtarget->getInstrInfo()->getGlobalBaseReg(*MF);
81 ReplaceNode(
N, CurDAG->getRegister(GP,
N->getValueType(0)).getNode());
88 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
90 ReplaceNode(
N, CurDAG->getMachineNode(Subtarget->hasE2() ? CSKY::ADDI32
98 IsSelected = selectBITCAST_TO_LOHI(
N);
102 IsSelected = selectInlineAsm(
N);
113 bool CSKYDAGToDAGISel::selectInlineAsm(
SDNode *
N) {
114 std::vector<SDValue> AsmNodeOperands;
116 bool Changed =
false;
117 unsigned NumOps =
N->getNumOperands();
126 N->getGluedNode() ?
N->getOperand(NumOps - 1) :
SDValue(
nullptr, 0);
130 for (
unsigned i = 0,
e =
N->getGluedNode() ? NumOps - 1 : NumOps;
i <
e;
133 AsmNodeOperands.push_back(
op);
139 Flag =
C->getZExtValue();
150 AsmNodeOperands.push_back(
op);
156 OpChanged.push_back(
false);
159 bool IsTiedToChangedOp =
false;
163 IsTiedToChangedOp = OpChanged[DefIdx];
172 AsmNodeOperands.push_back(
op);
182 if ((!IsTiedToChangedOp && (!HasRC || RC != CSKY::GPRRegClassID)) ||
186 assert((
i + 2 < NumOps) &&
"Invalid number of operands in inline asm");
189 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
190 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
200 PairedReg = CurDAG->getRegister(GPVR,
MVT::i64);
203 SDNode *GU =
N->getGluedUser();
209 CurDAG->getTargetExtractSubreg(CSKY::sub32_0, dl,
MVT::i32, RegCopy);
211 CurDAG->getTargetExtractSubreg(CSKY::sub32_32, dl,
MVT::i32, RegCopy);
213 CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0, RegCopy.
getValue(1));
218 Ops.push_back(
T1.getValue(1));
219 CurDAG->UpdateNodeOperands(GU, Ops);
235 PairedReg = CurDAG->getRegister(GPVR,
MVT::i64);
236 Chain = CurDAG->getCopyToReg(
T1, dl, GPVR, Pair,
T1.getValue(1));
245 OpChanged[OpChanged.size() - 1] =
true;
247 if (IsTiedToChangedOp)
252 AsmNodeOperands[AsmNodeOperands.size() - 1] =
255 AsmNodeOperands.push_back(PairedReg);
262 AsmNodeOperands.push_back(Glue);
270 ReplaceNode(
N,
New.getNode());
274 bool CSKYDAGToDAGISel::selectBITCAST_TO_LOHI(
SDNode *
N) {
276 auto VT =
N->getValueType(0);
277 auto V =
N->getOperand(0);
279 if (!Subtarget->hasFPUv2DoubleFloat())
282 SDValue V1 =
SDValue(CurDAG->getMachineNode(CSKY::FMFVRL_D, Dl, VT, V), 0);
287 CurDAG->RemoveDeadNode(
N);
292 bool CSKYDAGToDAGISel::selectAddCarry(
SDNode *
N) {
294 auto Type0 =
N->getValueType(0);
295 auto Type1 =
N->getValueType(1);
296 auto Op0 =
N->getOperand(0);
297 auto Op1 =
N->getOperand(1);
298 auto Op2 =
N->getOperand(2);
303 auto *CA = CurDAG->getMachineNode(
304 Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1);
305 NewNode = CurDAG->getMachineNode(
306 Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1},
307 {Op0, Op1, SDValue(CA, 0)});
309 auto *CA = CurDAG->getMachineNode(
310 Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1);
311 NewNode = CurDAG->getMachineNode(
312 Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1},
313 {Op0, Op1, SDValue(CA, 0)});
315 NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::ADDC32
317 Dl, {Type0, Type1}, {Op0, Op1, Op2});
319 ReplaceNode(
N, NewNode);
335 bool CSKYDAGToDAGISel::selectSubCarry(
SDNode *
N) {
337 auto Type0 =
N->getValueType(0);
338 auto Type1 =
N->getValueType(1);
339 auto Op0 =
N->getOperand(0);
340 auto Op1 =
N->getOperand(1);
341 auto Op2 =
N->getOperand(2);
346 auto *CA = CurDAG->getMachineNode(
347 Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1);
348 NewNode = CurDAG->getMachineNode(
349 Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1},
350 {Op0, Op1, SDValue(CA, 0)});
352 auto *CA = CurDAG->getMachineNode(
353 Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1);
354 NewNode = CurDAG->getMachineNode(
355 Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1},
356 {Op0, Op1, SDValue(CA, 0)});
359 NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::SUBC32
361 Dl, {Type0, Type1}, {Op0, Op1, CarryIn});
366 ReplaceUses(
SDValue(
N, 1), CarryOut);
367 CurDAG->RemoveDeadNode(
N);
375 CurDAG->getTargetConstant(CSKY::GPRPairRegClassID, dl,
MVT::i32);
376 SDValue SubReg0 = CurDAG->getTargetConstant(CSKY::sub32_0, dl,
MVT::i32);
377 SDValue SubReg1 = CurDAG->getTargetConstant(CSKY::sub32_32, dl,
MVT::i32);
378 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
379 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
382 bool CSKYDAGToDAGISel::SelectInlineAsmMemoryOperand(
383 const SDValue &
Op,
unsigned ConstraintID, std::vector<SDValue> &OutOps) {
384 switch (ConstraintID) {
388 OutOps.push_back(
Op);
398 return new CSKYDAGToDAGISel(
TM);