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