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)
isLongCall(const char * str)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
XtensaTargetLowering(const TargetMachine & TM,const XtensaSubtarget & STI)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
isOffsetFoldingLegal(const GlobalAddressSDNode * GA) const111*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
CC_Xtensa_Custom(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)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
CCAssignFnForCall(CallingConv::ID CC,bool IsVarArg) const199*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
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const204*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
LowerCall(CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const295*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
CanLowerReturn(CallingConv::ID CallConv,MachineFunction & MF,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,LLVMContext & Context) const471*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
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const480*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
getBranchOpcode(ISD::CondCode Cond)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
LowerSELECT_CC(SDValue Op,SelectionDAG & DAG) const552*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
LowerImmediate(SDValue Op,SelectionDAG & DAG) const569*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
LowerGlobalAddress(SDValue Op,SelectionDAG & DAG) const592*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
LowerBlockAddress(SDValue Op,SelectionDAG & DAG) const605*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
LowerBR_JT(SDValue Op,SelectionDAG & DAG) const619*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
LowerJumpTable(SDValue Op,SelectionDAG & DAG) const643*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
getAddrPCRel(SDValue Op,SelectionDAG & DAG) const658*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
LowerConstantPool(ConstantPoolSDNode * CP,SelectionDAG & DAG) const665*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
LowerSTACKSAVE(SDValue Op,SelectionDAG & DAG) const679*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
LowerSTACKRESTORE(SDValue Op,SelectionDAG & DAG) const685*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
LowerDYNAMIC_STACKALLOC(SDValue Op,SelectionDAG & DAG) const691*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
LowerOperation(SDValue Op,SelectionDAG & DAG) const716*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
getTargetNodeName(unsigned Opcode) const744*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 *
emitSelectCC(MachineInstr & MI,MachineBasicBlock * MBB) const765*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
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * MBB) const828*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