xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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