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