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 "CSKYMachineFunctionInfo.h"
17 #include "CSKYRegisterInfo.h"
18 #include "CSKYSubtarget.h"
19 #include "llvm/ADT/Statistic.h"
20 #include "llvm/CodeGen/CallingConvLower.h"
21 #include "llvm/CodeGen/MachineJumpTableInfo.h"
22 #include "llvm/Support/Debug.h"
23 
24 using namespace llvm;
25 
26 #define DEBUG_TYPE "csky-isel-lowering"
27 
28 STATISTIC(NumTailCalls, "Number of tail calls");
29 
30 #include "CSKYGenCallingConv.inc"
31 
32 static const MCPhysReg GPRArgRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3};
33 
34 CSKYTargetLowering::CSKYTargetLowering(const TargetMachine &TM,
35                                        const CSKYSubtarget &STI)
36     : TargetLowering(TM), Subtarget(STI) {
37   // Register Class
38   addRegisterClass(MVT::i32, &CSKY::GPRRegClass);
39 
40   setOperationAction(ISD::ADDCARRY, MVT::i32, Legal);
41   setOperationAction(ISD::SUBCARRY, MVT::i32, Legal);
42   setOperationAction(ISD::BITREVERSE, MVT::i32, Legal);
43 
44   setOperationAction(ISD::SREM, MVT::i32, Expand);
45   setOperationAction(ISD::UREM, MVT::i32, Expand);
46   setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
47   setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
48   setOperationAction(ISD::CTTZ, MVT::i32, Expand);
49   setOperationAction(ISD::CTPOP, MVT::i32, Expand);
50   setOperationAction(ISD::ROTR, MVT::i32, Expand);
51   setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
52   setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
53   setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
54   setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
55   setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
56   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
57   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
58   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
59   setOperationAction(ISD::MULHS, MVT::i32, Expand);
60   setOperationAction(ISD::MULHU, MVT::i32, Expand);
61 
62   setLoadExtAction(ISD::EXTLOAD, MVT::i32, MVT::i1, Promote);
63   setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i1, Promote);
64   setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, MVT::i1, Promote);
65 
66   if (!Subtarget.hasE2()) {
67     setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i8, Expand);
68     setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i16, Expand);
69     setOperationAction(ISD::CTLZ, MVT::i32, Expand);
70     setOperationAction(ISD::BSWAP, MVT::i32, Expand);
71   }
72 
73   if (!Subtarget.has2E3()) {
74     setOperationAction(ISD::ABS, MVT::i32, Expand);
75     setOperationAction(ISD::BITREVERSE, MVT::i32, Expand);
76     setOperationAction(ISD::SDIV, MVT::i32, Expand);
77     setOperationAction(ISD::UDIV, MVT::i32, Expand);
78   }
79 
80   // Compute derived properties from the register classes.
81   computeRegisterProperties(STI.getRegisterInfo());
82 
83   setBooleanContents(UndefinedBooleanContent);
84   setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
85 
86   // TODO: Add atomic support fully.
87   setMaxAtomicSizeInBitsSupported(0);
88 
89   setStackPointerRegisterToSaveRestore(CSKY::R14);
90   const Align FunctionAlignment(2);
91   setMinFunctionAlignment(FunctionAlignment);
92   setSchedulingPreference(Sched::Source);
93 }
94 
95 EVT CSKYTargetLowering::getSetCCResultType(const DataLayout &DL,
96                                            LLVMContext &Context, EVT VT) const {
97   if (!VT.isVector())
98     return MVT::i32;
99 
100   return VT.changeVectorElementTypeToInteger();
101 }
102 
103 static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val,
104                                    const CCValAssign &VA, const SDLoc &DL) {
105   EVT LocVT = VA.getLocVT();
106 
107   switch (VA.getLocInfo()) {
108   default:
109     llvm_unreachable("Unexpected CCValAssign::LocInfo");
110   case CCValAssign::Full:
111     break;
112   case CCValAssign::BCvt:
113     Val = DAG.getNode(ISD::BITCAST, DL, LocVT, Val);
114     break;
115   }
116   return Val;
117 }
118 
119 static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val,
120                                    const CCValAssign &VA, const SDLoc &DL) {
121   switch (VA.getLocInfo()) {
122   default:
123     llvm_unreachable("Unexpected CCValAssign::LocInfo");
124   case CCValAssign::Full:
125     break;
126   case CCValAssign::BCvt:
127     Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
128     break;
129   }
130   return Val;
131 }
132 
133 static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget,
134                                 SelectionDAG &DAG, SDValue Chain,
135                                 const CCValAssign &VA, const SDLoc &DL) {
136   MachineFunction &MF = DAG.getMachineFunction();
137   MachineRegisterInfo &RegInfo = MF.getRegInfo();
138   EVT LocVT = VA.getLocVT();
139   SDValue Val;
140   const TargetRegisterClass *RC;
141 
142   switch (LocVT.getSimpleVT().SimpleTy) {
143   default:
144     llvm_unreachable("Unexpected register type");
145   case MVT::i32:
146     RC = &CSKY::GPRRegClass;
147     break;
148   }
149 
150   Register VReg = RegInfo.createVirtualRegister(RC);
151   RegInfo.addLiveIn(VA.getLocReg(), VReg);
152   Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT);
153 
154   return convertLocVTToValVT(DAG, Val, VA, DL);
155 }
156 
157 static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,
158                                 const CCValAssign &VA, const SDLoc &DL) {
159   MachineFunction &MF = DAG.getMachineFunction();
160   MachineFrameInfo &MFI = MF.getFrameInfo();
161   EVT LocVT = VA.getLocVT();
162   EVT ValVT = VA.getValVT();
163   EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0));
164   int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8,
165                                  VA.getLocMemOffset(), /*Immutable=*/true);
166   SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
167   SDValue Val;
168 
169   ISD::LoadExtType ExtType;
170   switch (VA.getLocInfo()) {
171   default:
172     llvm_unreachable("Unexpected CCValAssign::LocInfo");
173   case CCValAssign::Full:
174   case CCValAssign::BCvt:
175     ExtType = ISD::NON_EXTLOAD;
176     break;
177   }
178   Val = DAG.getExtLoad(
179       ExtType, DL, LocVT, Chain, FIN,
180       MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT);
181   return Val;
182 }
183 
184 // Transform physical registers into virtual registers.
185 SDValue CSKYTargetLowering::LowerFormalArguments(
186     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
187     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
188     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
189 
190   switch (CallConv) {
191   default:
192     report_fatal_error("Unsupported calling convention");
193   case CallingConv::C:
194   case CallingConv::Fast:
195     break;
196   }
197 
198   MachineFunction &MF = DAG.getMachineFunction();
199 
200   // Used with vargs to acumulate store chains.
201   std::vector<SDValue> OutChains;
202 
203   // Assign locations to all of the incoming arguments.
204   SmallVector<CCValAssign, 16> ArgLocs;
205   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
206 
207   CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForCall(CallConv, IsVarArg));
208 
209   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
210     CCValAssign &VA = ArgLocs[i];
211     SDValue ArgValue;
212 
213     if (VA.isRegLoc())
214       ArgValue = unpackFromRegLoc(Subtarget, DAG, Chain, VA, DL);
215     else
216       ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL);
217 
218     InVals.push_back(ArgValue);
219   }
220 
221   if (IsVarArg) {
222     const unsigned XLenInBytes = 4;
223     const MVT XLenVT = MVT::i32;
224 
225     ArrayRef<MCPhysReg> ArgRegs = makeArrayRef(GPRArgRegs);
226     unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
227     const TargetRegisterClass *RC = &CSKY::GPRRegClass;
228     MachineFrameInfo &MFI = MF.getFrameInfo();
229     MachineRegisterInfo &RegInfo = MF.getRegInfo();
230     CSKYMachineFunctionInfo *CSKYFI = MF.getInfo<CSKYMachineFunctionInfo>();
231 
232     // Offset of the first variable argument from stack pointer, and size of
233     // the vararg save area. For now, the varargs save area is either zero or
234     // large enough to hold a0-a4.
235     int VaArgOffset, VarArgsSaveSize;
236 
237     // If all registers are allocated, then all varargs must be passed on the
238     // stack and we don't need to save any argregs.
239     if (ArgRegs.size() == Idx) {
240       VaArgOffset = CCInfo.getNextStackOffset();
241       VarArgsSaveSize = 0;
242     } else {
243       VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);
244       VaArgOffset = -VarArgsSaveSize;
245     }
246 
247     // Record the frame index of the first variable argument
248     // which is a value necessary to VASTART.
249     int FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
250     CSKYFI->setVarArgsFrameIndex(FI);
251 
252     // Copy the integer registers that may have been used for passing varargs
253     // to the vararg save area.
254     for (unsigned I = Idx; I < ArgRegs.size();
255          ++I, VaArgOffset += XLenInBytes) {
256       const Register Reg = RegInfo.createVirtualRegister(RC);
257       RegInfo.addLiveIn(ArgRegs[I], Reg);
258       SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, XLenVT);
259       FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
260       SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
261       SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff,
262                                    MachinePointerInfo::getFixedStack(MF, FI));
263       cast<StoreSDNode>(Store.getNode())
264           ->getMemOperand()
265           ->setValue((Value *)nullptr);
266       OutChains.push_back(Store);
267     }
268     CSKYFI->setVarArgsSaveSize(VarArgsSaveSize);
269   }
270 
271   // All stores are grouped in one node to allow the matching between
272   // the size of Ins and InVals. This only happens for vararg functions.
273   if (!OutChains.empty()) {
274     OutChains.push_back(Chain);
275     Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
276   }
277 
278   return Chain;
279 }
280 
281 bool CSKYTargetLowering::CanLowerReturn(
282     CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
283     const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
284   SmallVector<CCValAssign, 16> CSKYLocs;
285   CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context);
286   return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));
287 }
288 
289 SDValue
290 CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
291                                 bool IsVarArg,
292                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
293                                 const SmallVectorImpl<SDValue> &OutVals,
294                                 const SDLoc &DL, SelectionDAG &DAG) const {
295   // Stores the assignment of the return value to a location.
296   SmallVector<CCValAssign, 16> CSKYLocs;
297 
298   // Info about the registers and stack slot.
299   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), CSKYLocs,
300                  *DAG.getContext());
301   CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));
302 
303   SDValue Glue;
304   SmallVector<SDValue, 4> RetOps(1, Chain);
305 
306   // Copy the result values into the output registers.
307   for (unsigned i = 0, e = CSKYLocs.size(); i < e; ++i) {
308     SDValue Val = OutVals[i];
309     CCValAssign &VA = CSKYLocs[i];
310     assert(VA.isRegLoc() && "Can only return in registers!");
311 
312     bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;
313 
314     if (IsF64OnCSKY) {
315 
316       assert(VA.isRegLoc() && "Expected return via registers");
317       SDValue Split64 = DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL,
318                                     DAG.getVTList(MVT::i32, MVT::i32), Val);
319       SDValue Lo = Split64.getValue(0);
320       SDValue Hi = Split64.getValue(1);
321 
322       Register RegLo = VA.getLocReg();
323       assert(RegLo < CSKY::R31 && "Invalid register pair");
324       Register RegHi = RegLo + 1;
325 
326       Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue);
327       Glue = Chain.getValue(1);
328       RetOps.push_back(DAG.getRegister(RegLo, MVT::i32));
329       Chain = DAG.getCopyToReg(Chain, DL, RegHi, Hi, Glue);
330       Glue = Chain.getValue(1);
331       RetOps.push_back(DAG.getRegister(RegHi, MVT::i32));
332     } else {
333       // Handle a 'normal' return.
334       Val = convertValVTToLocVT(DAG, Val, VA, DL);
335       Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue);
336 
337       // Guarantee that all emitted copies are stuck together.
338       Glue = Chain.getValue(1);
339       RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
340     }
341   }
342 
343   RetOps[0] = Chain; // Update chain.
344 
345   // Add the glue node if we have it.
346   if (Glue.getNode()) {
347     RetOps.push_back(Glue);
348   }
349 
350   // Interrupt service routines use different return instructions.
351   if (DAG.getMachineFunction().getFunction().hasFnAttribute("interrupt"))
352     return DAG.getNode(CSKYISD::NIR, DL, MVT::Other, RetOps);
353 
354   return DAG.getNode(CSKYISD::RET, DL, MVT::Other, RetOps);
355 }
356 
357 CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC,
358                                                     bool IsVarArg) const {
359   if (IsVarArg || !Subtarget.useHardFloatABI())
360     return RetCC_CSKY_ABIV2_SOFT;
361   else
362     return RetCC_CSKY_ABIV2_FP;
363 }
364 
365 CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC,
366                                                   bool IsVarArg) const {
367   if (IsVarArg || !Subtarget.useHardFloatABI())
368     return CC_CSKY_ABIV2_SOFT;
369   else
370     return CC_CSKY_ABIV2_FP;
371 }
372 
373 const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const {
374   switch (Opcode) {
375   default:
376     llvm_unreachable("unknown CSKYISD node");
377   case CSKYISD::NIE:
378     return "CSKYISD::NIE";
379   case CSKYISD::NIR:
380     return "CSKYISD::NIR";
381   case CSKYISD::RET:
382     return "CSKYISD::RET";
383   case CSKYISD::BITCAST_TO_LOHI:
384     return "CSKYISD::BITCAST_TO_LOHI";
385   }
386 }
387