LLVM: lib/Target/CSKY/CSKYISelDAGToDAG.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

20

21using namespace llvm;

22

23#define DEBUG_TYPE "csky-isel"

24#define PASS_NAME "CSKY DAG->DAG Pattern Instruction Selection"

25

26namespace {

29

30public:

33

35

38 return true;

39 }

40

42 bool selectAddCarry(SDNode *N);

43 bool selectSubCarry(SDNode *N);

44 bool selectBITCAST_TO_LOHI(SDNode *N);

45 bool selectInlineAsm(SDNode *N);

46

48

49 bool SelectInlineAsmMemoryOperand(const SDValue &Op,

51 std::vector &OutOps) override;

52

53#include "CSKYGenDAGISel.inc"

54};

55

57public:

58 static char ID;

62 ID, std::make_unique(TM, OptLevel)) {}

63};

64}

65

66char CSKYDAGToDAGISelLegacy::ID = 0;

67

69

71

72 if (N->isMachineOpcode()) {

73 LLVM_DEBUG(dbgs() << "== "; N->dump(CurDAG); dbgs() << "\n");

74 N->setNodeId(-1);

75 return;

76 }

77

79 unsigned Opcode = N->getOpcode();

80 bool IsSelected = false;

81

82 switch (Opcode) {

83 default:

84 break;

86 IsSelected = selectAddCarry(N);

87 break;

89 IsSelected = selectSubCarry(N);

90 break;

92 Register GP = Subtarget->getInstrInfo()->getGlobalBaseReg(*MF);

93 ReplaceNode(N, CurDAG->getRegister(GP, N->getValueType(0)).getNode());

94

95 IsSelected = true;

96 break;

97 }

99 SDValue Imm = CurDAG->getTargetConstant(0, Dl, MVT::i32);

101 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);

102 ReplaceNode(N, CurDAG->getMachineNode(Subtarget->hasE2() ? CSKY::ADDI32

103 : CSKY::ADDI16XZ,

104 Dl, MVT::i32, TFI, Imm));

105

106 IsSelected = true;

107 break;

108 }

109 case CSKYISD::BITCAST_TO_LOHI:

110 IsSelected = selectBITCAST_TO_LOHI(N);

111 break;

112 case ISD::INLINEASM:

113 case ISD::INLINEASM_BR:

114 IsSelected = selectInlineAsm(N);

115 break;

116 }

117

118 if (IsSelected)

119 return;

120

121

122 SelectCode(N);

123}

124

125bool CSKYDAGToDAGISel::selectInlineAsm(SDNode *N) {

126 std::vector AsmNodeOperands;

127 InlineAsm::Flag Flag;

129 unsigned NumOps = N->getNumOperands();

130

131

132

133

134

135

136 SDLoc dl(N);

138 N->getGluedNode() ? N->getOperand(NumOps - 1) : SDValue(nullptr, 0);

139

141

142 for (unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e;

143 ++i) {

145 AsmNodeOperands.push_back(op);

146

148 continue;

149

151 Flag = InlineAsm::Flag(C->getZExtValue());

152 else

153 continue;

154

155

156

157

158

159 if (Flag.isImmKind()) {

161 AsmNodeOperands.push_back(op);

162 continue;

163 }

164

165 const unsigned NumRegs = Flag.getNumOperandRegisters();

166 if (NumRegs)

168

169 unsigned DefIdx = 0;

170 bool IsTiedToChangedOp = false;

171

172

173 if (Changed && Flag.isUseOperandTiedToDef(DefIdx))

174 IsTiedToChangedOp = OpChanged[DefIdx];

175

176

177

178

179

180

181 if (Flag.isMemKind()) {

183 AsmNodeOperands.push_back(op);

184 continue;

185 }

186

187 if (Flag.isRegUseKind() && Flag.isRegDefKind() &&

188 Flag.isRegDefEarlyClobberKind())

189 continue;

190

191 unsigned RC;

192 const bool HasRC = Flag.hasRegClassConstraint(RC);

193 if ((!IsTiedToChangedOp && (!HasRC || RC != CSKY::GPRRegClassID)) ||

194 NumRegs != 2)

195 continue;

196

197 assert((i + 2 < NumOps) && "Invalid number of operands in inline asm");

198 SDValue V0 = N->getOperand(i + 1);

199 SDValue V1 = N->getOperand(i + 2);

203 MachineRegisterInfo &MRI = MF->getRegInfo();

204

205 if (Flag.isRegDefKind() || Flag.isRegDefEarlyClobberKind()) {

206

207

208

209 Register GPVR = MRI.createVirtualRegister(&CSKY::GPRPairRegClass);

210 PairedReg = CurDAG->getRegister(GPVR, MVT::i64);

212

213 SDNode *GU = N->getGluedUser();

215 CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::i64, Chain.getValue(1));

216

217

219 CurDAG->getTargetExtractSubreg(CSKY::sub32_0, dl, MVT::i32, RegCopy);

221 CurDAG->getTargetExtractSubreg(CSKY::sub32_32, dl, MVT::i32, RegCopy);

223 CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0, RegCopy.getValue(1));

224 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));

225

226

228 Ops.push_back(T1.getValue(1));

229 CurDAG->UpdateNodeOperands(GU, Ops);

230 } else {

231

232

234

235

237 CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32, Chain.getValue(1));

239 CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32, T0.getValue(1));

241

242

243

244 Register GPVR = MRI.createVirtualRegister(&CSKY::GPRPairRegClass);

245 PairedReg = CurDAG->getRegister(GPVR, MVT::i64);

246 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));

247

250 }

251

253

254 if (PairedReg.getNode()) {

255 OpChanged[OpChanged.size() - 1] = true;

256

257 Flag = InlineAsm::Flag(Flag.getKind(), 1 );

258 if (IsTiedToChangedOp)

259 Flag.setMatchingOp(DefIdx);

260 else

261 Flag.setRegClass(CSKY::GPRPairRegClassID);

262

263 AsmNodeOperands[AsmNodeOperands.size() - 1] =

264 CurDAG->getTargetConstant(Flag, dl, MVT::i32);

265

266 AsmNodeOperands.push_back(PairedReg);

267

268 i += 2;

269 }

270 }

271

273 AsmNodeOperands.push_back(Glue);

275 return false;

276

277 SDValue New = CurDAG->getNode(N->getOpcode(), SDLoc(N),

278 CurDAG->getVTList(MVT::Other, MVT::Glue),

279 AsmNodeOperands);

280 New->setNodeId(-1);

281 ReplaceNode(N, New.getNode());

282 return true;

283}

284

285bool CSKYDAGToDAGISel::selectBITCAST_TO_LOHI(SDNode *N) {

286 SDLoc Dl(N);

287 auto VT = N->getValueType(0);

288 auto V = N->getOperand(0);

289

291 return false;

292

293 SDValue V1 = SDValue(CurDAG->getMachineNode(CSKY::FMFVRL_D, Dl, VT, V), 0);

294 SDValue V2 = SDValue(CurDAG->getMachineNode(CSKY::FMFVRH_D, Dl, VT, V), 0);

295

296 ReplaceUses(SDValue(N, 0), V1);

297 ReplaceUses(SDValue(N, 1), V2);

298 CurDAG->RemoveDeadNode(N);

299

300 return true;

301}

302

303bool CSKYDAGToDAGISel::selectAddCarry(SDNode *N) {

304 MachineSDNode *NewNode = nullptr;

305 auto Type0 = N->getValueType(0);

306 auto Type1 = N->getValueType(1);

307 auto Op0 = N->getOperand(0);

308 auto Op1 = N->getOperand(1);

309 auto Op2 = N->getOperand(2);

310

311 SDLoc Dl(N);

312

314 auto *CA = CurDAG->getMachineNode(

315 Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1);

316 NewNode = CurDAG->getMachineNode(

317 Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1},

318 {Op0, Op1, SDValue(CA, 0)});

320 auto *CA = CurDAG->getMachineNode(

321 Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1);

322 NewNode = CurDAG->getMachineNode(

323 Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1},

324 {Op0, Op1, SDValue(CA, 0)});

325 } else {

326 NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::ADDC32

327 : CSKY::ADDC16,

328 Dl, {Type0, Type1}, {Op0, Op1, Op2});

329 }

330 ReplaceNode(N, NewNode);

331 return true;

332}

333

336 auto NewCarryReg =

338 MVT::i32, OldCarry);

339 auto NewCarry =

343 return SDValue(NewCarry, 0);

344}

345

346bool CSKYDAGToDAGISel::selectSubCarry(SDNode *N) {

347 MachineSDNode *NewNode = nullptr;

349 auto Type1 = N->getValueType(1);

350 auto Op0 = N->getOperand(0);

351 auto Op1 = N->getOperand(1);

352 auto Op2 = N->getOperand(2);

353

354 SDLoc Dl(N);

355

357 auto *CA = CurDAG->getMachineNode(

358 Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1);

359 NewNode = CurDAG->getMachineNode(

360 Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1},

361 {Op0, Op1, SDValue(CA, 0)});

363 auto *CA = CurDAG->getMachineNode(

364 Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1);

365 NewNode = CurDAG->getMachineNode(

366 Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1},

367 {Op0, Op1, SDValue(CA, 0)});

368 } else {

369 auto CarryIn = InvertCarryFlag(Subtarget, CurDAG, Dl, Op2);

370 NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::SUBC32

371 : CSKY::SUBC16,

372 Dl, {Type0, Type1}, {Op0, Op1, CarryIn});

373 }

375

377 ReplaceUses(SDValue(N, 1), CarryOut);

378 CurDAG->RemoveDeadNode(N);

379

380 return true;

381}

382

383SDNode *CSKYDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {

386 CurDAG->getTargetConstant(CSKY::GPRPairRegClassID, dl, MVT::i32);

387 SDValue SubReg0 = CurDAG->getTargetConstant(CSKY::sub32_0, dl, MVT::i32);

388 SDValue SubReg1 = CurDAG->getTargetConstant(CSKY::sub32_32, dl, MVT::i32);

389 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};

390 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);

391}

392

393bool CSKYDAGToDAGISel::SelectInlineAsmMemoryOperand(

395 std::vector &OutOps) {

396 switch (ConstraintID) {

397 case InlineAsm::ConstraintCode::m:

398

399

400 OutOps.push_back(Op);

401 return false;

402 default:

403 break;

404 }

405

406 return true;

407}

408

411 return new CSKYDAGToDAGISelLegacy(TM, OptLevel);

412}

unsigned const MachineRegisterInfo * MRI

static SDValue createGPRPairNode(SelectionDAG &DAG, SDValue V)

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

AMDGPU Register Bank Select

static SDValue InvertCarryFlag(const CSKYSubtarget *Subtarget, SelectionDAG *DAG, SDLoc Dl, SDValue OldCarry)

Definition CSKYISelDAGToDAG.cpp:334

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)

bool hasFPUv2DoubleFloat() const

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.

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.

EVT getValueType(unsigned ResNo) const

Return the type of a specified result.

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...

virtual bool runOnMachineFunction(MachineFunction &mf)

This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...

LLVM_ABI 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)

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

@ GLOBAL_OFFSET_TABLE

The address of the GOT.

@ UADDO_CARRY

Carry-using nodes for multiple precision addition and subtraction.

Flag

These should be considered private to the implementation of the MCInstrDesc class.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI bool isNullConstant(SDValue V)

Returns true if V is a constant integer zero.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - 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

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

LLVM_ABI bool isOneConstant(SDValue V)

Returns true if V is a constant integer one.

FunctionPass * createCSKYISelDag(CSKYTargetMachine &TM, CodeGenOptLevel OptLevel)

Definition CSKYISelDAGToDAG.cpp:409