1 | //===-- CSKYISelLowering.cpp - CSKY DAG Lowering Implementation ----------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines the interfaces that CSKY uses to lower LLVM code into a |
10 | // selection DAG. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "CSKYISelLowering.h" |
15 | #include "CSKYCallingConv.h" |
16 | #include "CSKYConstantPoolValue.h" |
17 | #include "CSKYMachineFunctionInfo.h" |
18 | #include "CSKYRegisterInfo.h" |
19 | #include "CSKYSubtarget.h" |
20 | #include "llvm/ADT/Statistic.h" |
21 | #include "llvm/CodeGen/CallingConvLower.h" |
22 | #include "llvm/CodeGen/MachineFrameInfo.h" |
23 | #include "llvm/CodeGen/MachineJumpTableInfo.h" |
24 | #include "llvm/Support/Debug.h" |
25 | |
26 | using namespace llvm; |
27 | |
28 | #define DEBUG_TYPE "csky-isel-lowering" |
29 | |
30 | STATISTIC(NumTailCalls, "Number of tail calls" ); |
31 | |
32 | #include "CSKYGenCallingConv.inc" |
33 | |
34 | static const MCPhysReg GPRArgRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3}; |
35 | |
36 | CSKYTargetLowering::CSKYTargetLowering(const TargetMachine &TM, |
37 | const CSKYSubtarget &STI) |
38 | : TargetLowering(TM), Subtarget(STI) { |
39 | // Register Class |
40 | addRegisterClass(MVT::i32, &CSKY::GPRRegClass); |
41 | |
42 | if (STI.useHardFloat()) { |
43 | if (STI.hasFPUv2SingleFloat()) |
44 | addRegisterClass(MVT::f32, &CSKY::sFPR32RegClass); |
45 | else if (STI.hasFPUv3SingleFloat()) |
46 | addRegisterClass(MVT::f32, &CSKY::FPR32RegClass); |
47 | |
48 | if (STI.hasFPUv2DoubleFloat()) |
49 | addRegisterClass(MVT::f64, &CSKY::sFPR64RegClass); |
50 | else if (STI.hasFPUv3DoubleFloat()) |
51 | addRegisterClass(MVT::f64, &CSKY::FPR64RegClass); |
52 | } |
53 | |
54 | setOperationAction(ISD::UADDO_CARRY, MVT::i32, Legal); |
55 | setOperationAction(ISD::USUBO_CARRY, MVT::i32, Legal); |
56 | setOperationAction(ISD::BITREVERSE, MVT::i32, Legal); |
57 | |
58 | setOperationAction(ISD::SREM, MVT::i32, Expand); |
59 | setOperationAction(ISD::UREM, MVT::i32, Expand); |
60 | setOperationAction(ISD::UDIVREM, MVT::i32, Expand); |
61 | setOperationAction(ISD::SDIVREM, MVT::i32, Expand); |
62 | setOperationAction(ISD::CTPOP, MVT::i32, Expand); |
63 | setOperationAction(ISD::ROTR, MVT::i32, Expand); |
64 | setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); |
65 | setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); |
66 | setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); |
67 | setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); |
68 | setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); |
69 | setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); |
70 | setOperationAction(ISD::BR_CC, MVT::i32, Expand); |
71 | setOperationAction(ISD::BR_JT, MVT::Other, Expand); |
72 | setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); |
73 | setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); |
74 | setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); |
75 | setOperationAction(ISD::MULHS, MVT::i32, Expand); |
76 | setOperationAction(ISD::MULHU, MVT::i32, Expand); |
77 | setOperationAction(ISD::VAARG, MVT::Other, Expand); |
78 | setOperationAction(ISD::VACOPY, MVT::Other, Expand); |
79 | setOperationAction(ISD::VAEND, MVT::Other, Expand); |
80 | |
81 | setLoadExtAction(ISD::EXTLOAD, MVT::i32, MVT::i1, Promote); |
82 | setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i1, Promote); |
83 | setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, MVT::i1, Promote); |
84 | |
85 | setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); |
86 | setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom); |
87 | setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); |
88 | setOperationAction(ISD::BlockAddress, MVT::i32, Custom); |
89 | if (!Subtarget.hasE2()) { |
90 | setOperationAction(ISD::ConstantPool, MVT::i32, Custom); |
91 | } |
92 | setOperationAction(ISD::JumpTable, MVT::i32, Custom); |
93 | setOperationAction(ISD::VASTART, MVT::Other, Custom); |
94 | |
95 | if (!Subtarget.hasE2()) { |
96 | setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i8, Expand); |
97 | setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i16, Expand); |
98 | setOperationAction(ISD::CTLZ, MVT::i32, Expand); |
99 | setOperationAction(ISD::BSWAP, MVT::i32, Expand); |
100 | } |
101 | |
102 | if (!Subtarget.has2E3()) { |
103 | setOperationAction(ISD::ABS, MVT::i32, Expand); |
104 | setOperationAction(ISD::BITREVERSE, MVT::i32, Expand); |
105 | setOperationAction(ISD::CTTZ, MVT::i32, Expand); |
106 | setOperationAction(ISD::SDIV, MVT::i32, Expand); |
107 | setOperationAction(ISD::UDIV, MVT::i32, Expand); |
108 | } |
109 | |
110 | setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); |
111 | |
112 | // Float |
113 | |
114 | ISD::CondCode FPCCToExtend[] = { |
115 | ISD::SETONE, ISD::SETUEQ, ISD::SETUGT, |
116 | ISD::SETUGE, ISD::SETULT, ISD::SETULE, |
117 | }; |
118 | |
119 | ISD::NodeType FPOpToExpand[] = { |
120 | ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, |
121 | ISD::FREM, ISD::FCOPYSIGN, ISD::FP16_TO_FP, ISD::FP_TO_FP16}; |
122 | |
123 | if (STI.useHardFloat()) { |
124 | |
125 | MVT AllVTy[] = {MVT::f32, MVT::f64}; |
126 | |
127 | for (auto VT : AllVTy) { |
128 | setOperationAction(ISD::FREM, VT, Expand); |
129 | setOperationAction(ISD::SELECT_CC, VT, Expand); |
130 | setOperationAction(ISD::BR_CC, VT, Expand); |
131 | |
132 | for (auto CC : FPCCToExtend) |
133 | setCondCodeAction(CC, VT, Expand); |
134 | for (auto Op : FPOpToExpand) |
135 | setOperationAction(Op, VT, Expand); |
136 | } |
137 | |
138 | if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat()) { |
139 | setOperationAction(ISD::ConstantFP, MVT::f32, Legal); |
140 | setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand); |
141 | setTruncStoreAction(MVT::f32, MVT::f16, Expand); |
142 | } |
143 | if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat()) { |
144 | setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); |
145 | setTruncStoreAction(MVT::f64, MVT::f32, Expand); |
146 | setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand); |
147 | setTruncStoreAction(MVT::f64, MVT::f16, Expand); |
148 | } |
149 | } |
150 | |
151 | // Compute derived properties from the register classes. |
152 | computeRegisterProperties(STI.getRegisterInfo()); |
153 | |
154 | setBooleanContents(UndefinedBooleanContent); |
155 | setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); |
156 | |
157 | // TODO: Add atomic support fully. |
158 | setMaxAtomicSizeInBitsSupported(0); |
159 | |
160 | setStackPointerRegisterToSaveRestore(CSKY::R14); |
161 | setMinFunctionAlignment(Align(2)); |
162 | setSchedulingPreference(Sched::Source); |
163 | } |
164 | |
165 | SDValue CSKYTargetLowering::LowerOperation(SDValue Op, |
166 | SelectionDAG &DAG) const { |
167 | switch (Op.getOpcode()) { |
168 | default: |
169 | llvm_unreachable("unimplemented op" ); |
170 | case ISD::GlobalAddress: |
171 | return LowerGlobalAddress(Op, DAG); |
172 | case ISD::ExternalSymbol: |
173 | return LowerExternalSymbol(Op, DAG); |
174 | case ISD::GlobalTLSAddress: |
175 | return LowerGlobalTLSAddress(Op, DAG); |
176 | case ISD::JumpTable: |
177 | return LowerJumpTable(Op, DAG); |
178 | case ISD::BlockAddress: |
179 | return LowerBlockAddress(Op, DAG); |
180 | case ISD::ConstantPool: |
181 | return LowerConstantPool(Op, DAG); |
182 | case ISD::VASTART: |
183 | return LowerVASTART(Op, DAG); |
184 | case ISD::FRAMEADDR: |
185 | return LowerFRAMEADDR(Op, DAG); |
186 | case ISD::RETURNADDR: |
187 | return LowerRETURNADDR(Op, DAG); |
188 | } |
189 | } |
190 | |
191 | EVT CSKYTargetLowering::getSetCCResultType(const DataLayout &DL, |
192 | LLVMContext &Context, EVT VT) const { |
193 | if (!VT.isVector()) |
194 | return MVT::i32; |
195 | |
196 | return VT.changeVectorElementTypeToInteger(); |
197 | } |
198 | |
199 | static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, |
200 | const CCValAssign &VA, const SDLoc &DL) { |
201 | EVT LocVT = VA.getLocVT(); |
202 | |
203 | switch (VA.getLocInfo()) { |
204 | default: |
205 | llvm_unreachable("Unexpected CCValAssign::LocInfo" ); |
206 | case CCValAssign::Full: |
207 | break; |
208 | case CCValAssign::BCvt: |
209 | Val = DAG.getNode(Opcode: ISD::BITCAST, DL, VT: LocVT, Operand: Val); |
210 | break; |
211 | } |
212 | return Val; |
213 | } |
214 | |
215 | static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, |
216 | const CCValAssign &VA, const SDLoc &DL) { |
217 | switch (VA.getLocInfo()) { |
218 | default: |
219 | llvm_unreachable("Unexpected CCValAssign::LocInfo" ); |
220 | case CCValAssign::Full: |
221 | break; |
222 | case CCValAssign::BCvt: |
223 | Val = DAG.getNode(Opcode: ISD::BITCAST, DL, VT: VA.getValVT(), Operand: Val); |
224 | break; |
225 | } |
226 | return Val; |
227 | } |
228 | |
229 | static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, |
230 | SelectionDAG &DAG, SDValue Chain, |
231 | const CCValAssign &VA, const SDLoc &DL) { |
232 | MachineFunction &MF = DAG.getMachineFunction(); |
233 | MachineRegisterInfo &RegInfo = MF.getRegInfo(); |
234 | EVT LocVT = VA.getLocVT(); |
235 | SDValue Val; |
236 | const TargetRegisterClass *RC; |
237 | |
238 | switch (LocVT.getSimpleVT().SimpleTy) { |
239 | default: |
240 | llvm_unreachable("Unexpected register type" ); |
241 | case MVT::i32: |
242 | RC = &CSKY::GPRRegClass; |
243 | break; |
244 | case MVT::f32: |
245 | RC = Subtarget.hasFPUv2SingleFloat() ? &CSKY::sFPR32RegClass |
246 | : &CSKY::FPR32RegClass; |
247 | break; |
248 | case MVT::f64: |
249 | RC = Subtarget.hasFPUv2DoubleFloat() ? &CSKY::sFPR64RegClass |
250 | : &CSKY::FPR64RegClass; |
251 | break; |
252 | } |
253 | |
254 | Register VReg = RegInfo.createVirtualRegister(RegClass: RC); |
255 | RegInfo.addLiveIn(Reg: VA.getLocReg(), vreg: VReg); |
256 | Val = DAG.getCopyFromReg(Chain, dl: DL, Reg: VReg, VT: LocVT); |
257 | |
258 | return convertLocVTToValVT(DAG, Val, VA, DL); |
259 | } |
260 | |
261 | static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, |
262 | const CCValAssign &VA, const SDLoc &DL) { |
263 | MachineFunction &MF = DAG.getMachineFunction(); |
264 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
265 | EVT LocVT = VA.getLocVT(); |
266 | EVT ValVT = VA.getValVT(); |
267 | EVT PtrVT = MVT::getIntegerVT(BitWidth: DAG.getDataLayout().getPointerSizeInBits(AS: 0)); |
268 | int FI = MFI.CreateFixedObject(Size: ValVT.getSizeInBits() / 8, |
269 | SPOffset: VA.getLocMemOffset(), /*Immutable=*/IsImmutable: true); |
270 | SDValue FIN = DAG.getFrameIndex(FI, VT: PtrVT); |
271 | SDValue Val; |
272 | |
273 | ISD::LoadExtType ExtType; |
274 | switch (VA.getLocInfo()) { |
275 | default: |
276 | llvm_unreachable("Unexpected CCValAssign::LocInfo" ); |
277 | case CCValAssign::Full: |
278 | case CCValAssign::BCvt: |
279 | ExtType = ISD::NON_EXTLOAD; |
280 | break; |
281 | } |
282 | Val = DAG.getExtLoad( |
283 | ExtType, dl: DL, VT: LocVT, Chain, Ptr: FIN, |
284 | PtrInfo: MachinePointerInfo::getFixedStack(MF&: DAG.getMachineFunction(), FI), MemVT: ValVT); |
285 | return Val; |
286 | } |
287 | |
288 | static SDValue unpack64(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, |
289 | const SDLoc &DL) { |
290 | assert(VA.getLocVT() == MVT::i32 && |
291 | (VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::i64) && |
292 | "Unexpected VA" ); |
293 | MachineFunction &MF = DAG.getMachineFunction(); |
294 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
295 | MachineRegisterInfo &RegInfo = MF.getRegInfo(); |
296 | |
297 | if (VA.isMemLoc()) { |
298 | // f64/i64 is passed on the stack. |
299 | int FI = MFI.CreateFixedObject(Size: 8, SPOffset: VA.getLocMemOffset(), /*Immutable=*/IsImmutable: true); |
300 | SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); |
301 | return DAG.getLoad(VT: VA.getValVT(), dl: DL, Chain, Ptr: FIN, |
302 | PtrInfo: MachinePointerInfo::getFixedStack(MF, FI)); |
303 | } |
304 | |
305 | assert(VA.isRegLoc() && "Expected register VA assignment" ); |
306 | |
307 | Register LoVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass); |
308 | RegInfo.addLiveIn(Reg: VA.getLocReg(), vreg: LoVReg); |
309 | SDValue Lo = DAG.getCopyFromReg(Chain, DL, LoVReg, MVT::i32); |
310 | SDValue Hi; |
311 | if (VA.getLocReg() == CSKY::R3) { |
312 | // Second half of f64/i64 is passed on the stack. |
313 | int FI = MFI.CreateFixedObject(Size: 4, SPOffset: 0, /*Immutable=*/IsImmutable: true); |
314 | SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); |
315 | Hi = DAG.getLoad(MVT::i32, DL, Chain, FIN, |
316 | MachinePointerInfo::getFixedStack(MF, FI)); |
317 | } else { |
318 | // Second half of f64/i64 is passed in another GPR. |
319 | Register HiVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass); |
320 | RegInfo.addLiveIn(Reg: VA.getLocReg() + 1, vreg: HiVReg); |
321 | Hi = DAG.getCopyFromReg(Chain, DL, HiVReg, MVT::i32); |
322 | } |
323 | return DAG.getNode(Opcode: CSKYISD::BITCAST_FROM_LOHI, DL, VT: VA.getValVT(), N1: Lo, N2: Hi); |
324 | } |
325 | |
326 | // Transform physical registers into virtual registers. |
327 | SDValue CSKYTargetLowering::LowerFormalArguments( |
328 | SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, |
329 | const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, |
330 | SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { |
331 | |
332 | switch (CallConv) { |
333 | default: |
334 | report_fatal_error(reason: "Unsupported calling convention" ); |
335 | case CallingConv::C: |
336 | case CallingConv::Fast: |
337 | break; |
338 | } |
339 | |
340 | MachineFunction &MF = DAG.getMachineFunction(); |
341 | |
342 | // Used with vargs to acumulate store chains. |
343 | std::vector<SDValue> OutChains; |
344 | |
345 | // Assign locations to all of the incoming arguments. |
346 | SmallVector<CCValAssign, 16> ArgLocs; |
347 | CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); |
348 | |
349 | CCInfo.AnalyzeFormalArguments(Ins, Fn: CCAssignFnForCall(CC: CallConv, IsVarArg)); |
350 | |
351 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { |
352 | CCValAssign &VA = ArgLocs[i]; |
353 | SDValue ArgValue; |
354 | |
355 | bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; |
356 | |
357 | if (IsF64OnCSKY) |
358 | ArgValue = unpack64(DAG, Chain, VA, DL); |
359 | else if (VA.isRegLoc()) |
360 | ArgValue = unpackFromRegLoc(Subtarget, DAG, Chain, VA, DL); |
361 | else |
362 | ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL); |
363 | |
364 | InVals.push_back(Elt: ArgValue); |
365 | } |
366 | |
367 | if (IsVarArg) { |
368 | const unsigned XLenInBytes = 4; |
369 | const MVT XLenVT = MVT::i32; |
370 | |
371 | ArrayRef<MCPhysReg> ArgRegs = ArrayRef(GPRArgRegs); |
372 | unsigned Idx = CCInfo.getFirstUnallocated(Regs: ArgRegs); |
373 | const TargetRegisterClass *RC = &CSKY::GPRRegClass; |
374 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
375 | MachineRegisterInfo &RegInfo = MF.getRegInfo(); |
376 | CSKYMachineFunctionInfo *CSKYFI = MF.getInfo<CSKYMachineFunctionInfo>(); |
377 | |
378 | // Offset of the first variable argument from stack pointer, and size of |
379 | // the vararg save area. For now, the varargs save area is either zero or |
380 | // large enough to hold a0-a4. |
381 | int VaArgOffset, VarArgsSaveSize; |
382 | |
383 | // If all registers are allocated, then all varargs must be passed on the |
384 | // stack and we don't need to save any argregs. |
385 | if (ArgRegs.size() == Idx) { |
386 | VaArgOffset = CCInfo.getStackSize(); |
387 | VarArgsSaveSize = 0; |
388 | } else { |
389 | VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx); |
390 | VaArgOffset = -VarArgsSaveSize; |
391 | } |
392 | |
393 | // Record the frame index of the first variable argument |
394 | // which is a value necessary to VASTART. |
395 | int FI = MFI.CreateFixedObject(Size: XLenInBytes, SPOffset: VaArgOffset, IsImmutable: true); |
396 | CSKYFI->setVarArgsFrameIndex(FI); |
397 | |
398 | // Copy the integer registers that may have been used for passing varargs |
399 | // to the vararg save area. |
400 | for (unsigned I = Idx; I < ArgRegs.size(); |
401 | ++I, VaArgOffset += XLenInBytes) { |
402 | const Register Reg = RegInfo.createVirtualRegister(RegClass: RC); |
403 | RegInfo.addLiveIn(Reg: ArgRegs[I], vreg: Reg); |
404 | SDValue ArgValue = DAG.getCopyFromReg(Chain, dl: DL, Reg, VT: XLenVT); |
405 | FI = MFI.CreateFixedObject(Size: XLenInBytes, SPOffset: VaArgOffset, IsImmutable: true); |
406 | SDValue PtrOff = DAG.getFrameIndex(FI, VT: getPointerTy(DL: DAG.getDataLayout())); |
407 | SDValue Store = DAG.getStore(Chain, dl: DL, Val: ArgValue, Ptr: PtrOff, |
408 | PtrInfo: MachinePointerInfo::getFixedStack(MF, FI)); |
409 | cast<StoreSDNode>(Val: Store.getNode()) |
410 | ->getMemOperand() |
411 | ->setValue((Value *)nullptr); |
412 | OutChains.push_back(x: Store); |
413 | } |
414 | CSKYFI->setVarArgsSaveSize(VarArgsSaveSize); |
415 | } |
416 | |
417 | // All stores are grouped in one node to allow the matching between |
418 | // the size of Ins and InVals. This only happens for vararg functions. |
419 | if (!OutChains.empty()) { |
420 | OutChains.push_back(x: Chain); |
421 | Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); |
422 | } |
423 | |
424 | return Chain; |
425 | } |
426 | |
427 | bool CSKYTargetLowering::CanLowerReturn( |
428 | CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, |
429 | const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { |
430 | SmallVector<CCValAssign, 16> CSKYLocs; |
431 | CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context); |
432 | return CCInfo.CheckReturn(Outs, Fn: CCAssignFnForReturn(CC: CallConv, IsVarArg)); |
433 | } |
434 | |
435 | SDValue |
436 | CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, |
437 | bool IsVarArg, |
438 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
439 | const SmallVectorImpl<SDValue> &OutVals, |
440 | const SDLoc &DL, SelectionDAG &DAG) const { |
441 | // Stores the assignment of the return value to a location. |
442 | SmallVector<CCValAssign, 16> CSKYLocs; |
443 | |
444 | // Info about the registers and stack slot. |
445 | CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), CSKYLocs, |
446 | *DAG.getContext()); |
447 | CCInfo.AnalyzeReturn(Outs, Fn: CCAssignFnForReturn(CC: CallConv, IsVarArg)); |
448 | |
449 | SDValue Glue; |
450 | SmallVector<SDValue, 4> RetOps(1, Chain); |
451 | |
452 | // Copy the result values into the output registers. |
453 | for (unsigned i = 0, e = CSKYLocs.size(); i < e; ++i) { |
454 | SDValue Val = OutVals[i]; |
455 | CCValAssign &VA = CSKYLocs[i]; |
456 | assert(VA.isRegLoc() && "Can only return in registers!" ); |
457 | |
458 | bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; |
459 | |
460 | if (IsF64OnCSKY) { |
461 | |
462 | assert(VA.isRegLoc() && "Expected return via registers" ); |
463 | SDValue Split64 = DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL, |
464 | DAG.getVTList(MVT::i32, MVT::i32), Val); |
465 | SDValue Lo = Split64.getValue(R: 0); |
466 | SDValue Hi = Split64.getValue(R: 1); |
467 | |
468 | Register RegLo = VA.getLocReg(); |
469 | assert(RegLo < CSKY::R31 && "Invalid register pair" ); |
470 | Register RegHi = RegLo + 1; |
471 | |
472 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: RegLo, N: Lo, Glue); |
473 | Glue = Chain.getValue(R: 1); |
474 | RetOps.push_back(DAG.getRegister(RegLo, MVT::i32)); |
475 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: RegHi, N: Hi, Glue); |
476 | Glue = Chain.getValue(R: 1); |
477 | RetOps.push_back(DAG.getRegister(RegHi, MVT::i32)); |
478 | } else { |
479 | // Handle a 'normal' return. |
480 | Val = convertValVTToLocVT(DAG, Val, VA, DL); |
481 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: VA.getLocReg(), N: Val, Glue); |
482 | |
483 | // Guarantee that all emitted copies are stuck together. |
484 | Glue = Chain.getValue(R: 1); |
485 | RetOps.push_back(Elt: DAG.getRegister(Reg: VA.getLocReg(), VT: VA.getLocVT())); |
486 | } |
487 | } |
488 | |
489 | RetOps[0] = Chain; // Update chain. |
490 | |
491 | // Add the glue node if we have it. |
492 | if (Glue.getNode()) { |
493 | RetOps.push_back(Elt: Glue); |
494 | } |
495 | |
496 | // Interrupt service routines use different return instructions. |
497 | if (DAG.getMachineFunction().getFunction().hasFnAttribute("interrupt" )) |
498 | return DAG.getNode(CSKYISD::NIR, DL, MVT::Other, RetOps); |
499 | |
500 | return DAG.getNode(CSKYISD::RET, DL, MVT::Other, RetOps); |
501 | } |
502 | |
503 | // Lower a call to a callseq_start + CALL + callseq_end chain, and add input |
504 | // and output parameter nodes. |
505 | SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI, |
506 | SmallVectorImpl<SDValue> &InVals) const { |
507 | SelectionDAG &DAG = CLI.DAG; |
508 | SDLoc &DL = CLI.DL; |
509 | SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; |
510 | SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; |
511 | SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; |
512 | SDValue Chain = CLI.Chain; |
513 | SDValue Callee = CLI.Callee; |
514 | bool &IsTailCall = CLI.IsTailCall; |
515 | CallingConv::ID CallConv = CLI.CallConv; |
516 | bool IsVarArg = CLI.IsVarArg; |
517 | EVT PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
518 | MVT XLenVT = MVT::i32; |
519 | |
520 | MachineFunction &MF = DAG.getMachineFunction(); |
521 | |
522 | // Analyze the operands of the call, assigning locations to each operand. |
523 | SmallVector<CCValAssign, 16> ArgLocs; |
524 | CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); |
525 | |
526 | ArgCCInfo.AnalyzeCallOperands(Outs, Fn: CCAssignFnForCall(CC: CallConv, IsVarArg)); |
527 | |
528 | // Check if it's really possible to do a tail call. |
529 | if (IsTailCall) |
530 | IsTailCall = false; // TODO: TailCallOptimization; |
531 | |
532 | if (IsTailCall) |
533 | ++NumTailCalls; |
534 | else if (CLI.CB && CLI.CB->isMustTailCall()) |
535 | report_fatal_error(reason: "failed to perform tail call elimination on a call " |
536 | "site marked musttail" ); |
537 | |
538 | // Get a count of how many bytes are to be pushed on the stack. |
539 | unsigned NumBytes = ArgCCInfo.getStackSize(); |
540 | |
541 | // Create local copies for byval args |
542 | SmallVector<SDValue, 8> ByValArgs; |
543 | for (unsigned i = 0, e = Outs.size(); i != e; ++i) { |
544 | ISD::ArgFlagsTy Flags = Outs[i].Flags; |
545 | if (!Flags.isByVal()) |
546 | continue; |
547 | |
548 | SDValue Arg = OutVals[i]; |
549 | unsigned Size = Flags.getByValSize(); |
550 | Align Alignment = Flags.getNonZeroByValAlign(); |
551 | |
552 | int FI = |
553 | MF.getFrameInfo().CreateStackObject(Size, Alignment, /*isSS=*/isSpillSlot: false); |
554 | SDValue FIPtr = DAG.getFrameIndex(FI, VT: getPointerTy(DL: DAG.getDataLayout())); |
555 | SDValue SizeNode = DAG.getConstant(Val: Size, DL, VT: XLenVT); |
556 | |
557 | Chain = DAG.getMemcpy(Chain, dl: DL, Dst: FIPtr, Src: Arg, Size: SizeNode, Alignment, |
558 | /*IsVolatile=*/isVol: false, |
559 | /*AlwaysInline=*/false, isTailCall: IsTailCall, |
560 | DstPtrInfo: MachinePointerInfo(), SrcPtrInfo: MachinePointerInfo()); |
561 | ByValArgs.push_back(Elt: FIPtr); |
562 | } |
563 | |
564 | if (!IsTailCall) |
565 | Chain = DAG.getCALLSEQ_START(Chain, InSize: NumBytes, OutSize: 0, DL: CLI.DL); |
566 | |
567 | // Copy argument values to their designated locations. |
568 | SmallVector<std::pair<Register, SDValue>, 8> RegsToPass; |
569 | SmallVector<SDValue, 8> MemOpChains; |
570 | SDValue StackPtr; |
571 | for (unsigned i = 0, j = 0, e = ArgLocs.size(); i != e; ++i) { |
572 | CCValAssign &VA = ArgLocs[i]; |
573 | SDValue ArgValue = OutVals[i]; |
574 | ISD::ArgFlagsTy Flags = Outs[i].Flags; |
575 | |
576 | bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; |
577 | |
578 | if (IsF64OnCSKY && VA.isRegLoc()) { |
579 | SDValue Split64 = |
580 | DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL, |
581 | DAG.getVTList(MVT::i32, MVT::i32), ArgValue); |
582 | SDValue Lo = Split64.getValue(R: 0); |
583 | SDValue Hi = Split64.getValue(R: 1); |
584 | |
585 | Register RegLo = VA.getLocReg(); |
586 | RegsToPass.push_back(Elt: std::make_pair(x&: RegLo, y&: Lo)); |
587 | |
588 | if (RegLo == CSKY::R3) { |
589 | // Second half of f64/i64 is passed on the stack. |
590 | // Work out the address of the stack slot. |
591 | if (!StackPtr.getNode()) |
592 | StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT); |
593 | // Emit the store. |
594 | MemOpChains.push_back( |
595 | Elt: DAG.getStore(Chain, dl: DL, Val: Hi, Ptr: StackPtr, PtrInfo: MachinePointerInfo())); |
596 | } else { |
597 | // Second half of f64/i64 is passed in another GPR. |
598 | assert(RegLo < CSKY::R31 && "Invalid register pair" ); |
599 | Register RegHigh = RegLo + 1; |
600 | RegsToPass.push_back(Elt: std::make_pair(x&: RegHigh, y&: Hi)); |
601 | } |
602 | continue; |
603 | } |
604 | |
605 | ArgValue = convertValVTToLocVT(DAG, Val: ArgValue, VA, DL); |
606 | |
607 | // Use local copy if it is a byval arg. |
608 | if (Flags.isByVal()) |
609 | ArgValue = ByValArgs[j++]; |
610 | |
611 | if (VA.isRegLoc()) { |
612 | // Queue up the argument copies and emit them at the end. |
613 | RegsToPass.push_back(Elt: std::make_pair(x: VA.getLocReg(), y&: ArgValue)); |
614 | } else { |
615 | assert(VA.isMemLoc() && "Argument not register or memory" ); |
616 | assert(!IsTailCall && "Tail call not allowed if stack is used " |
617 | "for passing parameters" ); |
618 | |
619 | // Work out the address of the stack slot. |
620 | if (!StackPtr.getNode()) |
621 | StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT); |
622 | SDValue Address = |
623 | DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, N1: StackPtr, |
624 | N2: DAG.getIntPtrConstant(Val: VA.getLocMemOffset(), DL)); |
625 | |
626 | // Emit the store. |
627 | MemOpChains.push_back( |
628 | Elt: DAG.getStore(Chain, dl: DL, Val: ArgValue, Ptr: Address, PtrInfo: MachinePointerInfo())); |
629 | } |
630 | } |
631 | |
632 | // Join the stores, which are independent of one another. |
633 | if (!MemOpChains.empty()) |
634 | Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); |
635 | |
636 | SDValue Glue; |
637 | |
638 | // Build a sequence of copy-to-reg nodes, chained and glued together. |
639 | for (auto &Reg : RegsToPass) { |
640 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: Reg.first, N: Reg.second, Glue); |
641 | Glue = Chain.getValue(R: 1); |
642 | } |
643 | |
644 | SmallVector<SDValue, 8> Ops; |
645 | EVT Ty = getPointerTy(DL: DAG.getDataLayout()); |
646 | bool IsRegCall = false; |
647 | |
648 | Ops.push_back(Elt: Chain); |
649 | |
650 | if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Val&: Callee)) { |
651 | const GlobalValue *GV = S->getGlobal(); |
652 | bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV); |
653 | |
654 | if (isPositionIndependent() || !Subtarget.has2E3()) { |
655 | IsRegCall = true; |
656 | Ops.push_back(Elt: getAddr<GlobalAddressSDNode, true>(N: S, DAG, IsLocal)); |
657 | } else { |
658 | Ops.push_back(Elt: getTargetNode(N: cast<GlobalAddressSDNode>(Val&: Callee), DL, Ty, |
659 | DAG, Flags: CSKYII::MO_None)); |
660 | Ops.push_back(Elt: getTargetConstantPoolValue( |
661 | N: cast<GlobalAddressSDNode>(Val&: Callee), Ty, DAG, Flags: CSKYII::MO_None)); |
662 | } |
663 | } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Val&: Callee)) { |
664 | bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV: nullptr); |
665 | |
666 | if (isPositionIndependent() || !Subtarget.has2E3()) { |
667 | IsRegCall = true; |
668 | Ops.push_back(Elt: getAddr<ExternalSymbolSDNode, true>(N: S, DAG, IsLocal)); |
669 | } else { |
670 | Ops.push_back(Elt: getTargetNode(N: cast<ExternalSymbolSDNode>(Val&: Callee), DL, Ty, |
671 | DAG, Flags: CSKYII::MO_None)); |
672 | Ops.push_back(Elt: getTargetConstantPoolValue( |
673 | N: cast<ExternalSymbolSDNode>(Val&: Callee), Ty, DAG, Flags: CSKYII::MO_None)); |
674 | } |
675 | } else { |
676 | IsRegCall = true; |
677 | Ops.push_back(Elt: Callee); |
678 | } |
679 | |
680 | // Add argument registers to the end of the list so that they are |
681 | // known live into the call. |
682 | for (auto &Reg : RegsToPass) |
683 | Ops.push_back(Elt: DAG.getRegister(Reg: Reg.first, VT: Reg.second.getValueType())); |
684 | |
685 | if (!IsTailCall) { |
686 | // Add a register mask operand representing the call-preserved registers. |
687 | const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); |
688 | const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); |
689 | assert(Mask && "Missing call preserved mask for calling convention" ); |
690 | Ops.push_back(Elt: DAG.getRegisterMask(RegMask: Mask)); |
691 | } |
692 | |
693 | // Glue the call to the argument copies, if any. |
694 | if (Glue.getNode()) |
695 | Ops.push_back(Elt: Glue); |
696 | |
697 | // Emit the call. |
698 | SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); |
699 | |
700 | if (IsTailCall) { |
701 | MF.getFrameInfo().setHasTailCall(); |
702 | return DAG.getNode(Opcode: IsRegCall ? CSKYISD::TAILReg : CSKYISD::TAIL, DL, |
703 | VTList: NodeTys, Ops); |
704 | } |
705 | |
706 | Chain = DAG.getNode(Opcode: IsRegCall ? CSKYISD::CALLReg : CSKYISD::CALL, DL, VTList: NodeTys, |
707 | Ops); |
708 | DAG.addNoMergeSiteInfo(Node: Chain.getNode(), NoMerge: CLI.NoMerge); |
709 | Glue = Chain.getValue(R: 1); |
710 | |
711 | // Mark the end of the call, which is glued to the call itself. |
712 | Chain = DAG.getCALLSEQ_END(Chain, Size1: NumBytes, Size2: 0, Glue, DL); |
713 | Glue = Chain.getValue(R: 1); |
714 | |
715 | // Assign locations to each value returned by this call. |
716 | SmallVector<CCValAssign, 16> CSKYLocs; |
717 | CCState RetCCInfo(CallConv, IsVarArg, MF, CSKYLocs, *DAG.getContext()); |
718 | RetCCInfo.AnalyzeCallResult(Ins, Fn: CCAssignFnForReturn(CC: CallConv, IsVarArg)); |
719 | |
720 | // Copy all of the result registers out of their specified physreg. |
721 | for (auto &VA : CSKYLocs) { |
722 | // Copy the value out |
723 | SDValue RetValue = |
724 | DAG.getCopyFromReg(Chain, dl: DL, Reg: VA.getLocReg(), VT: VA.getLocVT(), Glue); |
725 | // Glue the RetValue to the end of the call sequence |
726 | Chain = RetValue.getValue(R: 1); |
727 | Glue = RetValue.getValue(R: 2); |
728 | |
729 | bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; |
730 | |
731 | if (IsF64OnCSKY) { |
732 | assert(VA.getLocReg() == GPRArgRegs[0] && "Unexpected reg assignment" ); |
733 | SDValue RetValue2 = |
734 | DAG.getCopyFromReg(Chain, DL, GPRArgRegs[1], MVT::i32, Glue); |
735 | Chain = RetValue2.getValue(R: 1); |
736 | Glue = RetValue2.getValue(R: 2); |
737 | RetValue = DAG.getNode(Opcode: CSKYISD::BITCAST_FROM_LOHI, DL, VT: VA.getValVT(), |
738 | N1: RetValue, N2: RetValue2); |
739 | } |
740 | |
741 | RetValue = convertLocVTToValVT(DAG, Val: RetValue, VA, DL); |
742 | |
743 | InVals.push_back(Elt: RetValue); |
744 | } |
745 | |
746 | return Chain; |
747 | } |
748 | |
749 | CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC, |
750 | bool IsVarArg) const { |
751 | if (IsVarArg || !Subtarget.useHardFloatABI()) |
752 | return RetCC_CSKY_ABIV2_SOFT; |
753 | else |
754 | return RetCC_CSKY_ABIV2_FP; |
755 | } |
756 | |
757 | CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC, |
758 | bool IsVarArg) const { |
759 | if (IsVarArg || !Subtarget.useHardFloatABI()) |
760 | return CC_CSKY_ABIV2_SOFT; |
761 | else |
762 | return CC_CSKY_ABIV2_FP; |
763 | } |
764 | |
765 | static CSKYCP::CSKYCPModifier getModifier(unsigned Flags) { |
766 | |
767 | if (Flags == CSKYII::MO_ADDR32) |
768 | return CSKYCP::ADDR; |
769 | else if (Flags == CSKYII::MO_GOT32) |
770 | return CSKYCP::GOT; |
771 | else if (Flags == CSKYII::MO_GOTOFF) |
772 | return CSKYCP::GOTOFF; |
773 | else if (Flags == CSKYII::MO_PLT32) |
774 | return CSKYCP::PLT; |
775 | else if (Flags == CSKYII::MO_None) |
776 | return CSKYCP::NO_MOD; |
777 | else |
778 | assert(0 && "unknown CSKYII Modifier" ); |
779 | return CSKYCP::NO_MOD; |
780 | } |
781 | |
782 | SDValue CSKYTargetLowering::getTargetConstantPoolValue(GlobalAddressSDNode *N, |
783 | EVT Ty, |
784 | SelectionDAG &DAG, |
785 | unsigned Flags) const { |
786 | CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create( |
787 | C: N->getGlobal(), Kind: CSKYCP::CPValue, PCAdjust: 0, Modifier: getModifier(Flags), AddCurrentAddress: false); |
788 | |
789 | return DAG.getTargetConstantPool(C: CPV, VT: Ty); |
790 | } |
791 | |
792 | CSKYTargetLowering::ConstraintType |
793 | CSKYTargetLowering::getConstraintType(StringRef Constraint) const { |
794 | if (Constraint.size() == 1) { |
795 | switch (Constraint[0]) { |
796 | default: |
797 | break; |
798 | case 'a': |
799 | case 'b': |
800 | case 'v': |
801 | case 'w': |
802 | case 'y': |
803 | return C_RegisterClass; |
804 | case 'c': |
805 | case 'l': |
806 | case 'h': |
807 | case 'z': |
808 | return C_Register; |
809 | } |
810 | } |
811 | return TargetLowering::getConstraintType(Constraint); |
812 | } |
813 | |
814 | std::pair<unsigned, const TargetRegisterClass *> |
815 | CSKYTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, |
816 | StringRef Constraint, |
817 | MVT VT) const { |
818 | if (Constraint.size() == 1) { |
819 | switch (Constraint[0]) { |
820 | case 'r': |
821 | return std::make_pair(0U, &CSKY::GPRRegClass); |
822 | case 'a': |
823 | return std::make_pair(0U, &CSKY::mGPRRegClass); |
824 | case 'b': |
825 | return std::make_pair(0U, &CSKY::sGPRRegClass); |
826 | case 'z': |
827 | return std::make_pair(CSKY::R14, &CSKY::GPRRegClass); |
828 | case 'c': |
829 | return std::make_pair(CSKY::C, &CSKY::CARRYRegClass); |
830 | case 'w': |
831 | if ((Subtarget.hasFPUv2SingleFloat() || |
832 | Subtarget.hasFPUv3SingleFloat()) && |
833 | VT == MVT::f32) |
834 | return std::make_pair(0U, &CSKY::sFPR32RegClass); |
835 | if ((Subtarget.hasFPUv2DoubleFloat() || |
836 | Subtarget.hasFPUv3DoubleFloat()) && |
837 | VT == MVT::f64) |
838 | return std::make_pair(0U, &CSKY::sFPR64RegClass); |
839 | break; |
840 | case 'v': |
841 | if (Subtarget.hasFPUv2SingleFloat() && VT == MVT::f32) |
842 | return std::make_pair(0U, &CSKY::sFPR32RegClass); |
843 | if (Subtarget.hasFPUv3SingleFloat() && VT == MVT::f32) |
844 | return std::make_pair(0U, &CSKY::FPR32RegClass); |
845 | if (Subtarget.hasFPUv2DoubleFloat() && VT == MVT::f64) |
846 | return std::make_pair(0U, &CSKY::sFPR64RegClass); |
847 | if (Subtarget.hasFPUv3DoubleFloat() && VT == MVT::f64) |
848 | return std::make_pair(0U, &CSKY::FPR64RegClass); |
849 | break; |
850 | default: |
851 | break; |
852 | } |
853 | } |
854 | |
855 | if (Constraint == "{c}" ) |
856 | return std::make_pair(CSKY::C, &CSKY::CARRYRegClass); |
857 | |
858 | // Clang will correctly decode the usage of register name aliases into their |
859 | // official names. However, other frontends like `rustc` do not. This allows |
860 | // users of these frontends to use the ABI names for registers in LLVM-style |
861 | // register constraints. |
862 | unsigned XRegFromAlias = StringSwitch<unsigned>(Constraint.lower()) |
863 | .Case("{a0}" , CSKY::R0) |
864 | .Case("{a1}" , CSKY::R1) |
865 | .Case("{a2}" , CSKY::R2) |
866 | .Case("{a3}" , CSKY::R3) |
867 | .Case("{l0}" , CSKY::R4) |
868 | .Case("{l1}" , CSKY::R5) |
869 | .Case("{l2}" , CSKY::R6) |
870 | .Case("{l3}" , CSKY::R7) |
871 | .Case("{l4}" , CSKY::R8) |
872 | .Case("{l5}" , CSKY::R9) |
873 | .Case("{l6}" , CSKY::R10) |
874 | .Case("{l7}" , CSKY::R11) |
875 | .Case("{t0}" , CSKY::R12) |
876 | .Case("{t1}" , CSKY::R13) |
877 | .Case("{sp}" , CSKY::R14) |
878 | .Case("{lr}" , CSKY::R15) |
879 | .Case("{l8}" , CSKY::R16) |
880 | .Case("{l9}" , CSKY::R17) |
881 | .Case("{t2}" , CSKY::R18) |
882 | .Case("{t3}" , CSKY::R19) |
883 | .Case("{t4}" , CSKY::R20) |
884 | .Case("{t5}" , CSKY::R21) |
885 | .Case("{t6}" , CSKY::R22) |
886 | .Cases("{t7}" , "{fp}" , CSKY::R23) |
887 | .Cases("{t8}" , "{top}" , CSKY::R24) |
888 | .Cases("{t9}" , "{bsp}" , CSKY::R25) |
889 | .Case("{r26}" , CSKY::R26) |
890 | .Case("{r27}" , CSKY::R27) |
891 | .Cases("{gb}" , "{rgb}" , "{rdb}" , CSKY::R28) |
892 | .Cases("{tb}" , "{rtb}" , CSKY::R29) |
893 | .Case("{svbr}" , CSKY::R30) |
894 | .Case("{tls}" , CSKY::R31) |
895 | .Default(CSKY::NoRegister); |
896 | |
897 | if (XRegFromAlias != CSKY::NoRegister) |
898 | return std::make_pair(XRegFromAlias, &CSKY::GPRRegClass); |
899 | |
900 | // Since TargetLowering::getRegForInlineAsmConstraint uses the name of the |
901 | // TableGen record rather than the AsmName to choose registers for InlineAsm |
902 | // constraints, plus we want to match those names to the widest floating point |
903 | // register type available, manually select floating point registers here. |
904 | // |
905 | // The second case is the ABI name of the register, so that frontends can also |
906 | // use the ABI names in register constraint lists. |
907 | if (Subtarget.useHardFloat()) { |
908 | unsigned FReg = StringSwitch<unsigned>(Constraint.lower()) |
909 | .Cases("{fr0}" , "{vr0}" , CSKY::F0_32) |
910 | .Cases("{fr1}" , "{vr1}" , CSKY::F1_32) |
911 | .Cases("{fr2}" , "{vr2}" , CSKY::F2_32) |
912 | .Cases("{fr3}" , "{vr3}" , CSKY::F3_32) |
913 | .Cases("{fr4}" , "{vr4}" , CSKY::F4_32) |
914 | .Cases("{fr5}" , "{vr5}" , CSKY::F5_32) |
915 | .Cases("{fr6}" , "{vr6}" , CSKY::F6_32) |
916 | .Cases("{fr7}" , "{vr7}" , CSKY::F7_32) |
917 | .Cases("{fr8}" , "{vr8}" , CSKY::F8_32) |
918 | .Cases("{fr9}" , "{vr9}" , CSKY::F9_32) |
919 | .Cases("{fr10}" , "{vr10}" , CSKY::F10_32) |
920 | .Cases("{fr11}" , "{vr11}" , CSKY::F11_32) |
921 | .Cases("{fr12}" , "{vr12}" , CSKY::F12_32) |
922 | .Cases("{fr13}" , "{vr13}" , CSKY::F13_32) |
923 | .Cases("{fr14}" , "{vr14}" , CSKY::F14_32) |
924 | .Cases("{fr15}" , "{vr15}" , CSKY::F15_32) |
925 | .Cases("{fr16}" , "{vr16}" , CSKY::F16_32) |
926 | .Cases("{fr17}" , "{vr17}" , CSKY::F17_32) |
927 | .Cases("{fr18}" , "{vr18}" , CSKY::F18_32) |
928 | .Cases("{fr19}" , "{vr19}" , CSKY::F19_32) |
929 | .Cases("{fr20}" , "{vr20}" , CSKY::F20_32) |
930 | .Cases("{fr21}" , "{vr21}" , CSKY::F21_32) |
931 | .Cases("{fr22}" , "{vr22}" , CSKY::F22_32) |
932 | .Cases("{fr23}" , "{vr23}" , CSKY::F23_32) |
933 | .Cases("{fr24}" , "{vr24}" , CSKY::F24_32) |
934 | .Cases("{fr25}" , "{vr25}" , CSKY::F25_32) |
935 | .Cases("{fr26}" , "{vr26}" , CSKY::F26_32) |
936 | .Cases("{fr27}" , "{vr27}" , CSKY::F27_32) |
937 | .Cases("{fr28}" , "{vr28}" , CSKY::F28_32) |
938 | .Cases("{fr29}" , "{vr29}" , CSKY::F29_32) |
939 | .Cases("{fr30}" , "{vr30}" , CSKY::F30_32) |
940 | .Cases("{fr31}" , "{vr31}" , CSKY::F31_32) |
941 | .Default(CSKY::NoRegister); |
942 | if (FReg != CSKY::NoRegister) { |
943 | assert(CSKY::F0_32 <= FReg && FReg <= CSKY::F31_32 && "Unknown fp-reg" ); |
944 | unsigned RegNo = FReg - CSKY::F0_32; |
945 | unsigned DReg = CSKY::F0_64 + RegNo; |
946 | |
947 | if (Subtarget.hasFPUv2DoubleFloat()) |
948 | return std::make_pair(DReg, &CSKY::sFPR64RegClass); |
949 | else if (Subtarget.hasFPUv3DoubleFloat()) |
950 | return std::make_pair(DReg, &CSKY::FPR64RegClass); |
951 | else if (Subtarget.hasFPUv2SingleFloat()) |
952 | return std::make_pair(FReg, &CSKY::sFPR32RegClass); |
953 | else if (Subtarget.hasFPUv3SingleFloat()) |
954 | return std::make_pair(FReg, &CSKY::FPR32RegClass); |
955 | } |
956 | } |
957 | |
958 | return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); |
959 | } |
960 | |
961 | static MachineBasicBlock * |
962 | emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode) { |
963 | |
964 | const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo(); |
965 | DebugLoc DL = MI.getDebugLoc(); |
966 | |
967 | // To "insert" a SELECT instruction, we actually have to insert the |
968 | // diamond control-flow pattern. The incoming instruction knows the |
969 | // destination vreg to set, the condition code register to branch on, the |
970 | // true/false values to select between, and a branch opcode to use. |
971 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); |
972 | MachineFunction::iterator It = ++BB->getIterator(); |
973 | |
974 | // thisMBB: |
975 | // ... |
976 | // TrueVal = ... |
977 | // bt32 c, sinkMBB |
978 | // fallthrough --> copyMBB |
979 | MachineBasicBlock *thisMBB = BB; |
980 | MachineFunction *F = BB->getParent(); |
981 | MachineBasicBlock *copyMBB = F->CreateMachineBasicBlock(BB: LLVM_BB); |
982 | MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(BB: LLVM_BB); |
983 | F->insert(MBBI: It, MBB: copyMBB); |
984 | F->insert(MBBI: It, MBB: sinkMBB); |
985 | |
986 | // Transfer the remainder of BB and its successor edges to sinkMBB. |
987 | sinkMBB->splice(Where: sinkMBB->begin(), Other: BB, |
988 | From: std::next(x: MachineBasicBlock::iterator(MI)), To: BB->end()); |
989 | sinkMBB->transferSuccessorsAndUpdatePHIs(FromMBB: BB); |
990 | |
991 | // Next, add the true and fallthrough blocks as its successors. |
992 | BB->addSuccessor(Succ: copyMBB); |
993 | BB->addSuccessor(Succ: sinkMBB); |
994 | |
995 | // bt32 condition, sinkMBB |
996 | BuildMI(BB, MIMD: DL, MCID: TII.get(Opcode)) |
997 | .addReg(RegNo: MI.getOperand(i: 1).getReg()) |
998 | .addMBB(MBB: sinkMBB); |
999 | |
1000 | // copyMBB: |
1001 | // %FalseValue = ... |
1002 | // # fallthrough to sinkMBB |
1003 | BB = copyMBB; |
1004 | |
1005 | // Update machine-CFG edges |
1006 | BB->addSuccessor(Succ: sinkMBB); |
1007 | |
1008 | // sinkMBB: |
1009 | // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copyMBB ] |
1010 | // ... |
1011 | BB = sinkMBB; |
1012 | |
1013 | BuildMI(*BB, BB->begin(), DL, TII.get(CSKY::PHI), MI.getOperand(0).getReg()) |
1014 | .addReg(MI.getOperand(2).getReg()) |
1015 | .addMBB(thisMBB) |
1016 | .addReg(MI.getOperand(3).getReg()) |
1017 | .addMBB(copyMBB); |
1018 | |
1019 | MI.eraseFromParent(); // The pseudo instruction is gone now. |
1020 | |
1021 | return BB; |
1022 | } |
1023 | |
1024 | MachineBasicBlock * |
1025 | CSKYTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, |
1026 | MachineBasicBlock *BB) const { |
1027 | switch (MI.getOpcode()) { |
1028 | default: |
1029 | llvm_unreachable("Unexpected instr type to insert" ); |
1030 | case CSKY::FSELS: |
1031 | case CSKY::FSELD: |
1032 | if (Subtarget.hasE2()) |
1033 | return emitSelectPseudo(MI, BB, CSKY::BT32); |
1034 | else |
1035 | return emitSelectPseudo(MI, BB, CSKY::BT16); |
1036 | case CSKY::ISEL32: |
1037 | return emitSelectPseudo(MI, BB, CSKY::BT32); |
1038 | case CSKY::ISEL16: |
1039 | return emitSelectPseudo(MI, BB, CSKY::BT16); |
1040 | } |
1041 | } |
1042 | |
1043 | SDValue CSKYTargetLowering::getTargetConstantPoolValue(ExternalSymbolSDNode *N, |
1044 | EVT Ty, |
1045 | SelectionDAG &DAG, |
1046 | unsigned Flags) const { |
1047 | CSKYConstantPoolValue *CPV = |
1048 | CSKYConstantPoolSymbol::Create(Ty: Type::getInt32Ty(C&: *DAG.getContext()), |
1049 | S: N->getSymbol(), PCAdjust: 0, Modifier: getModifier(Flags)); |
1050 | |
1051 | return DAG.getTargetConstantPool(C: CPV, VT: Ty); |
1052 | } |
1053 | |
1054 | SDValue CSKYTargetLowering::getTargetConstantPoolValue(JumpTableSDNode *N, |
1055 | EVT Ty, |
1056 | SelectionDAG &DAG, |
1057 | unsigned Flags) const { |
1058 | CSKYConstantPoolValue *CPV = |
1059 | CSKYConstantPoolJT::Create(Ty: Type::getInt32Ty(C&: *DAG.getContext()), |
1060 | JTI: N->getIndex(), PCAdj: 0, Modifier: getModifier(Flags)); |
1061 | return DAG.getTargetConstantPool(C: CPV, VT: Ty); |
1062 | } |
1063 | |
1064 | SDValue CSKYTargetLowering::getTargetConstantPoolValue(BlockAddressSDNode *N, |
1065 | EVT Ty, |
1066 | SelectionDAG &DAG, |
1067 | unsigned Flags) const { |
1068 | assert(N->getOffset() == 0); |
1069 | CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create( |
1070 | C: N->getBlockAddress(), Kind: CSKYCP::CPBlockAddress, PCAdjust: 0, Modifier: getModifier(Flags), |
1071 | AddCurrentAddress: false); |
1072 | return DAG.getTargetConstantPool(C: CPV, VT: Ty); |
1073 | } |
1074 | |
1075 | SDValue CSKYTargetLowering::getTargetConstantPoolValue(ConstantPoolSDNode *N, |
1076 | EVT Ty, |
1077 | SelectionDAG &DAG, |
1078 | unsigned Flags) const { |
1079 | assert(N->getOffset() == 0); |
1080 | CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create( |
1081 | C: N->getConstVal(), Ty: Type::getInt32Ty(C&: *DAG.getContext()), |
1082 | Kind: CSKYCP::CPConstPool, PCAdjust: 0, Modifier: getModifier(Flags), AddCurrentAddress: false); |
1083 | return DAG.getTargetConstantPool(C: CPV, VT: Ty); |
1084 | } |
1085 | |
1086 | SDValue CSKYTargetLowering::getTargetNode(GlobalAddressSDNode *N, SDLoc DL, |
1087 | EVT Ty, SelectionDAG &DAG, |
1088 | unsigned Flags) const { |
1089 | return DAG.getTargetGlobalAddress(GV: N->getGlobal(), DL, VT: Ty, offset: 0, TargetFlags: Flags); |
1090 | } |
1091 | |
1092 | SDValue CSKYTargetLowering::getTargetNode(ExternalSymbolSDNode *N, SDLoc DL, |
1093 | EVT Ty, SelectionDAG &DAG, |
1094 | unsigned Flags) const { |
1095 | return DAG.getTargetExternalSymbol(Sym: N->getSymbol(), VT: Ty, TargetFlags: Flags); |
1096 | } |
1097 | |
1098 | SDValue CSKYTargetLowering::getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty, |
1099 | SelectionDAG &DAG, |
1100 | unsigned Flags) const { |
1101 | return DAG.getTargetJumpTable(JTI: N->getIndex(), VT: Ty, TargetFlags: Flags); |
1102 | } |
1103 | |
1104 | SDValue CSKYTargetLowering::getTargetNode(BlockAddressSDNode *N, SDLoc DL, |
1105 | EVT Ty, SelectionDAG &DAG, |
1106 | unsigned Flags) const { |
1107 | return DAG.getTargetBlockAddress(BA: N->getBlockAddress(), VT: Ty, Offset: N->getOffset(), |
1108 | TargetFlags: Flags); |
1109 | } |
1110 | |
1111 | SDValue CSKYTargetLowering::getTargetNode(ConstantPoolSDNode *N, SDLoc DL, |
1112 | EVT Ty, SelectionDAG &DAG, |
1113 | unsigned Flags) const { |
1114 | |
1115 | return DAG.getTargetConstantPool(C: N->getConstVal(), VT: Ty, Align: N->getAlign(), |
1116 | Offset: N->getOffset(), TargetFlags: Flags); |
1117 | } |
1118 | |
1119 | const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const { |
1120 | switch (Opcode) { |
1121 | default: |
1122 | llvm_unreachable("unknown CSKYISD node" ); |
1123 | case CSKYISD::NIE: |
1124 | return "CSKYISD::NIE" ; |
1125 | case CSKYISD::NIR: |
1126 | return "CSKYISD::NIR" ; |
1127 | case CSKYISD::RET: |
1128 | return "CSKYISD::RET" ; |
1129 | case CSKYISD::CALL: |
1130 | return "CSKYISD::CALL" ; |
1131 | case CSKYISD::CALLReg: |
1132 | return "CSKYISD::CALLReg" ; |
1133 | case CSKYISD::TAIL: |
1134 | return "CSKYISD::TAIL" ; |
1135 | case CSKYISD::TAILReg: |
1136 | return "CSKYISD::TAILReg" ; |
1137 | case CSKYISD::LOAD_ADDR: |
1138 | return "CSKYISD::LOAD_ADDR" ; |
1139 | case CSKYISD::BITCAST_TO_LOHI: |
1140 | return "CSKYISD::BITCAST_TO_LOHI" ; |
1141 | case CSKYISD::BITCAST_FROM_LOHI: |
1142 | return "CSKYISD::BITCAST_FROM_LOHI" ; |
1143 | } |
1144 | } |
1145 | |
1146 | SDValue CSKYTargetLowering::LowerGlobalAddress(SDValue Op, |
1147 | SelectionDAG &DAG) const { |
1148 | SDLoc DL(Op); |
1149 | EVT Ty = Op.getValueType(); |
1150 | GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Val&: Op); |
1151 | int64_t Offset = N->getOffset(); |
1152 | |
1153 | const GlobalValue *GV = N->getGlobal(); |
1154 | bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV); |
1155 | SDValue Addr = getAddr<GlobalAddressSDNode, false>(N, DAG, IsLocal); |
1156 | |
1157 | // In order to maximise the opportunity for common subexpression elimination, |
1158 | // emit a separate ADD node for the global address offset instead of folding |
1159 | // it in the global address node. Later peephole optimisations may choose to |
1160 | // fold it back in when profitable. |
1161 | if (Offset != 0) |
1162 | return DAG.getNode(ISD::ADD, DL, Ty, Addr, |
1163 | DAG.getConstant(Offset, DL, MVT::i32)); |
1164 | return Addr; |
1165 | } |
1166 | |
1167 | SDValue CSKYTargetLowering::LowerExternalSymbol(SDValue Op, |
1168 | SelectionDAG &DAG) const { |
1169 | ExternalSymbolSDNode *N = cast<ExternalSymbolSDNode>(Val&: Op); |
1170 | |
1171 | return getAddr(N, DAG, IsLocal: false); |
1172 | } |
1173 | |
1174 | SDValue CSKYTargetLowering::LowerJumpTable(SDValue Op, |
1175 | SelectionDAG &DAG) const { |
1176 | JumpTableSDNode *N = cast<JumpTableSDNode>(Val&: Op); |
1177 | |
1178 | return getAddr<JumpTableSDNode, false>(N, DAG); |
1179 | } |
1180 | |
1181 | SDValue CSKYTargetLowering::LowerBlockAddress(SDValue Op, |
1182 | SelectionDAG &DAG) const { |
1183 | BlockAddressSDNode *N = cast<BlockAddressSDNode>(Val&: Op); |
1184 | |
1185 | return getAddr(N, DAG); |
1186 | } |
1187 | |
1188 | SDValue CSKYTargetLowering::LowerConstantPool(SDValue Op, |
1189 | SelectionDAG &DAG) const { |
1190 | assert(!Subtarget.hasE2()); |
1191 | ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Val&: Op); |
1192 | |
1193 | return getAddr(N, DAG); |
1194 | } |
1195 | |
1196 | SDValue CSKYTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { |
1197 | MachineFunction &MF = DAG.getMachineFunction(); |
1198 | CSKYMachineFunctionInfo *FuncInfo = MF.getInfo<CSKYMachineFunctionInfo>(); |
1199 | |
1200 | SDLoc DL(Op); |
1201 | SDValue FI = DAG.getFrameIndex(FI: FuncInfo->getVarArgsFrameIndex(), |
1202 | VT: getPointerTy(DL: MF.getDataLayout())); |
1203 | |
1204 | // vastart just stores the address of the VarArgsFrameIndex slot into the |
1205 | // memory location argument. |
1206 | const Value *SV = cast<SrcValueSDNode>(Val: Op.getOperand(i: 2))->getValue(); |
1207 | return DAG.getStore(Chain: Op.getOperand(i: 0), dl: DL, Val: FI, Ptr: Op.getOperand(i: 1), |
1208 | PtrInfo: MachinePointerInfo(SV)); |
1209 | } |
1210 | |
1211 | SDValue CSKYTargetLowering::LowerFRAMEADDR(SDValue Op, |
1212 | SelectionDAG &DAG) const { |
1213 | const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo(); |
1214 | MachineFunction &MF = DAG.getMachineFunction(); |
1215 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
1216 | MFI.setFrameAddressIsTaken(true); |
1217 | |
1218 | EVT VT = Op.getValueType(); |
1219 | SDLoc dl(Op); |
1220 | unsigned Depth = Op.getConstantOperandVal(i: 0); |
1221 | Register FrameReg = RI.getFrameRegister(MF); |
1222 | SDValue FrameAddr = DAG.getCopyFromReg(Chain: DAG.getEntryNode(), dl, Reg: FrameReg, VT); |
1223 | while (Depth--) |
1224 | FrameAddr = DAG.getLoad(VT, dl, Chain: DAG.getEntryNode(), Ptr: FrameAddr, |
1225 | PtrInfo: MachinePointerInfo()); |
1226 | return FrameAddr; |
1227 | } |
1228 | |
1229 | SDValue CSKYTargetLowering::LowerRETURNADDR(SDValue Op, |
1230 | SelectionDAG &DAG) const { |
1231 | const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo(); |
1232 | MachineFunction &MF = DAG.getMachineFunction(); |
1233 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
1234 | MFI.setReturnAddressIsTaken(true); |
1235 | |
1236 | if (verifyReturnAddressArgumentIsConstant(Op, DAG)) |
1237 | return SDValue(); |
1238 | |
1239 | EVT VT = Op.getValueType(); |
1240 | SDLoc dl(Op); |
1241 | unsigned Depth = Op.getConstantOperandVal(i: 0); |
1242 | if (Depth) { |
1243 | SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); |
1244 | SDValue Offset = DAG.getConstant(4, dl, MVT::i32); |
1245 | return DAG.getLoad(VT, dl, Chain: DAG.getEntryNode(), |
1246 | Ptr: DAG.getNode(Opcode: ISD::ADD, DL: dl, VT, N1: FrameAddr, N2: Offset), |
1247 | PtrInfo: MachinePointerInfo()); |
1248 | } |
1249 | // Return the value of the return address register, marking it an implicit |
1250 | // live-in. |
1251 | unsigned Reg = MF.addLiveIn(RI.getRARegister(), getRegClassFor(MVT::i32)); |
1252 | return DAG.getCopyFromReg(Chain: DAG.getEntryNode(), dl, Reg, VT); |
1253 | } |
1254 | |
1255 | Register CSKYTargetLowering::getExceptionPointerRegister( |
1256 | const Constant *PersonalityFn) const { |
1257 | return CSKY::R0; |
1258 | } |
1259 | |
1260 | Register CSKYTargetLowering::getExceptionSelectorRegister( |
1261 | const Constant *PersonalityFn) const { |
1262 | return CSKY::R1; |
1263 | } |
1264 | |
1265 | SDValue CSKYTargetLowering::LowerGlobalTLSAddress(SDValue Op, |
1266 | SelectionDAG &DAG) const { |
1267 | SDLoc DL(Op); |
1268 | EVT Ty = Op.getValueType(); |
1269 | GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Val&: Op); |
1270 | int64_t Offset = N->getOffset(); |
1271 | MVT XLenVT = MVT::i32; |
1272 | |
1273 | TLSModel::Model Model = getTargetMachine().getTLSModel(GV: N->getGlobal()); |
1274 | SDValue Addr; |
1275 | switch (Model) { |
1276 | case TLSModel::LocalExec: |
1277 | Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/false); |
1278 | break; |
1279 | case TLSModel::InitialExec: |
1280 | Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/true); |
1281 | break; |
1282 | case TLSModel::LocalDynamic: |
1283 | case TLSModel::GeneralDynamic: |
1284 | Addr = getDynamicTLSAddr(N, DAG); |
1285 | break; |
1286 | } |
1287 | |
1288 | // In order to maximise the opportunity for common subexpression elimination, |
1289 | // emit a separate ADD node for the global address offset instead of folding |
1290 | // it in the global address node. Later peephole optimisations may choose to |
1291 | // fold it back in when profitable. |
1292 | if (Offset != 0) |
1293 | return DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Addr, |
1294 | N2: DAG.getConstant(Val: Offset, DL, VT: XLenVT)); |
1295 | return Addr; |
1296 | } |
1297 | |
1298 | SDValue CSKYTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N, |
1299 | SelectionDAG &DAG, |
1300 | bool UseGOT) const { |
1301 | MachineFunction &MF = DAG.getMachineFunction(); |
1302 | CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); |
1303 | |
1304 | unsigned CSKYPCLabelIndex = CFI->createPICLabelUId(); |
1305 | |
1306 | SDLoc DL(N); |
1307 | EVT Ty = getPointerTy(DL: DAG.getDataLayout()); |
1308 | |
1309 | CSKYCP::CSKYCPModifier Flag = UseGOT ? CSKYCP::TLSIE : CSKYCP::TLSLE; |
1310 | bool AddCurrentAddr = UseGOT ? true : false; |
1311 | unsigned char PCAjust = UseGOT ? 4 : 0; |
1312 | |
1313 | CSKYConstantPoolValue *CPV = |
1314 | CSKYConstantPoolConstant::Create(C: N->getGlobal(), Kind: CSKYCP::CPValue, PCAdjust: PCAjust, |
1315 | Modifier: Flag, AddCurrentAddress: AddCurrentAddr, ID: CSKYPCLabelIndex); |
1316 | SDValue CAddr = DAG.getTargetConstantPool(C: CPV, VT: Ty); |
1317 | |
1318 | SDValue Load; |
1319 | if (UseGOT) { |
1320 | SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32); |
1321 | auto *LRWGRS = DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, |
1322 | {CAddr, PICLabel}); |
1323 | auto LRWADDGRS = |
1324 | DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: SDValue(LRWGRS, 0), N2: SDValue(LRWGRS, 1)); |
1325 | Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), LRWADDGRS, |
1326 | MachinePointerInfo(N->getGlobal())); |
1327 | } else { |
1328 | Load = SDValue(DAG.getMachineNode(CSKY::LRW32, DL, Ty, CAddr), 0); |
1329 | } |
1330 | |
1331 | // Add the thread pointer. |
1332 | SDValue TPReg = DAG.getRegister(CSKY::R31, MVT::i32); |
1333 | return DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Load, N2: TPReg); |
1334 | } |
1335 | |
1336 | SDValue CSKYTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N, |
1337 | SelectionDAG &DAG) const { |
1338 | MachineFunction &MF = DAG.getMachineFunction(); |
1339 | CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); |
1340 | |
1341 | unsigned CSKYPCLabelIndex = CFI->createPICLabelUId(); |
1342 | |
1343 | SDLoc DL(N); |
1344 | EVT Ty = getPointerTy(DL: DAG.getDataLayout()); |
1345 | IntegerType *CallTy = Type::getIntNTy(C&: *DAG.getContext(), N: Ty.getSizeInBits()); |
1346 | |
1347 | CSKYConstantPoolValue *CPV = |
1348 | CSKYConstantPoolConstant::Create(C: N->getGlobal(), Kind: CSKYCP::CPValue, PCAdjust: 4, |
1349 | Modifier: CSKYCP::TLSGD, AddCurrentAddress: true, ID: CSKYPCLabelIndex); |
1350 | SDValue Addr = DAG.getTargetConstantPool(C: CPV, VT: Ty); |
1351 | SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32); |
1352 | |
1353 | auto *LRWGRS = |
1354 | DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, {Addr, PICLabel}); |
1355 | |
1356 | auto Load = |
1357 | DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: SDValue(LRWGRS, 0), N2: SDValue(LRWGRS, 1)); |
1358 | |
1359 | // Prepare argument list to generate call. |
1360 | ArgListTy Args; |
1361 | ArgListEntry Entry; |
1362 | Entry.Node = Load; |
1363 | Entry.Ty = CallTy; |
1364 | Args.push_back(x: Entry); |
1365 | |
1366 | // Setup call to __tls_get_addr. |
1367 | TargetLowering::CallLoweringInfo CLI(DAG); |
1368 | CLI.setDebugLoc(DL) |
1369 | .setChain(DAG.getEntryNode()) |
1370 | .setLibCallee(CC: CallingConv::C, ResultType: CallTy, |
1371 | Target: DAG.getExternalSymbol(Sym: "__tls_get_addr" , VT: Ty), |
1372 | ArgsList: std::move(Args)); |
1373 | SDValue V = LowerCallTo(CLI).first; |
1374 | |
1375 | return V; |
1376 | } |
1377 | |
1378 | bool CSKYTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT, |
1379 | SDValue C) const { |
1380 | if (!VT.isScalarInteger()) |
1381 | return false; |
1382 | |
1383 | // Omit if data size exceeds. |
1384 | if (VT.getSizeInBits() > Subtarget.XLen) |
1385 | return false; |
1386 | |
1387 | if (auto *ConstNode = dyn_cast<ConstantSDNode>(Val: C.getNode())) { |
1388 | const APInt &Imm = ConstNode->getAPIntValue(); |
1389 | // Break MULT to LSLI + ADDU/SUBU. |
1390 | if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() || |
1391 | (1 - Imm).isPowerOf2()) |
1392 | return true; |
1393 | // Only break MULT for sub targets without MULT32, since an extra |
1394 | // instruction will be generated against the above 3 cases. We leave it |
1395 | // unchanged on sub targets with MULT32, since not sure it is better. |
1396 | if (!Subtarget.hasE2() && (-1 - Imm).isPowerOf2()) |
1397 | return true; |
1398 | // Break (MULT x, imm) to ([IXH32|IXW32|IXD32] (LSLI32 x, i0), x) when |
1399 | // imm=(1<<i0)+[2|4|8] and imm has to be composed via a MOVIH32/ORI32 pair. |
1400 | if (Imm.ugt(RHS: 0xffff) && ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2()) && |
1401 | Subtarget.hasE2()) |
1402 | return true; |
1403 | if (Imm.ugt(RHS: 0xffff) && (Imm - 8).isPowerOf2() && Subtarget.has2E3()) |
1404 | return true; |
1405 | } |
1406 | |
1407 | return false; |
1408 | } |
1409 | |
1410 | bool CSKYTargetLowering::isCheapToSpeculateCttz(Type *Ty) const { |
1411 | return Subtarget.has2E3(); |
1412 | } |
1413 | |
1414 | bool CSKYTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const { |
1415 | return Subtarget.hasE2(); |
1416 | } |
1417 | |