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 (.isRegUseKind() &&
.isRegDefKind() &&
188 .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