1*0fca6ea1SDimitry Andric //===- XtensaISelLowering.cpp - Xtensa DAG Lowering Implementation --------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This file defines the interfaces that Xtensa uses to lower LLVM code into a 10*0fca6ea1SDimitry Andric // selection DAG. 11*0fca6ea1SDimitry Andric // 12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 13*0fca6ea1SDimitry Andric 14*0fca6ea1SDimitry Andric #include "XtensaISelLowering.h" 15*0fca6ea1SDimitry Andric #include "XtensaConstantPoolValue.h" 16*0fca6ea1SDimitry Andric #include "XtensaSubtarget.h" 17*0fca6ea1SDimitry Andric #include "XtensaTargetMachine.h" 18*0fca6ea1SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 19*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 20*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 21*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h" 22*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 23*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 24*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h" 25*0fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h" 26*0fca6ea1SDimitry Andric #include "llvm/Support/MathExtras.h" 27*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h" 28*0fca6ea1SDimitry Andric #include <deque> 29*0fca6ea1SDimitry Andric 30*0fca6ea1SDimitry Andric using namespace llvm; 31*0fca6ea1SDimitry Andric 32*0fca6ea1SDimitry Andric #define DEBUG_TYPE "xtensa-lower" 33*0fca6ea1SDimitry Andric 34*0fca6ea1SDimitry Andric // Return true if we must use long (in fact, indirect) function call. 35*0fca6ea1SDimitry Andric // It's simplified version, production implimentation must 36*0fca6ea1SDimitry Andric // resolve a functions in ROM (usually glibc functions) 37*0fca6ea1SDimitry Andric static bool isLongCall(const char *str) { 38*0fca6ea1SDimitry Andric // Currently always use long calls 39*0fca6ea1SDimitry Andric return true; 40*0fca6ea1SDimitry Andric } 41*0fca6ea1SDimitry Andric 42*0fca6ea1SDimitry Andric XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM, 43*0fca6ea1SDimitry Andric const XtensaSubtarget &STI) 44*0fca6ea1SDimitry Andric : TargetLowering(TM), Subtarget(STI) { 45*0fca6ea1SDimitry Andric MVT PtrVT = MVT::i32; 46*0fca6ea1SDimitry Andric // Set up the register classes. 47*0fca6ea1SDimitry Andric addRegisterClass(MVT::i32, &Xtensa::ARRegClass); 48*0fca6ea1SDimitry Andric 49*0fca6ea1SDimitry Andric // Set up special registers. 50*0fca6ea1SDimitry Andric setStackPointerRegisterToSaveRestore(Xtensa::SP); 51*0fca6ea1SDimitry Andric 52*0fca6ea1SDimitry Andric setSchedulingPreference(Sched::RegPressure); 53*0fca6ea1SDimitry Andric 54*0fca6ea1SDimitry Andric setMinFunctionAlignment(Align(4)); 55*0fca6ea1SDimitry Andric 56*0fca6ea1SDimitry Andric setOperationAction(ISD::Constant, MVT::i32, Custom); 57*0fca6ea1SDimitry Andric setOperationAction(ISD::Constant, MVT::i64, Expand); 58*0fca6ea1SDimitry Andric 59*0fca6ea1SDimitry Andric setBooleanContents(ZeroOrOneBooleanContent); 60*0fca6ea1SDimitry Andric 61*0fca6ea1SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); 62*0fca6ea1SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); 63*0fca6ea1SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); 64*0fca6ea1SDimitry Andric 65*0fca6ea1SDimitry Andric setOperationAction(ISD::BITCAST, MVT::i32, Expand); 66*0fca6ea1SDimitry Andric setOperationAction(ISD::BITCAST, MVT::f32, Expand); 67*0fca6ea1SDimitry Andric setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); 68*0fca6ea1SDimitry Andric setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); 69*0fca6ea1SDimitry Andric setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); 70*0fca6ea1SDimitry Andric setOperationAction(ISD::FP_TO_SINT, MVT::i32, Expand); 71*0fca6ea1SDimitry Andric 72*0fca6ea1SDimitry Andric // No sign extend instructions for i1 73*0fca6ea1SDimitry Andric for (MVT VT : MVT::integer_valuetypes()) { 74*0fca6ea1SDimitry Andric setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); 75*0fca6ea1SDimitry Andric setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); 76*0fca6ea1SDimitry Andric setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); 77*0fca6ea1SDimitry Andric } 78*0fca6ea1SDimitry Andric 79*0fca6ea1SDimitry Andric setOperationAction(ISD::ConstantPool, PtrVT, Custom); 80*0fca6ea1SDimitry Andric setOperationAction(ISD::GlobalAddress, PtrVT, Custom); 81*0fca6ea1SDimitry Andric setOperationAction(ISD::BlockAddress, PtrVT, Custom); 82*0fca6ea1SDimitry Andric setOperationAction(ISD::JumpTable, PtrVT, Custom); 83*0fca6ea1SDimitry Andric 84*0fca6ea1SDimitry Andric // Expand jump table branches as address arithmetic followed by an 85*0fca6ea1SDimitry Andric // indirect jump. 86*0fca6ea1SDimitry Andric setOperationAction(ISD::BR_JT, MVT::Other, Custom); 87*0fca6ea1SDimitry Andric 88*0fca6ea1SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i32, Legal); 89*0fca6ea1SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i64, Expand); 90*0fca6ea1SDimitry Andric setOperationAction(ISD::BR_CC, MVT::f32, Expand); 91*0fca6ea1SDimitry Andric 92*0fca6ea1SDimitry Andric setOperationAction(ISD::SELECT, MVT::i32, Expand); 93*0fca6ea1SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); 94*0fca6ea1SDimitry Andric setOperationAction(ISD::SETCC, MVT::i32, Expand); 95*0fca6ea1SDimitry Andric 96*0fca6ea1SDimitry Andric setCondCodeAction(ISD::SETGT, MVT::i32, Expand); 97*0fca6ea1SDimitry Andric setCondCodeAction(ISD::SETLE, MVT::i32, Expand); 98*0fca6ea1SDimitry Andric setCondCodeAction(ISD::SETUGT, MVT::i32, Expand); 99*0fca6ea1SDimitry Andric setCondCodeAction(ISD::SETULE, MVT::i32, Expand); 100*0fca6ea1SDimitry Andric 101*0fca6ea1SDimitry Andric // Implement custom stack allocations 102*0fca6ea1SDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom); 103*0fca6ea1SDimitry Andric // Implement custom stack save and restore 104*0fca6ea1SDimitry Andric setOperationAction(ISD::STACKSAVE, MVT::Other, Custom); 105*0fca6ea1SDimitry Andric setOperationAction(ISD::STACKRESTORE, MVT::Other, Custom); 106*0fca6ea1SDimitry Andric 107*0fca6ea1SDimitry Andric // Compute derived properties from the register classes 108*0fca6ea1SDimitry Andric computeRegisterProperties(STI.getRegisterInfo()); 109*0fca6ea1SDimitry Andric } 110*0fca6ea1SDimitry Andric 111*0fca6ea1SDimitry Andric bool XtensaTargetLowering::isOffsetFoldingLegal( 112*0fca6ea1SDimitry Andric const GlobalAddressSDNode *GA) const { 113*0fca6ea1SDimitry Andric // The Xtensa target isn't yet aware of offsets. 114*0fca6ea1SDimitry Andric return false; 115*0fca6ea1SDimitry Andric } 116*0fca6ea1SDimitry Andric 117*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 118*0fca6ea1SDimitry Andric // Calling conventions 119*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 120*0fca6ea1SDimitry Andric 121*0fca6ea1SDimitry Andric #include "XtensaGenCallingConv.inc" 122*0fca6ea1SDimitry Andric 123*0fca6ea1SDimitry Andric static bool CC_Xtensa_Custom(unsigned ValNo, MVT ValVT, MVT LocVT, 124*0fca6ea1SDimitry Andric CCValAssign::LocInfo LocInfo, 125*0fca6ea1SDimitry Andric ISD::ArgFlagsTy ArgFlags, CCState &State) { 126*0fca6ea1SDimitry Andric static const MCPhysReg IntRegs[] = {Xtensa::A2, Xtensa::A3, Xtensa::A4, 127*0fca6ea1SDimitry Andric Xtensa::A5, Xtensa::A6, Xtensa::A7}; 128*0fca6ea1SDimitry Andric 129*0fca6ea1SDimitry Andric if (ArgFlags.isByVal()) { 130*0fca6ea1SDimitry Andric Align ByValAlign = ArgFlags.getNonZeroByValAlign(); 131*0fca6ea1SDimitry Andric unsigned ByValSize = ArgFlags.getByValSize(); 132*0fca6ea1SDimitry Andric if (ByValSize < 4) { 133*0fca6ea1SDimitry Andric ByValSize = 4; 134*0fca6ea1SDimitry Andric } 135*0fca6ea1SDimitry Andric if (ByValAlign < Align(4)) { 136*0fca6ea1SDimitry Andric ByValAlign = Align(4); 137*0fca6ea1SDimitry Andric } 138*0fca6ea1SDimitry Andric unsigned Offset = State.AllocateStack(ByValSize, ByValAlign); 139*0fca6ea1SDimitry Andric State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 140*0fca6ea1SDimitry Andric // Mark all unused registers as allocated to avoid misuse 141*0fca6ea1SDimitry Andric // of such registers. 142*0fca6ea1SDimitry Andric while (State.AllocateReg(IntRegs)) 143*0fca6ea1SDimitry Andric ; 144*0fca6ea1SDimitry Andric return false; 145*0fca6ea1SDimitry Andric } 146*0fca6ea1SDimitry Andric 147*0fca6ea1SDimitry Andric // Promote i8 and i16 148*0fca6ea1SDimitry Andric if (LocVT == MVT::i8 || LocVT == MVT::i16) { 149*0fca6ea1SDimitry Andric LocVT = MVT::i32; 150*0fca6ea1SDimitry Andric if (ArgFlags.isSExt()) 151*0fca6ea1SDimitry Andric LocInfo = CCValAssign::SExt; 152*0fca6ea1SDimitry Andric else if (ArgFlags.isZExt()) 153*0fca6ea1SDimitry Andric LocInfo = CCValAssign::ZExt; 154*0fca6ea1SDimitry Andric else 155*0fca6ea1SDimitry Andric LocInfo = CCValAssign::AExt; 156*0fca6ea1SDimitry Andric } 157*0fca6ea1SDimitry Andric 158*0fca6ea1SDimitry Andric unsigned Register; 159*0fca6ea1SDimitry Andric 160*0fca6ea1SDimitry Andric Align OrigAlign = ArgFlags.getNonZeroOrigAlign(); 161*0fca6ea1SDimitry Andric bool needs64BitAlign = (ValVT == MVT::i32 && OrigAlign == Align(8)); 162*0fca6ea1SDimitry Andric bool needs128BitAlign = (ValVT == MVT::i32 && OrigAlign == Align(16)); 163*0fca6ea1SDimitry Andric 164*0fca6ea1SDimitry Andric if (ValVT == MVT::i32) { 165*0fca6ea1SDimitry Andric Register = State.AllocateReg(IntRegs); 166*0fca6ea1SDimitry Andric // If this is the first part of an i64 arg, 167*0fca6ea1SDimitry Andric // the allocated register must be either A2, A4 or A6. 168*0fca6ea1SDimitry Andric if (needs64BitAlign && (Register == Xtensa::A3 || Register == Xtensa::A5 || 169*0fca6ea1SDimitry Andric Register == Xtensa::A7)) 170*0fca6ea1SDimitry Andric Register = State.AllocateReg(IntRegs); 171*0fca6ea1SDimitry Andric // arguments with 16byte alignment must be passed in the first register or 172*0fca6ea1SDimitry Andric // passed via stack 173*0fca6ea1SDimitry Andric if (needs128BitAlign && (Register != Xtensa::A2)) 174*0fca6ea1SDimitry Andric while ((Register = State.AllocateReg(IntRegs))) 175*0fca6ea1SDimitry Andric ; 176*0fca6ea1SDimitry Andric LocVT = MVT::i32; 177*0fca6ea1SDimitry Andric } else if (ValVT == MVT::f64) { 178*0fca6ea1SDimitry Andric // Allocate int register and shadow next int register. 179*0fca6ea1SDimitry Andric Register = State.AllocateReg(IntRegs); 180*0fca6ea1SDimitry Andric if (Register == Xtensa::A3 || Register == Xtensa::A5 || 181*0fca6ea1SDimitry Andric Register == Xtensa::A7) 182*0fca6ea1SDimitry Andric Register = State.AllocateReg(IntRegs); 183*0fca6ea1SDimitry Andric State.AllocateReg(IntRegs); 184*0fca6ea1SDimitry Andric LocVT = MVT::i32; 185*0fca6ea1SDimitry Andric } else { 186*0fca6ea1SDimitry Andric report_fatal_error("Cannot handle this ValVT."); 187*0fca6ea1SDimitry Andric } 188*0fca6ea1SDimitry Andric 189*0fca6ea1SDimitry Andric if (!Register) { 190*0fca6ea1SDimitry Andric unsigned Offset = State.AllocateStack(ValVT.getStoreSize(), OrigAlign); 191*0fca6ea1SDimitry Andric State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 192*0fca6ea1SDimitry Andric } else { 193*0fca6ea1SDimitry Andric State.addLoc(CCValAssign::getReg(ValNo, ValVT, Register, LocVT, LocInfo)); 194*0fca6ea1SDimitry Andric } 195*0fca6ea1SDimitry Andric 196*0fca6ea1SDimitry Andric return false; 197*0fca6ea1SDimitry Andric } 198*0fca6ea1SDimitry Andric 199*0fca6ea1SDimitry Andric CCAssignFn *XtensaTargetLowering::CCAssignFnForCall(CallingConv::ID CC, 200*0fca6ea1SDimitry Andric bool IsVarArg) const { 201*0fca6ea1SDimitry Andric return CC_Xtensa_Custom; 202*0fca6ea1SDimitry Andric } 203*0fca6ea1SDimitry Andric 204*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerFormalArguments( 205*0fca6ea1SDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 206*0fca6ea1SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, 207*0fca6ea1SDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 208*0fca6ea1SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 209*0fca6ea1SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 210*0fca6ea1SDimitry Andric 211*0fca6ea1SDimitry Andric // Used with vargs to acumulate store chains. 212*0fca6ea1SDimitry Andric std::vector<SDValue> OutChains; 213*0fca6ea1SDimitry Andric 214*0fca6ea1SDimitry Andric if (IsVarArg) 215*0fca6ea1SDimitry Andric report_fatal_error("Var arg not supported by FormalArguments Lowering"); 216*0fca6ea1SDimitry Andric 217*0fca6ea1SDimitry Andric // Assign locations to all of the incoming arguments. 218*0fca6ea1SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 219*0fca6ea1SDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, 220*0fca6ea1SDimitry Andric *DAG.getContext()); 221*0fca6ea1SDimitry Andric 222*0fca6ea1SDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForCall(CallConv, IsVarArg)); 223*0fca6ea1SDimitry Andric 224*0fca6ea1SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 225*0fca6ea1SDimitry Andric CCValAssign &VA = ArgLocs[i]; 226*0fca6ea1SDimitry Andric // Arguments stored on registers 227*0fca6ea1SDimitry Andric if (VA.isRegLoc()) { 228*0fca6ea1SDimitry Andric EVT RegVT = VA.getLocVT(); 229*0fca6ea1SDimitry Andric const TargetRegisterClass *RC; 230*0fca6ea1SDimitry Andric 231*0fca6ea1SDimitry Andric if (RegVT == MVT::i32) 232*0fca6ea1SDimitry Andric RC = &Xtensa::ARRegClass; 233*0fca6ea1SDimitry Andric else 234*0fca6ea1SDimitry Andric report_fatal_error("RegVT not supported by FormalArguments Lowering"); 235*0fca6ea1SDimitry Andric 236*0fca6ea1SDimitry Andric // Transform the arguments stored on 237*0fca6ea1SDimitry Andric // physical registers into virtual ones 238*0fca6ea1SDimitry Andric unsigned Register = MF.addLiveIn(VA.getLocReg(), RC); 239*0fca6ea1SDimitry Andric SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Register, RegVT); 240*0fca6ea1SDimitry Andric 241*0fca6ea1SDimitry Andric // If this is an 8 or 16-bit value, it has been passed promoted 242*0fca6ea1SDimitry Andric // to 32 bits. Insert an assert[sz]ext to capture this, then 243*0fca6ea1SDimitry Andric // truncate to the right size. 244*0fca6ea1SDimitry Andric if (VA.getLocInfo() != CCValAssign::Full) { 245*0fca6ea1SDimitry Andric unsigned Opcode = 0; 246*0fca6ea1SDimitry Andric if (VA.getLocInfo() == CCValAssign::SExt) 247*0fca6ea1SDimitry Andric Opcode = ISD::AssertSext; 248*0fca6ea1SDimitry Andric else if (VA.getLocInfo() == CCValAssign::ZExt) 249*0fca6ea1SDimitry Andric Opcode = ISD::AssertZext; 250*0fca6ea1SDimitry Andric if (Opcode) 251*0fca6ea1SDimitry Andric ArgValue = DAG.getNode(Opcode, DL, RegVT, ArgValue, 252*0fca6ea1SDimitry Andric DAG.getValueType(VA.getValVT())); 253*0fca6ea1SDimitry Andric ArgValue = DAG.getNode((VA.getValVT() == MVT::f32) ? ISD::BITCAST 254*0fca6ea1SDimitry Andric : ISD::TRUNCATE, 255*0fca6ea1SDimitry Andric DL, VA.getValVT(), ArgValue); 256*0fca6ea1SDimitry Andric } 257*0fca6ea1SDimitry Andric 258*0fca6ea1SDimitry Andric InVals.push_back(ArgValue); 259*0fca6ea1SDimitry Andric 260*0fca6ea1SDimitry Andric } else { 261*0fca6ea1SDimitry Andric assert(VA.isMemLoc()); 262*0fca6ea1SDimitry Andric 263*0fca6ea1SDimitry Andric EVT ValVT = VA.getValVT(); 264*0fca6ea1SDimitry Andric 265*0fca6ea1SDimitry Andric // The stack pointer offset is relative to the caller stack frame. 266*0fca6ea1SDimitry Andric int FI = MFI.CreateFixedObject(ValVT.getStoreSize(), VA.getLocMemOffset(), 267*0fca6ea1SDimitry Andric true); 268*0fca6ea1SDimitry Andric 269*0fca6ea1SDimitry Andric if (Ins[VA.getValNo()].Flags.isByVal()) { 270*0fca6ea1SDimitry Andric // Assume that in this case load operation is created 271*0fca6ea1SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 272*0fca6ea1SDimitry Andric InVals.push_back(FIN); 273*0fca6ea1SDimitry Andric } else { 274*0fca6ea1SDimitry Andric // Create load nodes to retrieve arguments from the stack 275*0fca6ea1SDimitry Andric SDValue FIN = 276*0fca6ea1SDimitry Andric DAG.getFrameIndex(FI, getFrameIndexTy(DAG.getDataLayout())); 277*0fca6ea1SDimitry Andric InVals.push_back(DAG.getLoad( 278*0fca6ea1SDimitry Andric ValVT, DL, Chain, FIN, 279*0fca6ea1SDimitry Andric MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI))); 280*0fca6ea1SDimitry Andric } 281*0fca6ea1SDimitry Andric } 282*0fca6ea1SDimitry Andric } 283*0fca6ea1SDimitry Andric 284*0fca6ea1SDimitry Andric // All stores are grouped in one node to allow the matching between 285*0fca6ea1SDimitry Andric // the size of Ins and InVals. This only happens when on varg functions 286*0fca6ea1SDimitry Andric if (!OutChains.empty()) { 287*0fca6ea1SDimitry Andric OutChains.push_back(Chain); 288*0fca6ea1SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 289*0fca6ea1SDimitry Andric } 290*0fca6ea1SDimitry Andric 291*0fca6ea1SDimitry Andric return Chain; 292*0fca6ea1SDimitry Andric } 293*0fca6ea1SDimitry Andric 294*0fca6ea1SDimitry Andric SDValue 295*0fca6ea1SDimitry Andric XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI, 296*0fca6ea1SDimitry Andric SmallVectorImpl<SDValue> &InVals) const { 297*0fca6ea1SDimitry Andric SelectionDAG &DAG = CLI.DAG; 298*0fca6ea1SDimitry Andric SDLoc &DL = CLI.DL; 299*0fca6ea1SDimitry Andric SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs; 300*0fca6ea1SDimitry Andric SmallVector<SDValue, 32> &OutVals = CLI.OutVals; 301*0fca6ea1SDimitry Andric SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins; 302*0fca6ea1SDimitry Andric SDValue Chain = CLI.Chain; 303*0fca6ea1SDimitry Andric SDValue Callee = CLI.Callee; 304*0fca6ea1SDimitry Andric bool &IsTailCall = CLI.IsTailCall; 305*0fca6ea1SDimitry Andric CallingConv::ID CallConv = CLI.CallConv; 306*0fca6ea1SDimitry Andric bool IsVarArg = CLI.IsVarArg; 307*0fca6ea1SDimitry Andric 308*0fca6ea1SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 309*0fca6ea1SDimitry Andric EVT PtrVT = getPointerTy(DAG.getDataLayout()); 310*0fca6ea1SDimitry Andric const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); 311*0fca6ea1SDimitry Andric 312*0fca6ea1SDimitry Andric // TODO: Support tail call optimization. 313*0fca6ea1SDimitry Andric IsTailCall = false; 314*0fca6ea1SDimitry Andric 315*0fca6ea1SDimitry Andric // Analyze the operands of the call, assigning locations to each operand. 316*0fca6ea1SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 317*0fca6ea1SDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 318*0fca6ea1SDimitry Andric 319*0fca6ea1SDimitry Andric CCAssignFn *CC = CCAssignFnForCall(CallConv, IsVarArg); 320*0fca6ea1SDimitry Andric 321*0fca6ea1SDimitry Andric CCInfo.AnalyzeCallOperands(Outs, CC); 322*0fca6ea1SDimitry Andric 323*0fca6ea1SDimitry Andric // Get a count of how many bytes are to be pushed on the stack. 324*0fca6ea1SDimitry Andric unsigned NumBytes = CCInfo.getStackSize(); 325*0fca6ea1SDimitry Andric 326*0fca6ea1SDimitry Andric Align StackAlignment = TFL->getStackAlign(); 327*0fca6ea1SDimitry Andric unsigned NextStackOffset = alignTo(NumBytes, StackAlignment); 328*0fca6ea1SDimitry Andric 329*0fca6ea1SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, NextStackOffset, 0, DL); 330*0fca6ea1SDimitry Andric 331*0fca6ea1SDimitry Andric // Copy argument values to their designated locations. 332*0fca6ea1SDimitry Andric std::deque<std::pair<unsigned, SDValue>> RegsToPass; 333*0fca6ea1SDimitry Andric SmallVector<SDValue, 8> MemOpChains; 334*0fca6ea1SDimitry Andric SDValue StackPtr; 335*0fca6ea1SDimitry Andric for (unsigned I = 0, E = ArgLocs.size(); I != E; ++I) { 336*0fca6ea1SDimitry Andric CCValAssign &VA = ArgLocs[I]; 337*0fca6ea1SDimitry Andric SDValue ArgValue = OutVals[I]; 338*0fca6ea1SDimitry Andric ISD::ArgFlagsTy Flags = Outs[I].Flags; 339*0fca6ea1SDimitry Andric 340*0fca6ea1SDimitry Andric if (VA.isRegLoc()) 341*0fca6ea1SDimitry Andric // Queue up the argument copies and emit them at the end. 342*0fca6ea1SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue)); 343*0fca6ea1SDimitry Andric else if (Flags.isByVal()) { 344*0fca6ea1SDimitry Andric assert(VA.isMemLoc()); 345*0fca6ea1SDimitry Andric assert(Flags.getByValSize() && 346*0fca6ea1SDimitry Andric "ByVal args of size 0 should have been ignored by front-end."); 347*0fca6ea1SDimitry Andric assert(!IsTailCall && 348*0fca6ea1SDimitry Andric "Do not tail-call optimize if there is a byval argument."); 349*0fca6ea1SDimitry Andric 350*0fca6ea1SDimitry Andric if (!StackPtr.getNode()) 351*0fca6ea1SDimitry Andric StackPtr = DAG.getCopyFromReg(Chain, DL, Xtensa::SP, PtrVT); 352*0fca6ea1SDimitry Andric unsigned Offset = VA.getLocMemOffset(); 353*0fca6ea1SDimitry Andric SDValue Address = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, 354*0fca6ea1SDimitry Andric DAG.getIntPtrConstant(Offset, DL)); 355*0fca6ea1SDimitry Andric SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), DL, MVT::i32); 356*0fca6ea1SDimitry Andric SDValue Memcpy = DAG.getMemcpy( 357*0fca6ea1SDimitry Andric Chain, DL, Address, ArgValue, SizeNode, Flags.getNonZeroByValAlign(), 358*0fca6ea1SDimitry Andric /*isVolatile=*/false, /*AlwaysInline=*/false, 359*0fca6ea1SDimitry Andric /*CI=*/nullptr, std::nullopt, MachinePointerInfo(), MachinePointerInfo()); 360*0fca6ea1SDimitry Andric MemOpChains.push_back(Memcpy); 361*0fca6ea1SDimitry Andric } else { 362*0fca6ea1SDimitry Andric assert(VA.isMemLoc() && "Argument not register or memory"); 363*0fca6ea1SDimitry Andric 364*0fca6ea1SDimitry Andric // Work out the address of the stack slot. Unpromoted ints and 365*0fca6ea1SDimitry Andric // floats are passed as right-justified 8-byte values. 366*0fca6ea1SDimitry Andric if (!StackPtr.getNode()) 367*0fca6ea1SDimitry Andric StackPtr = DAG.getCopyFromReg(Chain, DL, Xtensa::SP, PtrVT); 368*0fca6ea1SDimitry Andric unsigned Offset = VA.getLocMemOffset(); 369*0fca6ea1SDimitry Andric SDValue Address = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, 370*0fca6ea1SDimitry Andric DAG.getIntPtrConstant(Offset, DL)); 371*0fca6ea1SDimitry Andric 372*0fca6ea1SDimitry Andric // Emit the store. 373*0fca6ea1SDimitry Andric MemOpChains.push_back( 374*0fca6ea1SDimitry Andric DAG.getStore(Chain, DL, ArgValue, Address, MachinePointerInfo())); 375*0fca6ea1SDimitry Andric } 376*0fca6ea1SDimitry Andric } 377*0fca6ea1SDimitry Andric 378*0fca6ea1SDimitry Andric // Join the stores, which are independent of one another. 379*0fca6ea1SDimitry Andric if (!MemOpChains.empty()) 380*0fca6ea1SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); 381*0fca6ea1SDimitry Andric 382*0fca6ea1SDimitry Andric // Build a sequence of copy-to-reg nodes, chained and glued together. 383*0fca6ea1SDimitry Andric SDValue Glue; 384*0fca6ea1SDimitry Andric for (unsigned I = 0, E = RegsToPass.size(); I != E; ++I) { 385*0fca6ea1SDimitry Andric unsigned Reg = RegsToPass[I].first; 386*0fca6ea1SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, Reg, RegsToPass[I].second, Glue); 387*0fca6ea1SDimitry Andric Glue = Chain.getValue(1); 388*0fca6ea1SDimitry Andric } 389*0fca6ea1SDimitry Andric std::string name; 390*0fca6ea1SDimitry Andric unsigned char TF = 0; 391*0fca6ea1SDimitry Andric 392*0fca6ea1SDimitry Andric // Accept direct calls by converting symbolic call addresses to the 393*0fca6ea1SDimitry Andric // associated Target* opcodes. 394*0fca6ea1SDimitry Andric if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) { 395*0fca6ea1SDimitry Andric name = E->getSymbol(); 396*0fca6ea1SDimitry Andric TF = E->getTargetFlags(); 397*0fca6ea1SDimitry Andric if (isPositionIndependent()) { 398*0fca6ea1SDimitry Andric report_fatal_error("PIC relocations is not supported"); 399*0fca6ea1SDimitry Andric } else 400*0fca6ea1SDimitry Andric Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, TF); 401*0fca6ea1SDimitry Andric } else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { 402*0fca6ea1SDimitry Andric const GlobalValue *GV = G->getGlobal(); 403*0fca6ea1SDimitry Andric name = GV->getName().str(); 404*0fca6ea1SDimitry Andric } 405*0fca6ea1SDimitry Andric 406*0fca6ea1SDimitry Andric if ((!name.empty()) && isLongCall(name.c_str())) { 407*0fca6ea1SDimitry Andric // Create a constant pool entry for the callee address 408*0fca6ea1SDimitry Andric XtensaCP::XtensaCPModifier Modifier = XtensaCP::no_modifier; 409*0fca6ea1SDimitry Andric 410*0fca6ea1SDimitry Andric XtensaConstantPoolValue *CPV = XtensaConstantPoolSymbol::Create( 411*0fca6ea1SDimitry Andric *DAG.getContext(), name.c_str(), 0 /* XtensaCLabelIndex */, false, 412*0fca6ea1SDimitry Andric Modifier); 413*0fca6ea1SDimitry Andric 414*0fca6ea1SDimitry Andric // Get the address of the callee into a register 415*0fca6ea1SDimitry Andric SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4), 0, TF); 416*0fca6ea1SDimitry Andric SDValue CPWrap = getAddrPCRel(CPAddr, DAG); 417*0fca6ea1SDimitry Andric Callee = CPWrap; 418*0fca6ea1SDimitry Andric } 419*0fca6ea1SDimitry Andric 420*0fca6ea1SDimitry Andric // The first call operand is the chain and the second is the target address. 421*0fca6ea1SDimitry Andric SmallVector<SDValue, 8> Ops; 422*0fca6ea1SDimitry Andric Ops.push_back(Chain); 423*0fca6ea1SDimitry Andric Ops.push_back(Callee); 424*0fca6ea1SDimitry Andric 425*0fca6ea1SDimitry Andric // Add a register mask operand representing the call-preserved registers. 426*0fca6ea1SDimitry Andric const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 427*0fca6ea1SDimitry Andric const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); 428*0fca6ea1SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention"); 429*0fca6ea1SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask)); 430*0fca6ea1SDimitry Andric 431*0fca6ea1SDimitry Andric // Add argument registers to the end of the list so that they are 432*0fca6ea1SDimitry Andric // known live into the call. 433*0fca6ea1SDimitry Andric for (unsigned I = 0, E = RegsToPass.size(); I != E; ++I) { 434*0fca6ea1SDimitry Andric unsigned Reg = RegsToPass[I].first; 435*0fca6ea1SDimitry Andric Ops.push_back(DAG.getRegister(Reg, RegsToPass[I].second.getValueType())); 436*0fca6ea1SDimitry Andric } 437*0fca6ea1SDimitry Andric 438*0fca6ea1SDimitry Andric // Glue the call to the argument copies, if any. 439*0fca6ea1SDimitry Andric if (Glue.getNode()) 440*0fca6ea1SDimitry Andric Ops.push_back(Glue); 441*0fca6ea1SDimitry Andric 442*0fca6ea1SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 443*0fca6ea1SDimitry Andric Chain = DAG.getNode(XtensaISD::CALL, DL, NodeTys, Ops); 444*0fca6ea1SDimitry Andric Glue = Chain.getValue(1); 445*0fca6ea1SDimitry Andric 446*0fca6ea1SDimitry Andric // Mark the end of the call, which is glued to the call itself. 447*0fca6ea1SDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, DL, PtrVT, true), 448*0fca6ea1SDimitry Andric DAG.getConstant(0, DL, PtrVT, true), Glue, DL); 449*0fca6ea1SDimitry Andric Glue = Chain.getValue(1); 450*0fca6ea1SDimitry Andric 451*0fca6ea1SDimitry Andric // Assign locations to each value returned by this call. 452*0fca6ea1SDimitry Andric SmallVector<CCValAssign, 16> RetLocs; 453*0fca6ea1SDimitry Andric CCState RetCCInfo(CallConv, IsVarArg, MF, RetLocs, *DAG.getContext()); 454*0fca6ea1SDimitry Andric RetCCInfo.AnalyzeCallResult(Ins, RetCC_Xtensa); 455*0fca6ea1SDimitry Andric 456*0fca6ea1SDimitry Andric // Copy all of the result registers out of their specified physreg. 457*0fca6ea1SDimitry Andric for (unsigned I = 0, E = RetLocs.size(); I != E; ++I) { 458*0fca6ea1SDimitry Andric CCValAssign &VA = RetLocs[I]; 459*0fca6ea1SDimitry Andric 460*0fca6ea1SDimitry Andric // Copy the value out, gluing the copy to the end of the call sequence. 461*0fca6ea1SDimitry Andric unsigned Reg = VA.getLocReg(); 462*0fca6ea1SDimitry Andric SDValue RetValue = DAG.getCopyFromReg(Chain, DL, Reg, VA.getLocVT(), Glue); 463*0fca6ea1SDimitry Andric Chain = RetValue.getValue(1); 464*0fca6ea1SDimitry Andric Glue = RetValue.getValue(2); 465*0fca6ea1SDimitry Andric 466*0fca6ea1SDimitry Andric InVals.push_back(RetValue); 467*0fca6ea1SDimitry Andric } 468*0fca6ea1SDimitry Andric return Chain; 469*0fca6ea1SDimitry Andric } 470*0fca6ea1SDimitry Andric 471*0fca6ea1SDimitry Andric bool XtensaTargetLowering::CanLowerReturn( 472*0fca6ea1SDimitry Andric CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, 473*0fca6ea1SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 474*0fca6ea1SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 475*0fca6ea1SDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); 476*0fca6ea1SDimitry Andric return CCInfo.CheckReturn(Outs, RetCC_Xtensa); 477*0fca6ea1SDimitry Andric } 478*0fca6ea1SDimitry Andric 479*0fca6ea1SDimitry Andric SDValue 480*0fca6ea1SDimitry Andric XtensaTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, 481*0fca6ea1SDimitry Andric bool IsVarArg, 482*0fca6ea1SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 483*0fca6ea1SDimitry Andric const SmallVectorImpl<SDValue> &OutVals, 484*0fca6ea1SDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const { 485*0fca6ea1SDimitry Andric if (IsVarArg) 486*0fca6ea1SDimitry Andric report_fatal_error("VarArg not supported"); 487*0fca6ea1SDimitry Andric 488*0fca6ea1SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 489*0fca6ea1SDimitry Andric 490*0fca6ea1SDimitry Andric // Assign locations to each returned value. 491*0fca6ea1SDimitry Andric SmallVector<CCValAssign, 16> RetLocs; 492*0fca6ea1SDimitry Andric CCState RetCCInfo(CallConv, IsVarArg, MF, RetLocs, *DAG.getContext()); 493*0fca6ea1SDimitry Andric RetCCInfo.AnalyzeReturn(Outs, RetCC_Xtensa); 494*0fca6ea1SDimitry Andric 495*0fca6ea1SDimitry Andric SDValue Glue; 496*0fca6ea1SDimitry Andric // Quick exit for void returns 497*0fca6ea1SDimitry Andric if (RetLocs.empty()) 498*0fca6ea1SDimitry Andric return DAG.getNode(XtensaISD::RET, DL, MVT::Other, Chain); 499*0fca6ea1SDimitry Andric 500*0fca6ea1SDimitry Andric // Copy the result values into the output registers. 501*0fca6ea1SDimitry Andric SmallVector<SDValue, 4> RetOps; 502*0fca6ea1SDimitry Andric RetOps.push_back(Chain); 503*0fca6ea1SDimitry Andric for (unsigned I = 0, E = RetLocs.size(); I != E; ++I) { 504*0fca6ea1SDimitry Andric CCValAssign &VA = RetLocs[I]; 505*0fca6ea1SDimitry Andric SDValue RetValue = OutVals[I]; 506*0fca6ea1SDimitry Andric 507*0fca6ea1SDimitry Andric // Make the return register live on exit. 508*0fca6ea1SDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!"); 509*0fca6ea1SDimitry Andric 510*0fca6ea1SDimitry Andric // Chain and glue the copies together. 511*0fca6ea1SDimitry Andric unsigned Register = VA.getLocReg(); 512*0fca6ea1SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, Register, RetValue, Glue); 513*0fca6ea1SDimitry Andric Glue = Chain.getValue(1); 514*0fca6ea1SDimitry Andric RetOps.push_back(DAG.getRegister(Register, VA.getLocVT())); 515*0fca6ea1SDimitry Andric } 516*0fca6ea1SDimitry Andric 517*0fca6ea1SDimitry Andric // Update chain and glue. 518*0fca6ea1SDimitry Andric RetOps[0] = Chain; 519*0fca6ea1SDimitry Andric if (Glue.getNode()) 520*0fca6ea1SDimitry Andric RetOps.push_back(Glue); 521*0fca6ea1SDimitry Andric 522*0fca6ea1SDimitry Andric return DAG.getNode(XtensaISD::RET, DL, MVT::Other, RetOps); 523*0fca6ea1SDimitry Andric } 524*0fca6ea1SDimitry Andric 525*0fca6ea1SDimitry Andric static unsigned getBranchOpcode(ISD::CondCode Cond) { 526*0fca6ea1SDimitry Andric switch (Cond) { 527*0fca6ea1SDimitry Andric case ISD::SETEQ: 528*0fca6ea1SDimitry Andric return Xtensa::BEQ; 529*0fca6ea1SDimitry Andric case ISD::SETNE: 530*0fca6ea1SDimitry Andric return Xtensa::BNE; 531*0fca6ea1SDimitry Andric case ISD::SETLT: 532*0fca6ea1SDimitry Andric return Xtensa::BLT; 533*0fca6ea1SDimitry Andric case ISD::SETLE: 534*0fca6ea1SDimitry Andric return Xtensa::BGE; 535*0fca6ea1SDimitry Andric case ISD::SETGT: 536*0fca6ea1SDimitry Andric return Xtensa::BLT; 537*0fca6ea1SDimitry Andric case ISD::SETGE: 538*0fca6ea1SDimitry Andric return Xtensa::BGE; 539*0fca6ea1SDimitry Andric case ISD::SETULT: 540*0fca6ea1SDimitry Andric return Xtensa::BLTU; 541*0fca6ea1SDimitry Andric case ISD::SETULE: 542*0fca6ea1SDimitry Andric return Xtensa::BGEU; 543*0fca6ea1SDimitry Andric case ISD::SETUGT: 544*0fca6ea1SDimitry Andric return Xtensa::BLTU; 545*0fca6ea1SDimitry Andric case ISD::SETUGE: 546*0fca6ea1SDimitry Andric return Xtensa::BGEU; 547*0fca6ea1SDimitry Andric default: 548*0fca6ea1SDimitry Andric llvm_unreachable("Unknown branch kind"); 549*0fca6ea1SDimitry Andric } 550*0fca6ea1SDimitry Andric } 551*0fca6ea1SDimitry Andric 552*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerSELECT_CC(SDValue Op, 553*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 554*0fca6ea1SDimitry Andric SDLoc DL(Op); 555*0fca6ea1SDimitry Andric EVT Ty = Op.getOperand(0).getValueType(); 556*0fca6ea1SDimitry Andric SDValue LHS = Op.getOperand(0); 557*0fca6ea1SDimitry Andric SDValue RHS = Op.getOperand(1); 558*0fca6ea1SDimitry Andric SDValue TrueValue = Op.getOperand(2); 559*0fca6ea1SDimitry Andric SDValue FalseValue = Op.getOperand(3); 560*0fca6ea1SDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(Op->getOperand(4))->get(); 561*0fca6ea1SDimitry Andric 562*0fca6ea1SDimitry Andric unsigned BrOpcode = getBranchOpcode(CC); 563*0fca6ea1SDimitry Andric SDValue TargetCC = DAG.getConstant(BrOpcode, DL, MVT::i32); 564*0fca6ea1SDimitry Andric 565*0fca6ea1SDimitry Andric return DAG.getNode(XtensaISD::SELECT_CC, DL, Ty, LHS, RHS, TrueValue, 566*0fca6ea1SDimitry Andric FalseValue, TargetCC); 567*0fca6ea1SDimitry Andric } 568*0fca6ea1SDimitry Andric 569*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerImmediate(SDValue Op, 570*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 571*0fca6ea1SDimitry Andric const ConstantSDNode *CN = cast<ConstantSDNode>(Op); 572*0fca6ea1SDimitry Andric SDLoc DL(CN); 573*0fca6ea1SDimitry Andric APInt APVal = CN->getAPIntValue(); 574*0fca6ea1SDimitry Andric int64_t Value = APVal.getSExtValue(); 575*0fca6ea1SDimitry Andric if (Op.getValueType() == MVT::i32) { 576*0fca6ea1SDimitry Andric // Check if use node maybe lowered to the MOVI instruction 577*0fca6ea1SDimitry Andric if (Value > -2048 && Value <= 2047) 578*0fca6ea1SDimitry Andric return Op; 579*0fca6ea1SDimitry Andric // Check if use node maybe lowered to the ADDMI instruction 580*0fca6ea1SDimitry Andric SDNode &OpNode = *Op.getNode(); 581*0fca6ea1SDimitry Andric if ((OpNode.hasOneUse() && OpNode.use_begin()->getOpcode() == ISD::ADD) && 582*0fca6ea1SDimitry Andric isShiftedInt<16, 8>(Value)) 583*0fca6ea1SDimitry Andric return Op; 584*0fca6ea1SDimitry Andric Type *Ty = Type::getInt32Ty(*DAG.getContext()); 585*0fca6ea1SDimitry Andric Constant *CV = ConstantInt::get(Ty, Value); 586*0fca6ea1SDimitry Andric SDValue CP = DAG.getConstantPool(CV, MVT::i32); 587*0fca6ea1SDimitry Andric return CP; 588*0fca6ea1SDimitry Andric } 589*0fca6ea1SDimitry Andric return Op; 590*0fca6ea1SDimitry Andric } 591*0fca6ea1SDimitry Andric 592*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerGlobalAddress(SDValue Op, 593*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 594*0fca6ea1SDimitry Andric const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Op); 595*0fca6ea1SDimitry Andric SDLoc DL(Op); 596*0fca6ea1SDimitry Andric auto PtrVT = Op.getValueType(); 597*0fca6ea1SDimitry Andric const GlobalValue *GV = G->getGlobal(); 598*0fca6ea1SDimitry Andric 599*0fca6ea1SDimitry Andric SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, Align(4)); 600*0fca6ea1SDimitry Andric SDValue CPWrap = getAddrPCRel(CPAddr, DAG); 601*0fca6ea1SDimitry Andric 602*0fca6ea1SDimitry Andric return CPWrap; 603*0fca6ea1SDimitry Andric } 604*0fca6ea1SDimitry Andric 605*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerBlockAddress(SDValue Op, 606*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 607*0fca6ea1SDimitry Andric BlockAddressSDNode *Node = cast<BlockAddressSDNode>(Op); 608*0fca6ea1SDimitry Andric const BlockAddress *BA = Node->getBlockAddress(); 609*0fca6ea1SDimitry Andric EVT PtrVT = Op.getValueType(); 610*0fca6ea1SDimitry Andric 611*0fca6ea1SDimitry Andric XtensaConstantPoolValue *CPV = 612*0fca6ea1SDimitry Andric XtensaConstantPoolConstant::Create(BA, 0, XtensaCP::CPBlockAddress); 613*0fca6ea1SDimitry Andric SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4)); 614*0fca6ea1SDimitry Andric SDValue CPWrap = getAddrPCRel(CPAddr, DAG); 615*0fca6ea1SDimitry Andric 616*0fca6ea1SDimitry Andric return CPWrap; 617*0fca6ea1SDimitry Andric } 618*0fca6ea1SDimitry Andric 619*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) const { 620*0fca6ea1SDimitry Andric SDValue Chain = Op.getOperand(0); 621*0fca6ea1SDimitry Andric SDValue Table = Op.getOperand(1); 622*0fca6ea1SDimitry Andric SDValue Index = Op.getOperand(2); 623*0fca6ea1SDimitry Andric SDLoc DL(Op); 624*0fca6ea1SDimitry Andric JumpTableSDNode *JT = cast<JumpTableSDNode>(Table); 625*0fca6ea1SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 626*0fca6ea1SDimitry Andric const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); 627*0fca6ea1SDimitry Andric SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32); 628*0fca6ea1SDimitry Andric const DataLayout &TD = DAG.getDataLayout(); 629*0fca6ea1SDimitry Andric EVT PtrVT = Table.getValueType(); 630*0fca6ea1SDimitry Andric unsigned EntrySize = MJTI->getEntrySize(TD); 631*0fca6ea1SDimitry Andric 632*0fca6ea1SDimitry Andric Index = DAG.getNode(ISD::MUL, DL, Index.getValueType(), Index, 633*0fca6ea1SDimitry Andric DAG.getConstant(EntrySize, DL, Index.getValueType())); 634*0fca6ea1SDimitry Andric SDValue Addr = DAG.getNode(ISD::ADD, DL, Index.getValueType(), Index, Table); 635*0fca6ea1SDimitry Andric SDValue LD = 636*0fca6ea1SDimitry Andric DAG.getLoad(PtrVT, DL, Chain, Addr, 637*0fca6ea1SDimitry Andric MachinePointerInfo::getJumpTable(DAG.getMachineFunction())); 638*0fca6ea1SDimitry Andric 639*0fca6ea1SDimitry Andric return DAG.getNode(XtensaISD::BR_JT, DL, MVT::Other, LD.getValue(1), LD, 640*0fca6ea1SDimitry Andric TargetJT); 641*0fca6ea1SDimitry Andric } 642*0fca6ea1SDimitry Andric 643*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerJumpTable(SDValue Op, 644*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 645*0fca6ea1SDimitry Andric JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); 646*0fca6ea1SDimitry Andric EVT PtrVT = Op.getValueType(); 647*0fca6ea1SDimitry Andric 648*0fca6ea1SDimitry Andric // Create a constant pool entry for the callee address 649*0fca6ea1SDimitry Andric XtensaConstantPoolValue *CPV = 650*0fca6ea1SDimitry Andric XtensaConstantPoolJumpTable::Create(*DAG.getContext(), JT->getIndex()); 651*0fca6ea1SDimitry Andric 652*0fca6ea1SDimitry Andric // Get the address of the callee into a register 653*0fca6ea1SDimitry Andric SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4)); 654*0fca6ea1SDimitry Andric 655*0fca6ea1SDimitry Andric return getAddrPCRel(CPAddr, DAG); 656*0fca6ea1SDimitry Andric } 657*0fca6ea1SDimitry Andric 658*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::getAddrPCRel(SDValue Op, 659*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 660*0fca6ea1SDimitry Andric SDLoc DL(Op); 661*0fca6ea1SDimitry Andric EVT Ty = Op.getValueType(); 662*0fca6ea1SDimitry Andric return DAG.getNode(XtensaISD::PCREL_WRAPPER, DL, Ty, Op); 663*0fca6ea1SDimitry Andric } 664*0fca6ea1SDimitry Andric 665*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerConstantPool(ConstantPoolSDNode *CP, 666*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 667*0fca6ea1SDimitry Andric EVT PtrVT = getPointerTy(DAG.getDataLayout()); 668*0fca6ea1SDimitry Andric SDValue Result; 669*0fca6ea1SDimitry Andric if (!CP->isMachineConstantPoolEntry()) { 670*0fca6ea1SDimitry Andric Result = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, CP->getAlign(), 671*0fca6ea1SDimitry Andric CP->getOffset()); 672*0fca6ea1SDimitry Andric } else { 673*0fca6ea1SDimitry Andric report_fatal_error("This constantpool type is not supported yet"); 674*0fca6ea1SDimitry Andric } 675*0fca6ea1SDimitry Andric 676*0fca6ea1SDimitry Andric return getAddrPCRel(Result, DAG); 677*0fca6ea1SDimitry Andric } 678*0fca6ea1SDimitry Andric 679*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerSTACKSAVE(SDValue Op, 680*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 681*0fca6ea1SDimitry Andric return DAG.getCopyFromReg(Op.getOperand(0), SDLoc(Op), Xtensa::SP, 682*0fca6ea1SDimitry Andric Op.getValueType()); 683*0fca6ea1SDimitry Andric } 684*0fca6ea1SDimitry Andric 685*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerSTACKRESTORE(SDValue Op, 686*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 687*0fca6ea1SDimitry Andric return DAG.getCopyToReg(Op.getOperand(0), SDLoc(Op), Xtensa::SP, 688*0fca6ea1SDimitry Andric Op.getOperand(1)); 689*0fca6ea1SDimitry Andric } 690*0fca6ea1SDimitry Andric 691*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, 692*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 693*0fca6ea1SDimitry Andric SDValue Chain = Op.getOperand(0); // Legalize the chain. 694*0fca6ea1SDimitry Andric SDValue Size = Op.getOperand(1); // Legalize the size. 695*0fca6ea1SDimitry Andric EVT VT = Size->getValueType(0); 696*0fca6ea1SDimitry Andric SDLoc DL(Op); 697*0fca6ea1SDimitry Andric 698*0fca6ea1SDimitry Andric // Round up Size to 32 699*0fca6ea1SDimitry Andric SDValue SizeTmp = 700*0fca6ea1SDimitry Andric DAG.getNode(ISD::ADD, DL, VT, Size, DAG.getConstant(31, DL, MVT::i32)); 701*0fca6ea1SDimitry Andric SDValue SizeRoundUp = DAG.getNode(ISD::AND, DL, VT, SizeTmp, 702*0fca6ea1SDimitry Andric DAG.getConstant(~31, DL, MVT::i32)); 703*0fca6ea1SDimitry Andric 704*0fca6ea1SDimitry Andric unsigned SPReg = Xtensa::SP; 705*0fca6ea1SDimitry Andric SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT); 706*0fca6ea1SDimitry Andric SDValue NewSP = DAG.getNode(ISD::SUB, DL, VT, SP, SizeRoundUp); // Value 707*0fca6ea1SDimitry Andric Chain = DAG.getCopyToReg(SP.getValue(1), DL, SPReg, NewSP); // Output chain 708*0fca6ea1SDimitry Andric 709*0fca6ea1SDimitry Andric SDValue NewVal = DAG.getCopyFromReg(Chain, DL, SPReg, MVT::i32); 710*0fca6ea1SDimitry Andric Chain = NewVal.getValue(1); 711*0fca6ea1SDimitry Andric 712*0fca6ea1SDimitry Andric SDValue Ops[2] = {NewVal, Chain}; 713*0fca6ea1SDimitry Andric return DAG.getMergeValues(Ops, DL); 714*0fca6ea1SDimitry Andric } 715*0fca6ea1SDimitry Andric 716*0fca6ea1SDimitry Andric SDValue XtensaTargetLowering::LowerOperation(SDValue Op, 717*0fca6ea1SDimitry Andric SelectionDAG &DAG) const { 718*0fca6ea1SDimitry Andric switch (Op.getOpcode()) { 719*0fca6ea1SDimitry Andric case ISD::BR_JT: 720*0fca6ea1SDimitry Andric return LowerBR_JT(Op, DAG); 721*0fca6ea1SDimitry Andric case ISD::Constant: 722*0fca6ea1SDimitry Andric return LowerImmediate(Op, DAG); 723*0fca6ea1SDimitry Andric case ISD::GlobalAddress: 724*0fca6ea1SDimitry Andric return LowerGlobalAddress(Op, DAG); 725*0fca6ea1SDimitry Andric case ISD::BlockAddress: 726*0fca6ea1SDimitry Andric return LowerBlockAddress(Op, DAG); 727*0fca6ea1SDimitry Andric case ISD::JumpTable: 728*0fca6ea1SDimitry Andric return LowerJumpTable(Op, DAG); 729*0fca6ea1SDimitry Andric case ISD::ConstantPool: 730*0fca6ea1SDimitry Andric return LowerConstantPool(cast<ConstantPoolSDNode>(Op), DAG); 731*0fca6ea1SDimitry Andric case ISD::SELECT_CC: 732*0fca6ea1SDimitry Andric return LowerSELECT_CC(Op, DAG); 733*0fca6ea1SDimitry Andric case ISD::STACKSAVE: 734*0fca6ea1SDimitry Andric return LowerSTACKSAVE(Op, DAG); 735*0fca6ea1SDimitry Andric case ISD::STACKRESTORE: 736*0fca6ea1SDimitry Andric return LowerSTACKRESTORE(Op, DAG); 737*0fca6ea1SDimitry Andric case ISD::DYNAMIC_STACKALLOC: 738*0fca6ea1SDimitry Andric return LowerDYNAMIC_STACKALLOC(Op, DAG); 739*0fca6ea1SDimitry Andric default: 740*0fca6ea1SDimitry Andric report_fatal_error("Unexpected node to lower"); 741*0fca6ea1SDimitry Andric } 742*0fca6ea1SDimitry Andric } 743*0fca6ea1SDimitry Andric 744*0fca6ea1SDimitry Andric const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const { 745*0fca6ea1SDimitry Andric switch (Opcode) { 746*0fca6ea1SDimitry Andric case XtensaISD::BR_JT: 747*0fca6ea1SDimitry Andric return "XtensaISD::BR_JT"; 748*0fca6ea1SDimitry Andric case XtensaISD::CALL: 749*0fca6ea1SDimitry Andric return "XtensaISD::CALL"; 750*0fca6ea1SDimitry Andric case XtensaISD::PCREL_WRAPPER: 751*0fca6ea1SDimitry Andric return "XtensaISD::PCREL_WRAPPER"; 752*0fca6ea1SDimitry Andric case XtensaISD::RET: 753*0fca6ea1SDimitry Andric return "XtensaISD::RET"; 754*0fca6ea1SDimitry Andric case XtensaISD::SELECT_CC: 755*0fca6ea1SDimitry Andric return "XtensaISD::SELECT_CC"; 756*0fca6ea1SDimitry Andric } 757*0fca6ea1SDimitry Andric return nullptr; 758*0fca6ea1SDimitry Andric } 759*0fca6ea1SDimitry Andric 760*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 761*0fca6ea1SDimitry Andric // Custom insertion 762*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 763*0fca6ea1SDimitry Andric 764*0fca6ea1SDimitry Andric MachineBasicBlock * 765*0fca6ea1SDimitry Andric XtensaTargetLowering::emitSelectCC(MachineInstr &MI, 766*0fca6ea1SDimitry Andric MachineBasicBlock *MBB) const { 767*0fca6ea1SDimitry Andric const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 768*0fca6ea1SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 769*0fca6ea1SDimitry Andric 770*0fca6ea1SDimitry Andric MachineOperand &LHS = MI.getOperand(1); 771*0fca6ea1SDimitry Andric MachineOperand &RHS = MI.getOperand(2); 772*0fca6ea1SDimitry Andric MachineOperand &TrueValue = MI.getOperand(3); 773*0fca6ea1SDimitry Andric MachineOperand &FalseValue = MI.getOperand(4); 774*0fca6ea1SDimitry Andric unsigned BrKind = MI.getOperand(5).getImm(); 775*0fca6ea1SDimitry Andric 776*0fca6ea1SDimitry Andric // To "insert" a SELECT_CC instruction, we actually have to insert 777*0fca6ea1SDimitry Andric // CopyMBB and SinkMBB blocks and add branch to MBB. We build phi 778*0fca6ea1SDimitry Andric // operation in SinkMBB like phi (TrueVakue,FalseValue), where TrueValue 779*0fca6ea1SDimitry Andric // is passed from MMB and FalseValue is passed from CopyMBB. 780*0fca6ea1SDimitry Andric // MBB 781*0fca6ea1SDimitry Andric // | \ 782*0fca6ea1SDimitry Andric // | CopyMBB 783*0fca6ea1SDimitry Andric // | / 784*0fca6ea1SDimitry Andric // SinkMBB 785*0fca6ea1SDimitry Andric // The incoming instruction knows the 786*0fca6ea1SDimitry Andric // destination vreg to set, the condition code register to branch on, the 787*0fca6ea1SDimitry Andric // true/false values to select between, and a branch opcode to use. 788*0fca6ea1SDimitry Andric const BasicBlock *LLVM_BB = MBB->getBasicBlock(); 789*0fca6ea1SDimitry Andric MachineFunction::iterator It = ++MBB->getIterator(); 790*0fca6ea1SDimitry Andric 791*0fca6ea1SDimitry Andric MachineFunction *F = MBB->getParent(); 792*0fca6ea1SDimitry Andric MachineBasicBlock *CopyMBB = F->CreateMachineBasicBlock(LLVM_BB); 793*0fca6ea1SDimitry Andric MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 794*0fca6ea1SDimitry Andric 795*0fca6ea1SDimitry Andric F->insert(It, CopyMBB); 796*0fca6ea1SDimitry Andric F->insert(It, SinkMBB); 797*0fca6ea1SDimitry Andric 798*0fca6ea1SDimitry Andric // Transfer the remainder of MBB and its successor edges to SinkMBB. 799*0fca6ea1SDimitry Andric SinkMBB->splice(SinkMBB->begin(), MBB, 800*0fca6ea1SDimitry Andric std::next(MachineBasicBlock::iterator(MI)), MBB->end()); 801*0fca6ea1SDimitry Andric SinkMBB->transferSuccessorsAndUpdatePHIs(MBB); 802*0fca6ea1SDimitry Andric 803*0fca6ea1SDimitry Andric MBB->addSuccessor(CopyMBB); 804*0fca6ea1SDimitry Andric MBB->addSuccessor(SinkMBB); 805*0fca6ea1SDimitry Andric 806*0fca6ea1SDimitry Andric BuildMI(MBB, DL, TII.get(BrKind)) 807*0fca6ea1SDimitry Andric .addReg(LHS.getReg()) 808*0fca6ea1SDimitry Andric .addReg(RHS.getReg()) 809*0fca6ea1SDimitry Andric .addMBB(SinkMBB); 810*0fca6ea1SDimitry Andric 811*0fca6ea1SDimitry Andric CopyMBB->addSuccessor(SinkMBB); 812*0fca6ea1SDimitry Andric 813*0fca6ea1SDimitry Andric // SinkMBB: 814*0fca6ea1SDimitry Andric // %Result = phi [ %FalseValue, CopyMBB ], [ %TrueValue, MBB ] 815*0fca6ea1SDimitry Andric // ... 816*0fca6ea1SDimitry Andric 817*0fca6ea1SDimitry Andric BuildMI(*SinkMBB, SinkMBB->begin(), DL, TII.get(Xtensa::PHI), 818*0fca6ea1SDimitry Andric MI.getOperand(0).getReg()) 819*0fca6ea1SDimitry Andric .addReg(FalseValue.getReg()) 820*0fca6ea1SDimitry Andric .addMBB(CopyMBB) 821*0fca6ea1SDimitry Andric .addReg(TrueValue.getReg()) 822*0fca6ea1SDimitry Andric .addMBB(MBB); 823*0fca6ea1SDimitry Andric 824*0fca6ea1SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now. 825*0fca6ea1SDimitry Andric return SinkMBB; 826*0fca6ea1SDimitry Andric } 827*0fca6ea1SDimitry Andric 828*0fca6ea1SDimitry Andric MachineBasicBlock *XtensaTargetLowering::EmitInstrWithCustomInserter( 829*0fca6ea1SDimitry Andric MachineInstr &MI, MachineBasicBlock *MBB) const { 830*0fca6ea1SDimitry Andric switch (MI.getOpcode()) { 831*0fca6ea1SDimitry Andric case Xtensa::SELECT: 832*0fca6ea1SDimitry Andric return emitSelectCC(MI, MBB); 833*0fca6ea1SDimitry Andric default: 834*0fca6ea1SDimitry Andric llvm_unreachable("Unexpected instr type to insert"); 835*0fca6ea1SDimitry Andric } 836*0fca6ea1SDimitry Andric } 837