]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- MipsISelLowering.cpp - Mips DAG Lowering Implementation -----------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file defines the interfaces that Mips uses to lower LLVM code into a | |
11 | // selection DAG. | |
12 | // | |
13 | //===----------------------------------------------------------------------===// | |
223e47cc | 14 | #include "MipsISelLowering.h" |
970d7e83 LB |
15 | #include "InstPrinter/MipsInstPrinter.h" |
16 | #include "MCTargetDesc/MipsBaseInfo.h" | |
85aaf69f | 17 | #include "MipsCCState.h" |
223e47cc | 18 | #include "MipsMachineFunction.h" |
970d7e83 | 19 | #include "MipsSubtarget.h" |
223e47cc LB |
20 | #include "MipsTargetMachine.h" |
21 | #include "MipsTargetObjectFile.h" | |
970d7e83 | 22 | #include "llvm/ADT/Statistic.h" |
1a4d82fc | 23 | #include "llvm/ADT/StringSwitch.h" |
223e47cc LB |
24 | #include "llvm/CodeGen/CallingConvLower.h" |
25 | #include "llvm/CodeGen/MachineFrameInfo.h" | |
26 | #include "llvm/CodeGen/MachineFunction.h" | |
27 | #include "llvm/CodeGen/MachineInstrBuilder.h" | |
1a4d82fc | 28 | #include "llvm/CodeGen/MachineJumpTableInfo.h" |
223e47cc LB |
29 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
30 | #include "llvm/CodeGen/SelectionDAGISel.h" | |
31 | #include "llvm/CodeGen/ValueTypes.h" | |
970d7e83 LB |
32 | #include "llvm/IR/CallingConv.h" |
33 | #include "llvm/IR/DerivedTypes.h" | |
34 | #include "llvm/IR/GlobalVariable.h" | |
970d7e83 | 35 | #include "llvm/Support/CommandLine.h" |
223e47cc LB |
36 | #include "llvm/Support/Debug.h" |
37 | #include "llvm/Support/ErrorHandling.h" | |
38 | #include "llvm/Support/raw_ostream.h" | |
1a4d82fc | 39 | #include <cctype> |
223e47cc LB |
40 | |
41 | using namespace llvm; | |
42 | ||
1a4d82fc JJ |
43 | #define DEBUG_TYPE "mips-lower" |
44 | ||
970d7e83 LB |
45 | STATISTIC(NumTailCalls, "Number of tail calls"); |
46 | ||
47 | static cl::opt<bool> | |
48 | LargeGOT("mxgot", cl::Hidden, | |
49 | cl::desc("MIPS: Enable GOT larger than 64k."), cl::init(false)); | |
50 | ||
1a4d82fc JJ |
51 | static cl::opt<bool> |
52 | NoZeroDivCheck("mno-check-zero-division", cl::Hidden, | |
53 | cl::desc("MIPS: Don't trap on integer division by zero."), | |
54 | cl::init(false)); | |
55 | ||
56 | cl::opt<bool> | |
57 | EnableMipsFastISel("mips-fast-isel", cl::Hidden, | |
58 | cl::desc("Allow mips-fast-isel to be used"), | |
59 | cl::init(false)); | |
60 | ||
1a4d82fc | 61 | static const MCPhysReg Mips64DPRegs[8] = { |
970d7e83 LB |
62 | Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64, |
63 | Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64 | |
64 | }; | |
65 | ||
223e47cc LB |
66 | // If I is a shifted mask, set the size (Size) and the first bit of the |
67 | // mask (Pos), and return true. | |
68 | // For example, if I is 0x003ff800, (Pos, Size) = (11, 11). | |
970d7e83 | 69 | static bool isShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) { |
223e47cc | 70 | if (!isShiftedMask_64(I)) |
1a4d82fc | 71 | return false; |
223e47cc LB |
72 | |
73 | Size = CountPopulation_64(I); | |
1a4d82fc | 74 | Pos = countTrailingZeros(I); |
223e47cc LB |
75 | return true; |
76 | } | |
77 | ||
970d7e83 | 78 | SDValue MipsTargetLowering::getGlobalReg(SelectionDAG &DAG, EVT Ty) const { |
223e47cc LB |
79 | MipsFunctionInfo *FI = DAG.getMachineFunction().getInfo<MipsFunctionInfo>(); |
80 | return DAG.getRegister(FI->getGlobalBaseReg(), Ty); | |
81 | } | |
82 | ||
1a4d82fc JJ |
83 | SDValue MipsTargetLowering::getTargetNode(GlobalAddressSDNode *N, EVT Ty, |
84 | SelectionDAG &DAG, | |
85 | unsigned Flag) const { | |
86 | return DAG.getTargetGlobalAddress(N->getGlobal(), SDLoc(N), Ty, 0, Flag); | |
87 | } | |
970d7e83 | 88 | |
1a4d82fc JJ |
89 | SDValue MipsTargetLowering::getTargetNode(ExternalSymbolSDNode *N, EVT Ty, |
90 | SelectionDAG &DAG, | |
91 | unsigned Flag) const { | |
92 | return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flag); | |
970d7e83 LB |
93 | } |
94 | ||
1a4d82fc JJ |
95 | SDValue MipsTargetLowering::getTargetNode(BlockAddressSDNode *N, EVT Ty, |
96 | SelectionDAG &DAG, | |
97 | unsigned Flag) const { | |
98 | return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, 0, Flag); | |
970d7e83 LB |
99 | } |
100 | ||
1a4d82fc JJ |
101 | SDValue MipsTargetLowering::getTargetNode(JumpTableSDNode *N, EVT Ty, |
102 | SelectionDAG &DAG, | |
970d7e83 | 103 | unsigned Flag) const { |
1a4d82fc | 104 | return DAG.getTargetJumpTable(N->getIndex(), Ty, Flag); |
970d7e83 LB |
105 | } |
106 | ||
1a4d82fc JJ |
107 | SDValue MipsTargetLowering::getTargetNode(ConstantPoolSDNode *N, EVT Ty, |
108 | SelectionDAG &DAG, | |
109 | unsigned Flag) const { | |
110 | return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlignment(), | |
111 | N->getOffset(), Flag); | |
970d7e83 LB |
112 | } |
113 | ||
223e47cc LB |
114 | const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { |
115 | switch (Opcode) { | |
116 | case MipsISD::JmpLink: return "MipsISD::JmpLink"; | |
970d7e83 | 117 | case MipsISD::TailCall: return "MipsISD::TailCall"; |
223e47cc LB |
118 | case MipsISD::Hi: return "MipsISD::Hi"; |
119 | case MipsISD::Lo: return "MipsISD::Lo"; | |
120 | case MipsISD::GPRel: return "MipsISD::GPRel"; | |
121 | case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer"; | |
122 | case MipsISD::Ret: return "MipsISD::Ret"; | |
970d7e83 | 123 | case MipsISD::EH_RETURN: return "MipsISD::EH_RETURN"; |
223e47cc LB |
124 | case MipsISD::FPBrcond: return "MipsISD::FPBrcond"; |
125 | case MipsISD::FPCmp: return "MipsISD::FPCmp"; | |
126 | case MipsISD::CMovFP_T: return "MipsISD::CMovFP_T"; | |
127 | case MipsISD::CMovFP_F: return "MipsISD::CMovFP_F"; | |
1a4d82fc JJ |
128 | case MipsISD::TruncIntFP: return "MipsISD::TruncIntFP"; |
129 | case MipsISD::MFHI: return "MipsISD::MFHI"; | |
130 | case MipsISD::MFLO: return "MipsISD::MFLO"; | |
131 | case MipsISD::MTLOHI: return "MipsISD::MTLOHI"; | |
132 | case MipsISD::Mult: return "MipsISD::Mult"; | |
133 | case MipsISD::Multu: return "MipsISD::Multu"; | |
223e47cc LB |
134 | case MipsISD::MAdd: return "MipsISD::MAdd"; |
135 | case MipsISD::MAddu: return "MipsISD::MAddu"; | |
136 | case MipsISD::MSub: return "MipsISD::MSub"; | |
137 | case MipsISD::MSubu: return "MipsISD::MSubu"; | |
138 | case MipsISD::DivRem: return "MipsISD::DivRem"; | |
139 | case MipsISD::DivRemU: return "MipsISD::DivRemU"; | |
1a4d82fc JJ |
140 | case MipsISD::DivRem16: return "MipsISD::DivRem16"; |
141 | case MipsISD::DivRemU16: return "MipsISD::DivRemU16"; | |
223e47cc LB |
142 | case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64"; |
143 | case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64"; | |
144 | case MipsISD::Wrapper: return "MipsISD::Wrapper"; | |
223e47cc LB |
145 | case MipsISD::Sync: return "MipsISD::Sync"; |
146 | case MipsISD::Ext: return "MipsISD::Ext"; | |
147 | case MipsISD::Ins: return "MipsISD::Ins"; | |
148 | case MipsISD::LWL: return "MipsISD::LWL"; | |
149 | case MipsISD::LWR: return "MipsISD::LWR"; | |
150 | case MipsISD::SWL: return "MipsISD::SWL"; | |
151 | case MipsISD::SWR: return "MipsISD::SWR"; | |
152 | case MipsISD::LDL: return "MipsISD::LDL"; | |
153 | case MipsISD::LDR: return "MipsISD::LDR"; | |
154 | case MipsISD::SDL: return "MipsISD::SDL"; | |
155 | case MipsISD::SDR: return "MipsISD::SDR"; | |
156 | case MipsISD::EXTP: return "MipsISD::EXTP"; | |
157 | case MipsISD::EXTPDP: return "MipsISD::EXTPDP"; | |
158 | case MipsISD::EXTR_S_H: return "MipsISD::EXTR_S_H"; | |
159 | case MipsISD::EXTR_W: return "MipsISD::EXTR_W"; | |
160 | case MipsISD::EXTR_R_W: return "MipsISD::EXTR_R_W"; | |
161 | case MipsISD::EXTR_RS_W: return "MipsISD::EXTR_RS_W"; | |
162 | case MipsISD::SHILO: return "MipsISD::SHILO"; | |
163 | case MipsISD::MTHLIP: return "MipsISD::MTHLIP"; | |
164 | case MipsISD::MULT: return "MipsISD::MULT"; | |
165 | case MipsISD::MULTU: return "MipsISD::MULTU"; | |
970d7e83 | 166 | case MipsISD::MADD_DSP: return "MipsISD::MADD_DSP"; |
223e47cc LB |
167 | case MipsISD::MADDU_DSP: return "MipsISD::MADDU_DSP"; |
168 | case MipsISD::MSUB_DSP: return "MipsISD::MSUB_DSP"; | |
169 | case MipsISD::MSUBU_DSP: return "MipsISD::MSUBU_DSP"; | |
1a4d82fc JJ |
170 | case MipsISD::SHLL_DSP: return "MipsISD::SHLL_DSP"; |
171 | case MipsISD::SHRA_DSP: return "MipsISD::SHRA_DSP"; | |
172 | case MipsISD::SHRL_DSP: return "MipsISD::SHRL_DSP"; | |
173 | case MipsISD::SETCC_DSP: return "MipsISD::SETCC_DSP"; | |
174 | case MipsISD::SELECT_CC_DSP: return "MipsISD::SELECT_CC_DSP"; | |
175 | case MipsISD::VALL_ZERO: return "MipsISD::VALL_ZERO"; | |
176 | case MipsISD::VANY_ZERO: return "MipsISD::VANY_ZERO"; | |
177 | case MipsISD::VALL_NONZERO: return "MipsISD::VALL_NONZERO"; | |
178 | case MipsISD::VANY_NONZERO: return "MipsISD::VANY_NONZERO"; | |
179 | case MipsISD::VCEQ: return "MipsISD::VCEQ"; | |
180 | case MipsISD::VCLE_S: return "MipsISD::VCLE_S"; | |
181 | case MipsISD::VCLE_U: return "MipsISD::VCLE_U"; | |
182 | case MipsISD::VCLT_S: return "MipsISD::VCLT_S"; | |
183 | case MipsISD::VCLT_U: return "MipsISD::VCLT_U"; | |
184 | case MipsISD::VSMAX: return "MipsISD::VSMAX"; | |
185 | case MipsISD::VSMIN: return "MipsISD::VSMIN"; | |
186 | case MipsISD::VUMAX: return "MipsISD::VUMAX"; | |
187 | case MipsISD::VUMIN: return "MipsISD::VUMIN"; | |
188 | case MipsISD::VEXTRACT_SEXT_ELT: return "MipsISD::VEXTRACT_SEXT_ELT"; | |
189 | case MipsISD::VEXTRACT_ZEXT_ELT: return "MipsISD::VEXTRACT_ZEXT_ELT"; | |
190 | case MipsISD::VNOR: return "MipsISD::VNOR"; | |
191 | case MipsISD::VSHF: return "MipsISD::VSHF"; | |
192 | case MipsISD::SHF: return "MipsISD::SHF"; | |
193 | case MipsISD::ILVEV: return "MipsISD::ILVEV"; | |
194 | case MipsISD::ILVOD: return "MipsISD::ILVOD"; | |
195 | case MipsISD::ILVL: return "MipsISD::ILVL"; | |
196 | case MipsISD::ILVR: return "MipsISD::ILVR"; | |
197 | case MipsISD::PCKEV: return "MipsISD::PCKEV"; | |
198 | case MipsISD::PCKOD: return "MipsISD::PCKOD"; | |
199 | case MipsISD::INSVE: return "MipsISD::INSVE"; | |
200 | default: return nullptr; | |
223e47cc LB |
201 | } |
202 | } | |
203 | ||
1a4d82fc JJ |
204 | MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, |
205 | const MipsSubtarget &STI) | |
85aaf69f | 206 | : TargetLowering(TM), Subtarget(STI) { |
223e47cc LB |
207 | // Mips does not have i1 type, so use i32 for |
208 | // setcc operations results (slt, sgt, ...). | |
209 | setBooleanContents(ZeroOrOneBooleanContent); | |
1a4d82fc JJ |
210 | setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); |
211 | // The cmp.cond.fmt instruction in MIPS32r6/MIPS64r6 uses 0 and -1 like MSA | |
212 | // does. Integer booleans still use 0 and 1. | |
213 | if (Subtarget.hasMips32r6()) | |
214 | setBooleanContents(ZeroOrOneBooleanContent, | |
215 | ZeroOrNegativeOneBooleanContent); | |
223e47cc | 216 | |
223e47cc | 217 | // Load extented operations for i1 types must be promoted |
85aaf69f SL |
218 | for (MVT VT : MVT::integer_valuetypes()) { |
219 | setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); | |
220 | setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); | |
221 | setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); | |
222 | } | |
223e47cc LB |
223 | |
224 | // MIPS doesn't have extending float->double load/store | |
85aaf69f SL |
225 | for (MVT VT : MVT::fp_valuetypes()) |
226 | setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); | |
223e47cc LB |
227 | setTruncStoreAction(MVT::f64, MVT::f32, Expand); |
228 | ||
229 | // Used by legalize types to correctly generate the setcc result. | |
230 | // Without this, every float setcc comes with a AND/OR with the result, | |
231 | // we don't want this, since the fpcmp result goes to a flag register, | |
232 | // which is used implicitly by brcond and select operations. | |
233 | AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32); | |
234 | ||
235 | // Mips Custom Operations | |
970d7e83 | 236 | setOperationAction(ISD::BR_JT, MVT::Other, Custom); |
223e47cc LB |
237 | setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); |
238 | setOperationAction(ISD::BlockAddress, MVT::i32, Custom); | |
239 | setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); | |
240 | setOperationAction(ISD::JumpTable, MVT::i32, Custom); | |
241 | setOperationAction(ISD::ConstantPool, MVT::i32, Custom); | |
242 | setOperationAction(ISD::SELECT, MVT::f32, Custom); | |
243 | setOperationAction(ISD::SELECT, MVT::f64, Custom); | |
244 | setOperationAction(ISD::SELECT, MVT::i32, Custom); | |
245 | setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); | |
246 | setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); | |
247 | setOperationAction(ISD::SETCC, MVT::f32, Custom); | |
248 | setOperationAction(ISD::SETCC, MVT::f64, Custom); | |
249 | setOperationAction(ISD::BRCOND, MVT::Other, Custom); | |
223e47cc LB |
250 | setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom); |
251 | setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); | |
1a4d82fc | 252 | setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); |
223e47cc | 253 | |
1a4d82fc | 254 | if (Subtarget.isGP64bit()) { |
223e47cc LB |
255 | setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); |
256 | setOperationAction(ISD::BlockAddress, MVT::i64, Custom); | |
257 | setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); | |
258 | setOperationAction(ISD::JumpTable, MVT::i64, Custom); | |
259 | setOperationAction(ISD::ConstantPool, MVT::i64, Custom); | |
260 | setOperationAction(ISD::SELECT, MVT::i64, Custom); | |
261 | setOperationAction(ISD::LOAD, MVT::i64, Custom); | |
262 | setOperationAction(ISD::STORE, MVT::i64, Custom); | |
1a4d82fc | 263 | setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); |
223e47cc LB |
264 | } |
265 | ||
1a4d82fc | 266 | if (!Subtarget.isGP64bit()) { |
223e47cc LB |
267 | setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); |
268 | setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); | |
269 | setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); | |
270 | } | |
271 | ||
970d7e83 | 272 | setOperationAction(ISD::ADD, MVT::i32, Custom); |
1a4d82fc | 273 | if (Subtarget.isGP64bit()) |
970d7e83 LB |
274 | setOperationAction(ISD::ADD, MVT::i64, Custom); |
275 | ||
223e47cc LB |
276 | setOperationAction(ISD::SDIV, MVT::i32, Expand); |
277 | setOperationAction(ISD::SREM, MVT::i32, Expand); | |
278 | setOperationAction(ISD::UDIV, MVT::i32, Expand); | |
279 | setOperationAction(ISD::UREM, MVT::i32, Expand); | |
280 | setOperationAction(ISD::SDIV, MVT::i64, Expand); | |
281 | setOperationAction(ISD::SREM, MVT::i64, Expand); | |
282 | setOperationAction(ISD::UDIV, MVT::i64, Expand); | |
283 | setOperationAction(ISD::UREM, MVT::i64, Expand); | |
284 | ||
285 | // Operations not directly supported by Mips. | |
970d7e83 LB |
286 | setOperationAction(ISD::BR_CC, MVT::f32, Expand); |
287 | setOperationAction(ISD::BR_CC, MVT::f64, Expand); | |
288 | setOperationAction(ISD::BR_CC, MVT::i32, Expand); | |
289 | setOperationAction(ISD::BR_CC, MVT::i64, Expand); | |
1a4d82fc JJ |
290 | setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); |
291 | setOperationAction(ISD::SELECT_CC, MVT::i64, Expand); | |
223e47cc LB |
292 | setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); |
293 | setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); | |
294 | setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); | |
295 | setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); | |
296 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); | |
1a4d82fc JJ |
297 | if (Subtarget.hasCnMips()) { |
298 | setOperationAction(ISD::CTPOP, MVT::i32, Legal); | |
299 | setOperationAction(ISD::CTPOP, MVT::i64, Legal); | |
300 | } else { | |
301 | setOperationAction(ISD::CTPOP, MVT::i32, Expand); | |
302 | setOperationAction(ISD::CTPOP, MVT::i64, Expand); | |
303 | } | |
223e47cc LB |
304 | setOperationAction(ISD::CTTZ, MVT::i32, Expand); |
305 | setOperationAction(ISD::CTTZ, MVT::i64, Expand); | |
306 | setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); | |
307 | setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand); | |
308 | setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); | |
309 | setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand); | |
310 | setOperationAction(ISD::ROTL, MVT::i32, Expand); | |
311 | setOperationAction(ISD::ROTL, MVT::i64, Expand); | |
312 | setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); | |
313 | setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand); | |
314 | ||
1a4d82fc | 315 | if (!Subtarget.hasMips32r2()) |
223e47cc LB |
316 | setOperationAction(ISD::ROTR, MVT::i32, Expand); |
317 | ||
1a4d82fc | 318 | if (!Subtarget.hasMips64r2()) |
223e47cc LB |
319 | setOperationAction(ISD::ROTR, MVT::i64, Expand); |
320 | ||
321 | setOperationAction(ISD::FSIN, MVT::f32, Expand); | |
322 | setOperationAction(ISD::FSIN, MVT::f64, Expand); | |
323 | setOperationAction(ISD::FCOS, MVT::f32, Expand); | |
324 | setOperationAction(ISD::FCOS, MVT::f64, Expand); | |
970d7e83 LB |
325 | setOperationAction(ISD::FSINCOS, MVT::f32, Expand); |
326 | setOperationAction(ISD::FSINCOS, MVT::f64, Expand); | |
223e47cc LB |
327 | setOperationAction(ISD::FPOWI, MVT::f32, Expand); |
328 | setOperationAction(ISD::FPOW, MVT::f32, Expand); | |
329 | setOperationAction(ISD::FPOW, MVT::f64, Expand); | |
330 | setOperationAction(ISD::FLOG, MVT::f32, Expand); | |
331 | setOperationAction(ISD::FLOG2, MVT::f32, Expand); | |
332 | setOperationAction(ISD::FLOG10, MVT::f32, Expand); | |
333 | setOperationAction(ISD::FEXP, MVT::f32, Expand); | |
334 | setOperationAction(ISD::FMA, MVT::f32, Expand); | |
335 | setOperationAction(ISD::FMA, MVT::f64, Expand); | |
336 | setOperationAction(ISD::FREM, MVT::f32, Expand); | |
337 | setOperationAction(ISD::FREM, MVT::f64, Expand); | |
338 | ||
970d7e83 LB |
339 | setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); |
340 | ||
1a4d82fc JJ |
341 | setOperationAction(ISD::VASTART, MVT::Other, Custom); |
342 | setOperationAction(ISD::VAARG, MVT::Other, Custom); | |
223e47cc LB |
343 | setOperationAction(ISD::VACOPY, MVT::Other, Expand); |
344 | setOperationAction(ISD::VAEND, MVT::Other, Expand); | |
345 | ||
223e47cc LB |
346 | // Use the default for now |
347 | setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); | |
348 | setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); | |
349 | ||
350 | setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Expand); | |
351 | setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Expand); | |
352 | setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Expand); | |
353 | setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Expand); | |
354 | ||
355 | setInsertFencesForAtomic(true); | |
356 | ||
1a4d82fc | 357 | if (!Subtarget.hasMips32r2()) { |
223e47cc LB |
358 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); |
359 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); | |
360 | } | |
361 | ||
1a4d82fc JJ |
362 | // MIPS16 lacks MIPS32's clz and clo instructions. |
363 | if (!Subtarget.hasMips32() || Subtarget.inMips16Mode()) | |
223e47cc | 364 | setOperationAction(ISD::CTLZ, MVT::i32, Expand); |
1a4d82fc | 365 | if (!Subtarget.hasMips64()) |
223e47cc | 366 | setOperationAction(ISD::CTLZ, MVT::i64, Expand); |
223e47cc | 367 | |
1a4d82fc | 368 | if (!Subtarget.hasMips32r2()) |
223e47cc | 369 | setOperationAction(ISD::BSWAP, MVT::i32, Expand); |
1a4d82fc | 370 | if (!Subtarget.hasMips64r2()) |
223e47cc | 371 | setOperationAction(ISD::BSWAP, MVT::i64, Expand); |
223e47cc | 372 | |
1a4d82fc | 373 | if (Subtarget.isGP64bit()) { |
85aaf69f SL |
374 | setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Custom); |
375 | setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Custom); | |
376 | setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom); | |
223e47cc LB |
377 | setTruncStoreAction(MVT::i64, MVT::i32, Custom); |
378 | } | |
379 | ||
1a4d82fc JJ |
380 | setOperationAction(ISD::TRAP, MVT::Other, Legal); |
381 | ||
223e47cc LB |
382 | setTargetDAGCombine(ISD::SDIVREM); |
383 | setTargetDAGCombine(ISD::UDIVREM); | |
384 | setTargetDAGCombine(ISD::SELECT); | |
385 | setTargetDAGCombine(ISD::AND); | |
386 | setTargetDAGCombine(ISD::OR); | |
387 | setTargetDAGCombine(ISD::ADD); | |
388 | ||
1a4d82fc | 389 | setMinFunctionAlignment(Subtarget.isGP64bit() ? 3 : 2); |
223e47cc | 390 | |
1a4d82fc JJ |
391 | // The arguments on the stack are defined in terms of 4-byte slots on O32 |
392 | // and 8-byte slots on N32/N64. | |
393 | setMinStackArgumentAlignment( | |
394 | (Subtarget.isABI_N32() || Subtarget.isABI_N64()) ? 8 : 4); | |
223e47cc | 395 | |
1a4d82fc JJ |
396 | setStackPointerRegisterToSaveRestore(Subtarget.isABI_N64() ? Mips::SP_64 |
397 | : Mips::SP); | |
223e47cc | 398 | |
1a4d82fc JJ |
399 | setExceptionPointerRegister(Subtarget.isABI_N64() ? Mips::A0_64 : Mips::A0); |
400 | setExceptionSelectorRegister(Subtarget.isABI_N64() ? Mips::A1_64 : Mips::A1); | |
223e47cc | 401 | |
1a4d82fc | 402 | MaxStoresPerMemcpy = 16; |
223e47cc | 403 | |
1a4d82fc | 404 | isMicroMips = Subtarget.inMicroMipsMode(); |
223e47cc LB |
405 | } |
406 | ||
1a4d82fc JJ |
407 | const MipsTargetLowering *MipsTargetLowering::create(const MipsTargetMachine &TM, |
408 | const MipsSubtarget &STI) { | |
409 | if (STI.inMips16Mode()) | |
410 | return llvm::createMips16TargetLowering(TM, STI); | |
223e47cc | 411 | |
1a4d82fc | 412 | return llvm::createMipsSETargetLowering(TM, STI); |
223e47cc LB |
413 | } |
414 | ||
1a4d82fc JJ |
415 | // Create a fast isel object. |
416 | FastISel * | |
417 | MipsTargetLowering::createFastISel(FunctionLoweringInfo &funcInfo, | |
418 | const TargetLibraryInfo *libInfo) const { | |
419 | if (!EnableMipsFastISel) | |
420 | return TargetLowering::createFastISel(funcInfo, libInfo); | |
421 | return Mips::createFastISel(funcInfo, libInfo); | |
223e47cc LB |
422 | } |
423 | ||
1a4d82fc JJ |
424 | EVT MipsTargetLowering::getSetCCResultType(LLVMContext &, EVT VT) const { |
425 | if (!VT.isVector()) | |
426 | return MVT::i32; | |
427 | return VT.changeVectorElementTypeToInteger(); | |
223e47cc LB |
428 | } |
429 | ||
970d7e83 | 430 | static SDValue performDivRemCombine(SDNode *N, SelectionDAG &DAG, |
223e47cc | 431 | TargetLowering::DAGCombinerInfo &DCI, |
1a4d82fc | 432 | const MipsSubtarget &Subtarget) { |
223e47cc LB |
433 | if (DCI.isBeforeLegalizeOps()) |
434 | return SDValue(); | |
435 | ||
436 | EVT Ty = N->getValueType(0); | |
1a4d82fc JJ |
437 | unsigned LO = (Ty == MVT::i32) ? Mips::LO0 : Mips::LO0_64; |
438 | unsigned HI = (Ty == MVT::i32) ? Mips::HI0 : Mips::HI0_64; | |
439 | unsigned Opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem16 : | |
440 | MipsISD::DivRemU16; | |
441 | SDLoc DL(N); | |
223e47cc | 442 | |
970d7e83 | 443 | SDValue DivRem = DAG.getNode(Opc, DL, MVT::Glue, |
223e47cc LB |
444 | N->getOperand(0), N->getOperand(1)); |
445 | SDValue InChain = DAG.getEntryNode(); | |
446 | SDValue InGlue = DivRem; | |
447 | ||
448 | // insert MFLO | |
449 | if (N->hasAnyUseOfValue(0)) { | |
970d7e83 | 450 | SDValue CopyFromLo = DAG.getCopyFromReg(InChain, DL, LO, Ty, |
223e47cc LB |
451 | InGlue); |
452 | DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo); | |
453 | InChain = CopyFromLo.getValue(1); | |
454 | InGlue = CopyFromLo.getValue(2); | |
455 | } | |
456 | ||
457 | // insert MFHI | |
458 | if (N->hasAnyUseOfValue(1)) { | |
970d7e83 | 459 | SDValue CopyFromHi = DAG.getCopyFromReg(InChain, DL, |
223e47cc LB |
460 | HI, Ty, InGlue); |
461 | DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi); | |
462 | } | |
463 | ||
464 | return SDValue(); | |
465 | } | |
466 | ||
1a4d82fc | 467 | static Mips::CondCode condCodeToFCC(ISD::CondCode CC) { |
223e47cc LB |
468 | switch (CC) { |
469 | default: llvm_unreachable("Unknown fp condition code!"); | |
470 | case ISD::SETEQ: | |
471 | case ISD::SETOEQ: return Mips::FCOND_OEQ; | |
472 | case ISD::SETUNE: return Mips::FCOND_UNE; | |
473 | case ISD::SETLT: | |
474 | case ISD::SETOLT: return Mips::FCOND_OLT; | |
475 | case ISD::SETGT: | |
476 | case ISD::SETOGT: return Mips::FCOND_OGT; | |
477 | case ISD::SETLE: | |
478 | case ISD::SETOLE: return Mips::FCOND_OLE; | |
479 | case ISD::SETGE: | |
480 | case ISD::SETOGE: return Mips::FCOND_OGE; | |
481 | case ISD::SETULT: return Mips::FCOND_ULT; | |
482 | case ISD::SETULE: return Mips::FCOND_ULE; | |
483 | case ISD::SETUGT: return Mips::FCOND_UGT; | |
484 | case ISD::SETUGE: return Mips::FCOND_UGE; | |
485 | case ISD::SETUO: return Mips::FCOND_UN; | |
486 | case ISD::SETO: return Mips::FCOND_OR; | |
487 | case ISD::SETNE: | |
488 | case ISD::SETONE: return Mips::FCOND_ONE; | |
489 | case ISD::SETUEQ: return Mips::FCOND_UEQ; | |
490 | } | |
491 | } | |
492 | ||
493 | ||
1a4d82fc JJ |
494 | /// This function returns true if the floating point conditional branches and |
495 | /// conditional moves which use condition code CC should be inverted. | |
496 | static bool invertFPCondCodeUser(Mips::CondCode CC) { | |
223e47cc LB |
497 | if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT) |
498 | return false; | |
499 | ||
500 | assert((CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT) && | |
501 | "Illegal Condition Code"); | |
502 | ||
503 | return true; | |
504 | } | |
505 | ||
506 | // Creates and returns an FPCmp node from a setcc node. | |
507 | // Returns Op if setcc is not a floating point comparison. | |
970d7e83 | 508 | static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) { |
223e47cc LB |
509 | // must be a SETCC node |
510 | if (Op.getOpcode() != ISD::SETCC) | |
511 | return Op; | |
512 | ||
513 | SDValue LHS = Op.getOperand(0); | |
514 | ||
515 | if (!LHS.getValueType().isFloatingPoint()) | |
516 | return Op; | |
517 | ||
518 | SDValue RHS = Op.getOperand(1); | |
1a4d82fc | 519 | SDLoc DL(Op); |
223e47cc LB |
520 | |
521 | // Assume the 3rd operand is a CondCodeSDNode. Add code to check the type of | |
522 | // node if necessary. | |
523 | ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); | |
524 | ||
970d7e83 | 525 | return DAG.getNode(MipsISD::FPCmp, DL, MVT::Glue, LHS, RHS, |
1a4d82fc | 526 | DAG.getConstant(condCodeToFCC(CC), MVT::i32)); |
223e47cc LB |
527 | } |
528 | ||
529 | // Creates and returns a CMovFPT/F node. | |
970d7e83 | 530 | static SDValue createCMovFP(SelectionDAG &DAG, SDValue Cond, SDValue True, |
1a4d82fc JJ |
531 | SDValue False, SDLoc DL) { |
532 | ConstantSDNode *CC = cast<ConstantSDNode>(Cond.getOperand(2)); | |
533 | bool invert = invertFPCondCodeUser((Mips::CondCode)CC->getSExtValue()); | |
534 | SDValue FCC0 = DAG.getRegister(Mips::FCC0, MVT::i32); | |
223e47cc LB |
535 | |
536 | return DAG.getNode((invert ? MipsISD::CMovFP_F : MipsISD::CMovFP_T), DL, | |
1a4d82fc | 537 | True.getValueType(), True, FCC0, False, Cond); |
223e47cc LB |
538 | } |
539 | ||
970d7e83 | 540 | static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, |
223e47cc | 541 | TargetLowering::DAGCombinerInfo &DCI, |
1a4d82fc | 542 | const MipsSubtarget &Subtarget) { |
223e47cc LB |
543 | if (DCI.isBeforeLegalizeOps()) |
544 | return SDValue(); | |
545 | ||
546 | SDValue SetCC = N->getOperand(0); | |
547 | ||
548 | if ((SetCC.getOpcode() != ISD::SETCC) || | |
549 | !SetCC.getOperand(0).getValueType().isInteger()) | |
550 | return SDValue(); | |
551 | ||
552 | SDValue False = N->getOperand(2); | |
553 | EVT FalseTy = False.getValueType(); | |
554 | ||
555 | if (!FalseTy.isInteger()) | |
556 | return SDValue(); | |
557 | ||
1a4d82fc | 558 | ConstantSDNode *FalseC = dyn_cast<ConstantSDNode>(False); |
223e47cc | 559 | |
1a4d82fc JJ |
560 | // If the RHS (False) is 0, we swap the order of the operands |
561 | // of ISD::SELECT (obviously also inverting the condition) so that we can | |
562 | // take advantage of conditional moves using the $0 register. | |
563 | // Example: | |
564 | // return (a != 0) ? x : 0; | |
565 | // load $reg, x | |
566 | // movz $reg, $0, a | |
567 | if (!FalseC) | |
223e47cc LB |
568 | return SDValue(); |
569 | ||
1a4d82fc JJ |
570 | const SDLoc DL(N); |
571 | ||
572 | if (!FalseC->getZExtValue()) { | |
573 | ISD::CondCode CC = cast<CondCodeSDNode>(SetCC.getOperand(2))->get(); | |
574 | SDValue True = N->getOperand(1); | |
575 | ||
576 | SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), | |
577 | SetCC.getOperand(1), ISD::getSetCCInverse(CC, true)); | |
578 | ||
579 | return DAG.getNode(ISD::SELECT, DL, FalseTy, SetCC, False, True); | |
580 | } | |
581 | ||
582 | // If both operands are integer constants there's a possibility that we | |
583 | // can do some interesting optimizations. | |
223e47cc | 584 | SDValue True = N->getOperand(1); |
1a4d82fc | 585 | ConstantSDNode *TrueC = dyn_cast<ConstantSDNode>(True); |
223e47cc | 586 | |
1a4d82fc JJ |
587 | if (!TrueC || !True.getValueType().isInteger()) |
588 | return SDValue(); | |
223e47cc | 589 | |
1a4d82fc JJ |
590 | // We'll also ignore MVT::i64 operands as this optimizations proves |
591 | // to be ineffective because of the required sign extensions as the result | |
592 | // of a SETCC operator is always MVT::i32 for non-vector types. | |
593 | if (True.getValueType() == MVT::i64) | |
594 | return SDValue(); | |
595 | ||
596 | int64_t Diff = TrueC->getSExtValue() - FalseC->getSExtValue(); | |
597 | ||
598 | // 1) (a < x) ? y : y-1 | |
599 | // slti $reg1, a, x | |
600 | // addiu $reg2, $reg1, y-1 | |
601 | if (Diff == 1) | |
602 | return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, False); | |
603 | ||
604 | // 2) (a < x) ? y-1 : y | |
605 | // slti $reg1, a, x | |
606 | // xor $reg1, $reg1, 1 | |
607 | // addiu $reg2, $reg1, y-1 | |
608 | if (Diff == -1) { | |
609 | ISD::CondCode CC = cast<CondCodeSDNode>(SetCC.getOperand(2))->get(); | |
610 | SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), | |
611 | SetCC.getOperand(1), ISD::getSetCCInverse(CC, true)); | |
612 | return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, True); | |
613 | } | |
614 | ||
615 | // Couldn't optimize. | |
616 | return SDValue(); | |
223e47cc LB |
617 | } |
618 | ||
970d7e83 | 619 | static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, |
223e47cc | 620 | TargetLowering::DAGCombinerInfo &DCI, |
1a4d82fc | 621 | const MipsSubtarget &Subtarget) { |
223e47cc LB |
622 | // Pattern match EXT. |
623 | // $dst = and ((sra or srl) $src , pos), (2**size - 1) | |
624 | // => ext $dst, $src, size, pos | |
1a4d82fc | 625 | if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert()) |
223e47cc LB |
626 | return SDValue(); |
627 | ||
628 | SDValue ShiftRight = N->getOperand(0), Mask = N->getOperand(1); | |
629 | unsigned ShiftRightOpc = ShiftRight.getOpcode(); | |
630 | ||
631 | // Op's first operand must be a shift right. | |
632 | if (ShiftRightOpc != ISD::SRA && ShiftRightOpc != ISD::SRL) | |
633 | return SDValue(); | |
634 | ||
635 | // The second operand of the shift must be an immediate. | |
636 | ConstantSDNode *CN; | |
637 | if (!(CN = dyn_cast<ConstantSDNode>(ShiftRight.getOperand(1)))) | |
638 | return SDValue(); | |
639 | ||
640 | uint64_t Pos = CN->getZExtValue(); | |
641 | uint64_t SMPos, SMSize; | |
642 | ||
643 | // Op's second operand must be a shifted mask. | |
644 | if (!(CN = dyn_cast<ConstantSDNode>(Mask)) || | |
970d7e83 | 645 | !isShiftedMask(CN->getZExtValue(), SMPos, SMSize)) |
223e47cc LB |
646 | return SDValue(); |
647 | ||
648 | // Return if the shifted mask does not start at bit 0 or the sum of its size | |
649 | // and Pos exceeds the word's size. | |
650 | EVT ValTy = N->getValueType(0); | |
651 | if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits()) | |
652 | return SDValue(); | |
653 | ||
1a4d82fc | 654 | return DAG.getNode(MipsISD::Ext, SDLoc(N), ValTy, |
223e47cc LB |
655 | ShiftRight.getOperand(0), DAG.getConstant(Pos, MVT::i32), |
656 | DAG.getConstant(SMSize, MVT::i32)); | |
657 | } | |
658 | ||
970d7e83 | 659 | static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, |
223e47cc | 660 | TargetLowering::DAGCombinerInfo &DCI, |
1a4d82fc | 661 | const MipsSubtarget &Subtarget) { |
223e47cc LB |
662 | // Pattern match INS. |
663 | // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1), | |
664 | // where mask1 = (2**size - 1) << pos, mask0 = ~mask1 | |
665 | // => ins $dst, $src, size, pos, $src1 | |
1a4d82fc | 666 | if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert()) |
223e47cc LB |
667 | return SDValue(); |
668 | ||
669 | SDValue And0 = N->getOperand(0), And1 = N->getOperand(1); | |
670 | uint64_t SMPos0, SMSize0, SMPos1, SMSize1; | |
671 | ConstantSDNode *CN; | |
672 | ||
673 | // See if Op's first operand matches (and $src1 , mask0). | |
674 | if (And0.getOpcode() != ISD::AND) | |
675 | return SDValue(); | |
676 | ||
677 | if (!(CN = dyn_cast<ConstantSDNode>(And0.getOperand(1))) || | |
970d7e83 | 678 | !isShiftedMask(~CN->getSExtValue(), SMPos0, SMSize0)) |
223e47cc LB |
679 | return SDValue(); |
680 | ||
681 | // See if Op's second operand matches (and (shl $src, pos), mask1). | |
682 | if (And1.getOpcode() != ISD::AND) | |
683 | return SDValue(); | |
684 | ||
685 | if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) || | |
970d7e83 | 686 | !isShiftedMask(CN->getZExtValue(), SMPos1, SMSize1)) |
223e47cc LB |
687 | return SDValue(); |
688 | ||
689 | // The shift masks must have the same position and size. | |
690 | if (SMPos0 != SMPos1 || SMSize0 != SMSize1) | |
691 | return SDValue(); | |
692 | ||
693 | SDValue Shl = And1.getOperand(0); | |
694 | if (Shl.getOpcode() != ISD::SHL) | |
695 | return SDValue(); | |
696 | ||
697 | if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1)))) | |
698 | return SDValue(); | |
699 | ||
700 | unsigned Shamt = CN->getZExtValue(); | |
701 | ||
702 | // Return if the shift amount and the first bit position of mask are not the | |
703 | // same. | |
704 | EVT ValTy = N->getValueType(0); | |
705 | if ((Shamt != SMPos0) || (SMPos0 + SMSize0 > ValTy.getSizeInBits())) | |
706 | return SDValue(); | |
707 | ||
1a4d82fc | 708 | return DAG.getNode(MipsISD::Ins, SDLoc(N), ValTy, Shl.getOperand(0), |
223e47cc LB |
709 | DAG.getConstant(SMPos0, MVT::i32), |
710 | DAG.getConstant(SMSize0, MVT::i32), And0.getOperand(0)); | |
711 | } | |
712 | ||
970d7e83 | 713 | static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, |
223e47cc | 714 | TargetLowering::DAGCombinerInfo &DCI, |
1a4d82fc | 715 | const MipsSubtarget &Subtarget) { |
223e47cc LB |
716 | // (add v0, (add v1, abs_lo(tjt))) => (add (add v0, v1), abs_lo(tjt)) |
717 | ||
718 | if (DCI.isBeforeLegalizeOps()) | |
719 | return SDValue(); | |
720 | ||
721 | SDValue Add = N->getOperand(1); | |
722 | ||
723 | if (Add.getOpcode() != ISD::ADD) | |
724 | return SDValue(); | |
725 | ||
726 | SDValue Lo = Add.getOperand(1); | |
727 | ||
728 | if ((Lo.getOpcode() != MipsISD::Lo) || | |
729 | (Lo.getOperand(0).getOpcode() != ISD::TargetJumpTable)) | |
730 | return SDValue(); | |
731 | ||
732 | EVT ValTy = N->getValueType(0); | |
1a4d82fc | 733 | SDLoc DL(N); |
223e47cc LB |
734 | |
735 | SDValue Add1 = DAG.getNode(ISD::ADD, DL, ValTy, N->getOperand(0), | |
736 | Add.getOperand(0)); | |
737 | return DAG.getNode(ISD::ADD, DL, ValTy, Add1, Lo); | |
738 | } | |
739 | ||
740 | SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) | |
741 | const { | |
742 | SelectionDAG &DAG = DCI.DAG; | |
970d7e83 | 743 | unsigned Opc = N->getOpcode(); |
223e47cc | 744 | |
970d7e83 | 745 | switch (Opc) { |
223e47cc | 746 | default: break; |
223e47cc LB |
747 | case ISD::SDIVREM: |
748 | case ISD::UDIVREM: | |
970d7e83 | 749 | return performDivRemCombine(N, DAG, DCI, Subtarget); |
223e47cc | 750 | case ISD::SELECT: |
970d7e83 | 751 | return performSELECTCombine(N, DAG, DCI, Subtarget); |
223e47cc | 752 | case ISD::AND: |
970d7e83 | 753 | return performANDCombine(N, DAG, DCI, Subtarget); |
223e47cc | 754 | case ISD::OR: |
970d7e83 | 755 | return performORCombine(N, DAG, DCI, Subtarget); |
223e47cc | 756 | case ISD::ADD: |
970d7e83 | 757 | return performADDCombine(N, DAG, DCI, Subtarget); |
223e47cc LB |
758 | } |
759 | ||
760 | return SDValue(); | |
761 | } | |
762 | ||
763 | void | |
764 | MipsTargetLowering::LowerOperationWrapper(SDNode *N, | |
765 | SmallVectorImpl<SDValue> &Results, | |
766 | SelectionDAG &DAG) const { | |
767 | SDValue Res = LowerOperation(SDValue(N, 0), DAG); | |
768 | ||
769 | for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I) | |
770 | Results.push_back(Res.getValue(I)); | |
771 | } | |
772 | ||
773 | void | |
774 | MipsTargetLowering::ReplaceNodeResults(SDNode *N, | |
775 | SmallVectorImpl<SDValue> &Results, | |
776 | SelectionDAG &DAG) const { | |
1a4d82fc | 777 | return LowerOperationWrapper(N, Results, DAG); |
223e47cc LB |
778 | } |
779 | ||
780 | SDValue MipsTargetLowering:: | |
781 | LowerOperation(SDValue Op, SelectionDAG &DAG) const | |
782 | { | |
783 | switch (Op.getOpcode()) | |
784 | { | |
1a4d82fc JJ |
785 | case ISD::BR_JT: return lowerBR_JT(Op, DAG); |
786 | case ISD::BRCOND: return lowerBRCOND(Op, DAG); | |
787 | case ISD::ConstantPool: return lowerConstantPool(Op, DAG); | |
788 | case ISD::GlobalAddress: return lowerGlobalAddress(Op, DAG); | |
789 | case ISD::BlockAddress: return lowerBlockAddress(Op, DAG); | |
790 | case ISD::GlobalTLSAddress: return lowerGlobalTLSAddress(Op, DAG); | |
791 | case ISD::JumpTable: return lowerJumpTable(Op, DAG); | |
792 | case ISD::SELECT: return lowerSELECT(Op, DAG); | |
793 | case ISD::SELECT_CC: return lowerSELECT_CC(Op, DAG); | |
794 | case ISD::SETCC: return lowerSETCC(Op, DAG); | |
795 | case ISD::VASTART: return lowerVASTART(Op, DAG); | |
796 | case ISD::VAARG: return lowerVAARG(Op, DAG); | |
797 | case ISD::FCOPYSIGN: return lowerFCOPYSIGN(Op, DAG); | |
798 | case ISD::FRAMEADDR: return lowerFRAMEADDR(Op, DAG); | |
799 | case ISD::RETURNADDR: return lowerRETURNADDR(Op, DAG); | |
800 | case ISD::EH_RETURN: return lowerEH_RETURN(Op, DAG); | |
801 | case ISD::ATOMIC_FENCE: return lowerATOMIC_FENCE(Op, DAG); | |
802 | case ISD::SHL_PARTS: return lowerShiftLeftParts(Op, DAG); | |
803 | case ISD::SRA_PARTS: return lowerShiftRightParts(Op, DAG, true); | |
804 | case ISD::SRL_PARTS: return lowerShiftRightParts(Op, DAG, false); | |
805 | case ISD::LOAD: return lowerLOAD(Op, DAG); | |
806 | case ISD::STORE: return lowerSTORE(Op, DAG); | |
807 | case ISD::ADD: return lowerADD(Op, DAG); | |
808 | case ISD::FP_TO_SINT: return lowerFP_TO_SINT(Op, DAG); | |
223e47cc LB |
809 | } |
810 | return SDValue(); | |
811 | } | |
812 | ||
813 | //===----------------------------------------------------------------------===// | |
814 | // Lower helper functions | |
815 | //===----------------------------------------------------------------------===// | |
816 | ||
970d7e83 | 817 | // addLiveIn - This helper function adds the specified physical register to the |
223e47cc LB |
818 | // MachineFunction as a live in value. It also creates a corresponding |
819 | // virtual register for it. | |
820 | static unsigned | |
970d7e83 | 821 | addLiveIn(MachineFunction &MF, unsigned PReg, const TargetRegisterClass *RC) |
223e47cc | 822 | { |
223e47cc LB |
823 | unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); |
824 | MF.getRegInfo().addLiveIn(PReg, VReg); | |
825 | return VReg; | |
826 | } | |
827 | ||
1a4d82fc JJ |
828 | static MachineBasicBlock *insertDivByZeroTrap(MachineInstr *MI, |
829 | MachineBasicBlock &MBB, | |
830 | const TargetInstrInfo &TII, | |
831 | bool Is64Bit) { | |
832 | if (NoZeroDivCheck) | |
833 | return &MBB; | |
223e47cc | 834 | |
1a4d82fc JJ |
835 | // Insert instruction "teq $divisor_reg, $zero, 7". |
836 | MachineBasicBlock::iterator I(MI); | |
837 | MachineInstrBuilder MIB; | |
838 | MachineOperand &Divisor = MI->getOperand(2); | |
839 | MIB = BuildMI(MBB, std::next(I), MI->getDebugLoc(), TII.get(Mips::TEQ)) | |
840 | .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill())) | |
841 | .addReg(Mips::ZERO).addImm(7); | |
842 | ||
843 | // Use the 32-bit sub-register if this is a 64-bit division. | |
844 | if (Is64Bit) | |
845 | MIB->getOperand(0).setSubReg(Mips::sub_32); | |
846 | ||
847 | // Clear Divisor's kill flag. | |
848 | Divisor.setIsKill(false); | |
849 | ||
850 | // We would normally delete the original instruction here but in this case | |
851 | // we only needed to inject an additional instruction rather than replace it. | |
223e47cc | 852 | |
1a4d82fc | 853 | return &MBB; |
223e47cc LB |
854 | } |
855 | ||
223e47cc LB |
856 | MachineBasicBlock * |
857 | MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, | |
858 | MachineBasicBlock *BB) const { | |
859 | switch (MI->getOpcode()) { | |
970d7e83 LB |
860 | default: |
861 | llvm_unreachable("Unexpected instr type to insert"); | |
223e47cc | 862 | case Mips::ATOMIC_LOAD_ADD_I8: |
970d7e83 | 863 | return emitAtomicBinaryPartword(MI, BB, 1, Mips::ADDu); |
223e47cc | 864 | case Mips::ATOMIC_LOAD_ADD_I16: |
970d7e83 | 865 | return emitAtomicBinaryPartword(MI, BB, 2, Mips::ADDu); |
223e47cc | 866 | case Mips::ATOMIC_LOAD_ADD_I32: |
970d7e83 | 867 | return emitAtomicBinary(MI, BB, 4, Mips::ADDu); |
223e47cc | 868 | case Mips::ATOMIC_LOAD_ADD_I64: |
970d7e83 | 869 | return emitAtomicBinary(MI, BB, 8, Mips::DADDu); |
223e47cc LB |
870 | |
871 | case Mips::ATOMIC_LOAD_AND_I8: | |
970d7e83 | 872 | return emitAtomicBinaryPartword(MI, BB, 1, Mips::AND); |
223e47cc | 873 | case Mips::ATOMIC_LOAD_AND_I16: |
970d7e83 | 874 | return emitAtomicBinaryPartword(MI, BB, 2, Mips::AND); |
223e47cc | 875 | case Mips::ATOMIC_LOAD_AND_I32: |
970d7e83 | 876 | return emitAtomicBinary(MI, BB, 4, Mips::AND); |
223e47cc | 877 | case Mips::ATOMIC_LOAD_AND_I64: |
970d7e83 | 878 | return emitAtomicBinary(MI, BB, 8, Mips::AND64); |
223e47cc LB |
879 | |
880 | case Mips::ATOMIC_LOAD_OR_I8: | |
970d7e83 | 881 | return emitAtomicBinaryPartword(MI, BB, 1, Mips::OR); |
223e47cc | 882 | case Mips::ATOMIC_LOAD_OR_I16: |
970d7e83 | 883 | return emitAtomicBinaryPartword(MI, BB, 2, Mips::OR); |
223e47cc | 884 | case Mips::ATOMIC_LOAD_OR_I32: |
970d7e83 | 885 | return emitAtomicBinary(MI, BB, 4, Mips::OR); |
223e47cc | 886 | case Mips::ATOMIC_LOAD_OR_I64: |
970d7e83 | 887 | return emitAtomicBinary(MI, BB, 8, Mips::OR64); |
223e47cc LB |
888 | |
889 | case Mips::ATOMIC_LOAD_XOR_I8: | |
970d7e83 | 890 | return emitAtomicBinaryPartword(MI, BB, 1, Mips::XOR); |
223e47cc | 891 | case Mips::ATOMIC_LOAD_XOR_I16: |
970d7e83 | 892 | return emitAtomicBinaryPartword(MI, BB, 2, Mips::XOR); |
223e47cc | 893 | case Mips::ATOMIC_LOAD_XOR_I32: |
970d7e83 | 894 | return emitAtomicBinary(MI, BB, 4, Mips::XOR); |
223e47cc | 895 | case Mips::ATOMIC_LOAD_XOR_I64: |
970d7e83 | 896 | return emitAtomicBinary(MI, BB, 8, Mips::XOR64); |
223e47cc LB |
897 | |
898 | case Mips::ATOMIC_LOAD_NAND_I8: | |
970d7e83 | 899 | return emitAtomicBinaryPartword(MI, BB, 1, 0, true); |
223e47cc | 900 | case Mips::ATOMIC_LOAD_NAND_I16: |
970d7e83 | 901 | return emitAtomicBinaryPartword(MI, BB, 2, 0, true); |
223e47cc | 902 | case Mips::ATOMIC_LOAD_NAND_I32: |
970d7e83 | 903 | return emitAtomicBinary(MI, BB, 4, 0, true); |
223e47cc | 904 | case Mips::ATOMIC_LOAD_NAND_I64: |
970d7e83 | 905 | return emitAtomicBinary(MI, BB, 8, 0, true); |
223e47cc LB |
906 | |
907 | case Mips::ATOMIC_LOAD_SUB_I8: | |
970d7e83 | 908 | return emitAtomicBinaryPartword(MI, BB, 1, Mips::SUBu); |
223e47cc | 909 | case Mips::ATOMIC_LOAD_SUB_I16: |
970d7e83 | 910 | return emitAtomicBinaryPartword(MI, BB, 2, Mips::SUBu); |
223e47cc | 911 | case Mips::ATOMIC_LOAD_SUB_I32: |
970d7e83 | 912 | return emitAtomicBinary(MI, BB, 4, Mips::SUBu); |
223e47cc | 913 | case Mips::ATOMIC_LOAD_SUB_I64: |
970d7e83 | 914 | return emitAtomicBinary(MI, BB, 8, Mips::DSUBu); |
223e47cc LB |
915 | |
916 | case Mips::ATOMIC_SWAP_I8: | |
970d7e83 | 917 | return emitAtomicBinaryPartword(MI, BB, 1, 0); |
223e47cc | 918 | case Mips::ATOMIC_SWAP_I16: |
970d7e83 | 919 | return emitAtomicBinaryPartword(MI, BB, 2, 0); |
223e47cc | 920 | case Mips::ATOMIC_SWAP_I32: |
970d7e83 | 921 | return emitAtomicBinary(MI, BB, 4, 0); |
223e47cc | 922 | case Mips::ATOMIC_SWAP_I64: |
970d7e83 | 923 | return emitAtomicBinary(MI, BB, 8, 0); |
223e47cc LB |
924 | |
925 | case Mips::ATOMIC_CMP_SWAP_I8: | |
970d7e83 | 926 | return emitAtomicCmpSwapPartword(MI, BB, 1); |
223e47cc | 927 | case Mips::ATOMIC_CMP_SWAP_I16: |
970d7e83 | 928 | return emitAtomicCmpSwapPartword(MI, BB, 2); |
223e47cc | 929 | case Mips::ATOMIC_CMP_SWAP_I32: |
970d7e83 | 930 | return emitAtomicCmpSwap(MI, BB, 4); |
223e47cc | 931 | case Mips::ATOMIC_CMP_SWAP_I64: |
970d7e83 | 932 | return emitAtomicCmpSwap(MI, BB, 8); |
1a4d82fc JJ |
933 | case Mips::PseudoSDIV: |
934 | case Mips::PseudoUDIV: | |
935 | case Mips::DIV: | |
936 | case Mips::DIVU: | |
937 | case Mips::MOD: | |
938 | case Mips::MODU: | |
939 | return insertDivByZeroTrap( | |
940 | MI, *BB, *getTargetMachine().getSubtargetImpl()->getInstrInfo(), false); | |
941 | case Mips::PseudoDSDIV: | |
942 | case Mips::PseudoDUDIV: | |
943 | case Mips::DDIV: | |
944 | case Mips::DDIVU: | |
945 | case Mips::DMOD: | |
946 | case Mips::DMODU: | |
947 | return insertDivByZeroTrap( | |
948 | MI, *BB, *getTargetMachine().getSubtargetImpl()->getInstrInfo(), true); | |
949 | case Mips::SEL_D: | |
950 | return emitSEL_D(MI, BB); | |
85aaf69f SL |
951 | |
952 | case Mips::PseudoSELECT_I: | |
953 | case Mips::PseudoSELECT_I64: | |
954 | case Mips::PseudoSELECT_S: | |
955 | case Mips::PseudoSELECT_D32: | |
956 | case Mips::PseudoSELECT_D64: | |
957 | return emitPseudoSELECT(MI, BB, false, Mips::BNE); | |
958 | case Mips::PseudoSELECTFP_F_I: | |
959 | case Mips::PseudoSELECTFP_F_I64: | |
960 | case Mips::PseudoSELECTFP_F_S: | |
961 | case Mips::PseudoSELECTFP_F_D32: | |
962 | case Mips::PseudoSELECTFP_F_D64: | |
963 | return emitPseudoSELECT(MI, BB, true, Mips::BC1F); | |
964 | case Mips::PseudoSELECTFP_T_I: | |
965 | case Mips::PseudoSELECTFP_T_I64: | |
966 | case Mips::PseudoSELECTFP_T_S: | |
967 | case Mips::PseudoSELECTFP_T_D32: | |
968 | case Mips::PseudoSELECTFP_T_D64: | |
969 | return emitPseudoSELECT(MI, BB, true, Mips::BC1T); | |
223e47cc LB |
970 | } |
971 | } | |
972 | ||
973 | // This function also handles Mips::ATOMIC_SWAP_I32 (when BinOpcode == 0), and | |
974 | // Mips::ATOMIC_LOAD_NAND_I32 (when Nand == true) | |
975 | MachineBasicBlock * | |
970d7e83 | 976 | MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, |
223e47cc LB |
977 | unsigned Size, unsigned BinOpcode, |
978 | bool Nand) const { | |
979 | assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicBinary."); | |
980 | ||
981 | MachineFunction *MF = BB->getParent(); | |
982 | MachineRegisterInfo &RegInfo = MF->getRegInfo(); | |
983 | const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); | |
1a4d82fc JJ |
984 | const TargetInstrInfo *TII = |
985 | getTargetMachine().getSubtargetImpl()->getInstrInfo(); | |
970d7e83 | 986 | DebugLoc DL = MI->getDebugLoc(); |
223e47cc LB |
987 | unsigned LL, SC, AND, NOR, ZERO, BEQ; |
988 | ||
989 | if (Size == 4) { | |
1a4d82fc JJ |
990 | if (isMicroMips) { |
991 | LL = Mips::LL_MM; | |
992 | SC = Mips::SC_MM; | |
993 | } else { | |
994 | LL = Subtarget.hasMips32r6() ? Mips::LL_R6 : Mips::LL; | |
995 | SC = Subtarget.hasMips32r6() ? Mips::SC_R6 : Mips::SC; | |
996 | } | |
223e47cc LB |
997 | AND = Mips::AND; |
998 | NOR = Mips::NOR; | |
999 | ZERO = Mips::ZERO; | |
1000 | BEQ = Mips::BEQ; | |
1a4d82fc JJ |
1001 | } else { |
1002 | LL = Subtarget.hasMips64r6() ? Mips::LLD_R6 : Mips::LLD; | |
1003 | SC = Subtarget.hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; | |
223e47cc LB |
1004 | AND = Mips::AND64; |
1005 | NOR = Mips::NOR64; | |
1006 | ZERO = Mips::ZERO_64; | |
1007 | BEQ = Mips::BEQ64; | |
1008 | } | |
1009 | ||
1010 | unsigned OldVal = MI->getOperand(0).getReg(); | |
1011 | unsigned Ptr = MI->getOperand(1).getReg(); | |
1012 | unsigned Incr = MI->getOperand(2).getReg(); | |
1013 | ||
1014 | unsigned StoreVal = RegInfo.createVirtualRegister(RC); | |
1015 | unsigned AndRes = RegInfo.createVirtualRegister(RC); | |
1016 | unsigned Success = RegInfo.createVirtualRegister(RC); | |
1017 | ||
1018 | // insert new blocks after the current block | |
1019 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | |
1020 | MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1021 | MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1022 | MachineFunction::iterator It = BB; | |
1023 | ++It; | |
1024 | MF->insert(It, loopMBB); | |
1025 | MF->insert(It, exitMBB); | |
1026 | ||
1027 | // Transfer the remainder of BB and its successor edges to exitMBB. | |
1028 | exitMBB->splice(exitMBB->begin(), BB, | |
1a4d82fc | 1029 | std::next(MachineBasicBlock::iterator(MI)), BB->end()); |
223e47cc LB |
1030 | exitMBB->transferSuccessorsAndUpdatePHIs(BB); |
1031 | ||
1032 | // thisMBB: | |
1033 | // ... | |
1034 | // fallthrough --> loopMBB | |
1035 | BB->addSuccessor(loopMBB); | |
1036 | loopMBB->addSuccessor(loopMBB); | |
1037 | loopMBB->addSuccessor(exitMBB); | |
1038 | ||
1039 | // loopMBB: | |
1040 | // ll oldval, 0(ptr) | |
1041 | // <binop> storeval, oldval, incr | |
1042 | // sc success, storeval, 0(ptr) | |
1043 | // beq success, $0, loopMBB | |
1044 | BB = loopMBB; | |
970d7e83 | 1045 | BuildMI(BB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); |
223e47cc LB |
1046 | if (Nand) { |
1047 | // and andres, oldval, incr | |
1048 | // nor storeval, $0, andres | |
970d7e83 LB |
1049 | BuildMI(BB, DL, TII->get(AND), AndRes).addReg(OldVal).addReg(Incr); |
1050 | BuildMI(BB, DL, TII->get(NOR), StoreVal).addReg(ZERO).addReg(AndRes); | |
223e47cc LB |
1051 | } else if (BinOpcode) { |
1052 | // <binop> storeval, oldval, incr | |
970d7e83 | 1053 | BuildMI(BB, DL, TII->get(BinOpcode), StoreVal).addReg(OldVal).addReg(Incr); |
223e47cc LB |
1054 | } else { |
1055 | StoreVal = Incr; | |
1056 | } | |
970d7e83 LB |
1057 | BuildMI(BB, DL, TII->get(SC), Success).addReg(StoreVal).addReg(Ptr).addImm(0); |
1058 | BuildMI(BB, DL, TII->get(BEQ)).addReg(Success).addReg(ZERO).addMBB(loopMBB); | |
223e47cc | 1059 | |
1a4d82fc | 1060 | MI->eraseFromParent(); // The instruction is gone now. |
223e47cc LB |
1061 | |
1062 | return exitMBB; | |
1063 | } | |
1064 | ||
1a4d82fc JJ |
1065 | MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( |
1066 | MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, | |
1067 | unsigned SrcReg) const { | |
1068 | const TargetInstrInfo *TII = | |
1069 | getTargetMachine().getSubtargetImpl()->getInstrInfo(); | |
1070 | DebugLoc DL = MI->getDebugLoc(); | |
1071 | ||
1072 | if (Subtarget.hasMips32r2() && Size == 1) { | |
1073 | BuildMI(BB, DL, TII->get(Mips::SEB), DstReg).addReg(SrcReg); | |
1074 | return BB; | |
1075 | } | |
1076 | ||
1077 | if (Subtarget.hasMips32r2() && Size == 2) { | |
1078 | BuildMI(BB, DL, TII->get(Mips::SEH), DstReg).addReg(SrcReg); | |
1079 | return BB; | |
1080 | } | |
1081 | ||
1082 | MachineFunction *MF = BB->getParent(); | |
1083 | MachineRegisterInfo &RegInfo = MF->getRegInfo(); | |
1084 | const TargetRegisterClass *RC = getRegClassFor(MVT::i32); | |
1085 | unsigned ScrReg = RegInfo.createVirtualRegister(RC); | |
1086 | ||
1087 | assert(Size < 32); | |
1088 | int64_t ShiftImm = 32 - (Size * 8); | |
1089 | ||
1090 | BuildMI(BB, DL, TII->get(Mips::SLL), ScrReg).addReg(SrcReg).addImm(ShiftImm); | |
1091 | BuildMI(BB, DL, TII->get(Mips::SRA), DstReg).addReg(ScrReg).addImm(ShiftImm); | |
1092 | ||
1093 | return BB; | |
1094 | } | |
1095 | ||
1096 | MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( | |
1097 | MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode, | |
1098 | bool Nand) const { | |
223e47cc | 1099 | assert((Size == 1 || Size == 2) && |
1a4d82fc | 1100 | "Unsupported size for EmitAtomicBinaryPartial."); |
223e47cc LB |
1101 | |
1102 | MachineFunction *MF = BB->getParent(); | |
1103 | MachineRegisterInfo &RegInfo = MF->getRegInfo(); | |
1104 | const TargetRegisterClass *RC = getRegClassFor(MVT::i32); | |
1a4d82fc JJ |
1105 | const TargetInstrInfo *TII = |
1106 | getTargetMachine().getSubtargetImpl()->getInstrInfo(); | |
970d7e83 | 1107 | DebugLoc DL = MI->getDebugLoc(); |
223e47cc LB |
1108 | |
1109 | unsigned Dest = MI->getOperand(0).getReg(); | |
1110 | unsigned Ptr = MI->getOperand(1).getReg(); | |
1111 | unsigned Incr = MI->getOperand(2).getReg(); | |
1112 | ||
1113 | unsigned AlignedAddr = RegInfo.createVirtualRegister(RC); | |
1114 | unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); | |
1115 | unsigned Mask = RegInfo.createVirtualRegister(RC); | |
1116 | unsigned Mask2 = RegInfo.createVirtualRegister(RC); | |
1117 | unsigned NewVal = RegInfo.createVirtualRegister(RC); | |
1118 | unsigned OldVal = RegInfo.createVirtualRegister(RC); | |
1119 | unsigned Incr2 = RegInfo.createVirtualRegister(RC); | |
1120 | unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC); | |
1121 | unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); | |
1122 | unsigned MaskUpper = RegInfo.createVirtualRegister(RC); | |
1123 | unsigned AndRes = RegInfo.createVirtualRegister(RC); | |
1124 | unsigned BinOpRes = RegInfo.createVirtualRegister(RC); | |
1125 | unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC); | |
1126 | unsigned StoreVal = RegInfo.createVirtualRegister(RC); | |
1127 | unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC); | |
1128 | unsigned SrlRes = RegInfo.createVirtualRegister(RC); | |
223e47cc LB |
1129 | unsigned Success = RegInfo.createVirtualRegister(RC); |
1130 | ||
1131 | // insert new blocks after the current block | |
1132 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | |
1133 | MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1134 | MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1135 | MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1136 | MachineFunction::iterator It = BB; | |
1137 | ++It; | |
1138 | MF->insert(It, loopMBB); | |
1139 | MF->insert(It, sinkMBB); | |
1140 | MF->insert(It, exitMBB); | |
1141 | ||
1142 | // Transfer the remainder of BB and its successor edges to exitMBB. | |
1143 | exitMBB->splice(exitMBB->begin(), BB, | |
1a4d82fc | 1144 | std::next(MachineBasicBlock::iterator(MI)), BB->end()); |
223e47cc LB |
1145 | exitMBB->transferSuccessorsAndUpdatePHIs(BB); |
1146 | ||
1147 | BB->addSuccessor(loopMBB); | |
1148 | loopMBB->addSuccessor(loopMBB); | |
1149 | loopMBB->addSuccessor(sinkMBB); | |
1150 | sinkMBB->addSuccessor(exitMBB); | |
1151 | ||
1152 | // thisMBB: | |
1153 | // addiu masklsb2,$0,-4 # 0xfffffffc | |
1154 | // and alignedaddr,ptr,masklsb2 | |
1155 | // andi ptrlsb2,ptr,3 | |
1156 | // sll shiftamt,ptrlsb2,3 | |
1157 | // ori maskupper,$0,255 # 0xff | |
1158 | // sll mask,maskupper,shiftamt | |
1159 | // nor mask2,$0,mask | |
1160 | // sll incr2,incr,shiftamt | |
1161 | ||
1162 | int64_t MaskImm = (Size == 1) ? 255 : 65535; | |
970d7e83 | 1163 | BuildMI(BB, DL, TII->get(Mips::ADDiu), MaskLSB2) |
223e47cc | 1164 | .addReg(Mips::ZERO).addImm(-4); |
970d7e83 | 1165 | BuildMI(BB, DL, TII->get(Mips::AND), AlignedAddr) |
223e47cc | 1166 | .addReg(Ptr).addReg(MaskLSB2); |
970d7e83 | 1167 | BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3); |
1a4d82fc JJ |
1168 | if (Subtarget.isLittle()) { |
1169 | BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3); | |
1170 | } else { | |
1171 | unsigned Off = RegInfo.createVirtualRegister(RC); | |
1172 | BuildMI(BB, DL, TII->get(Mips::XORi), Off) | |
1173 | .addReg(PtrLSB2).addImm((Size == 1) ? 3 : 2); | |
1174 | BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(Off).addImm(3); | |
1175 | } | |
970d7e83 | 1176 | BuildMI(BB, DL, TII->get(Mips::ORi), MaskUpper) |
223e47cc | 1177 | .addReg(Mips::ZERO).addImm(MaskImm); |
970d7e83 | 1178 | BuildMI(BB, DL, TII->get(Mips::SLLV), Mask) |
1a4d82fc | 1179 | .addReg(MaskUpper).addReg(ShiftAmt); |
970d7e83 | 1180 | BuildMI(BB, DL, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask); |
1a4d82fc | 1181 | BuildMI(BB, DL, TII->get(Mips::SLLV), Incr2).addReg(Incr).addReg(ShiftAmt); |
223e47cc LB |
1182 | |
1183 | // atomic.load.binop | |
1184 | // loopMBB: | |
1185 | // ll oldval,0(alignedaddr) | |
1186 | // binop binopres,oldval,incr2 | |
1187 | // and newval,binopres,mask | |
1188 | // and maskedoldval0,oldval,mask2 | |
1189 | // or storeval,maskedoldval0,newval | |
1190 | // sc success,storeval,0(alignedaddr) | |
1191 | // beq success,$0,loopMBB | |
1192 | ||
1193 | // atomic.swap | |
1194 | // loopMBB: | |
1195 | // ll oldval,0(alignedaddr) | |
1196 | // and newval,incr2,mask | |
1197 | // and maskedoldval0,oldval,mask2 | |
1198 | // or storeval,maskedoldval0,newval | |
1199 | // sc success,storeval,0(alignedaddr) | |
1200 | // beq success,$0,loopMBB | |
1201 | ||
1202 | BB = loopMBB; | |
85aaf69f SL |
1203 | unsigned LL = isMicroMips ? Mips::LL_MM : Mips::LL; |
1204 | BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); | |
223e47cc LB |
1205 | if (Nand) { |
1206 | // and andres, oldval, incr2 | |
1207 | // nor binopres, $0, andres | |
1208 | // and newval, binopres, mask | |
970d7e83 LB |
1209 | BuildMI(BB, DL, TII->get(Mips::AND), AndRes).addReg(OldVal).addReg(Incr2); |
1210 | BuildMI(BB, DL, TII->get(Mips::NOR), BinOpRes) | |
223e47cc | 1211 | .addReg(Mips::ZERO).addReg(AndRes); |
970d7e83 | 1212 | BuildMI(BB, DL, TII->get(Mips::AND), NewVal).addReg(BinOpRes).addReg(Mask); |
223e47cc LB |
1213 | } else if (BinOpcode) { |
1214 | // <binop> binopres, oldval, incr2 | |
1215 | // and newval, binopres, mask | |
970d7e83 LB |
1216 | BuildMI(BB, DL, TII->get(BinOpcode), BinOpRes).addReg(OldVal).addReg(Incr2); |
1217 | BuildMI(BB, DL, TII->get(Mips::AND), NewVal).addReg(BinOpRes).addReg(Mask); | |
1a4d82fc | 1218 | } else { // atomic.swap |
223e47cc | 1219 | // and newval, incr2, mask |
970d7e83 | 1220 | BuildMI(BB, DL, TII->get(Mips::AND), NewVal).addReg(Incr2).addReg(Mask); |
223e47cc LB |
1221 | } |
1222 | ||
970d7e83 | 1223 | BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal0) |
223e47cc | 1224 | .addReg(OldVal).addReg(Mask2); |
970d7e83 | 1225 | BuildMI(BB, DL, TII->get(Mips::OR), StoreVal) |
223e47cc | 1226 | .addReg(MaskedOldVal0).addReg(NewVal); |
85aaf69f SL |
1227 | unsigned SC = isMicroMips ? Mips::SC_MM : Mips::SC; |
1228 | BuildMI(BB, DL, TII->get(SC), Success) | |
223e47cc | 1229 | .addReg(StoreVal).addReg(AlignedAddr).addImm(0); |
970d7e83 | 1230 | BuildMI(BB, DL, TII->get(Mips::BEQ)) |
223e47cc LB |
1231 | .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB); |
1232 | ||
1233 | // sinkMBB: | |
1234 | // and maskedoldval1,oldval,mask | |
1235 | // srl srlres,maskedoldval1,shiftamt | |
1a4d82fc | 1236 | // sign_extend dest,srlres |
223e47cc | 1237 | BB = sinkMBB; |
223e47cc | 1238 | |
970d7e83 | 1239 | BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal1) |
223e47cc | 1240 | .addReg(OldVal).addReg(Mask); |
970d7e83 | 1241 | BuildMI(BB, DL, TII->get(Mips::SRLV), SrlRes) |
1a4d82fc JJ |
1242 | .addReg(MaskedOldVal1).addReg(ShiftAmt); |
1243 | BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes); | |
223e47cc | 1244 | |
1a4d82fc | 1245 | MI->eraseFromParent(); // The instruction is gone now. |
223e47cc LB |
1246 | |
1247 | return exitMBB; | |
1248 | } | |
1249 | ||
1a4d82fc JJ |
1250 | MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI, |
1251 | MachineBasicBlock *BB, | |
1252 | unsigned Size) const { | |
223e47cc LB |
1253 | assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicCmpSwap."); |
1254 | ||
1255 | MachineFunction *MF = BB->getParent(); | |
1256 | MachineRegisterInfo &RegInfo = MF->getRegInfo(); | |
1257 | const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); | |
1a4d82fc JJ |
1258 | const TargetInstrInfo *TII = |
1259 | getTargetMachine().getSubtargetImpl()->getInstrInfo(); | |
970d7e83 | 1260 | DebugLoc DL = MI->getDebugLoc(); |
223e47cc LB |
1261 | unsigned LL, SC, ZERO, BNE, BEQ; |
1262 | ||
1263 | if (Size == 4) { | |
1a4d82fc JJ |
1264 | LL = isMicroMips ? Mips::LL_MM : Mips::LL; |
1265 | SC = isMicroMips ? Mips::SC_MM : Mips::SC; | |
223e47cc LB |
1266 | ZERO = Mips::ZERO; |
1267 | BNE = Mips::BNE; | |
1268 | BEQ = Mips::BEQ; | |
1a4d82fc JJ |
1269 | } else { |
1270 | LL = Mips::LLD; | |
1271 | SC = Mips::SCD; | |
223e47cc LB |
1272 | ZERO = Mips::ZERO_64; |
1273 | BNE = Mips::BNE64; | |
1274 | BEQ = Mips::BEQ64; | |
1275 | } | |
1276 | ||
1277 | unsigned Dest = MI->getOperand(0).getReg(); | |
1278 | unsigned Ptr = MI->getOperand(1).getReg(); | |
1279 | unsigned OldVal = MI->getOperand(2).getReg(); | |
1280 | unsigned NewVal = MI->getOperand(3).getReg(); | |
1281 | ||
1282 | unsigned Success = RegInfo.createVirtualRegister(RC); | |
1283 | ||
1284 | // insert new blocks after the current block | |
1285 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | |
1286 | MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1287 | MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1288 | MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1289 | MachineFunction::iterator It = BB; | |
1290 | ++It; | |
1291 | MF->insert(It, loop1MBB); | |
1292 | MF->insert(It, loop2MBB); | |
1293 | MF->insert(It, exitMBB); | |
1294 | ||
1295 | // Transfer the remainder of BB and its successor edges to exitMBB. | |
1296 | exitMBB->splice(exitMBB->begin(), BB, | |
1a4d82fc | 1297 | std::next(MachineBasicBlock::iterator(MI)), BB->end()); |
223e47cc LB |
1298 | exitMBB->transferSuccessorsAndUpdatePHIs(BB); |
1299 | ||
1300 | // thisMBB: | |
1301 | // ... | |
1302 | // fallthrough --> loop1MBB | |
1303 | BB->addSuccessor(loop1MBB); | |
1304 | loop1MBB->addSuccessor(exitMBB); | |
1305 | loop1MBB->addSuccessor(loop2MBB); | |
1306 | loop2MBB->addSuccessor(loop1MBB); | |
1307 | loop2MBB->addSuccessor(exitMBB); | |
1308 | ||
1309 | // loop1MBB: | |
1310 | // ll dest, 0(ptr) | |
1311 | // bne dest, oldval, exitMBB | |
1312 | BB = loop1MBB; | |
970d7e83 LB |
1313 | BuildMI(BB, DL, TII->get(LL), Dest).addReg(Ptr).addImm(0); |
1314 | BuildMI(BB, DL, TII->get(BNE)) | |
223e47cc LB |
1315 | .addReg(Dest).addReg(OldVal).addMBB(exitMBB); |
1316 | ||
1317 | // loop2MBB: | |
1318 | // sc success, newval, 0(ptr) | |
1319 | // beq success, $0, loop1MBB | |
1320 | BB = loop2MBB; | |
970d7e83 | 1321 | BuildMI(BB, DL, TII->get(SC), Success) |
223e47cc | 1322 | .addReg(NewVal).addReg(Ptr).addImm(0); |
970d7e83 | 1323 | BuildMI(BB, DL, TII->get(BEQ)) |
223e47cc LB |
1324 | .addReg(Success).addReg(ZERO).addMBB(loop1MBB); |
1325 | ||
1a4d82fc | 1326 | MI->eraseFromParent(); // The instruction is gone now. |
223e47cc LB |
1327 | |
1328 | return exitMBB; | |
1329 | } | |
1330 | ||
1331 | MachineBasicBlock * | |
970d7e83 | 1332 | MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, |
223e47cc LB |
1333 | MachineBasicBlock *BB, |
1334 | unsigned Size) const { | |
1335 | assert((Size == 1 || Size == 2) && | |
1336 | "Unsupported size for EmitAtomicCmpSwapPartial."); | |
1337 | ||
1338 | MachineFunction *MF = BB->getParent(); | |
1339 | MachineRegisterInfo &RegInfo = MF->getRegInfo(); | |
1340 | const TargetRegisterClass *RC = getRegClassFor(MVT::i32); | |
1a4d82fc JJ |
1341 | const TargetInstrInfo *TII = |
1342 | getTargetMachine().getSubtargetImpl()->getInstrInfo(); | |
970d7e83 | 1343 | DebugLoc DL = MI->getDebugLoc(); |
223e47cc LB |
1344 | |
1345 | unsigned Dest = MI->getOperand(0).getReg(); | |
1346 | unsigned Ptr = MI->getOperand(1).getReg(); | |
1347 | unsigned CmpVal = MI->getOperand(2).getReg(); | |
1348 | unsigned NewVal = MI->getOperand(3).getReg(); | |
1349 | ||
1350 | unsigned AlignedAddr = RegInfo.createVirtualRegister(RC); | |
1351 | unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); | |
1352 | unsigned Mask = RegInfo.createVirtualRegister(RC); | |
1353 | unsigned Mask2 = RegInfo.createVirtualRegister(RC); | |
1354 | unsigned ShiftedCmpVal = RegInfo.createVirtualRegister(RC); | |
1355 | unsigned OldVal = RegInfo.createVirtualRegister(RC); | |
1356 | unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC); | |
1357 | unsigned ShiftedNewVal = RegInfo.createVirtualRegister(RC); | |
1358 | unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC); | |
1359 | unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); | |
1360 | unsigned MaskUpper = RegInfo.createVirtualRegister(RC); | |
1361 | unsigned MaskedCmpVal = RegInfo.createVirtualRegister(RC); | |
1362 | unsigned MaskedNewVal = RegInfo.createVirtualRegister(RC); | |
1363 | unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC); | |
1364 | unsigned StoreVal = RegInfo.createVirtualRegister(RC); | |
1365 | unsigned SrlRes = RegInfo.createVirtualRegister(RC); | |
223e47cc LB |
1366 | unsigned Success = RegInfo.createVirtualRegister(RC); |
1367 | ||
1368 | // insert new blocks after the current block | |
1369 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | |
1370 | MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1371 | MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1372 | MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1373 | MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); | |
1374 | MachineFunction::iterator It = BB; | |
1375 | ++It; | |
1376 | MF->insert(It, loop1MBB); | |
1377 | MF->insert(It, loop2MBB); | |
1378 | MF->insert(It, sinkMBB); | |
1379 | MF->insert(It, exitMBB); | |
1380 | ||
1381 | // Transfer the remainder of BB and its successor edges to exitMBB. | |
1382 | exitMBB->splice(exitMBB->begin(), BB, | |
1a4d82fc | 1383 | std::next(MachineBasicBlock::iterator(MI)), BB->end()); |
223e47cc LB |
1384 | exitMBB->transferSuccessorsAndUpdatePHIs(BB); |
1385 | ||
1386 | BB->addSuccessor(loop1MBB); | |
1387 | loop1MBB->addSuccessor(sinkMBB); | |
1388 | loop1MBB->addSuccessor(loop2MBB); | |
1389 | loop2MBB->addSuccessor(loop1MBB); | |
1390 | loop2MBB->addSuccessor(sinkMBB); | |
1391 | sinkMBB->addSuccessor(exitMBB); | |
1392 | ||
1393 | // FIXME: computation of newval2 can be moved to loop2MBB. | |
1394 | // thisMBB: | |
1395 | // addiu masklsb2,$0,-4 # 0xfffffffc | |
1396 | // and alignedaddr,ptr,masklsb2 | |
1397 | // andi ptrlsb2,ptr,3 | |
1398 | // sll shiftamt,ptrlsb2,3 | |
1399 | // ori maskupper,$0,255 # 0xff | |
1400 | // sll mask,maskupper,shiftamt | |
1401 | // nor mask2,$0,mask | |
1402 | // andi maskedcmpval,cmpval,255 | |
1403 | // sll shiftedcmpval,maskedcmpval,shiftamt | |
1404 | // andi maskednewval,newval,255 | |
1405 | // sll shiftednewval,maskednewval,shiftamt | |
1406 | int64_t MaskImm = (Size == 1) ? 255 : 65535; | |
970d7e83 | 1407 | BuildMI(BB, DL, TII->get(Mips::ADDiu), MaskLSB2) |
223e47cc | 1408 | .addReg(Mips::ZERO).addImm(-4); |
970d7e83 | 1409 | BuildMI(BB, DL, TII->get(Mips::AND), AlignedAddr) |
223e47cc | 1410 | .addReg(Ptr).addReg(MaskLSB2); |
970d7e83 | 1411 | BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3); |
1a4d82fc JJ |
1412 | if (Subtarget.isLittle()) { |
1413 | BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3); | |
1414 | } else { | |
1415 | unsigned Off = RegInfo.createVirtualRegister(RC); | |
1416 | BuildMI(BB, DL, TII->get(Mips::XORi), Off) | |
1417 | .addReg(PtrLSB2).addImm((Size == 1) ? 3 : 2); | |
1418 | BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(Off).addImm(3); | |
1419 | } | |
970d7e83 | 1420 | BuildMI(BB, DL, TII->get(Mips::ORi), MaskUpper) |
223e47cc | 1421 | .addReg(Mips::ZERO).addImm(MaskImm); |
970d7e83 | 1422 | BuildMI(BB, DL, TII->get(Mips::SLLV), Mask) |
1a4d82fc | 1423 | .addReg(MaskUpper).addReg(ShiftAmt); |
970d7e83 LB |
1424 | BuildMI(BB, DL, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask); |
1425 | BuildMI(BB, DL, TII->get(Mips::ANDi), MaskedCmpVal) | |
223e47cc | 1426 | .addReg(CmpVal).addImm(MaskImm); |
970d7e83 | 1427 | BuildMI(BB, DL, TII->get(Mips::SLLV), ShiftedCmpVal) |
1a4d82fc | 1428 | .addReg(MaskedCmpVal).addReg(ShiftAmt); |
970d7e83 | 1429 | BuildMI(BB, DL, TII->get(Mips::ANDi), MaskedNewVal) |
223e47cc | 1430 | .addReg(NewVal).addImm(MaskImm); |
970d7e83 | 1431 | BuildMI(BB, DL, TII->get(Mips::SLLV), ShiftedNewVal) |
1a4d82fc | 1432 | .addReg(MaskedNewVal).addReg(ShiftAmt); |
223e47cc LB |
1433 | |
1434 | // loop1MBB: | |
1435 | // ll oldval,0(alginedaddr) | |
1436 | // and maskedoldval0,oldval,mask | |
1437 | // bne maskedoldval0,shiftedcmpval,sinkMBB | |
1438 | BB = loop1MBB; | |
85aaf69f SL |
1439 | unsigned LL = isMicroMips ? Mips::LL_MM : Mips::LL; |
1440 | BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); | |
970d7e83 | 1441 | BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal0) |
223e47cc | 1442 | .addReg(OldVal).addReg(Mask); |
970d7e83 | 1443 | BuildMI(BB, DL, TII->get(Mips::BNE)) |
223e47cc LB |
1444 | .addReg(MaskedOldVal0).addReg(ShiftedCmpVal).addMBB(sinkMBB); |
1445 | ||
1446 | // loop2MBB: | |
1447 | // and maskedoldval1,oldval,mask2 | |
1448 | // or storeval,maskedoldval1,shiftednewval | |
1449 | // sc success,storeval,0(alignedaddr) | |
1450 | // beq success,$0,loop1MBB | |
1451 | BB = loop2MBB; | |
970d7e83 | 1452 | BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal1) |
223e47cc | 1453 | .addReg(OldVal).addReg(Mask2); |
970d7e83 | 1454 | BuildMI(BB, DL, TII->get(Mips::OR), StoreVal) |
223e47cc | 1455 | .addReg(MaskedOldVal1).addReg(ShiftedNewVal); |
85aaf69f SL |
1456 | unsigned SC = isMicroMips ? Mips::SC_MM : Mips::SC; |
1457 | BuildMI(BB, DL, TII->get(SC), Success) | |
223e47cc | 1458 | .addReg(StoreVal).addReg(AlignedAddr).addImm(0); |
970d7e83 | 1459 | BuildMI(BB, DL, TII->get(Mips::BEQ)) |
223e47cc LB |
1460 | .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB); |
1461 | ||
1462 | // sinkMBB: | |
1463 | // srl srlres,maskedoldval0,shiftamt | |
1a4d82fc | 1464 | // sign_extend dest,srlres |
223e47cc | 1465 | BB = sinkMBB; |
223e47cc | 1466 | |
970d7e83 | 1467 | BuildMI(BB, DL, TII->get(Mips::SRLV), SrlRes) |
1a4d82fc JJ |
1468 | .addReg(MaskedOldVal0).addReg(ShiftAmt); |
1469 | BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes); | |
223e47cc LB |
1470 | |
1471 | MI->eraseFromParent(); // The instruction is gone now. | |
1472 | ||
1473 | return exitMBB; | |
1474 | } | |
1475 | ||
1a4d82fc JJ |
1476 | MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr *MI, |
1477 | MachineBasicBlock *BB) const { | |
1478 | MachineFunction *MF = BB->getParent(); | |
1479 | const TargetRegisterInfo *TRI = | |
1480 | getTargetMachine().getSubtargetImpl()->getRegisterInfo(); | |
1481 | const TargetInstrInfo *TII = | |
1482 | getTargetMachine().getSubtargetImpl()->getInstrInfo(); | |
1483 | MachineRegisterInfo &RegInfo = MF->getRegInfo(); | |
1484 | DebugLoc DL = MI->getDebugLoc(); | |
1485 | MachineBasicBlock::iterator II(MI); | |
1486 | ||
1487 | unsigned Fc = MI->getOperand(1).getReg(); | |
1488 | const auto &FGR64RegClass = TRI->getRegClass(Mips::FGR64RegClassID); | |
1489 | ||
1490 | unsigned Fc2 = RegInfo.createVirtualRegister(FGR64RegClass); | |
1491 | ||
1492 | BuildMI(*BB, II, DL, TII->get(Mips::SUBREG_TO_REG), Fc2) | |
1493 | .addImm(0) | |
1494 | .addReg(Fc) | |
1495 | .addImm(Mips::sub_lo); | |
1496 | ||
1497 | // We don't erase the original instruction, we just replace the condition | |
1498 | // register with the 64-bit super-register. | |
1499 | MI->getOperand(1).setReg(Fc2); | |
1500 | ||
1501 | return BB; | |
1502 | } | |
1503 | ||
223e47cc LB |
1504 | //===----------------------------------------------------------------------===// |
1505 | // Misc Lower Operation implementation | |
1506 | //===----------------------------------------------------------------------===// | |
970d7e83 LB |
1507 | SDValue MipsTargetLowering::lowerBR_JT(SDValue Op, SelectionDAG &DAG) const { |
1508 | SDValue Chain = Op.getOperand(0); | |
1509 | SDValue Table = Op.getOperand(1); | |
1510 | SDValue Index = Op.getOperand(2); | |
1a4d82fc | 1511 | SDLoc DL(Op); |
970d7e83 LB |
1512 | EVT PTy = getPointerTy(); |
1513 | unsigned EntrySize = | |
1514 | DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(*getDataLayout()); | |
1515 | ||
1516 | Index = DAG.getNode(ISD::MUL, DL, PTy, Index, | |
1517 | DAG.getConstant(EntrySize, PTy)); | |
1518 | SDValue Addr = DAG.getNode(ISD::ADD, DL, PTy, Index, Table); | |
1519 | ||
1520 | EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8); | |
1521 | Addr = DAG.getExtLoad(ISD::SEXTLOAD, DL, PTy, Chain, Addr, | |
1522 | MachinePointerInfo::getJumpTable(), MemVT, false, false, | |
1a4d82fc | 1523 | false, 0); |
970d7e83 LB |
1524 | Chain = Addr.getValue(1); |
1525 | ||
1a4d82fc JJ |
1526 | if ((getTargetMachine().getRelocationModel() == Reloc::PIC_) || |
1527 | Subtarget.isABI_N64()) { | |
970d7e83 LB |
1528 | // For PIC, the sequence is: |
1529 | // BRIND(load(Jumptable + index) + RelocBase) | |
1530 | // RelocBase can be JumpTable, GOT or some sort of global base. | |
1531 | Addr = DAG.getNode(ISD::ADD, DL, PTy, Addr, | |
1532 | getPICJumpTableRelocBase(Table, DAG)); | |
1533 | } | |
1534 | ||
1535 | return DAG.getNode(ISD::BRIND, DL, MVT::Other, Chain, Addr); | |
1536 | } | |
1537 | ||
1a4d82fc | 1538 | SDValue MipsTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const { |
223e47cc LB |
1539 | // The first operand is the chain, the second is the condition, the third is |
1540 | // the block to branch to if the condition is true. | |
1541 | SDValue Chain = Op.getOperand(0); | |
1542 | SDValue Dest = Op.getOperand(2); | |
1a4d82fc | 1543 | SDLoc DL(Op); |
223e47cc | 1544 | |
1a4d82fc | 1545 | assert(!Subtarget.hasMips32r6() && !Subtarget.hasMips64r6()); |
970d7e83 | 1546 | SDValue CondRes = createFPCmp(DAG, Op.getOperand(1)); |
223e47cc LB |
1547 | |
1548 | // Return if flag is not set by a floating point comparison. | |
1549 | if (CondRes.getOpcode() != MipsISD::FPCmp) | |
1550 | return Op; | |
1551 | ||
1552 | SDValue CCNode = CondRes.getOperand(2); | |
1553 | Mips::CondCode CC = | |
1554 | (Mips::CondCode)cast<ConstantSDNode>(CCNode)->getZExtValue(); | |
1a4d82fc JJ |
1555 | unsigned Opc = invertFPCondCodeUser(CC) ? Mips::BRANCH_F : Mips::BRANCH_T; |
1556 | SDValue BrCode = DAG.getConstant(Opc, MVT::i32); | |
1557 | SDValue FCC0 = DAG.getRegister(Mips::FCC0, MVT::i32); | |
970d7e83 | 1558 | return DAG.getNode(MipsISD::FPBrcond, DL, Op.getValueType(), Chain, BrCode, |
1a4d82fc | 1559 | FCC0, Dest, CondRes); |
223e47cc LB |
1560 | } |
1561 | ||
1562 | SDValue MipsTargetLowering:: | |
970d7e83 | 1563 | lowerSELECT(SDValue Op, SelectionDAG &DAG) const |
223e47cc | 1564 | { |
1a4d82fc | 1565 | assert(!Subtarget.hasMips32r6() && !Subtarget.hasMips64r6()); |
970d7e83 | 1566 | SDValue Cond = createFPCmp(DAG, Op.getOperand(0)); |
223e47cc LB |
1567 | |
1568 | // Return if flag is not set by a floating point comparison. | |
1569 | if (Cond.getOpcode() != MipsISD::FPCmp) | |
1570 | return Op; | |
1571 | ||
970d7e83 | 1572 | return createCMovFP(DAG, Cond, Op.getOperand(1), Op.getOperand(2), |
1a4d82fc | 1573 | SDLoc(Op)); |
223e47cc LB |
1574 | } |
1575 | ||
1576 | SDValue MipsTargetLowering:: | |
970d7e83 | 1577 | lowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const |
223e47cc | 1578 | { |
1a4d82fc | 1579 | SDLoc DL(Op); |
223e47cc | 1580 | EVT Ty = Op.getOperand(0).getValueType(); |
1a4d82fc JJ |
1581 | SDValue Cond = DAG.getNode(ISD::SETCC, DL, |
1582 | getSetCCResultType(*DAG.getContext(), Ty), | |
223e47cc LB |
1583 | Op.getOperand(0), Op.getOperand(1), |
1584 | Op.getOperand(4)); | |
1585 | ||
1586 | return DAG.getNode(ISD::SELECT, DL, Op.getValueType(), Cond, Op.getOperand(2), | |
1587 | Op.getOperand(3)); | |
1588 | } | |
1589 | ||
970d7e83 | 1590 | SDValue MipsTargetLowering::lowerSETCC(SDValue Op, SelectionDAG &DAG) const { |
1a4d82fc | 1591 | assert(!Subtarget.hasMips32r6() && !Subtarget.hasMips64r6()); |
970d7e83 | 1592 | SDValue Cond = createFPCmp(DAG, Op); |
223e47cc LB |
1593 | |
1594 | assert(Cond.getOpcode() == MipsISD::FPCmp && | |
1595 | "Floating point operand expected."); | |
1596 | ||
1597 | SDValue True = DAG.getConstant(1, MVT::i32); | |
1598 | SDValue False = DAG.getConstant(0, MVT::i32); | |
1599 | ||
1a4d82fc | 1600 | return createCMovFP(DAG, Cond, True, False, SDLoc(Op)); |
223e47cc LB |
1601 | } |
1602 | ||
970d7e83 | 1603 | SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, |
223e47cc | 1604 | SelectionDAG &DAG) const { |
1a4d82fc JJ |
1605 | EVT Ty = Op.getValueType(); |
1606 | GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); | |
1607 | const GlobalValue *GV = N->getGlobal(); | |
223e47cc | 1608 | |
1a4d82fc JJ |
1609 | if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && |
1610 | !Subtarget.isABI_N64()) { | |
223e47cc LB |
1611 | const MipsTargetObjectFile &TLOF = |
1612 | (const MipsTargetObjectFile&)getObjFileLowering(); | |
1613 | ||
85aaf69f SL |
1614 | if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) |
1615 | // %gp_rel relocation | |
1616 | return getAddrGPRel(N, SDLoc(N), Ty, DAG); | |
970d7e83 | 1617 | |
223e47cc | 1618 | // %hi/%lo relocation |
85aaf69f | 1619 | return getAddrNonPIC(N, SDLoc(N), Ty, DAG); |
223e47cc LB |
1620 | } |
1621 | ||
970d7e83 | 1622 | if (GV->hasInternalLinkage() || (GV->hasLocalLinkage() && !isa<Function>(GV))) |
85aaf69f | 1623 | return getAddrLocal(N, SDLoc(N), Ty, DAG, |
1a4d82fc | 1624 | Subtarget.isABI_N32() || Subtarget.isABI_N64()); |
223e47cc | 1625 | |
970d7e83 | 1626 | if (LargeGOT) |
85aaf69f | 1627 | return getAddrGlobalLargeGOT(N, SDLoc(N), Ty, DAG, MipsII::MO_GOT_HI16, |
1a4d82fc JJ |
1628 | MipsII::MO_GOT_LO16, DAG.getEntryNode(), |
1629 | MachinePointerInfo::getGOT()); | |
223e47cc | 1630 | |
85aaf69f | 1631 | return getAddrGlobal(N, SDLoc(N), Ty, DAG, |
1a4d82fc JJ |
1632 | (Subtarget.isABI_N32() || Subtarget.isABI_N64()) |
1633 | ? MipsII::MO_GOT_DISP | |
1634 | : MipsII::MO_GOT16, | |
1635 | DAG.getEntryNode(), MachinePointerInfo::getGOT()); | |
970d7e83 LB |
1636 | } |
1637 | ||
1638 | SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, | |
1639 | SelectionDAG &DAG) const { | |
1a4d82fc JJ |
1640 | BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); |
1641 | EVT Ty = Op.getValueType(); | |
1642 | ||
1643 | if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && | |
1644 | !Subtarget.isABI_N64()) | |
85aaf69f | 1645 | return getAddrNonPIC(N, SDLoc(N), Ty, DAG); |
970d7e83 | 1646 | |
85aaf69f | 1647 | return getAddrLocal(N, SDLoc(N), Ty, DAG, |
1a4d82fc | 1648 | Subtarget.isABI_N32() || Subtarget.isABI_N64()); |
223e47cc LB |
1649 | } |
1650 | ||
1651 | SDValue MipsTargetLowering:: | |
970d7e83 | 1652 | lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const |
223e47cc LB |
1653 | { |
1654 | // If the relocation model is PIC, use the General Dynamic TLS Model or | |
1655 | // Local Dynamic TLS model, otherwise use the Initial Exec or | |
1656 | // Local Exec TLS Model. | |
1657 | ||
1658 | GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); | |
1a4d82fc | 1659 | SDLoc DL(GA); |
223e47cc LB |
1660 | const GlobalValue *GV = GA->getGlobal(); |
1661 | EVT PtrVT = getPointerTy(); | |
1662 | ||
1663 | TLSModel::Model model = getTargetMachine().getTLSModel(GV); | |
1664 | ||
1665 | if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { | |
1666 | // General Dynamic and Local Dynamic TLS Model. | |
1667 | unsigned Flag = (model == TLSModel::LocalDynamic) ? MipsII::MO_TLSLDM | |
1668 | : MipsII::MO_TLSGD; | |
1669 | ||
970d7e83 LB |
1670 | SDValue TGA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, Flag); |
1671 | SDValue Argument = DAG.getNode(MipsISD::Wrapper, DL, PtrVT, | |
1672 | getGlobalReg(DAG, PtrVT), TGA); | |
223e47cc LB |
1673 | unsigned PtrSize = PtrVT.getSizeInBits(); |
1674 | IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize); | |
1675 | ||
1676 | SDValue TlsGetAddr = DAG.getExternalSymbol("__tls_get_addr", PtrVT); | |
1677 | ||
1678 | ArgListTy Args; | |
1679 | ArgListEntry Entry; | |
1680 | Entry.Node = Argument; | |
1681 | Entry.Ty = PtrTy; | |
1682 | Args.push_back(Entry); | |
1683 | ||
1a4d82fc JJ |
1684 | TargetLowering::CallLoweringInfo CLI(DAG); |
1685 | CLI.setDebugLoc(DL).setChain(DAG.getEntryNode()) | |
1686 | .setCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args), 0); | |
223e47cc LB |
1687 | std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); |
1688 | ||
1689 | SDValue Ret = CallResult.first; | |
1690 | ||
1691 | if (model != TLSModel::LocalDynamic) | |
1692 | return Ret; | |
1693 | ||
970d7e83 | 1694 | SDValue TGAHi = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, |
223e47cc | 1695 | MipsII::MO_DTPREL_HI); |
970d7e83 LB |
1696 | SDValue Hi = DAG.getNode(MipsISD::Hi, DL, PtrVT, TGAHi); |
1697 | SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, | |
223e47cc | 1698 | MipsII::MO_DTPREL_LO); |
970d7e83 LB |
1699 | SDValue Lo = DAG.getNode(MipsISD::Lo, DL, PtrVT, TGALo); |
1700 | SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Ret); | |
1701 | return DAG.getNode(ISD::ADD, DL, PtrVT, Add, Lo); | |
223e47cc LB |
1702 | } |
1703 | ||
1704 | SDValue Offset; | |
1705 | if (model == TLSModel::InitialExec) { | |
1706 | // Initial Exec TLS Model | |
970d7e83 | 1707 | SDValue TGA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, |
223e47cc | 1708 | MipsII::MO_GOTTPREL); |
970d7e83 | 1709 | TGA = DAG.getNode(MipsISD::Wrapper, DL, PtrVT, getGlobalReg(DAG, PtrVT), |
223e47cc | 1710 | TGA); |
970d7e83 | 1711 | Offset = DAG.getLoad(PtrVT, DL, |
223e47cc LB |
1712 | DAG.getEntryNode(), TGA, MachinePointerInfo(), |
1713 | false, false, false, 0); | |
1714 | } else { | |
1715 | // Local Exec TLS Model | |
1716 | assert(model == TLSModel::LocalExec); | |
970d7e83 | 1717 | SDValue TGAHi = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, |
223e47cc | 1718 | MipsII::MO_TPREL_HI); |
970d7e83 | 1719 | SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, |
223e47cc | 1720 | MipsII::MO_TPREL_LO); |
970d7e83 LB |
1721 | SDValue Hi = DAG.getNode(MipsISD::Hi, DL, PtrVT, TGAHi); |
1722 | SDValue Lo = DAG.getNode(MipsISD::Lo, DL, PtrVT, TGALo); | |
1723 | Offset = DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); | |
223e47cc LB |
1724 | } |
1725 | ||
970d7e83 LB |
1726 | SDValue ThreadPointer = DAG.getNode(MipsISD::ThreadPointer, DL, PtrVT); |
1727 | return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, Offset); | |
223e47cc LB |
1728 | } |
1729 | ||
1730 | SDValue MipsTargetLowering:: | |
970d7e83 | 1731 | lowerJumpTable(SDValue Op, SelectionDAG &DAG) const |
223e47cc | 1732 | { |
1a4d82fc JJ |
1733 | JumpTableSDNode *N = cast<JumpTableSDNode>(Op); |
1734 | EVT Ty = Op.getValueType(); | |
1735 | ||
1736 | if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && | |
1737 | !Subtarget.isABI_N64()) | |
85aaf69f | 1738 | return getAddrNonPIC(N, SDLoc(N), Ty, DAG); |
223e47cc | 1739 | |
85aaf69f | 1740 | return getAddrLocal(N, SDLoc(N), Ty, DAG, |
1a4d82fc | 1741 | Subtarget.isABI_N32() || Subtarget.isABI_N64()); |
223e47cc LB |
1742 | } |
1743 | ||
1744 | SDValue MipsTargetLowering:: | |
970d7e83 | 1745 | lowerConstantPool(SDValue Op, SelectionDAG &DAG) const |
223e47cc | 1746 | { |
1a4d82fc JJ |
1747 | ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); |
1748 | EVT Ty = Op.getValueType(); | |
223e47cc | 1749 | |
1a4d82fc | 1750 | if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && |
85aaf69f SL |
1751 | !Subtarget.isABI_N64()) { |
1752 | const MipsTargetObjectFile &TLOF = | |
1753 | (const MipsTargetObjectFile&)getObjFileLowering(); | |
1754 | ||
1755 | if (TLOF.IsConstantInSmallSection(N->getConstVal(), getTargetMachine())) | |
1756 | // %gp_rel relocation | |
1757 | return getAddrGPRel(N, SDLoc(N), Ty, DAG); | |
223e47cc | 1758 | |
85aaf69f SL |
1759 | return getAddrNonPIC(N, SDLoc(N), Ty, DAG); |
1760 | } | |
1761 | ||
1762 | return getAddrLocal(N, SDLoc(N), Ty, DAG, | |
1a4d82fc | 1763 | Subtarget.isABI_N32() || Subtarget.isABI_N64()); |
223e47cc LB |
1764 | } |
1765 | ||
970d7e83 | 1766 | SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { |
223e47cc LB |
1767 | MachineFunction &MF = DAG.getMachineFunction(); |
1768 | MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); | |
1769 | ||
1a4d82fc | 1770 | SDLoc DL(Op); |
223e47cc LB |
1771 | SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), |
1772 | getPointerTy()); | |
1773 | ||
1774 | // vastart just stores the address of the VarArgsFrameIndex slot into the | |
1775 | // memory location argument. | |
1776 | const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); | |
970d7e83 | 1777 | return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1), |
223e47cc LB |
1778 | MachinePointerInfo(SV), false, false, 0); |
1779 | } | |
1780 | ||
1a4d82fc JJ |
1781 | SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { |
1782 | SDNode *Node = Op.getNode(); | |
1783 | EVT VT = Node->getValueType(0); | |
1784 | SDValue Chain = Node->getOperand(0); | |
1785 | SDValue VAListPtr = Node->getOperand(1); | |
1786 | unsigned Align = Node->getConstantOperandVal(3); | |
1787 | const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); | |
1788 | SDLoc DL(Node); | |
1789 | unsigned ArgSlotSizeInBytes = | |
1790 | (Subtarget.isABI_N32() || Subtarget.isABI_N64()) ? 8 : 4; | |
1791 | ||
1792 | SDValue VAListLoad = DAG.getLoad(getPointerTy(), DL, Chain, VAListPtr, | |
1793 | MachinePointerInfo(SV), false, false, false, | |
1794 | 0); | |
1795 | SDValue VAList = VAListLoad; | |
1796 | ||
1797 | // Re-align the pointer if necessary. | |
1798 | // It should only ever be necessary for 64-bit types on O32 since the minimum | |
1799 | // argument alignment is the same as the maximum type alignment for N32/N64. | |
1800 | // | |
1801 | // FIXME: We currently align too often. The code generator doesn't notice | |
1802 | // when the pointer is still aligned from the last va_arg (or pair of | |
1803 | // va_args for the i64 on O32 case). | |
1804 | if (Align > getMinStackArgumentAlignment()) { | |
1805 | assert(((Align & (Align-1)) == 0) && "Expected Align to be a power of 2"); | |
1806 | ||
1807 | VAList = DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, | |
1808 | DAG.getConstant(Align - 1, | |
1809 | VAList.getValueType())); | |
1810 | ||
1811 | VAList = DAG.getNode(ISD::AND, DL, VAList.getValueType(), VAList, | |
1812 | DAG.getConstant(-(int64_t)Align, | |
1813 | VAList.getValueType())); | |
1814 | } | |
1815 | ||
1816 | // Increment the pointer, VAList, to the next vaarg. | |
1817 | unsigned ArgSizeInBytes = getDataLayout()->getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())); | |
1818 | SDValue Tmp3 = DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, | |
1819 | DAG.getConstant(RoundUpToAlignment(ArgSizeInBytes, ArgSlotSizeInBytes), | |
1820 | VAList.getValueType())); | |
1821 | // Store the incremented VAList to the legalized pointer | |
1822 | Chain = DAG.getStore(VAListLoad.getValue(1), DL, Tmp3, VAListPtr, | |
1823 | MachinePointerInfo(SV), false, false, 0); | |
1824 | ||
1825 | // In big-endian mode we must adjust the pointer when the load size is smaller | |
1826 | // than the argument slot size. We must also reduce the known alignment to | |
1827 | // match. For example in the N64 ABI, we must add 4 bytes to the offset to get | |
1828 | // the correct half of the slot, and reduce the alignment from 8 (slot | |
1829 | // alignment) down to 4 (type alignment). | |
1830 | if (!Subtarget.isLittle() && ArgSizeInBytes < ArgSlotSizeInBytes) { | |
1831 | unsigned Adjustment = ArgSlotSizeInBytes - ArgSizeInBytes; | |
1832 | VAList = DAG.getNode(ISD::ADD, DL, VAListPtr.getValueType(), VAList, | |
1833 | DAG.getIntPtrConstant(Adjustment)); | |
1834 | } | |
1835 | // Load the actual argument out of the pointer VAList | |
1836 | return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo(), false, false, | |
1837 | false, 0); | |
1838 | } | |
1839 | ||
1840 | static SDValue lowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG, | |
1841 | bool HasExtractInsert) { | |
223e47cc LB |
1842 | EVT TyX = Op.getOperand(0).getValueType(); |
1843 | EVT TyY = Op.getOperand(1).getValueType(); | |
1844 | SDValue Const1 = DAG.getConstant(1, MVT::i32); | |
1845 | SDValue Const31 = DAG.getConstant(31, MVT::i32); | |
1a4d82fc | 1846 | SDLoc DL(Op); |
223e47cc LB |
1847 | SDValue Res; |
1848 | ||
1849 | // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it | |
1850 | // to i32. | |
1851 | SDValue X = (TyX == MVT::f32) ? | |
1852 | DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(0)) : | |
1853 | DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0), | |
1854 | Const1); | |
1855 | SDValue Y = (TyY == MVT::f32) ? | |
1856 | DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(1)) : | |
1857 | DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(1), | |
1858 | Const1); | |
1859 | ||
1a4d82fc | 1860 | if (HasExtractInsert) { |
223e47cc LB |
1861 | // ext E, Y, 31, 1 ; extract bit31 of Y |
1862 | // ins X, E, 31, 1 ; insert extracted bit at bit31 of X | |
1863 | SDValue E = DAG.getNode(MipsISD::Ext, DL, MVT::i32, Y, Const31, Const1); | |
1864 | Res = DAG.getNode(MipsISD::Ins, DL, MVT::i32, E, Const31, Const1, X); | |
1865 | } else { | |
1866 | // sll SllX, X, 1 | |
1867 | // srl SrlX, SllX, 1 | |
1868 | // srl SrlY, Y, 31 | |
1869 | // sll SllY, SrlX, 31 | |
1870 | // or Or, SrlX, SllY | |
1871 | SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i32, X, Const1); | |
1872 | SDValue SrlX = DAG.getNode(ISD::SRL, DL, MVT::i32, SllX, Const1); | |
1873 | SDValue SrlY = DAG.getNode(ISD::SRL, DL, MVT::i32, Y, Const31); | |
1874 | SDValue SllY = DAG.getNode(ISD::SHL, DL, MVT::i32, SrlY, Const31); | |
1875 | Res = DAG.getNode(ISD::OR, DL, MVT::i32, SrlX, SllY); | |
1876 | } | |
1877 | ||
1878 | if (TyX == MVT::f32) | |
1879 | return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Res); | |
1880 | ||
1881 | SDValue LowX = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, | |
1882 | Op.getOperand(0), DAG.getConstant(0, MVT::i32)); | |
1883 | return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res); | |
1884 | } | |
1885 | ||
1a4d82fc JJ |
1886 | static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, |
1887 | bool HasExtractInsert) { | |
223e47cc LB |
1888 | unsigned WidthX = Op.getOperand(0).getValueSizeInBits(); |
1889 | unsigned WidthY = Op.getOperand(1).getValueSizeInBits(); | |
1890 | EVT TyX = MVT::getIntegerVT(WidthX), TyY = MVT::getIntegerVT(WidthY); | |
1891 | SDValue Const1 = DAG.getConstant(1, MVT::i32); | |
1a4d82fc | 1892 | SDLoc DL(Op); |
223e47cc LB |
1893 | |
1894 | // Bitcast to integer nodes. | |
1895 | SDValue X = DAG.getNode(ISD::BITCAST, DL, TyX, Op.getOperand(0)); | |
1896 | SDValue Y = DAG.getNode(ISD::BITCAST, DL, TyY, Op.getOperand(1)); | |
1897 | ||
1a4d82fc | 1898 | if (HasExtractInsert) { |
223e47cc LB |
1899 | // ext E, Y, width(Y) - 1, 1 ; extract bit width(Y)-1 of Y |
1900 | // ins X, E, width(X) - 1, 1 ; insert extracted bit at bit width(X)-1 of X | |
1901 | SDValue E = DAG.getNode(MipsISD::Ext, DL, TyY, Y, | |
1902 | DAG.getConstant(WidthY - 1, MVT::i32), Const1); | |
1903 | ||
1904 | if (WidthX > WidthY) | |
1905 | E = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, E); | |
1906 | else if (WidthY > WidthX) | |
1907 | E = DAG.getNode(ISD::TRUNCATE, DL, TyX, E); | |
1908 | ||
1909 | SDValue I = DAG.getNode(MipsISD::Ins, DL, TyX, E, | |
1910 | DAG.getConstant(WidthX - 1, MVT::i32), Const1, X); | |
1911 | return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), I); | |
1912 | } | |
1913 | ||
1914 | // (d)sll SllX, X, 1 | |
1915 | // (d)srl SrlX, SllX, 1 | |
1916 | // (d)srl SrlY, Y, width(Y)-1 | |
1917 | // (d)sll SllY, SrlX, width(Y)-1 | |
1918 | // or Or, SrlX, SllY | |
1919 | SDValue SllX = DAG.getNode(ISD::SHL, DL, TyX, X, Const1); | |
1920 | SDValue SrlX = DAG.getNode(ISD::SRL, DL, TyX, SllX, Const1); | |
1921 | SDValue SrlY = DAG.getNode(ISD::SRL, DL, TyY, Y, | |
1922 | DAG.getConstant(WidthY - 1, MVT::i32)); | |
1923 | ||
1924 | if (WidthX > WidthY) | |
1925 | SrlY = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, SrlY); | |
1926 | else if (WidthY > WidthX) | |
1927 | SrlY = DAG.getNode(ISD::TRUNCATE, DL, TyX, SrlY); | |
1928 | ||
1929 | SDValue SllY = DAG.getNode(ISD::SHL, DL, TyX, SrlY, | |
1930 | DAG.getConstant(WidthX - 1, MVT::i32)); | |
1931 | SDValue Or = DAG.getNode(ISD::OR, DL, TyX, SrlX, SllY); | |
1932 | return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Or); | |
1933 | } | |
1934 | ||
1935 | SDValue | |
970d7e83 | 1936 | MipsTargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { |
1a4d82fc JJ |
1937 | if (Subtarget.isGP64bit()) |
1938 | return lowerFCOPYSIGN64(Op, DAG, Subtarget.hasExtractInsert()); | |
223e47cc | 1939 | |
1a4d82fc | 1940 | return lowerFCOPYSIGN32(Op, DAG, Subtarget.hasExtractInsert()); |
223e47cc LB |
1941 | } |
1942 | ||
1943 | SDValue MipsTargetLowering:: | |
970d7e83 | 1944 | lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { |
223e47cc LB |
1945 | // check the depth |
1946 | assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && | |
1947 | "Frame address can only be determined for current frame."); | |
1948 | ||
1949 | MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); | |
1950 | MFI->setFrameAddressIsTaken(true); | |
1951 | EVT VT = Op.getValueType(); | |
1a4d82fc JJ |
1952 | SDLoc DL(Op); |
1953 | SDValue FrameAddr = | |
1954 | DAG.getCopyFromReg(DAG.getEntryNode(), DL, | |
1955 | Subtarget.isABI_N64() ? Mips::FP_64 : Mips::FP, VT); | |
223e47cc LB |
1956 | return FrameAddr; |
1957 | } | |
1958 | ||
970d7e83 | 1959 | SDValue MipsTargetLowering::lowerRETURNADDR(SDValue Op, |
223e47cc | 1960 | SelectionDAG &DAG) const { |
1a4d82fc JJ |
1961 | if (verifyReturnAddressArgumentIsConstant(Op, DAG)) |
1962 | return SDValue(); | |
1963 | ||
223e47cc LB |
1964 | // check the depth |
1965 | assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && | |
1966 | "Return address can be determined only for current frame."); | |
1967 | ||
1968 | MachineFunction &MF = DAG.getMachineFunction(); | |
1969 | MachineFrameInfo *MFI = MF.getFrameInfo(); | |
970d7e83 | 1970 | MVT VT = Op.getSimpleValueType(); |
1a4d82fc | 1971 | unsigned RA = Subtarget.isABI_N64() ? Mips::RA_64 : Mips::RA; |
223e47cc LB |
1972 | MFI->setReturnAddressIsTaken(true); |
1973 | ||
1974 | // Return RA, which contains the return address. Mark it an implicit live-in. | |
1975 | unsigned Reg = MF.addLiveIn(RA, getRegClassFor(VT)); | |
1a4d82fc | 1976 | return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), Reg, VT); |
223e47cc LB |
1977 | } |
1978 | ||
970d7e83 LB |
1979 | // An EH_RETURN is the result of lowering llvm.eh.return which in turn is |
1980 | // generated from __builtin_eh_return (offset, handler) | |
1981 | // The effect of this is to adjust the stack pointer by "offset" | |
1982 | // and then branch to "handler". | |
1983 | SDValue MipsTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) | |
1984 | const { | |
1985 | MachineFunction &MF = DAG.getMachineFunction(); | |
1986 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); | |
1987 | ||
1988 | MipsFI->setCallsEhReturn(); | |
1989 | SDValue Chain = Op.getOperand(0); | |
1990 | SDValue Offset = Op.getOperand(1); | |
1991 | SDValue Handler = Op.getOperand(2); | |
1a4d82fc JJ |
1992 | SDLoc DL(Op); |
1993 | EVT Ty = Subtarget.isABI_N64() ? MVT::i64 : MVT::i32; | |
970d7e83 LB |
1994 | |
1995 | // Store stack offset in V1, store jump target in V0. Glue CopyToReg and | |
1996 | // EH_RETURN nodes, so that instructions are emitted back-to-back. | |
1a4d82fc JJ |
1997 | unsigned OffsetReg = Subtarget.isABI_N64() ? Mips::V1_64 : Mips::V1; |
1998 | unsigned AddrReg = Subtarget.isABI_N64() ? Mips::V0_64 : Mips::V0; | |
970d7e83 LB |
1999 | Chain = DAG.getCopyToReg(Chain, DL, OffsetReg, Offset, SDValue()); |
2000 | Chain = DAG.getCopyToReg(Chain, DL, AddrReg, Handler, Chain.getValue(1)); | |
2001 | return DAG.getNode(MipsISD::EH_RETURN, DL, MVT::Other, Chain, | |
2002 | DAG.getRegister(OffsetReg, Ty), | |
2003 | DAG.getRegister(AddrReg, getPointerTy()), | |
2004 | Chain.getValue(1)); | |
2005 | } | |
2006 | ||
970d7e83 | 2007 | SDValue MipsTargetLowering::lowerATOMIC_FENCE(SDValue Op, |
223e47cc LB |
2008 | SelectionDAG &DAG) const { |
2009 | // FIXME: Need pseudo-fence for 'singlethread' fences | |
2010 | // FIXME: Set SType for weaker fences where supported/appropriate. | |
2011 | unsigned SType = 0; | |
1a4d82fc | 2012 | SDLoc DL(Op); |
970d7e83 | 2013 | return DAG.getNode(MipsISD::Sync, DL, MVT::Other, Op.getOperand(0), |
223e47cc LB |
2014 | DAG.getConstant(SType, MVT::i32)); |
2015 | } | |
2016 | ||
970d7e83 | 2017 | SDValue MipsTargetLowering::lowerShiftLeftParts(SDValue Op, |
223e47cc | 2018 | SelectionDAG &DAG) const { |
1a4d82fc | 2019 | SDLoc DL(Op); |
223e47cc LB |
2020 | SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); |
2021 | SDValue Shamt = Op.getOperand(2); | |
2022 | ||
2023 | // if shamt < 32: | |
2024 | // lo = (shl lo, shamt) | |
2025 | // hi = (or (shl hi, shamt) (srl (srl lo, 1), ~shamt)) | |
2026 | // else: | |
2027 | // lo = 0 | |
2028 | // hi = (shl lo, shamt[4:0]) | |
2029 | SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, | |
2030 | DAG.getConstant(-1, MVT::i32)); | |
2031 | SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, MVT::i32, Lo, | |
2032 | DAG.getConstant(1, MVT::i32)); | |
2033 | SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, MVT::i32, ShiftRight1Lo, | |
2034 | Not); | |
2035 | SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, MVT::i32, Hi, Shamt); | |
2036 | SDValue Or = DAG.getNode(ISD::OR, DL, MVT::i32, ShiftLeftHi, ShiftRightLo); | |
2037 | SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, MVT::i32, Lo, Shamt); | |
2038 | SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, | |
2039 | DAG.getConstant(0x20, MVT::i32)); | |
2040 | Lo = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, | |
2041 | DAG.getConstant(0, MVT::i32), ShiftLeftLo); | |
2042 | Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftLeftLo, Or); | |
2043 | ||
2044 | SDValue Ops[2] = {Lo, Hi}; | |
1a4d82fc | 2045 | return DAG.getMergeValues(Ops, DL); |
223e47cc LB |
2046 | } |
2047 | ||
970d7e83 | 2048 | SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, |
223e47cc | 2049 | bool IsSRA) const { |
1a4d82fc | 2050 | SDLoc DL(Op); |
223e47cc LB |
2051 | SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); |
2052 | SDValue Shamt = Op.getOperand(2); | |
2053 | ||
2054 | // if shamt < 32: | |
2055 | // lo = (or (shl (shl hi, 1), ~shamt) (srl lo, shamt)) | |
2056 | // if isSRA: | |
2057 | // hi = (sra hi, shamt) | |
2058 | // else: | |
2059 | // hi = (srl hi, shamt) | |
2060 | // else: | |
2061 | // if isSRA: | |
2062 | // lo = (sra hi, shamt[4:0]) | |
2063 | // hi = (sra hi, 31) | |
2064 | // else: | |
2065 | // lo = (srl hi, shamt[4:0]) | |
2066 | // hi = 0 | |
2067 | SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, | |
2068 | DAG.getConstant(-1, MVT::i32)); | |
2069 | SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, MVT::i32, Hi, | |
2070 | DAG.getConstant(1, MVT::i32)); | |
2071 | SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, MVT::i32, ShiftLeft1Hi, Not); | |
2072 | SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, MVT::i32, Lo, Shamt); | |
2073 | SDValue Or = DAG.getNode(ISD::OR, DL, MVT::i32, ShiftLeftHi, ShiftRightLo); | |
2074 | SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, DL, MVT::i32, | |
2075 | Hi, Shamt); | |
2076 | SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, | |
2077 | DAG.getConstant(0x20, MVT::i32)); | |
2078 | SDValue Shift31 = DAG.getNode(ISD::SRA, DL, MVT::i32, Hi, | |
2079 | DAG.getConstant(31, MVT::i32)); | |
2080 | Lo = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftRightHi, Or); | |
2081 | Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, | |
2082 | IsSRA ? Shift31 : DAG.getConstant(0, MVT::i32), | |
2083 | ShiftRightHi); | |
2084 | ||
2085 | SDValue Ops[2] = {Lo, Hi}; | |
1a4d82fc | 2086 | return DAG.getMergeValues(Ops, DL); |
223e47cc LB |
2087 | } |
2088 | ||
1a4d82fc | 2089 | static SDValue createLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD, |
223e47cc LB |
2090 | SDValue Chain, SDValue Src, unsigned Offset) { |
2091 | SDValue Ptr = LD->getBasePtr(); | |
2092 | EVT VT = LD->getValueType(0), MemVT = LD->getMemoryVT(); | |
2093 | EVT BasePtrVT = Ptr.getValueType(); | |
1a4d82fc | 2094 | SDLoc DL(LD); |
223e47cc LB |
2095 | SDVTList VTList = DAG.getVTList(VT, MVT::Other); |
2096 | ||
2097 | if (Offset) | |
2098 | Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr, | |
2099 | DAG.getConstant(Offset, BasePtrVT)); | |
2100 | ||
2101 | SDValue Ops[] = { Chain, Ptr, Src }; | |
1a4d82fc | 2102 | return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT, |
223e47cc LB |
2103 | LD->getMemOperand()); |
2104 | } | |
2105 | ||
2106 | // Expand an unaligned 32 or 64-bit integer load node. | |
970d7e83 | 2107 | SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { |
223e47cc LB |
2108 | LoadSDNode *LD = cast<LoadSDNode>(Op); |
2109 | EVT MemVT = LD->getMemoryVT(); | |
2110 | ||
1a4d82fc JJ |
2111 | if (Subtarget.systemSupportsUnalignedAccess()) |
2112 | return Op; | |
2113 | ||
223e47cc LB |
2114 | // Return if load is aligned or if MemVT is neither i32 nor i64. |
2115 | if ((LD->getAlignment() >= MemVT.getSizeInBits() / 8) || | |
2116 | ((MemVT != MVT::i32) && (MemVT != MVT::i64))) | |
2117 | return SDValue(); | |
2118 | ||
1a4d82fc | 2119 | bool IsLittle = Subtarget.isLittle(); |
223e47cc LB |
2120 | EVT VT = Op.getValueType(); |
2121 | ISD::LoadExtType ExtType = LD->getExtensionType(); | |
2122 | SDValue Chain = LD->getChain(), Undef = DAG.getUNDEF(VT); | |
2123 | ||
2124 | assert((VT == MVT::i32) || (VT == MVT::i64)); | |
2125 | ||
2126 | // Expand | |
2127 | // (set dst, (i64 (load baseptr))) | |
2128 | // to | |
2129 | // (set tmp, (ldl (add baseptr, 7), undef)) | |
2130 | // (set dst, (ldr baseptr, tmp)) | |
2131 | if ((VT == MVT::i64) && (ExtType == ISD::NON_EXTLOAD)) { | |
1a4d82fc | 2132 | SDValue LDL = createLoadLR(MipsISD::LDL, DAG, LD, Chain, Undef, |
223e47cc | 2133 | IsLittle ? 7 : 0); |
1a4d82fc | 2134 | return createLoadLR(MipsISD::LDR, DAG, LD, LDL.getValue(1), LDL, |
223e47cc LB |
2135 | IsLittle ? 0 : 7); |
2136 | } | |
2137 | ||
1a4d82fc | 2138 | SDValue LWL = createLoadLR(MipsISD::LWL, DAG, LD, Chain, Undef, |
223e47cc | 2139 | IsLittle ? 3 : 0); |
1a4d82fc | 2140 | SDValue LWR = createLoadLR(MipsISD::LWR, DAG, LD, LWL.getValue(1), LWL, |
223e47cc LB |
2141 | IsLittle ? 0 : 3); |
2142 | ||
2143 | // Expand | |
2144 | // (set dst, (i32 (load baseptr))) or | |
2145 | // (set dst, (i64 (sextload baseptr))) or | |
2146 | // (set dst, (i64 (extload baseptr))) | |
2147 | // to | |
2148 | // (set tmp, (lwl (add baseptr, 3), undef)) | |
2149 | // (set dst, (lwr baseptr, tmp)) | |
2150 | if ((VT == MVT::i32) || (ExtType == ISD::SEXTLOAD) || | |
2151 | (ExtType == ISD::EXTLOAD)) | |
2152 | return LWR; | |
2153 | ||
2154 | assert((VT == MVT::i64) && (ExtType == ISD::ZEXTLOAD)); | |
2155 | ||
2156 | // Expand | |
2157 | // (set dst, (i64 (zextload baseptr))) | |
2158 | // to | |
2159 | // (set tmp0, (lwl (add baseptr, 3), undef)) | |
2160 | // (set tmp1, (lwr baseptr, tmp0)) | |
2161 | // (set tmp2, (shl tmp1, 32)) | |
2162 | // (set dst, (srl tmp2, 32)) | |
1a4d82fc | 2163 | SDLoc DL(LD); |
223e47cc LB |
2164 | SDValue Const32 = DAG.getConstant(32, MVT::i32); |
2165 | SDValue SLL = DAG.getNode(ISD::SHL, DL, MVT::i64, LWR, Const32); | |
2166 | SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i64, SLL, Const32); | |
2167 | SDValue Ops[] = { SRL, LWR.getValue(1) }; | |
1a4d82fc | 2168 | return DAG.getMergeValues(Ops, DL); |
223e47cc LB |
2169 | } |
2170 | ||
1a4d82fc | 2171 | static SDValue createStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD, |
223e47cc LB |
2172 | SDValue Chain, unsigned Offset) { |
2173 | SDValue Ptr = SD->getBasePtr(), Value = SD->getValue(); | |
2174 | EVT MemVT = SD->getMemoryVT(), BasePtrVT = Ptr.getValueType(); | |
1a4d82fc | 2175 | SDLoc DL(SD); |
223e47cc LB |
2176 | SDVTList VTList = DAG.getVTList(MVT::Other); |
2177 | ||
2178 | if (Offset) | |
2179 | Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr, | |
2180 | DAG.getConstant(Offset, BasePtrVT)); | |
2181 | ||
2182 | SDValue Ops[] = { Chain, Value, Ptr }; | |
1a4d82fc | 2183 | return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT, |
223e47cc LB |
2184 | SD->getMemOperand()); |
2185 | } | |
2186 | ||
2187 | // Expand an unaligned 32 or 64-bit integer store node. | |
1a4d82fc JJ |
2188 | static SDValue lowerUnalignedIntStore(StoreSDNode *SD, SelectionDAG &DAG, |
2189 | bool IsLittle) { | |
223e47cc LB |
2190 | SDValue Value = SD->getValue(), Chain = SD->getChain(); |
2191 | EVT VT = Value.getValueType(); | |
2192 | ||
2193 | // Expand | |
2194 | // (store val, baseptr) or | |
2195 | // (truncstore val, baseptr) | |
2196 | // to | |
2197 | // (swl val, (add baseptr, 3)) | |
2198 | // (swr val, baseptr) | |
2199 | if ((VT == MVT::i32) || SD->isTruncatingStore()) { | |
1a4d82fc | 2200 | SDValue SWL = createStoreLR(MipsISD::SWL, DAG, SD, Chain, |
223e47cc | 2201 | IsLittle ? 3 : 0); |
1a4d82fc | 2202 | return createStoreLR(MipsISD::SWR, DAG, SD, SWL, IsLittle ? 0 : 3); |
223e47cc LB |
2203 | } |
2204 | ||
2205 | assert(VT == MVT::i64); | |
2206 | ||
2207 | // Expand | |
2208 | // (store val, baseptr) | |
2209 | // to | |
2210 | // (sdl val, (add baseptr, 7)) | |
2211 | // (sdr val, baseptr) | |
1a4d82fc JJ |
2212 | SDValue SDL = createStoreLR(MipsISD::SDL, DAG, SD, Chain, IsLittle ? 7 : 0); |
2213 | return createStoreLR(MipsISD::SDR, DAG, SD, SDL, IsLittle ? 0 : 7); | |
223e47cc LB |
2214 | } |
2215 | ||
1a4d82fc JJ |
2216 | // Lower (store (fp_to_sint $fp) $ptr) to (store (TruncIntFP $fp), $ptr). |
2217 | static SDValue lowerFP_TO_SINT_STORE(StoreSDNode *SD, SelectionDAG &DAG) { | |
2218 | SDValue Val = SD->getValue(); | |
223e47cc | 2219 | |
1a4d82fc JJ |
2220 | if (Val.getOpcode() != ISD::FP_TO_SINT) |
2221 | return SDValue(); | |
223e47cc | 2222 | |
1a4d82fc JJ |
2223 | EVT FPTy = EVT::getFloatingPointVT(Val.getValueSizeInBits()); |
2224 | SDValue Tr = DAG.getNode(MipsISD::TruncIntFP, SDLoc(Val), FPTy, | |
2225 | Val.getOperand(0)); | |
223e47cc | 2226 | |
1a4d82fc JJ |
2227 | return DAG.getStore(SD->getChain(), SDLoc(SD), Tr, SD->getBasePtr(), |
2228 | SD->getPointerInfo(), SD->isVolatile(), | |
2229 | SD->isNonTemporal(), SD->getAlignment()); | |
223e47cc LB |
2230 | } |
2231 | ||
1a4d82fc JJ |
2232 | SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { |
2233 | StoreSDNode *SD = cast<StoreSDNode>(Op); | |
2234 | EVT MemVT = SD->getMemoryVT(); | |
2235 | ||
2236 | // Lower unaligned integer stores. | |
2237 | if (!Subtarget.systemSupportsUnalignedAccess() && | |
2238 | (SD->getAlignment() < MemVT.getSizeInBits() / 8) && | |
2239 | ((MemVT == MVT::i32) || (MemVT == MVT::i64))) | |
2240 | return lowerUnalignedIntStore(SD, DAG, Subtarget.isLittle()); | |
2241 | ||
2242 | return lowerFP_TO_SINT_STORE(SD, DAG); | |
223e47cc LB |
2243 | } |
2244 | ||
970d7e83 LB |
2245 | SDValue MipsTargetLowering::lowerADD(SDValue Op, SelectionDAG &DAG) const { |
2246 | if (Op->getOperand(0).getOpcode() != ISD::FRAMEADDR | |
2247 | || cast<ConstantSDNode> | |
2248 | (Op->getOperand(0).getOperand(0))->getZExtValue() != 0 | |
2249 | || Op->getOperand(1).getOpcode() != ISD::FRAME_TO_ARGS_OFFSET) | |
2250 | return SDValue(); | |
2251 | ||
2252 | // The pattern | |
2253 | // (add (frameaddr 0), (frame_to_args_offset)) | |
2254 | // results from lowering llvm.eh.dwarf.cfa intrinsic. Transform it to | |
2255 | // (add FrameObject, 0) | |
2256 | // where FrameObject is a fixed StackObject with offset 0 which points to | |
2257 | // the old stack pointer. | |
2258 | MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); | |
2259 | EVT ValTy = Op->getValueType(0); | |
2260 | int FI = MFI->CreateFixedObject(Op.getValueSizeInBits() / 8, 0, false); | |
2261 | SDValue InArgsAddr = DAG.getFrameIndex(FI, ValTy); | |
1a4d82fc | 2262 | return DAG.getNode(ISD::ADD, SDLoc(Op), ValTy, InArgsAddr, |
970d7e83 LB |
2263 | DAG.getConstant(0, ValTy)); |
2264 | } | |
2265 | ||
1a4d82fc JJ |
2266 | SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op, |
2267 | SelectionDAG &DAG) const { | |
2268 | EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits()); | |
2269 | SDValue Trunc = DAG.getNode(MipsISD::TruncIntFP, SDLoc(Op), FPTy, | |
2270 | Op.getOperand(0)); | |
2271 | return DAG.getNode(ISD::BITCAST, SDLoc(Op), Op.getValueType(), Trunc); | |
2272 | } | |
2273 | ||
223e47cc LB |
2274 | //===----------------------------------------------------------------------===// |
2275 | // Calling Convention Implementation | |
2276 | //===----------------------------------------------------------------------===// | |
2277 | ||
2278 | //===----------------------------------------------------------------------===// | |
2279 | // TODO: Implement a generic logic using tblgen that can support this. | |
2280 | // Mips O32 ABI rules: | |
2281 | // --- | |
2282 | // i32 - Passed in A0, A1, A2, A3 and stack | |
2283 | // f32 - Only passed in f32 registers if no int reg has been used yet to hold | |
2284 | // an argument. Otherwise, passed in A1, A2, A3 and stack. | |
2285 | // f64 - Only passed in two aliased f32 registers if no int reg has been used | |
2286 | // yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is | |
1a4d82fc | 2287 | // not used, it must be shadowed. If only A3 is available, shadow it and |
223e47cc LB |
2288 | // go to stack. |
2289 | // | |
2290 | // For vararg functions, all arguments are passed in A0, A1, A2, A3 and stack. | |
2291 | //===----------------------------------------------------------------------===// | |
2292 | ||
1a4d82fc JJ |
2293 | static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, |
2294 | CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, | |
2295 | CCState &State, const MCPhysReg *F64Regs) { | |
85aaf69f SL |
2296 | const MipsSubtarget &Subtarget = |
2297 | State.getMachineFunction().getTarget() | |
2298 | .getSubtarget<const MipsSubtarget>(); | |
223e47cc | 2299 | |
1a4d82fc | 2300 | static const unsigned IntRegsSize = 4, FloatRegsSize = 2; |
223e47cc | 2301 | |
1a4d82fc JJ |
2302 | static const MCPhysReg IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 }; |
2303 | static const MCPhysReg F32Regs[] = { Mips::F12, Mips::F14 }; | |
223e47cc | 2304 | |
970d7e83 LB |
2305 | // Do not process byval args here. |
2306 | if (ArgFlags.isByVal()) | |
2307 | return true; | |
223e47cc | 2308 | |
85aaf69f SL |
2309 | // Promote i8 and i16 |
2310 | if (ArgFlags.isInReg() && !Subtarget.isLittle()) { | |
2311 | if (LocVT == MVT::i8 || LocVT == MVT::i16 || LocVT == MVT::i32) { | |
2312 | LocVT = MVT::i32; | |
2313 | if (ArgFlags.isSExt()) | |
2314 | LocInfo = CCValAssign::SExtUpper; | |
2315 | else if (ArgFlags.isZExt()) | |
2316 | LocInfo = CCValAssign::ZExtUpper; | |
2317 | else | |
2318 | LocInfo = CCValAssign::AExtUpper; | |
2319 | } | |
2320 | } | |
2321 | ||
223e47cc LB |
2322 | // Promote i8 and i16 |
2323 | if (LocVT == MVT::i8 || LocVT == MVT::i16) { | |
2324 | LocVT = MVT::i32; | |
2325 | if (ArgFlags.isSExt()) | |
2326 | LocInfo = CCValAssign::SExt; | |
2327 | else if (ArgFlags.isZExt()) | |
2328 | LocInfo = CCValAssign::ZExt; | |
2329 | else | |
2330 | LocInfo = CCValAssign::AExt; | |
2331 | } | |
2332 | ||
2333 | unsigned Reg; | |
2334 | ||
2335 | // f32 and f64 are allocated in A0, A1, A2, A3 when either of the following | |
2336 | // is true: function is vararg, argument is 3rd or higher, there is previous | |
2337 | // argument which is not f32 or f64. | |
2338 | bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 | |
2339 | || State.getFirstUnallocated(F32Regs, FloatRegsSize) != ValNo; | |
2340 | unsigned OrigAlign = ArgFlags.getOrigAlign(); | |
2341 | bool isI64 = (ValVT == MVT::i32 && OrigAlign == 8); | |
2342 | ||
2343 | if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) { | |
2344 | Reg = State.AllocateReg(IntRegs, IntRegsSize); | |
2345 | // If this is the first part of an i64 arg, | |
2346 | // the allocated register must be either A0 or A2. | |
2347 | if (isI64 && (Reg == Mips::A1 || Reg == Mips::A3)) | |
2348 | Reg = State.AllocateReg(IntRegs, IntRegsSize); | |
2349 | LocVT = MVT::i32; | |
2350 | } else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) { | |
2351 | // Allocate int register and shadow next int register. If first | |
2352 | // available register is Mips::A1 or Mips::A3, shadow it too. | |
2353 | Reg = State.AllocateReg(IntRegs, IntRegsSize); | |
2354 | if (Reg == Mips::A1 || Reg == Mips::A3) | |
2355 | Reg = State.AllocateReg(IntRegs, IntRegsSize); | |
2356 | State.AllocateReg(IntRegs, IntRegsSize); | |
2357 | LocVT = MVT::i32; | |
2358 | } else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) { | |
2359 | // we are guaranteed to find an available float register | |
2360 | if (ValVT == MVT::f32) { | |
2361 | Reg = State.AllocateReg(F32Regs, FloatRegsSize); | |
2362 | // Shadow int register | |
2363 | State.AllocateReg(IntRegs, IntRegsSize); | |
2364 | } else { | |
2365 | Reg = State.AllocateReg(F64Regs, FloatRegsSize); | |
2366 | // Shadow int registers | |
2367 | unsigned Reg2 = State.AllocateReg(IntRegs, IntRegsSize); | |
2368 | if (Reg2 == Mips::A1 || Reg2 == Mips::A3) | |
2369 | State.AllocateReg(IntRegs, IntRegsSize); | |
2370 | State.AllocateReg(IntRegs, IntRegsSize); | |
2371 | } | |
2372 | } else | |
2373 | llvm_unreachable("Cannot handle this ValVT."); | |
2374 | ||
970d7e83 LB |
2375 | if (!Reg) { |
2376 | unsigned Offset = State.AllocateStack(ValVT.getSizeInBits() >> 3, | |
2377 | OrigAlign); | |
223e47cc | 2378 | State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); |
970d7e83 | 2379 | } else |
223e47cc LB |
2380 | State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); |
2381 | ||
970d7e83 | 2382 | return false; |
223e47cc LB |
2383 | } |
2384 | ||
1a4d82fc JJ |
2385 | static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT, |
2386 | MVT LocVT, CCValAssign::LocInfo LocInfo, | |
2387 | ISD::ArgFlagsTy ArgFlags, CCState &State) { | |
2388 | static const MCPhysReg F64Regs[] = { Mips::D6, Mips::D7 }; | |
2389 | ||
2390 | return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); | |
2391 | } | |
2392 | ||
2393 | static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, | |
2394 | MVT LocVT, CCValAssign::LocInfo LocInfo, | |
2395 | ISD::ArgFlagsTy ArgFlags, CCState &State) { | |
2396 | static const MCPhysReg F64Regs[] = { Mips::D12_64, Mips::D14_64 }; | |
2397 | ||
2398 | return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); | |
2399 | } | |
2400 | ||
85aaf69f SL |
2401 | static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, |
2402 | CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, | |
2403 | CCState &State) LLVM_ATTRIBUTE_UNUSED; | |
2404 | ||
223e47cc LB |
2405 | #include "MipsGenCallingConv.inc" |
2406 | ||
223e47cc LB |
2407 | //===----------------------------------------------------------------------===// |
2408 | // Call Calling Convention Implementation | |
2409 | //===----------------------------------------------------------------------===// | |
2410 | ||
223e47cc LB |
2411 | // Return next O32 integer argument register. |
2412 | static unsigned getNextIntArgReg(unsigned Reg) { | |
2413 | assert((Reg == Mips::A0) || (Reg == Mips::A2)); | |
2414 | return (Reg == Mips::A0) ? Mips::A1 : Mips::A3; | |
2415 | } | |
2416 | ||
970d7e83 LB |
2417 | SDValue |
2418 | MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset, | |
1a4d82fc | 2419 | SDValue Chain, SDValue Arg, SDLoc DL, |
970d7e83 LB |
2420 | bool IsTailCall, SelectionDAG &DAG) const { |
2421 | if (!IsTailCall) { | |
2422 | SDValue PtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr, | |
2423 | DAG.getIntPtrConstant(Offset)); | |
2424 | return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo(), false, | |
2425 | false, 0); | |
223e47cc LB |
2426 | } |
2427 | ||
970d7e83 LB |
2428 | MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); |
2429 | int FI = MFI->CreateFixedObject(Arg.getValueSizeInBits() / 8, Offset, false); | |
2430 | SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); | |
2431 | return DAG.getStore(Chain, DL, Arg, FIN, MachinePointerInfo(), | |
2432 | /*isVolatile=*/ true, false, 0); | |
223e47cc LB |
2433 | } |
2434 | ||
970d7e83 LB |
2435 | void MipsTargetLowering:: |
2436 | getOpndList(SmallVectorImpl<SDValue> &Ops, | |
2437 | std::deque< std::pair<unsigned, SDValue> > &RegsToPass, | |
2438 | bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, | |
1a4d82fc JJ |
2439 | bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, |
2440 | SDValue Chain) const { | |
970d7e83 LB |
2441 | // Insert node "GP copy globalreg" before call to function. |
2442 | // | |
2443 | // R_MIPS_CALL* operators (emitted when non-internal functions are called | |
2444 | // in PIC mode) allow symbols to be resolved via lazy binding. | |
2445 | // The lazy binding stub requires GP to point to the GOT. | |
1a4d82fc JJ |
2446 | // Note that we don't need GP to point to the GOT for indirect calls |
2447 | // (when R_MIPS_CALL* is not used for the call) because Mips linker generates | |
2448 | // lazy binding stub for a function only when R_MIPS_CALL* are the only relocs | |
2449 | // used for the function (that is, Mips linker doesn't generate lazy binding | |
2450 | // stub for a function whose address is taken in the program). | |
2451 | if (IsPICCall && !InternalLinkage && IsCallReloc) { | |
2452 | unsigned GPReg = Subtarget.isABI_N64() ? Mips::GP_64 : Mips::GP; | |
2453 | EVT Ty = Subtarget.isABI_N64() ? MVT::i64 : MVT::i32; | |
970d7e83 LB |
2454 | RegsToPass.push_back(std::make_pair(GPReg, getGlobalReg(CLI.DAG, Ty))); |
2455 | } | |
223e47cc | 2456 | |
970d7e83 LB |
2457 | // Build a sequence of copy-to-reg nodes chained together with token |
2458 | // chain and flag operands which copy the outgoing args into registers. | |
2459 | // The InFlag in necessary since all emitted instructions must be | |
2460 | // stuck together. | |
2461 | SDValue InFlag; | |
223e47cc | 2462 | |
970d7e83 LB |
2463 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { |
2464 | Chain = CLI.DAG.getCopyToReg(Chain, CLI.DL, RegsToPass[i].first, | |
2465 | RegsToPass[i].second, InFlag); | |
2466 | InFlag = Chain.getValue(1); | |
223e47cc LB |
2467 | } |
2468 | ||
970d7e83 LB |
2469 | // Add argument registers to the end of the list so that they are |
2470 | // known live into the call. | |
2471 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) | |
2472 | Ops.push_back(CLI.DAG.getRegister(RegsToPass[i].first, | |
2473 | RegsToPass[i].second.getValueType())); | |
223e47cc | 2474 | |
970d7e83 | 2475 | // Add a register mask operand representing the call-preserved registers. |
1a4d82fc JJ |
2476 | const TargetRegisterInfo *TRI = |
2477 | getTargetMachine().getSubtargetImpl()->getRegisterInfo(); | |
970d7e83 LB |
2478 | const uint32_t *Mask = TRI->getCallPreservedMask(CLI.CallConv); |
2479 | assert(Mask && "Missing call preserved mask for calling convention"); | |
1a4d82fc JJ |
2480 | if (Subtarget.inMips16HardFloat()) { |
2481 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(CLI.Callee)) { | |
2482 | llvm::StringRef Sym = G->getGlobal()->getName(); | |
2483 | Function *F = G->getGlobal()->getParent()->getFunction(Sym); | |
2484 | if (F && F->hasFnAttribute("__Mips16RetHelper")) { | |
2485 | Mask = MipsRegisterInfo::getMips16RetHelperMask(); | |
2486 | } | |
2487 | } | |
2488 | } | |
970d7e83 LB |
2489 | Ops.push_back(CLI.DAG.getRegisterMask(Mask)); |
2490 | ||
2491 | if (InFlag.getNode()) | |
2492 | Ops.push_back(InFlag); | |
223e47cc LB |
2493 | } |
2494 | ||
2495 | /// LowerCall - functions arguments are copied from virtual regs to | |
2496 | /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. | |
223e47cc LB |
2497 | SDValue |
2498 | MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, | |
2499 | SmallVectorImpl<SDValue> &InVals) const { | |
2500 | SelectionDAG &DAG = CLI.DAG; | |
1a4d82fc JJ |
2501 | SDLoc DL = CLI.DL; |
2502 | SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; | |
2503 | SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; | |
2504 | SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; | |
223e47cc LB |
2505 | SDValue Chain = CLI.Chain; |
2506 | SDValue Callee = CLI.Callee; | |
970d7e83 | 2507 | bool &IsTailCall = CLI.IsTailCall; |
223e47cc | 2508 | CallingConv::ID CallConv = CLI.CallConv; |
970d7e83 | 2509 | bool IsVarArg = CLI.IsVarArg; |
223e47cc LB |
2510 | |
2511 | MachineFunction &MF = DAG.getMachineFunction(); | |
2512 | MachineFrameInfo *MFI = MF.getFrameInfo(); | |
1a4d82fc JJ |
2513 | const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); |
2514 | MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); | |
223e47cc | 2515 | bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; |
223e47cc LB |
2516 | |
2517 | // Analyze operands of the call, assigning locations to each operand. | |
2518 | SmallVector<CCValAssign, 16> ArgLocs; | |
85aaf69f SL |
2519 | MipsCCState CCInfo( |
2520 | CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext(), | |
2521 | MipsCCState::getSpecialCallingConvForCallee(Callee.getNode(), Subtarget)); | |
2522 | ||
2523 | // Allocate the reserved argument area. It seems strange to do this from the | |
2524 | // caller side but removing it breaks the frame size calculation. | |
2525 | const MipsABIInfo &ABI = Subtarget.getABI(); | |
2526 | CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); | |
223e47cc | 2527 | |
85aaf69f | 2528 | CCInfo.AnalyzeCallOperands(Outs, CC_Mips, CLI.getArgs(), Callee.getNode()); |
223e47cc LB |
2529 | |
2530 | // Get a count of how many bytes are to be pushed on the stack. | |
2531 | unsigned NextStackOffset = CCInfo.getNextStackOffset(); | |
223e47cc | 2532 | |
970d7e83 LB |
2533 | // Check if it's really possible to do a tail call. |
2534 | if (IsTailCall) | |
85aaf69f SL |
2535 | IsTailCall = isEligibleForTailCallOptimization( |
2536 | CCInfo, NextStackOffset, *MF.getInfo<MipsFunctionInfo>()); | |
970d7e83 | 2537 | |
1a4d82fc JJ |
2538 | if (!IsTailCall && CLI.CS && CLI.CS->isMustTailCall()) |
2539 | report_fatal_error("failed to perform tail call elimination on a call " | |
2540 | "site marked musttail"); | |
2541 | ||
970d7e83 LB |
2542 | if (IsTailCall) |
2543 | ++NumTailCalls; | |
223e47cc LB |
2544 | |
2545 | // Chain is the output chain of the last Load/Store or CopyToReg node. | |
2546 | // ByValChain is the output chain of the last Memcpy node created for copying | |
2547 | // byval arguments to the stack. | |
970d7e83 LB |
2548 | unsigned StackAlignment = TFL->getStackAlignment(); |
2549 | NextStackOffset = RoundUpToAlignment(NextStackOffset, StackAlignment); | |
2550 | SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true); | |
223e47cc | 2551 | |
970d7e83 | 2552 | if (!IsTailCall) |
1a4d82fc | 2553 | Chain = DAG.getCALLSEQ_START(Chain, NextStackOffsetVal, DL); |
970d7e83 | 2554 | |
1a4d82fc JJ |
2555 | SDValue StackPtr = DAG.getCopyFromReg( |
2556 | Chain, DL, Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP, | |
2557 | getPointerTy()); | |
223e47cc | 2558 | |
223e47cc | 2559 | // With EABI is it possible to have 16 args on registers. |
970d7e83 | 2560 | std::deque< std::pair<unsigned, SDValue> > RegsToPass; |
223e47cc | 2561 | SmallVector<SDValue, 8> MemOpChains; |
85aaf69f SL |
2562 | |
2563 | CCInfo.rewindByValRegsInfo(); | |
223e47cc LB |
2564 | |
2565 | // Walk the register/memloc assignments, inserting copies/loads. | |
2566 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | |
2567 | SDValue Arg = OutVals[i]; | |
2568 | CCValAssign &VA = ArgLocs[i]; | |
2569 | MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT(); | |
2570 | ISD::ArgFlagsTy Flags = Outs[i].Flags; | |
85aaf69f | 2571 | bool UseUpperBits = false; |
223e47cc LB |
2572 | |
2573 | // ByVal Arg. | |
2574 | if (Flags.isByVal()) { | |
85aaf69f SL |
2575 | unsigned FirstByValReg, LastByValReg; |
2576 | unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); | |
2577 | CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); | |
2578 | ||
223e47cc LB |
2579 | assert(Flags.getByValSize() && |
2580 | "ByVal args of size 0 should have been ignored by front-end."); | |
85aaf69f | 2581 | assert(ByValIdx < CCInfo.getInRegsParamsCount()); |
970d7e83 LB |
2582 | assert(!IsTailCall && |
2583 | "Do not tail-call optimize if there is a byval argument."); | |
2584 | passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg, | |
85aaf69f SL |
2585 | FirstByValReg, LastByValReg, Flags, Subtarget.isLittle(), |
2586 | VA); | |
2587 | CCInfo.nextInRegsParam(); | |
223e47cc LB |
2588 | continue; |
2589 | } | |
2590 | ||
2591 | // Promote the value if needed. | |
2592 | switch (VA.getLocInfo()) { | |
85aaf69f SL |
2593 | default: |
2594 | llvm_unreachable("Unknown loc info!"); | |
223e47cc LB |
2595 | case CCValAssign::Full: |
2596 | if (VA.isRegLoc()) { | |
2597 | if ((ValVT == MVT::f32 && LocVT == MVT::i32) || | |
970d7e83 LB |
2598 | (ValVT == MVT::f64 && LocVT == MVT::i64) || |
2599 | (ValVT == MVT::i64 && LocVT == MVT::f64)) | |
2600 | Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); | |
223e47cc | 2601 | else if (ValVT == MVT::f64 && LocVT == MVT::i32) { |
970d7e83 | 2602 | SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, |
223e47cc | 2603 | Arg, DAG.getConstant(0, MVT::i32)); |
970d7e83 | 2604 | SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, |
223e47cc | 2605 | Arg, DAG.getConstant(1, MVT::i32)); |
1a4d82fc | 2606 | if (!Subtarget.isLittle()) |
223e47cc LB |
2607 | std::swap(Lo, Hi); |
2608 | unsigned LocRegLo = VA.getLocReg(); | |
2609 | unsigned LocRegHigh = getNextIntArgReg(LocRegLo); | |
2610 | RegsToPass.push_back(std::make_pair(LocRegLo, Lo)); | |
2611 | RegsToPass.push_back(std::make_pair(LocRegHigh, Hi)); | |
2612 | continue; | |
2613 | } | |
2614 | } | |
2615 | break; | |
85aaf69f SL |
2616 | case CCValAssign::BCvt: |
2617 | Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); | |
2618 | break; | |
2619 | case CCValAssign::SExtUpper: | |
2620 | UseUpperBits = true; | |
2621 | // Fallthrough | |
223e47cc | 2622 | case CCValAssign::SExt: |
970d7e83 | 2623 | Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, LocVT, Arg); |
223e47cc | 2624 | break; |
85aaf69f SL |
2625 | case CCValAssign::ZExtUpper: |
2626 | UseUpperBits = true; | |
2627 | // Fallthrough | |
223e47cc | 2628 | case CCValAssign::ZExt: |
970d7e83 | 2629 | Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, LocVT, Arg); |
223e47cc | 2630 | break; |
85aaf69f SL |
2631 | case CCValAssign::AExtUpper: |
2632 | UseUpperBits = true; | |
2633 | // Fallthrough | |
223e47cc | 2634 | case CCValAssign::AExt: |
970d7e83 | 2635 | Arg = DAG.getNode(ISD::ANY_EXTEND, DL, LocVT, Arg); |
223e47cc LB |
2636 | break; |
2637 | } | |
2638 | ||
85aaf69f SL |
2639 | if (UseUpperBits) { |
2640 | unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); | |
2641 | unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); | |
2642 | Arg = DAG.getNode( | |
2643 | ISD::SHL, DL, VA.getLocVT(), Arg, | |
2644 | DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); | |
2645 | } | |
2646 | ||
223e47cc LB |
2647 | // Arguments that can be passed on register must be kept at |
2648 | // RegsToPass vector | |
2649 | if (VA.isRegLoc()) { | |
2650 | RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); | |
2651 | continue; | |
2652 | } | |
2653 | ||
2654 | // Register can't get to this point... | |
2655 | assert(VA.isMemLoc()); | |
2656 | ||
2657 | // emit ISD::STORE whichs stores the | |
2658 | // parameter value to a stack Location | |
970d7e83 LB |
2659 | MemOpChains.push_back(passArgOnStack(StackPtr, VA.getLocMemOffset(), |
2660 | Chain, Arg, DL, IsTailCall, DAG)); | |
223e47cc LB |
2661 | } |
2662 | ||
2663 | // Transform all store nodes into one single node because all store | |
2664 | // nodes are independent of each other. | |
2665 | if (!MemOpChains.empty()) | |
1a4d82fc | 2666 | Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); |
223e47cc LB |
2667 | |
2668 | // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every | |
2669 | // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol | |
2670 | // node so that legalize doesn't hack it. | |
1a4d82fc JJ |
2671 | bool IsPICCall = |
2672 | (Subtarget.isABI_N64() || IsPIC); // true if calls are translated to | |
2673 | // jalr $25 | |
2674 | bool GlobalOrExternal = false, InternalLinkage = false, IsCallReloc = false; | |
223e47cc | 2675 | SDValue CalleeLo; |
1a4d82fc | 2676 | EVT Ty = Callee.getValueType(); |
223e47cc LB |
2677 | |
2678 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { | |
970d7e83 | 2679 | if (IsPICCall) { |
1a4d82fc JJ |
2680 | const GlobalValue *Val = G->getGlobal(); |
2681 | InternalLinkage = Val->hasInternalLinkage(); | |
970d7e83 LB |
2682 | |
2683 | if (InternalLinkage) | |
85aaf69f | 2684 | Callee = getAddrLocal(G, DL, Ty, DAG, |
1a4d82fc JJ |
2685 | Subtarget.isABI_N32() || Subtarget.isABI_N64()); |
2686 | else if (LargeGOT) { | |
85aaf69f | 2687 | Callee = getAddrGlobalLargeGOT(G, DL, Ty, DAG, MipsII::MO_CALL_HI16, |
1a4d82fc JJ |
2688 | MipsII::MO_CALL_LO16, Chain, |
2689 | FuncInfo->callPtrInfo(Val)); | |
2690 | IsCallReloc = true; | |
2691 | } else { | |
85aaf69f | 2692 | Callee = getAddrGlobal(G, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain, |
1a4d82fc JJ |
2693 | FuncInfo->callPtrInfo(Val)); |
2694 | IsCallReloc = true; | |
2695 | } | |
970d7e83 LB |
2696 | } else |
2697 | Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0, | |
2698 | MipsII::MO_NO_FLAG); | |
223e47cc LB |
2699 | GlobalOrExternal = true; |
2700 | } | |
2701 | else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { | |
1a4d82fc JJ |
2702 | const char *Sym = S->getSymbol(); |
2703 | ||
2704 | if (!Subtarget.isABI_N64() && !IsPIC) // !N64 && static | |
85aaf69f SL |
2705 | Callee = |
2706 | DAG.getTargetExternalSymbol(Sym, getPointerTy(), MipsII::MO_NO_FLAG); | |
1a4d82fc | 2707 | else if (LargeGOT) { |
85aaf69f | 2708 | Callee = getAddrGlobalLargeGOT(S, DL, Ty, DAG, MipsII::MO_CALL_HI16, |
1a4d82fc JJ |
2709 | MipsII::MO_CALL_LO16, Chain, |
2710 | FuncInfo->callPtrInfo(Sym)); | |
2711 | IsCallReloc = true; | |
2712 | } else { // N64 || PIC | |
85aaf69f | 2713 | Callee = getAddrGlobal(S, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain, |
1a4d82fc JJ |
2714 | FuncInfo->callPtrInfo(Sym)); |
2715 | IsCallReloc = true; | |
2716 | } | |
223e47cc | 2717 | |
970d7e83 | 2718 | GlobalOrExternal = true; |
223e47cc LB |
2719 | } |
2720 | ||
970d7e83 | 2721 | SmallVector<SDValue, 8> Ops(1, Chain); |
223e47cc | 2722 | SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); |
223e47cc | 2723 | |
970d7e83 | 2724 | getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, InternalLinkage, |
1a4d82fc | 2725 | IsCallReloc, CLI, Callee, Chain); |
223e47cc | 2726 | |
970d7e83 | 2727 | if (IsTailCall) |
1a4d82fc | 2728 | return DAG.getNode(MipsISD::TailCall, DL, MVT::Other, Ops); |
223e47cc | 2729 | |
1a4d82fc | 2730 | Chain = DAG.getNode(MipsISD::JmpLink, DL, NodeTys, Ops); |
970d7e83 | 2731 | SDValue InFlag = Chain.getValue(1); |
223e47cc LB |
2732 | |
2733 | // Create the CALLSEQ_END node. | |
2734 | Chain = DAG.getCALLSEQ_END(Chain, NextStackOffsetVal, | |
1a4d82fc | 2735 | DAG.getIntPtrConstant(0, true), InFlag, DL); |
223e47cc LB |
2736 | InFlag = Chain.getValue(1); |
2737 | ||
2738 | // Handle result values, copying them out of physregs into vregs that we | |
2739 | // return. | |
1a4d82fc JJ |
2740 | return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG, |
2741 | InVals, CLI); | |
223e47cc LB |
2742 | } |
2743 | ||
2744 | /// LowerCallResult - Lower the result values of a call into the | |
2745 | /// appropriate copies out of appropriate physical registers. | |
1a4d82fc JJ |
2746 | SDValue MipsTargetLowering::LowerCallResult( |
2747 | SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, | |
2748 | const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG, | |
2749 | SmallVectorImpl<SDValue> &InVals, | |
2750 | TargetLowering::CallLoweringInfo &CLI) const { | |
223e47cc LB |
2751 | // Assign locations to each value returned by this call. |
2752 | SmallVector<CCValAssign, 16> RVLocs; | |
1a4d82fc JJ |
2753 | MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, |
2754 | *DAG.getContext()); | |
2755 | CCInfo.AnalyzeCallResult(Ins, RetCC_Mips, CLI); | |
223e47cc LB |
2756 | |
2757 | // Copy all of the result registers out of their specified physreg. | |
2758 | for (unsigned i = 0; i != RVLocs.size(); ++i) { | |
1a4d82fc JJ |
2759 | CCValAssign &VA = RVLocs[i]; |
2760 | assert(VA.isRegLoc() && "Can only return in registers!"); | |
2761 | ||
970d7e83 LB |
2762 | SDValue Val = DAG.getCopyFromReg(Chain, DL, RVLocs[i].getLocReg(), |
2763 | RVLocs[i].getLocVT(), InFlag); | |
2764 | Chain = Val.getValue(1); | |
2765 | InFlag = Val.getValue(2); | |
2766 | ||
1a4d82fc JJ |
2767 | if (VA.isUpperBitsInLoc()) { |
2768 | unsigned ValSizeInBits = Ins[i].ArgVT.getSizeInBits(); | |
2769 | unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); | |
2770 | unsigned Shift = | |
2771 | VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; | |
2772 | Val = DAG.getNode( | |
2773 | Shift, DL, VA.getLocVT(), Val, | |
2774 | DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); | |
2775 | } | |
2776 | ||
2777 | switch (VA.getLocInfo()) { | |
2778 | default: | |
2779 | llvm_unreachable("Unknown loc info!"); | |
2780 | case CCValAssign::Full: | |
2781 | break; | |
2782 | case CCValAssign::BCvt: | |
2783 | Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val); | |
2784 | break; | |
2785 | case CCValAssign::AExt: | |
2786 | case CCValAssign::AExtUpper: | |
2787 | Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); | |
2788 | break; | |
2789 | case CCValAssign::ZExt: | |
2790 | case CCValAssign::ZExtUpper: | |
2791 | Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val, | |
2792 | DAG.getValueType(VA.getValVT())); | |
2793 | Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); | |
2794 | break; | |
2795 | case CCValAssign::SExt: | |
2796 | case CCValAssign::SExtUpper: | |
2797 | Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val, | |
2798 | DAG.getValueType(VA.getValVT())); | |
2799 | Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); | |
2800 | break; | |
2801 | } | |
970d7e83 LB |
2802 | |
2803 | InVals.push_back(Val); | |
223e47cc LB |
2804 | } |
2805 | ||
2806 | return Chain; | |
2807 | } | |
2808 | ||
85aaf69f SL |
2809 | static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA, |
2810 | EVT ArgVT, SDLoc DL, SelectionDAG &DAG) { | |
2811 | MVT LocVT = VA.getLocVT(); | |
2812 | EVT ValVT = VA.getValVT(); | |
2813 | ||
2814 | // Shift into the upper bits if necessary. | |
2815 | switch (VA.getLocInfo()) { | |
2816 | default: | |
2817 | break; | |
2818 | case CCValAssign::AExtUpper: | |
2819 | case CCValAssign::SExtUpper: | |
2820 | case CCValAssign::ZExtUpper: { | |
2821 | unsigned ValSizeInBits = ArgVT.getSizeInBits(); | |
2822 | unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); | |
2823 | unsigned Opcode = | |
2824 | VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; | |
2825 | Val = DAG.getNode( | |
2826 | Opcode, DL, VA.getLocVT(), Val, | |
2827 | DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); | |
2828 | break; | |
2829 | } | |
2830 | } | |
2831 | ||
2832 | // If this is an value smaller than the argument slot size (32-bit for O32, | |
2833 | // 64-bit for N32/N64), it has been promoted in some way to the argument slot | |
2834 | // size. Extract the value and insert any appropriate assertions regarding | |
2835 | // sign/zero extension. | |
2836 | switch (VA.getLocInfo()) { | |
2837 | default: | |
2838 | llvm_unreachable("Unknown loc info!"); | |
2839 | case CCValAssign::Full: | |
2840 | break; | |
2841 | case CCValAssign::AExtUpper: | |
2842 | case CCValAssign::AExt: | |
2843 | Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); | |
2844 | break; | |
2845 | case CCValAssign::SExtUpper: | |
2846 | case CCValAssign::SExt: | |
2847 | Val = DAG.getNode(ISD::AssertSext, DL, LocVT, Val, DAG.getValueType(ValVT)); | |
2848 | Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); | |
2849 | break; | |
2850 | case CCValAssign::ZExtUpper: | |
2851 | case CCValAssign::ZExt: | |
2852 | Val = DAG.getNode(ISD::AssertZext, DL, LocVT, Val, DAG.getValueType(ValVT)); | |
2853 | Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); | |
2854 | break; | |
2855 | case CCValAssign::BCvt: | |
2856 | Val = DAG.getNode(ISD::BITCAST, DL, ValVT, Val); | |
2857 | break; | |
2858 | } | |
2859 | ||
2860 | return Val; | |
2861 | } | |
2862 | ||
223e47cc LB |
2863 | //===----------------------------------------------------------------------===// |
2864 | // Formal Arguments Calling Convention Implementation | |
2865 | //===----------------------------------------------------------------------===// | |
223e47cc LB |
2866 | /// LowerFormalArguments - transform physical registers into virtual registers |
2867 | /// and generate load operations for arguments places on the stack. | |
2868 | SDValue | |
2869 | MipsTargetLowering::LowerFormalArguments(SDValue Chain, | |
2870 | CallingConv::ID CallConv, | |
970d7e83 | 2871 | bool IsVarArg, |
223e47cc | 2872 | const SmallVectorImpl<ISD::InputArg> &Ins, |
1a4d82fc | 2873 | SDLoc DL, SelectionDAG &DAG, |
223e47cc LB |
2874 | SmallVectorImpl<SDValue> &InVals) |
2875 | const { | |
2876 | MachineFunction &MF = DAG.getMachineFunction(); | |
2877 | MachineFrameInfo *MFI = MF.getFrameInfo(); | |
2878 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); | |
2879 | ||
2880 | MipsFI->setVarArgsFrameIndex(0); | |
2881 | ||
2882 | // Used with vargs to acumulate store chains. | |
2883 | std::vector<SDValue> OutChains; | |
2884 | ||
2885 | // Assign locations to all of the incoming arguments. | |
2886 | SmallVector<CCValAssign, 16> ArgLocs; | |
85aaf69f SL |
2887 | MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, |
2888 | *DAG.getContext()); | |
2889 | const MipsABIInfo &ABI = Subtarget.getABI(); | |
2890 | CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); | |
223e47cc LB |
2891 | Function::const_arg_iterator FuncArg = |
2892 | DAG.getMachineFunction().getFunction()->arg_begin(); | |
970d7e83 | 2893 | |
85aaf69f | 2894 | CCInfo.AnalyzeFormalArguments(Ins, CC_Mips_FixedArg); |
970d7e83 | 2895 | MipsFI->setFormalArgInfo(CCInfo.getNextStackOffset(), |
85aaf69f | 2896 | CCInfo.getInRegsParamsCount() > 0); |
223e47cc | 2897 | |
970d7e83 | 2898 | unsigned CurArgIdx = 0; |
85aaf69f | 2899 | CCInfo.rewindByValRegsInfo(); |
970d7e83 LB |
2900 | |
2901 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | |
223e47cc | 2902 | CCValAssign &VA = ArgLocs[i]; |
970d7e83 LB |
2903 | std::advance(FuncArg, Ins[i].OrigArgIndex - CurArgIdx); |
2904 | CurArgIdx = Ins[i].OrigArgIndex; | |
223e47cc LB |
2905 | EVT ValVT = VA.getValVT(); |
2906 | ISD::ArgFlagsTy Flags = Ins[i].Flags; | |
2907 | bool IsRegLoc = VA.isRegLoc(); | |
2908 | ||
2909 | if (Flags.isByVal()) { | |
85aaf69f SL |
2910 | unsigned FirstByValReg, LastByValReg; |
2911 | unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); | |
2912 | CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); | |
2913 | ||
223e47cc LB |
2914 | assert(Flags.getByValSize() && |
2915 | "ByVal args of size 0 should have been ignored by front-end."); | |
85aaf69f | 2916 | assert(ByValIdx < CCInfo.getInRegsParamsCount()); |
970d7e83 | 2917 | copyByValRegs(Chain, DL, OutChains, DAG, Flags, InVals, &*FuncArg, |
85aaf69f SL |
2918 | FirstByValReg, LastByValReg, VA, CCInfo); |
2919 | CCInfo.nextInRegsParam(); | |
223e47cc LB |
2920 | continue; |
2921 | } | |
2922 | ||
2923 | // Arguments stored on registers | |
2924 | if (IsRegLoc) { | |
1a4d82fc | 2925 | MVT RegVT = VA.getLocVT(); |
223e47cc | 2926 | unsigned ArgReg = VA.getLocReg(); |
1a4d82fc | 2927 | const TargetRegisterClass *RC = getRegClassFor(RegVT); |
223e47cc LB |
2928 | |
2929 | // Transform the arguments stored on | |
2930 | // physical registers into virtual ones | |
970d7e83 LB |
2931 | unsigned Reg = addLiveIn(DAG.getMachineFunction(), ArgReg, RC); |
2932 | SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); | |
223e47cc | 2933 | |
85aaf69f | 2934 | ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); |
223e47cc | 2935 | |
970d7e83 LB |
2936 | // Handle floating point arguments passed in integer registers and |
2937 | // long double arguments passed in floating point registers. | |
223e47cc | 2938 | if ((RegVT == MVT::i32 && ValVT == MVT::f32) || |
970d7e83 LB |
2939 | (RegVT == MVT::i64 && ValVT == MVT::f64) || |
2940 | (RegVT == MVT::f64 && ValVT == MVT::i64)) | |
2941 | ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); | |
1a4d82fc JJ |
2942 | else if (Subtarget.isABI_O32() && RegVT == MVT::i32 && |
2943 | ValVT == MVT::f64) { | |
970d7e83 | 2944 | unsigned Reg2 = addLiveIn(DAG.getMachineFunction(), |
223e47cc | 2945 | getNextIntArgReg(ArgReg), RC); |
970d7e83 | 2946 | SDValue ArgValue2 = DAG.getCopyFromReg(Chain, DL, Reg2, RegVT); |
1a4d82fc | 2947 | if (!Subtarget.isLittle()) |
223e47cc | 2948 | std::swap(ArgValue, ArgValue2); |
970d7e83 | 2949 | ArgValue = DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, |
223e47cc LB |
2950 | ArgValue, ArgValue2); |
2951 | } | |
2952 | ||
2953 | InVals.push_back(ArgValue); | |
2954 | } else { // VA.isRegLoc() | |
85aaf69f SL |
2955 | MVT LocVT = VA.getLocVT(); |
2956 | ||
2957 | if (Subtarget.isABI_O32()) { | |
2958 | // We ought to be able to use LocVT directly but O32 sets it to i32 | |
2959 | // when allocating floating point values to integer registers. | |
2960 | // This shouldn't influence how we load the value into registers unless | |
2961 | // we are targetting softfloat. | |
2962 | if (VA.getValVT().isFloatingPoint() && !Subtarget.abiUsesSoftFloat()) | |
2963 | LocVT = VA.getValVT(); | |
2964 | } | |
223e47cc LB |
2965 | |
2966 | // sanity check | |
2967 | assert(VA.isMemLoc()); | |
2968 | ||
2969 | // The stack pointer offset is relative to the caller stack frame. | |
85aaf69f | 2970 | int FI = MFI->CreateFixedObject(LocVT.getSizeInBits() / 8, |
223e47cc LB |
2971 | VA.getLocMemOffset(), true); |
2972 | ||
2973 | // Create load nodes to retrieve arguments from the stack | |
970d7e83 | 2974 | SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); |
85aaf69f SL |
2975 | SDValue ArgValue = DAG.getLoad(LocVT, DL, Chain, FIN, |
2976 | MachinePointerInfo::getFixedStack(FI), | |
2977 | false, false, false, 0); | |
2978 | OutChains.push_back(ArgValue.getValue(1)); | |
2979 | ||
2980 | ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); | |
2981 | ||
2982 | InVals.push_back(ArgValue); | |
223e47cc LB |
2983 | } |
2984 | } | |
2985 | ||
1a4d82fc JJ |
2986 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { |
2987 | // The mips ABIs for returning structs by value requires that we copy | |
2988 | // the sret argument into $v0 for the return. Save the argument into | |
2989 | // a virtual register so that we can access it from the return points. | |
2990 | if (Ins[i].Flags.isSRet()) { | |
2991 | unsigned Reg = MipsFI->getSRetReturnReg(); | |
2992 | if (!Reg) { | |
2993 | Reg = MF.getRegInfo().createVirtualRegister( | |
2994 | getRegClassFor(Subtarget.isABI_N64() ? MVT::i64 : MVT::i32)); | |
2995 | MipsFI->setSRetReturnReg(Reg); | |
2996 | } | |
2997 | SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]); | |
2998 | Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain); | |
2999 | break; | |
223e47cc | 3000 | } |
223e47cc LB |
3001 | } |
3002 | ||
970d7e83 | 3003 | if (IsVarArg) |
85aaf69f | 3004 | writeVarArgRegs(OutChains, Chain, DL, DAG, CCInfo); |
223e47cc LB |
3005 | |
3006 | // All stores are grouped in one node to allow the matching between | |
3007 | // the size of Ins and InVals. This only happens when on varg functions | |
3008 | if (!OutChains.empty()) { | |
3009 | OutChains.push_back(Chain); | |
1a4d82fc | 3010 | Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); |
223e47cc LB |
3011 | } |
3012 | ||
3013 | return Chain; | |
3014 | } | |
3015 | ||
3016 | //===----------------------------------------------------------------------===// | |
3017 | // Return Value Calling Convention Implementation | |
3018 | //===----------------------------------------------------------------------===// | |
3019 | ||
970d7e83 LB |
3020 | bool |
3021 | MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv, | |
3022 | MachineFunction &MF, bool IsVarArg, | |
3023 | const SmallVectorImpl<ISD::OutputArg> &Outs, | |
3024 | LLVMContext &Context) const { | |
3025 | SmallVector<CCValAssign, 16> RVLocs; | |
1a4d82fc | 3026 | MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); |
970d7e83 LB |
3027 | return CCInfo.CheckReturn(Outs, RetCC_Mips); |
3028 | } | |
3029 | ||
223e47cc LB |
3030 | SDValue |
3031 | MipsTargetLowering::LowerReturn(SDValue Chain, | |
970d7e83 | 3032 | CallingConv::ID CallConv, bool IsVarArg, |
223e47cc LB |
3033 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
3034 | const SmallVectorImpl<SDValue> &OutVals, | |
1a4d82fc | 3035 | SDLoc DL, SelectionDAG &DAG) const { |
223e47cc LB |
3036 | // CCValAssign - represent the assignment of |
3037 | // the return value to a location | |
3038 | SmallVector<CCValAssign, 16> RVLocs; | |
970d7e83 | 3039 | MachineFunction &MF = DAG.getMachineFunction(); |
223e47cc LB |
3040 | |
3041 | // CCState - Info about the registers and stack slot. | |
1a4d82fc | 3042 | MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); |
223e47cc | 3043 | |
970d7e83 | 3044 | // Analyze return values. |
1a4d82fc | 3045 | CCInfo.AnalyzeReturn(Outs, RetCC_Mips); |
223e47cc LB |
3046 | |
3047 | SDValue Flag; | |
970d7e83 | 3048 | SmallVector<SDValue, 4> RetOps(1, Chain); |
223e47cc LB |
3049 | |
3050 | // Copy the result values into the output registers. | |
3051 | for (unsigned i = 0; i != RVLocs.size(); ++i) { | |
970d7e83 | 3052 | SDValue Val = OutVals[i]; |
223e47cc LB |
3053 | CCValAssign &VA = RVLocs[i]; |
3054 | assert(VA.isRegLoc() && "Can only return in registers!"); | |
1a4d82fc | 3055 | bool UseUpperBits = false; |
223e47cc | 3056 | |
1a4d82fc JJ |
3057 | switch (VA.getLocInfo()) { |
3058 | default: | |
3059 | llvm_unreachable("Unknown loc info!"); | |
3060 | case CCValAssign::Full: | |
3061 | break; | |
3062 | case CCValAssign::BCvt: | |
3063 | Val = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Val); | |
3064 | break; | |
3065 | case CCValAssign::AExtUpper: | |
3066 | UseUpperBits = true; | |
3067 | // Fallthrough | |
3068 | case CCValAssign::AExt: | |
3069 | Val = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Val); | |
3070 | break; | |
3071 | case CCValAssign::ZExtUpper: | |
3072 | UseUpperBits = true; | |
3073 | // Fallthrough | |
3074 | case CCValAssign::ZExt: | |
3075 | Val = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Val); | |
3076 | break; | |
3077 | case CCValAssign::SExtUpper: | |
3078 | UseUpperBits = true; | |
3079 | // Fallthrough | |
3080 | case CCValAssign::SExt: | |
3081 | Val = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Val); | |
3082 | break; | |
3083 | } | |
3084 | ||
3085 | if (UseUpperBits) { | |
3086 | unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); | |
3087 | unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); | |
3088 | Val = DAG.getNode( | |
3089 | ISD::SHL, DL, VA.getLocVT(), Val, | |
3090 | DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); | |
3091 | } | |
970d7e83 LB |
3092 | |
3093 | Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag); | |
223e47cc | 3094 | |
970d7e83 | 3095 | // Guarantee that all emitted copies are stuck together with flags. |
223e47cc | 3096 | Flag = Chain.getValue(1); |
970d7e83 | 3097 | RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); |
223e47cc LB |
3098 | } |
3099 | ||
3100 | // The mips ABIs for returning structs by value requires that we copy | |
3101 | // the sret argument into $v0 for the return. We saved the argument into | |
3102 | // a virtual register in the entry block, so now we copy the value out | |
3103 | // and into $v0. | |
970d7e83 | 3104 | if (MF.getFunction()->hasStructRetAttr()) { |
223e47cc LB |
3105 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
3106 | unsigned Reg = MipsFI->getSRetReturnReg(); | |
3107 | ||
3108 | if (!Reg) | |
3109 | llvm_unreachable("sret virtual register not created in the entry block"); | |
970d7e83 | 3110 | SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy()); |
1a4d82fc | 3111 | unsigned V0 = Subtarget.isABI_N64() ? Mips::V0_64 : Mips::V0; |
223e47cc | 3112 | |
970d7e83 | 3113 | Chain = DAG.getCopyToReg(Chain, DL, V0, Val, Flag); |
223e47cc | 3114 | Flag = Chain.getValue(1); |
970d7e83 | 3115 | RetOps.push_back(DAG.getRegister(V0, getPointerTy())); |
223e47cc LB |
3116 | } |
3117 | ||
970d7e83 LB |
3118 | RetOps[0] = Chain; // Update chain. |
3119 | ||
3120 | // Add the flag if we have it. | |
223e47cc | 3121 | if (Flag.getNode()) |
970d7e83 | 3122 | RetOps.push_back(Flag); |
223e47cc | 3123 | |
970d7e83 | 3124 | // Return on Mips is always a "jr $ra" |
1a4d82fc | 3125 | return DAG.getNode(MipsISD::Ret, DL, MVT::Other, RetOps); |
223e47cc LB |
3126 | } |
3127 | ||
3128 | //===----------------------------------------------------------------------===// | |
3129 | // Mips Inline Assembly Support | |
3130 | //===----------------------------------------------------------------------===// | |
3131 | ||
3132 | /// getConstraintType - Given a constraint letter, return the type of | |
3133 | /// constraint it is for this target. | |
3134 | MipsTargetLowering::ConstraintType MipsTargetLowering:: | |
3135 | getConstraintType(const std::string &Constraint) const | |
3136 | { | |
1a4d82fc | 3137 | // Mips specific constraints |
223e47cc LB |
3138 | // GCC config/mips/constraints.md |
3139 | // | |
3140 | // 'd' : An address register. Equivalent to r | |
3141 | // unless generating MIPS16 code. | |
3142 | // 'y' : Equivalent to r; retained for | |
3143 | // backwards compatibility. | |
3144 | // 'c' : A register suitable for use in an indirect | |
3145 | // jump. This will always be $25 for -mabicalls. | |
3146 | // 'l' : The lo register. 1 word storage. | |
3147 | // 'x' : The hilo register pair. Double word storage. | |
3148 | if (Constraint.size() == 1) { | |
3149 | switch (Constraint[0]) { | |
3150 | default : break; | |
3151 | case 'd': | |
3152 | case 'y': | |
3153 | case 'f': | |
3154 | case 'c': | |
3155 | case 'l': | |
3156 | case 'x': | |
3157 | return C_RegisterClass; | |
970d7e83 LB |
3158 | case 'R': |
3159 | return C_Memory; | |
223e47cc LB |
3160 | } |
3161 | } | |
3162 | return TargetLowering::getConstraintType(Constraint); | |
3163 | } | |
3164 | ||
3165 | /// Examine constraint type and operand type and determine a weight value. | |
3166 | /// This object must already have been set up with the operand type | |
3167 | /// and the current alternative constraint selected. | |
3168 | TargetLowering::ConstraintWeight | |
3169 | MipsTargetLowering::getSingleConstraintMatchWeight( | |
3170 | AsmOperandInfo &info, const char *constraint) const { | |
3171 | ConstraintWeight weight = CW_Invalid; | |
3172 | Value *CallOperandVal = info.CallOperandVal; | |
3173 | // If we don't have a value, we can't do a match, | |
3174 | // but allow it at the lowest weight. | |
1a4d82fc | 3175 | if (!CallOperandVal) |
223e47cc LB |
3176 | return CW_Default; |
3177 | Type *type = CallOperandVal->getType(); | |
3178 | // Look at the constraint type. | |
3179 | switch (*constraint) { | |
3180 | default: | |
3181 | weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); | |
3182 | break; | |
3183 | case 'd': | |
3184 | case 'y': | |
3185 | if (type->isIntegerTy()) | |
3186 | weight = CW_Register; | |
3187 | break; | |
1a4d82fc JJ |
3188 | case 'f': // FPU or MSA register |
3189 | if (Subtarget.hasMSA() && type->isVectorTy() && | |
3190 | cast<VectorType>(type)->getBitWidth() == 128) | |
3191 | weight = CW_Register; | |
3192 | else if (type->isFloatTy()) | |
223e47cc LB |
3193 | weight = CW_Register; |
3194 | break; | |
3195 | case 'c': // $25 for indirect jumps | |
3196 | case 'l': // lo register | |
3197 | case 'x': // hilo register pair | |
1a4d82fc | 3198 | if (type->isIntegerTy()) |
223e47cc | 3199 | weight = CW_SpecificReg; |
1a4d82fc | 3200 | break; |
223e47cc LB |
3201 | case 'I': // signed 16 bit immediate |
3202 | case 'J': // integer zero | |
3203 | case 'K': // unsigned 16 bit immediate | |
3204 | case 'L': // signed 32 bit immediate where lower 16 bits are 0 | |
3205 | case 'N': // immediate in the range of -65535 to -1 (inclusive) | |
3206 | case 'O': // signed 15 bit immediate (+- 16383) | |
3207 | case 'P': // immediate in the range of 65535 to 1 (inclusive) | |
3208 | if (isa<ConstantInt>(CallOperandVal)) | |
3209 | weight = CW_Constant; | |
3210 | break; | |
970d7e83 LB |
3211 | case 'R': |
3212 | weight = CW_Memory; | |
3213 | break; | |
223e47cc LB |
3214 | } |
3215 | return weight; | |
3216 | } | |
3217 | ||
1a4d82fc JJ |
3218 | /// This is a helper function to parse a physical register string and split it |
3219 | /// into non-numeric and numeric parts (Prefix and Reg). The first boolean flag | |
3220 | /// that is returned indicates whether parsing was successful. The second flag | |
3221 | /// is true if the numeric part exists. | |
3222 | static std::pair<bool, bool> | |
3223 | parsePhysicalReg(StringRef C, std::string &Prefix, | |
3224 | unsigned long long &Reg) { | |
3225 | if (C.front() != '{' || C.back() != '}') | |
3226 | return std::make_pair(false, false); | |
3227 | ||
3228 | // Search for the first numeric character. | |
3229 | StringRef::const_iterator I, B = C.begin() + 1, E = C.end() - 1; | |
3230 | I = std::find_if(B, E, std::ptr_fun(isdigit)); | |
3231 | ||
3232 | Prefix.assign(B, I - B); | |
3233 | ||
3234 | // The second flag is set to false if no numeric characters were found. | |
3235 | if (I == E) | |
3236 | return std::make_pair(true, false); | |
3237 | ||
3238 | // Parse the numeric characters. | |
3239 | return std::make_pair(!getAsUnsignedInteger(StringRef(I, E - I), 10, Reg), | |
3240 | true); | |
3241 | } | |
3242 | ||
3243 | std::pair<unsigned, const TargetRegisterClass *> MipsTargetLowering:: | |
3244 | parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { | |
3245 | const TargetRegisterInfo *TRI = | |
3246 | getTargetMachine().getSubtargetImpl()->getRegisterInfo(); | |
3247 | const TargetRegisterClass *RC; | |
3248 | std::string Prefix; | |
3249 | unsigned long long Reg; | |
3250 | ||
3251 | std::pair<bool, bool> R = parsePhysicalReg(C, Prefix, Reg); | |
3252 | ||
3253 | if (!R.first) | |
3254 | return std::make_pair(0U, nullptr); | |
3255 | ||
3256 | if ((Prefix == "hi" || Prefix == "lo")) { // Parse hi/lo. | |
3257 | // No numeric characters follow "hi" or "lo". | |
3258 | if (R.second) | |
3259 | return std::make_pair(0U, nullptr); | |
3260 | ||
3261 | RC = TRI->getRegClass(Prefix == "hi" ? | |
3262 | Mips::HI32RegClassID : Mips::LO32RegClassID); | |
3263 | return std::make_pair(*(RC->begin()), RC); | |
3264 | } else if (Prefix.compare(0, 4, "$msa") == 0) { | |
3265 | // Parse $msa(ir|csr|access|save|modify|request|map|unmap) | |
3266 | ||
3267 | // No numeric characters follow the name. | |
3268 | if (R.second) | |
3269 | return std::make_pair(0U, nullptr); | |
3270 | ||
3271 | Reg = StringSwitch<unsigned long long>(Prefix) | |
3272 | .Case("$msair", Mips::MSAIR) | |
3273 | .Case("$msacsr", Mips::MSACSR) | |
3274 | .Case("$msaaccess", Mips::MSAAccess) | |
3275 | .Case("$msasave", Mips::MSASave) | |
3276 | .Case("$msamodify", Mips::MSAModify) | |
3277 | .Case("$msarequest", Mips::MSARequest) | |
3278 | .Case("$msamap", Mips::MSAMap) | |
3279 | .Case("$msaunmap", Mips::MSAUnmap) | |
3280 | .Default(0); | |
3281 | ||
3282 | if (!Reg) | |
3283 | return std::make_pair(0U, nullptr); | |
3284 | ||
3285 | RC = TRI->getRegClass(Mips::MSACtrlRegClassID); | |
3286 | return std::make_pair(Reg, RC); | |
3287 | } | |
3288 | ||
3289 | if (!R.second) | |
3290 | return std::make_pair(0U, nullptr); | |
3291 | ||
3292 | if (Prefix == "$f") { // Parse $f0-$f31. | |
3293 | // If the size of FP registers is 64-bit or Reg is an even number, select | |
3294 | // the 64-bit register class. Otherwise, select the 32-bit register class. | |
3295 | if (VT == MVT::Other) | |
3296 | VT = (Subtarget.isFP64bit() || !(Reg % 2)) ? MVT::f64 : MVT::f32; | |
3297 | ||
3298 | RC = getRegClassFor(VT); | |
3299 | ||
3300 | if (RC == &Mips::AFGR64RegClass) { | |
3301 | assert(Reg % 2 == 0); | |
3302 | Reg >>= 1; | |
3303 | } | |
3304 | } else if (Prefix == "$fcc") // Parse $fcc0-$fcc7. | |
3305 | RC = TRI->getRegClass(Mips::FCCRegClassID); | |
3306 | else if (Prefix == "$w") { // Parse $w0-$w31. | |
3307 | RC = getRegClassFor((VT == MVT::Other) ? MVT::v16i8 : VT); | |
3308 | } else { // Parse $0-$31. | |
3309 | assert(Prefix == "$"); | |
3310 | RC = getRegClassFor((VT == MVT::Other) ? MVT::i32 : VT); | |
3311 | } | |
3312 | ||
3313 | assert(Reg < RC->getNumRegs()); | |
3314 | return std::make_pair(*(RC->begin() + Reg), RC); | |
3315 | } | |
3316 | ||
223e47cc LB |
3317 | /// Given a register class constraint, like 'r', if this corresponds directly |
3318 | /// to an LLVM register class, return a register of 0 and the register class | |
3319 | /// pointer. | |
3320 | std::pair<unsigned, const TargetRegisterClass*> MipsTargetLowering:: | |
1a4d82fc | 3321 | getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const |
223e47cc LB |
3322 | { |
3323 | if (Constraint.size() == 1) { | |
3324 | switch (Constraint[0]) { | |
3325 | case 'd': // Address register. Same as 'r' unless generating MIPS16 code. | |
3326 | case 'y': // Same as 'r'. Exists for compatibility. | |
3327 | case 'r': | |
3328 | if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) { | |
1a4d82fc | 3329 | if (Subtarget.inMips16Mode()) |
223e47cc | 3330 | return std::make_pair(0U, &Mips::CPU16RegsRegClass); |
1a4d82fc | 3331 | return std::make_pair(0U, &Mips::GPR32RegClass); |
223e47cc | 3332 | } |
1a4d82fc JJ |
3333 | if (VT == MVT::i64 && !Subtarget.isGP64bit()) |
3334 | return std::make_pair(0U, &Mips::GPR32RegClass); | |
3335 | if (VT == MVT::i64 && Subtarget.isGP64bit()) | |
3336 | return std::make_pair(0U, &Mips::GPR64RegClass); | |
223e47cc | 3337 | // This will generate an error message |
1a4d82fc JJ |
3338 | return std::make_pair(0U, nullptr); |
3339 | case 'f': // FPU or MSA register | |
3340 | if (VT == MVT::v16i8) | |
3341 | return std::make_pair(0U, &Mips::MSA128BRegClass); | |
3342 | else if (VT == MVT::v8i16 || VT == MVT::v8f16) | |
3343 | return std::make_pair(0U, &Mips::MSA128HRegClass); | |
3344 | else if (VT == MVT::v4i32 || VT == MVT::v4f32) | |
3345 | return std::make_pair(0U, &Mips::MSA128WRegClass); | |
3346 | else if (VT == MVT::v2i64 || VT == MVT::v2f64) | |
3347 | return std::make_pair(0U, &Mips::MSA128DRegClass); | |
3348 | else if (VT == MVT::f32) | |
223e47cc | 3349 | return std::make_pair(0U, &Mips::FGR32RegClass); |
1a4d82fc JJ |
3350 | else if ((VT == MVT::f64) && (!Subtarget.isSingleFloat())) { |
3351 | if (Subtarget.isFP64bit()) | |
223e47cc LB |
3352 | return std::make_pair(0U, &Mips::FGR64RegClass); |
3353 | return std::make_pair(0U, &Mips::AFGR64RegClass); | |
3354 | } | |
3355 | break; | |
3356 | case 'c': // register suitable for indirect jump | |
3357 | if (VT == MVT::i32) | |
1a4d82fc | 3358 | return std::make_pair((unsigned)Mips::T9, &Mips::GPR32RegClass); |
223e47cc | 3359 | assert(VT == MVT::i64 && "Unexpected type."); |
1a4d82fc | 3360 | return std::make_pair((unsigned)Mips::T9_64, &Mips::GPR64RegClass); |
223e47cc LB |
3361 | case 'l': // register suitable for indirect jump |
3362 | if (VT == MVT::i32) | |
1a4d82fc JJ |
3363 | return std::make_pair((unsigned)Mips::LO0, &Mips::LO32RegClass); |
3364 | return std::make_pair((unsigned)Mips::LO0_64, &Mips::LO64RegClass); | |
223e47cc LB |
3365 | case 'x': // register suitable for indirect jump |
3366 | // Fixme: Not triggering the use of both hi and low | |
3367 | // This will generate an error message | |
1a4d82fc | 3368 | return std::make_pair(0U, nullptr); |
223e47cc LB |
3369 | } |
3370 | } | |
1a4d82fc JJ |
3371 | |
3372 | std::pair<unsigned, const TargetRegisterClass *> R; | |
3373 | R = parseRegForInlineAsmConstraint(Constraint, VT); | |
3374 | ||
3375 | if (R.second) | |
3376 | return R; | |
3377 | ||
223e47cc LB |
3378 | return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); |
3379 | } | |
3380 | ||
3381 | /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops | |
3382 | /// vector. If it is invalid, don't add anything to Ops. | |
3383 | void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, | |
3384 | std::string &Constraint, | |
3385 | std::vector<SDValue>&Ops, | |
3386 | SelectionDAG &DAG) const { | |
1a4d82fc | 3387 | SDValue Result; |
223e47cc LB |
3388 | |
3389 | // Only support length 1 constraints for now. | |
3390 | if (Constraint.length() > 1) return; | |
3391 | ||
3392 | char ConstraintLetter = Constraint[0]; | |
3393 | switch (ConstraintLetter) { | |
3394 | default: break; // This will fall through to the generic implementation | |
3395 | case 'I': // Signed 16 bit constant | |
3396 | // If this fails, the parent routine will give an error | |
3397 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { | |
3398 | EVT Type = Op.getValueType(); | |
3399 | int64_t Val = C->getSExtValue(); | |
3400 | if (isInt<16>(Val)) { | |
3401 | Result = DAG.getTargetConstant(Val, Type); | |
3402 | break; | |
3403 | } | |
3404 | } | |
3405 | return; | |
3406 | case 'J': // integer zero | |
3407 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { | |
3408 | EVT Type = Op.getValueType(); | |
3409 | int64_t Val = C->getZExtValue(); | |
3410 | if (Val == 0) { | |
3411 | Result = DAG.getTargetConstant(0, Type); | |
3412 | break; | |
3413 | } | |
3414 | } | |
3415 | return; | |
3416 | case 'K': // unsigned 16 bit immediate | |
3417 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { | |
3418 | EVT Type = Op.getValueType(); | |
3419 | uint64_t Val = (uint64_t)C->getZExtValue(); | |
3420 | if (isUInt<16>(Val)) { | |
3421 | Result = DAG.getTargetConstant(Val, Type); | |
3422 | break; | |
3423 | } | |
3424 | } | |
3425 | return; | |
3426 | case 'L': // signed 32 bit immediate where lower 16 bits are 0 | |
3427 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { | |
3428 | EVT Type = Op.getValueType(); | |
3429 | int64_t Val = C->getSExtValue(); | |
3430 | if ((isInt<32>(Val)) && ((Val & 0xffff) == 0)){ | |
3431 | Result = DAG.getTargetConstant(Val, Type); | |
3432 | break; | |
3433 | } | |
3434 | } | |
3435 | return; | |
3436 | case 'N': // immediate in the range of -65535 to -1 (inclusive) | |
3437 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { | |
3438 | EVT Type = Op.getValueType(); | |
3439 | int64_t Val = C->getSExtValue(); | |
3440 | if ((Val >= -65535) && (Val <= -1)) { | |
3441 | Result = DAG.getTargetConstant(Val, Type); | |
3442 | break; | |
3443 | } | |
3444 | } | |
3445 | return; | |
3446 | case 'O': // signed 15 bit immediate | |
3447 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { | |
3448 | EVT Type = Op.getValueType(); | |
3449 | int64_t Val = C->getSExtValue(); | |
3450 | if ((isInt<15>(Val))) { | |
3451 | Result = DAG.getTargetConstant(Val, Type); | |
3452 | break; | |
3453 | } | |
3454 | } | |
3455 | return; | |
3456 | case 'P': // immediate in the range of 1 to 65535 (inclusive) | |
3457 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { | |
3458 | EVT Type = Op.getValueType(); | |
3459 | int64_t Val = C->getSExtValue(); | |
3460 | if ((Val <= 65535) && (Val >= 1)) { | |
3461 | Result = DAG.getTargetConstant(Val, Type); | |
3462 | break; | |
3463 | } | |
3464 | } | |
3465 | return; | |
3466 | } | |
3467 | ||
3468 | if (Result.getNode()) { | |
3469 | Ops.push_back(Result); | |
3470 | return; | |
3471 | } | |
3472 | ||
3473 | TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); | |
3474 | } | |
3475 | ||
1a4d82fc JJ |
3476 | bool MipsTargetLowering::isLegalAddressingMode(const AddrMode &AM, |
3477 | Type *Ty) const { | |
970d7e83 LB |
3478 | // No global is ever allowed as a base. |
3479 | if (AM.BaseGV) | |
3480 | return false; | |
3481 | ||
3482 | switch (AM.Scale) { | |
3483 | case 0: // "r+i" or just "i", depending on HasBaseReg. | |
3484 | break; | |
3485 | case 1: | |
3486 | if (!AM.HasBaseReg) // allow "r+i". | |
3487 | break; | |
3488 | return false; // disallow "r+r" or "r+r+i". | |
3489 | default: | |
3490 | return false; | |
3491 | } | |
3492 | ||
3493 | return true; | |
3494 | } | |
3495 | ||
223e47cc LB |
3496 | bool |
3497 | MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { | |
3498 | // The Mips target isn't yet aware of offsets. | |
3499 | return false; | |
3500 | } | |
3501 | ||
3502 | EVT MipsTargetLowering::getOptimalMemOpType(uint64_t Size, unsigned DstAlign, | |
970d7e83 LB |
3503 | unsigned SrcAlign, |
3504 | bool IsMemset, bool ZeroMemset, | |
223e47cc LB |
3505 | bool MemcpyStrSrc, |
3506 | MachineFunction &MF) const { | |
1a4d82fc | 3507 | if (Subtarget.hasMips64()) |
223e47cc LB |
3508 | return MVT::i64; |
3509 | ||
3510 | return MVT::i32; | |
3511 | } | |
3512 | ||
3513 | bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { | |
3514 | if (VT != MVT::f32 && VT != MVT::f64) | |
3515 | return false; | |
3516 | if (Imm.isNegZero()) | |
3517 | return false; | |
3518 | return Imm.isZero(); | |
3519 | } | |
3520 | ||
3521 | unsigned MipsTargetLowering::getJumpTableEncoding() const { | |
1a4d82fc | 3522 | if (Subtarget.isABI_N64()) |
223e47cc LB |
3523 | return MachineJumpTableInfo::EK_GPRel64BlockAddress; |
3524 | ||
3525 | return TargetLowering::getJumpTableEncoding(); | |
3526 | } | |
970d7e83 | 3527 | |
85aaf69f SL |
3528 | void MipsTargetLowering::copyByValRegs( |
3529 | SDValue Chain, SDLoc DL, std::vector<SDValue> &OutChains, SelectionDAG &DAG, | |
3530 | const ISD::ArgFlagsTy &Flags, SmallVectorImpl<SDValue> &InVals, | |
3531 | const Argument *FuncArg, unsigned FirstReg, unsigned LastReg, | |
3532 | const CCValAssign &VA, MipsCCState &State) const { | |
970d7e83 LB |
3533 | MachineFunction &MF = DAG.getMachineFunction(); |
3534 | MachineFrameInfo *MFI = MF.getFrameInfo(); | |
1a4d82fc | 3535 | unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes(); |
85aaf69f SL |
3536 | unsigned NumRegs = LastReg - FirstReg; |
3537 | unsigned RegAreaSize = NumRegs * GPRSizeInBytes; | |
970d7e83 LB |
3538 | unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize); |
3539 | int FrameObjOffset; | |
85aaf69f SL |
3540 | const MipsABIInfo &ABI = Subtarget.getABI(); |
3541 | ArrayRef<MCPhysReg> ByValArgRegs = ABI.GetByValArgRegs(); | |
970d7e83 LB |
3542 | |
3543 | if (RegAreaSize) | |
1a4d82fc | 3544 | FrameObjOffset = |
85aaf69f SL |
3545 | (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) - |
3546 | (int)((ByValArgRegs.size() - FirstReg) * GPRSizeInBytes); | |
970d7e83 | 3547 | else |
85aaf69f | 3548 | FrameObjOffset = VA.getLocMemOffset(); |
970d7e83 LB |
3549 | |
3550 | // Create frame object. | |
3551 | EVT PtrTy = getPointerTy(); | |
3552 | int FI = MFI->CreateFixedObject(FrameObjSize, FrameObjOffset, true); | |
3553 | SDValue FIN = DAG.getFrameIndex(FI, PtrTy); | |
3554 | InVals.push_back(FIN); | |
3555 | ||
85aaf69f | 3556 | if (!NumRegs) |
970d7e83 LB |
3557 | return; |
3558 | ||
3559 | // Copy arg registers. | |
1a4d82fc | 3560 | MVT RegTy = MVT::getIntegerVT(GPRSizeInBytes * 8); |
970d7e83 LB |
3561 | const TargetRegisterClass *RC = getRegClassFor(RegTy); |
3562 | ||
85aaf69f SL |
3563 | for (unsigned I = 0; I < NumRegs; ++I) { |
3564 | unsigned ArgReg = ByValArgRegs[FirstReg + I]; | |
970d7e83 | 3565 | unsigned VReg = addLiveIn(MF, ArgReg, RC); |
1a4d82fc | 3566 | unsigned Offset = I * GPRSizeInBytes; |
970d7e83 LB |
3567 | SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN, |
3568 | DAG.getConstant(Offset, PtrTy)); | |
3569 | SDValue Store = DAG.getStore(Chain, DL, DAG.getRegister(VReg, RegTy), | |
3570 | StorePtr, MachinePointerInfo(FuncArg, Offset), | |
3571 | false, false, 0); | |
3572 | OutChains.push_back(Store); | |
3573 | } | |
3574 | } | |
3575 | ||
3576 | // Copy byVal arg to registers and stack. | |
85aaf69f SL |
3577 | void MipsTargetLowering::passByValArg( |
3578 | SDValue Chain, SDLoc DL, | |
3579 | std::deque<std::pair<unsigned, SDValue>> &RegsToPass, | |
3580 | SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr, | |
3581 | MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, unsigned FirstReg, | |
3582 | unsigned LastReg, const ISD::ArgFlagsTy &Flags, bool isLittle, | |
3583 | const CCValAssign &VA) const { | |
1a4d82fc JJ |
3584 | unsigned ByValSizeInBytes = Flags.getByValSize(); |
3585 | unsigned OffsetInBytes = 0; // From beginning of struct | |
3586 | unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); | |
3587 | unsigned Alignment = std::min(Flags.getByValAlign(), RegSizeInBytes); | |
3588 | EVT PtrTy = getPointerTy(), RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); | |
85aaf69f | 3589 | unsigned NumRegs = LastReg - FirstReg; |
970d7e83 | 3590 | |
85aaf69f SL |
3591 | if (NumRegs) { |
3592 | const ArrayRef<MCPhysReg> ArgRegs = Subtarget.getABI().GetByValArgRegs(); | |
3593 | bool LeftoverBytes = (NumRegs * RegSizeInBytes > ByValSizeInBytes); | |
970d7e83 LB |
3594 | unsigned I = 0; |
3595 | ||
3596 | // Copy words to registers. | |
85aaf69f | 3597 | for (; I < NumRegs - LeftoverBytes; ++I, OffsetInBytes += RegSizeInBytes) { |
970d7e83 | 3598 | SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, |
1a4d82fc | 3599 | DAG.getConstant(OffsetInBytes, PtrTy)); |
970d7e83 LB |
3600 | SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr, |
3601 | MachinePointerInfo(), false, false, false, | |
3602 | Alignment); | |
3603 | MemOpChains.push_back(LoadVal.getValue(1)); | |
85aaf69f | 3604 | unsigned ArgReg = ArgRegs[FirstReg + I]; |
970d7e83 LB |
3605 | RegsToPass.push_back(std::make_pair(ArgReg, LoadVal)); |
3606 | } | |
3607 | ||
3608 | // Return if the struct has been fully copied. | |
1a4d82fc | 3609 | if (ByValSizeInBytes == OffsetInBytes) |
970d7e83 LB |
3610 | return; |
3611 | ||
3612 | // Copy the remainder of the byval argument with sub-word loads and shifts. | |
3613 | if (LeftoverBytes) { | |
970d7e83 LB |
3614 | SDValue Val; |
3615 | ||
1a4d82fc JJ |
3616 | for (unsigned LoadSizeInBytes = RegSizeInBytes / 2, TotalBytesLoaded = 0; |
3617 | OffsetInBytes < ByValSizeInBytes; LoadSizeInBytes /= 2) { | |
3618 | unsigned RemainingSizeInBytes = ByValSizeInBytes - OffsetInBytes; | |
970d7e83 | 3619 | |
1a4d82fc | 3620 | if (RemainingSizeInBytes < LoadSizeInBytes) |
970d7e83 LB |
3621 | continue; |
3622 | ||
3623 | // Load subword. | |
3624 | SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, | |
1a4d82fc JJ |
3625 | DAG.getConstant(OffsetInBytes, PtrTy)); |
3626 | SDValue LoadVal = DAG.getExtLoad( | |
3627 | ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(), | |
3628 | MVT::getIntegerVT(LoadSizeInBytes * 8), false, false, false, | |
3629 | Alignment); | |
970d7e83 LB |
3630 | MemOpChains.push_back(LoadVal.getValue(1)); |
3631 | ||
3632 | // Shift the loaded value. | |
3633 | unsigned Shamt; | |
3634 | ||
3635 | if (isLittle) | |
1a4d82fc | 3636 | Shamt = TotalBytesLoaded * 8; |
970d7e83 | 3637 | else |
1a4d82fc | 3638 | Shamt = (RegSizeInBytes - (TotalBytesLoaded + LoadSizeInBytes)) * 8; |
970d7e83 LB |
3639 | |
3640 | SDValue Shift = DAG.getNode(ISD::SHL, DL, RegTy, LoadVal, | |
3641 | DAG.getConstant(Shamt, MVT::i32)); | |
3642 | ||
3643 | if (Val.getNode()) | |
3644 | Val = DAG.getNode(ISD::OR, DL, RegTy, Val, Shift); | |
3645 | else | |
3646 | Val = Shift; | |
3647 | ||
1a4d82fc JJ |
3648 | OffsetInBytes += LoadSizeInBytes; |
3649 | TotalBytesLoaded += LoadSizeInBytes; | |
3650 | Alignment = std::min(Alignment, LoadSizeInBytes); | |
970d7e83 LB |
3651 | } |
3652 | ||
85aaf69f | 3653 | unsigned ArgReg = ArgRegs[FirstReg + I]; |
970d7e83 LB |
3654 | RegsToPass.push_back(std::make_pair(ArgReg, Val)); |
3655 | return; | |
3656 | } | |
3657 | } | |
3658 | ||
3659 | // Copy remainder of byval arg to it with memcpy. | |
1a4d82fc | 3660 | unsigned MemCpySize = ByValSizeInBytes - OffsetInBytes; |
970d7e83 | 3661 | SDValue Src = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, |
1a4d82fc | 3662 | DAG.getConstant(OffsetInBytes, PtrTy)); |
970d7e83 | 3663 | SDValue Dst = DAG.getNode(ISD::ADD, DL, PtrTy, StackPtr, |
85aaf69f | 3664 | DAG.getIntPtrConstant(VA.getLocMemOffset())); |
1a4d82fc JJ |
3665 | Chain = DAG.getMemcpy(Chain, DL, Dst, Src, DAG.getConstant(MemCpySize, PtrTy), |
3666 | Alignment, /*isVolatile=*/false, /*AlwaysInline=*/false, | |
3667 | MachinePointerInfo(), MachinePointerInfo()); | |
970d7e83 LB |
3668 | MemOpChains.push_back(Chain); |
3669 | } | |
3670 | ||
1a4d82fc | 3671 | void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, |
85aaf69f SL |
3672 | SDValue Chain, SDLoc DL, |
3673 | SelectionDAG &DAG, | |
3674 | CCState &State) const { | |
3675 | const ArrayRef<MCPhysReg> ArgRegs = Subtarget.getABI().GetVarArgRegs(); | |
3676 | unsigned Idx = State.getFirstUnallocated(ArgRegs.data(), ArgRegs.size()); | |
1a4d82fc JJ |
3677 | unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); |
3678 | MVT RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); | |
970d7e83 LB |
3679 | const TargetRegisterClass *RC = getRegClassFor(RegTy); |
3680 | MachineFunction &MF = DAG.getMachineFunction(); | |
3681 | MachineFrameInfo *MFI = MF.getFrameInfo(); | |
3682 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); | |
3683 | ||
3684 | // Offset of the first variable argument from stack pointer. | |
3685 | int VaArgOffset; | |
3686 | ||
1a4d82fc | 3687 | if (ArgRegs.size() == Idx) |
970d7e83 | 3688 | VaArgOffset = |
85aaf69f SL |
3689 | RoundUpToAlignment(State.getNextStackOffset(), RegSizeInBytes); |
3690 | else { | |
3691 | const MipsABIInfo &ABI = Subtarget.getABI(); | |
3692 | VaArgOffset = | |
3693 | (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) - | |
3694 | (int)(RegSizeInBytes * (ArgRegs.size() - Idx)); | |
3695 | } | |
970d7e83 LB |
3696 | |
3697 | // Record the frame index of the first variable argument | |
3698 | // which is a value necessary to VASTART. | |
1a4d82fc | 3699 | int FI = MFI->CreateFixedObject(RegSizeInBytes, VaArgOffset, true); |
970d7e83 LB |
3700 | MipsFI->setVarArgsFrameIndex(FI); |
3701 | ||
3702 | // Copy the integer registers that have not been used for argument passing | |
3703 | // to the argument register save area. For O32, the save area is allocated | |
3704 | // in the caller's stack frame, while for N32/64, it is allocated in the | |
3705 | // callee's stack frame. | |
1a4d82fc JJ |
3706 | for (unsigned I = Idx; I < ArgRegs.size(); |
3707 | ++I, VaArgOffset += RegSizeInBytes) { | |
970d7e83 LB |
3708 | unsigned Reg = addLiveIn(MF, ArgRegs[I], RC); |
3709 | SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegTy); | |
1a4d82fc | 3710 | FI = MFI->CreateFixedObject(RegSizeInBytes, VaArgOffset, true); |
970d7e83 LB |
3711 | SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); |
3712 | SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff, | |
3713 | MachinePointerInfo(), false, false, 0); | |
1a4d82fc JJ |
3714 | cast<StoreSDNode>(Store.getNode())->getMemOperand()->setValue( |
3715 | (Value *)nullptr); | |
970d7e83 LB |
3716 | OutChains.push_back(Store); |
3717 | } | |
3718 | } | |
85aaf69f SL |
3719 | |
3720 | void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, | |
3721 | unsigned Align) const { | |
3722 | MachineFunction &MF = State->getMachineFunction(); | |
3723 | const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); | |
3724 | ||
3725 | assert(Size && "Byval argument's size shouldn't be 0."); | |
3726 | ||
3727 | Align = std::min(Align, TFL->getStackAlignment()); | |
3728 | ||
3729 | unsigned FirstReg = 0; | |
3730 | unsigned NumRegs = 0; | |
3731 | ||
3732 | if (State->getCallingConv() != CallingConv::Fast) { | |
3733 | unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); | |
3734 | const ArrayRef<MCPhysReg> IntArgRegs = Subtarget.getABI().GetByValArgRegs(); | |
3735 | // FIXME: The O32 case actually describes no shadow registers. | |
3736 | const MCPhysReg *ShadowRegs = | |
3737 | Subtarget.isABI_O32() ? IntArgRegs.data() : Mips64DPRegs; | |
3738 | ||
3739 | // We used to check the size as well but we can't do that anymore since | |
3740 | // CCState::HandleByVal() rounds up the size after calling this function. | |
3741 | assert(!(Align % RegSizeInBytes) && | |
3742 | "Byval argument's alignment should be a multiple of" | |
3743 | "RegSizeInBytes."); | |
3744 | ||
3745 | FirstReg = State->getFirstUnallocated(IntArgRegs.data(), IntArgRegs.size()); | |
3746 | ||
3747 | // If Align > RegSizeInBytes, the first arg register must be even. | |
3748 | // FIXME: This condition happens to do the right thing but it's not the | |
3749 | // right way to test it. We want to check that the stack frame offset | |
3750 | // of the register is aligned. | |
3751 | if ((Align > RegSizeInBytes) && (FirstReg % 2)) { | |
3752 | State->AllocateReg(IntArgRegs[FirstReg], ShadowRegs[FirstReg]); | |
3753 | ++FirstReg; | |
3754 | } | |
3755 | ||
3756 | // Mark the registers allocated. | |
3757 | Size = RoundUpToAlignment(Size, RegSizeInBytes); | |
3758 | for (unsigned I = FirstReg; Size > 0 && (I < IntArgRegs.size()); | |
3759 | Size -= RegSizeInBytes, ++I, ++NumRegs) | |
3760 | State->AllocateReg(IntArgRegs[I], ShadowRegs[I]); | |
3761 | } | |
3762 | ||
3763 | State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs); | |
3764 | } | |
3765 | ||
3766 | MachineBasicBlock * | |
3767 | MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB, | |
3768 | bool isFPCmp, unsigned Opc) const { | |
3769 | assert(!(Subtarget.hasMips4() || Subtarget.hasMips32()) && | |
3770 | "Subtarget already supports SELECT nodes with the use of" | |
3771 | "conditional-move instructions."); | |
3772 | ||
3773 | const TargetInstrInfo *TII = | |
3774 | getTargetMachine().getSubtargetImpl()->getInstrInfo(); | |
3775 | DebugLoc DL = MI->getDebugLoc(); | |
3776 | ||
3777 | // To "insert" a SELECT instruction, we actually have to insert the | |
3778 | // diamond control-flow pattern. The incoming instruction knows the | |
3779 | // destination vreg to set, the condition code register to branch on, the | |
3780 | // true/false values to select between, and a branch opcode to use. | |
3781 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | |
3782 | MachineFunction::iterator It = BB; | |
3783 | ++It; | |
3784 | ||
3785 | // thisMBB: | |
3786 | // ... | |
3787 | // TrueVal = ... | |
3788 | // setcc r1, r2, r3 | |
3789 | // bNE r1, r0, copy1MBB | |
3790 | // fallthrough --> copy0MBB | |
3791 | MachineBasicBlock *thisMBB = BB; | |
3792 | MachineFunction *F = BB->getParent(); | |
3793 | MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); | |
3794 | MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); | |
3795 | F->insert(It, copy0MBB); | |
3796 | F->insert(It, sinkMBB); | |
3797 | ||
3798 | // Transfer the remainder of BB and its successor edges to sinkMBB. | |
3799 | sinkMBB->splice(sinkMBB->begin(), BB, | |
3800 | std::next(MachineBasicBlock::iterator(MI)), BB->end()); | |
3801 | sinkMBB->transferSuccessorsAndUpdatePHIs(BB); | |
3802 | ||
3803 | // Next, add the true and fallthrough blocks as its successors. | |
3804 | BB->addSuccessor(copy0MBB); | |
3805 | BB->addSuccessor(sinkMBB); | |
3806 | ||
3807 | if (isFPCmp) { | |
3808 | // bc1[tf] cc, sinkMBB | |
3809 | BuildMI(BB, DL, TII->get(Opc)) | |
3810 | .addReg(MI->getOperand(1).getReg()) | |
3811 | .addMBB(sinkMBB); | |
3812 | } else { | |
3813 | // bne rs, $0, sinkMBB | |
3814 | BuildMI(BB, DL, TII->get(Opc)) | |
3815 | .addReg(MI->getOperand(1).getReg()) | |
3816 | .addReg(Mips::ZERO) | |
3817 | .addMBB(sinkMBB); | |
3818 | } | |
3819 | ||
3820 | // copy0MBB: | |
3821 | // %FalseValue = ... | |
3822 | // # fallthrough to sinkMBB | |
3823 | BB = copy0MBB; | |
3824 | ||
3825 | // Update machine-CFG edges | |
3826 | BB->addSuccessor(sinkMBB); | |
3827 | ||
3828 | // sinkMBB: | |
3829 | // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] | |
3830 | // ... | |
3831 | BB = sinkMBB; | |
3832 | ||
3833 | BuildMI(*BB, BB->begin(), DL, | |
3834 | TII->get(Mips::PHI), MI->getOperand(0).getReg()) | |
3835 | .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB) | |
3836 | .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB); | |
3837 | ||
3838 | MI->eraseFromParent(); // The pseudo instruction is gone now. | |
3839 | ||
3840 | return BB; | |
3841 | } | |
3842 | ||
3843 | // FIXME? Maybe this could be a TableGen attribute on some registers and | |
3844 | // this table could be generated automatically from RegInfo. | |
3845 | unsigned MipsTargetLowering::getRegisterByName(const char* RegName, | |
3846 | EVT VT) const { | |
3847 | // Named registers is expected to be fairly rare. For now, just support $28 | |
3848 | // since the linux kernel uses it. | |
3849 | if (Subtarget.isGP64bit()) { | |
3850 | unsigned Reg = StringSwitch<unsigned>(RegName) | |
3851 | .Case("$28", Mips::GP_64) | |
3852 | .Default(0); | |
3853 | if (Reg) | |
3854 | return Reg; | |
3855 | } else { | |
3856 | unsigned Reg = StringSwitch<unsigned>(RegName) | |
3857 | .Case("$28", Mips::GP) | |
3858 | .Default(0); | |
3859 | if (Reg) | |
3860 | return Reg; | |
3861 | } | |
3862 | report_fatal_error("Invalid register name global variable"); | |
3863 | } |