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