1 | //===-- SparcISelLowering.cpp - Sparc DAG Lowering Implementation ---------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements the interfaces that Sparc uses to lower LLVM code into a |
10 | // selection DAG. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "SparcISelLowering.h" |
15 | #include "MCTargetDesc/SparcMCExpr.h" |
16 | #include "MCTargetDesc/SparcMCTargetDesc.h" |
17 | #include "SparcMachineFunctionInfo.h" |
18 | #include "SparcRegisterInfo.h" |
19 | #include "SparcTargetMachine.h" |
20 | #include "SparcTargetObjectFile.h" |
21 | #include "llvm/ADT/StringExtras.h" |
22 | #include "llvm/ADT/StringSwitch.h" |
23 | #include "llvm/CodeGen/CallingConvLower.h" |
24 | #include "llvm/CodeGen/MachineFrameInfo.h" |
25 | #include "llvm/CodeGen/MachineFunction.h" |
26 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
27 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
28 | #include "llvm/CodeGen/SelectionDAG.h" |
29 | #include "llvm/CodeGen/SelectionDAGNodes.h" |
30 | #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" |
31 | #include "llvm/IR/DerivedTypes.h" |
32 | #include "llvm/IR/DiagnosticInfo.h" |
33 | #include "llvm/IR/Function.h" |
34 | #include "llvm/IR/Module.h" |
35 | #include "llvm/Support/ErrorHandling.h" |
36 | #include "llvm/Support/KnownBits.h" |
37 | using namespace llvm; |
38 | |
39 | |
40 | //===----------------------------------------------------------------------===// |
41 | // Calling Convention Implementation |
42 | //===----------------------------------------------------------------------===// |
43 | |
44 | static bool CC_Sparc_Assign_SRet(unsigned &ValNo, MVT &ValVT, |
45 | MVT &LocVT, CCValAssign::LocInfo &LocInfo, |
46 | ISD::ArgFlagsTy &ArgFlags, CCState &State) |
47 | { |
48 | assert (ArgFlags.isSRet()); |
49 | |
50 | // Assign SRet argument. |
51 | State.addLoc(V: CCValAssign::getCustomMem(ValNo, ValVT, |
52 | Offset: 0, |
53 | LocVT, HTP: LocInfo)); |
54 | return true; |
55 | } |
56 | |
57 | static bool CC_Sparc_Assign_Split_64(unsigned &ValNo, MVT &ValVT, |
58 | MVT &LocVT, CCValAssign::LocInfo &LocInfo, |
59 | ISD::ArgFlagsTy &ArgFlags, CCState &State) |
60 | { |
61 | static const MCPhysReg RegList[] = { |
62 | SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 |
63 | }; |
64 | // Try to get first reg. |
65 | if (Register Reg = State.AllocateReg(Regs: RegList)) { |
66 | State.addLoc(V: CCValAssign::getCustomReg(ValNo, ValVT, RegNo: Reg, LocVT, HTP: LocInfo)); |
67 | } else { |
68 | // Assign whole thing in stack. |
69 | State.addLoc(V: CCValAssign::getCustomMem( |
70 | ValNo, ValVT, Offset: State.AllocateStack(Size: 8, Alignment: Align(4)), LocVT, HTP: LocInfo)); |
71 | return true; |
72 | } |
73 | |
74 | // Try to get second reg. |
75 | if (Register Reg = State.AllocateReg(Regs: RegList)) |
76 | State.addLoc(V: CCValAssign::getCustomReg(ValNo, ValVT, RegNo: Reg, LocVT, HTP: LocInfo)); |
77 | else |
78 | State.addLoc(V: CCValAssign::getCustomMem( |
79 | ValNo, ValVT, Offset: State.AllocateStack(Size: 4, Alignment: Align(4)), LocVT, HTP: LocInfo)); |
80 | return true; |
81 | } |
82 | |
83 | static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT, |
84 | MVT &LocVT, CCValAssign::LocInfo &LocInfo, |
85 | ISD::ArgFlagsTy &ArgFlags, CCState &State) |
86 | { |
87 | static const MCPhysReg RegList[] = { |
88 | SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 |
89 | }; |
90 | |
91 | // Try to get first reg. |
92 | if (Register Reg = State.AllocateReg(Regs: RegList)) |
93 | State.addLoc(V: CCValAssign::getCustomReg(ValNo, ValVT, RegNo: Reg, LocVT, HTP: LocInfo)); |
94 | else |
95 | return false; |
96 | |
97 | // Try to get second reg. |
98 | if (Register Reg = State.AllocateReg(Regs: RegList)) |
99 | State.addLoc(V: CCValAssign::getCustomReg(ValNo, ValVT, RegNo: Reg, LocVT, HTP: LocInfo)); |
100 | else |
101 | return false; |
102 | |
103 | return true; |
104 | } |
105 | |
106 | // Allocate a full-sized argument for the 64-bit ABI. |
107 | static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT, |
108 | MVT &LocVT, CCValAssign::LocInfo &LocInfo, |
109 | ISD::ArgFlagsTy &ArgFlags, CCState &State) { |
110 | assert((LocVT == MVT::f32 || LocVT == MVT::f128 |
111 | || LocVT.getSizeInBits() == 64) && |
112 | "Can't handle non-64 bits locations" ); |
113 | |
114 | // Stack space is allocated for all arguments starting from [%fp+BIAS+128]. |
115 | unsigned size = (LocVT == MVT::f128) ? 16 : 8; |
116 | Align alignment = (LocVT == MVT::f128) ? Align(16) : Align(8); |
117 | unsigned Offset = State.AllocateStack(Size: size, Alignment: alignment); |
118 | unsigned Reg = 0; |
119 | |
120 | if (LocVT == MVT::i64 && Offset < 6*8) |
121 | // Promote integers to %i0-%i5. |
122 | Reg = SP::I0 + Offset/8; |
123 | else if (LocVT == MVT::f64 && Offset < 16*8) |
124 | // Promote doubles to %d0-%d30. (Which LLVM calls D0-D15). |
125 | Reg = SP::D0 + Offset/8; |
126 | else if (LocVT == MVT::f32 && Offset < 16*8) |
127 | // Promote floats to %f1, %f3, ... |
128 | Reg = SP::F1 + Offset/4; |
129 | else if (LocVT == MVT::f128 && Offset < 16*8) |
130 | // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7). |
131 | Reg = SP::Q0 + Offset/16; |
132 | |
133 | // Promote to register when possible, otherwise use the stack slot. |
134 | if (Reg) { |
135 | State.addLoc(V: CCValAssign::getReg(ValNo, ValVT, RegNo: Reg, LocVT, HTP: LocInfo)); |
136 | return true; |
137 | } |
138 | |
139 | // Bail out if this is a return CC and we run out of registers to place |
140 | // values into. |
141 | if (IsReturn) |
142 | return false; |
143 | |
144 | // This argument goes on the stack in an 8-byte slot. |
145 | // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to |
146 | // the right-aligned float. The first 4 bytes of the stack slot are undefined. |
147 | if (LocVT == MVT::f32) |
148 | Offset += 4; |
149 | |
150 | State.addLoc(V: CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, HTP: LocInfo)); |
151 | return true; |
152 | } |
153 | |
154 | // Allocate a half-sized argument for the 64-bit ABI. |
155 | // |
156 | // This is used when passing { float, int } structs by value in registers. |
157 | static bool Analyze_CC_Sparc64_Half(bool IsReturn, unsigned &ValNo, MVT &ValVT, |
158 | MVT &LocVT, CCValAssign::LocInfo &LocInfo, |
159 | ISD::ArgFlagsTy &ArgFlags, CCState &State) { |
160 | assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations" ); |
161 | unsigned Offset = State.AllocateStack(Size: 4, Alignment: Align(4)); |
162 | |
163 | if (LocVT == MVT::f32 && Offset < 16*8) { |
164 | // Promote floats to %f0-%f31. |
165 | State.addLoc(V: CCValAssign::getReg(ValNo, ValVT, RegNo: SP::F0 + Offset/4, |
166 | LocVT, HTP: LocInfo)); |
167 | return true; |
168 | } |
169 | |
170 | if (LocVT == MVT::i32 && Offset < 6*8) { |
171 | // Promote integers to %i0-%i5, using half the register. |
172 | unsigned Reg = SP::I0 + Offset/8; |
173 | LocVT = MVT::i64; |
174 | LocInfo = CCValAssign::AExt; |
175 | |
176 | // Set the Custom bit if this i32 goes in the high bits of a register. |
177 | if (Offset % 8 == 0) |
178 | State.addLoc(V: CCValAssign::getCustomReg(ValNo, ValVT, RegNo: Reg, |
179 | LocVT, HTP: LocInfo)); |
180 | else |
181 | State.addLoc(V: CCValAssign::getReg(ValNo, ValVT, RegNo: Reg, LocVT, HTP: LocInfo)); |
182 | return true; |
183 | } |
184 | |
185 | // Bail out if this is a return CC and we run out of registers to place |
186 | // values into. |
187 | if (IsReturn) |
188 | return false; |
189 | |
190 | State.addLoc(V: CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, HTP: LocInfo)); |
191 | return true; |
192 | } |
193 | |
194 | static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
195 | CCValAssign::LocInfo &LocInfo, |
196 | ISD::ArgFlagsTy &ArgFlags, CCState &State) { |
197 | return Analyze_CC_Sparc64_Full(IsReturn: false, ValNo, ValVT, LocVT, LocInfo, ArgFlags, |
198 | State); |
199 | } |
200 | |
201 | static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
202 | CCValAssign::LocInfo &LocInfo, |
203 | ISD::ArgFlagsTy &ArgFlags, CCState &State) { |
204 | return Analyze_CC_Sparc64_Half(IsReturn: false, ValNo, ValVT, LocVT, LocInfo, ArgFlags, |
205 | State); |
206 | } |
207 | |
208 | static bool RetCC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
209 | CCValAssign::LocInfo &LocInfo, |
210 | ISD::ArgFlagsTy &ArgFlags, CCState &State) { |
211 | return Analyze_CC_Sparc64_Full(IsReturn: true, ValNo, ValVT, LocVT, LocInfo, ArgFlags, |
212 | State); |
213 | } |
214 | |
215 | static bool RetCC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
216 | CCValAssign::LocInfo &LocInfo, |
217 | ISD::ArgFlagsTy &ArgFlags, CCState &State) { |
218 | return Analyze_CC_Sparc64_Half(IsReturn: true, ValNo, ValVT, LocVT, LocInfo, ArgFlags, |
219 | State); |
220 | } |
221 | |
222 | #include "SparcGenCallingConv.inc" |
223 | |
224 | // The calling conventions in SparcCallingConv.td are described in terms of the |
225 | // callee's register window. This function translates registers to the |
226 | // corresponding caller window %o register. |
227 | static unsigned toCallerWindow(unsigned Reg) { |
228 | static_assert(SP::I0 + 7 == SP::I7 && SP::O0 + 7 == SP::O7, |
229 | "Unexpected enum" ); |
230 | if (Reg >= SP::I0 && Reg <= SP::I7) |
231 | return Reg - SP::I0 + SP::O0; |
232 | return Reg; |
233 | } |
234 | |
235 | bool SparcTargetLowering::CanLowerReturn( |
236 | CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, |
237 | const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { |
238 | SmallVector<CCValAssign, 16> RVLocs; |
239 | CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context); |
240 | return CCInfo.CheckReturn(Outs, Fn: Subtarget->is64Bit() ? RetCC_Sparc64 |
241 | : RetCC_Sparc32); |
242 | } |
243 | |
244 | SDValue |
245 | SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, |
246 | bool IsVarArg, |
247 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
248 | const SmallVectorImpl<SDValue> &OutVals, |
249 | const SDLoc &DL, SelectionDAG &DAG) const { |
250 | if (Subtarget->is64Bit()) |
251 | return LowerReturn_64(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG); |
252 | return LowerReturn_32(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG); |
253 | } |
254 | |
255 | SDValue |
256 | SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv, |
257 | bool IsVarArg, |
258 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
259 | const SmallVectorImpl<SDValue> &OutVals, |
260 | const SDLoc &DL, SelectionDAG &DAG) const { |
261 | MachineFunction &MF = DAG.getMachineFunction(); |
262 | |
263 | // CCValAssign - represent the assignment of the return value to locations. |
264 | SmallVector<CCValAssign, 16> RVLocs; |
265 | |
266 | // CCState - Info about the registers and stack slot. |
267 | CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, |
268 | *DAG.getContext()); |
269 | |
270 | // Analyze return values. |
271 | CCInfo.AnalyzeReturn(Outs, Fn: RetCC_Sparc32); |
272 | |
273 | SDValue Glue; |
274 | SmallVector<SDValue, 4> RetOps(1, Chain); |
275 | // Make room for the return address offset. |
276 | RetOps.push_back(Elt: SDValue()); |
277 | |
278 | // Copy the result values into the output registers. |
279 | for (unsigned i = 0, realRVLocIdx = 0; |
280 | i != RVLocs.size(); |
281 | ++i, ++realRVLocIdx) { |
282 | CCValAssign &VA = RVLocs[i]; |
283 | assert(VA.isRegLoc() && "Can only return in registers!" ); |
284 | |
285 | SDValue Arg = OutVals[realRVLocIdx]; |
286 | |
287 | if (VA.needsCustom()) { |
288 | assert(VA.getLocVT() == MVT::v2i32); |
289 | // Legalize ret v2i32 -> ret 2 x i32 (Basically: do what would |
290 | // happen by default if this wasn't a legal type) |
291 | |
292 | SDValue Part0 = DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL, VT: MVT::i32, |
293 | N1: Arg, |
294 | N2: DAG.getConstant(Val: 0, DL, VT: getVectorIdxTy(DL: DAG.getDataLayout()))); |
295 | SDValue Part1 = DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL, VT: MVT::i32, |
296 | N1: Arg, |
297 | N2: DAG.getConstant(Val: 1, DL, VT: getVectorIdxTy(DL: DAG.getDataLayout()))); |
298 | |
299 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: VA.getLocReg(), N: Part0, Glue); |
300 | Glue = Chain.getValue(R: 1); |
301 | RetOps.push_back(Elt: DAG.getRegister(Reg: VA.getLocReg(), VT: VA.getLocVT())); |
302 | VA = RVLocs[++i]; // skip ahead to next loc |
303 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: VA.getLocReg(), N: Part1, |
304 | Glue); |
305 | } else |
306 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: VA.getLocReg(), N: Arg, Glue); |
307 | |
308 | // Guarantee that all emitted copies are stuck together with flags. |
309 | Glue = Chain.getValue(R: 1); |
310 | RetOps.push_back(Elt: DAG.getRegister(Reg: VA.getLocReg(), VT: VA.getLocVT())); |
311 | } |
312 | |
313 | unsigned RetAddrOffset = 8; // Call Inst + Delay Slot |
314 | // If the function returns a struct, copy the SRetReturnReg to I0 |
315 | if (MF.getFunction().hasStructRetAttr()) { |
316 | SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>(); |
317 | Register Reg = SFI->getSRetReturnReg(); |
318 | if (!Reg) |
319 | llvm_unreachable("sret virtual register not created in the entry block" ); |
320 | auto PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
321 | SDValue Val = DAG.getCopyFromReg(Chain, dl: DL, Reg, VT: PtrVT); |
322 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: SP::I0, N: Val, Glue); |
323 | Glue = Chain.getValue(R: 1); |
324 | RetOps.push_back(Elt: DAG.getRegister(Reg: SP::I0, VT: PtrVT)); |
325 | RetAddrOffset = 12; // CallInst + Delay Slot + Unimp |
326 | } |
327 | |
328 | RetOps[0] = Chain; // Update chain. |
329 | RetOps[1] = DAG.getConstant(Val: RetAddrOffset, DL, VT: MVT::i32); |
330 | |
331 | // Add the glue if we have it. |
332 | if (Glue.getNode()) |
333 | RetOps.push_back(Elt: Glue); |
334 | |
335 | return DAG.getNode(Opcode: SPISD::RET_GLUE, DL, VT: MVT::Other, Ops: RetOps); |
336 | } |
337 | |
338 | // Lower return values for the 64-bit ABI. |
339 | // Return values are passed the exactly the same way as function arguments. |
340 | SDValue |
341 | SparcTargetLowering::LowerReturn_64(SDValue Chain, CallingConv::ID CallConv, |
342 | bool IsVarArg, |
343 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
344 | const SmallVectorImpl<SDValue> &OutVals, |
345 | const SDLoc &DL, SelectionDAG &DAG) const { |
346 | // CCValAssign - represent the assignment of the return value to locations. |
347 | SmallVector<CCValAssign, 16> RVLocs; |
348 | |
349 | // CCState - Info about the registers and stack slot. |
350 | CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, |
351 | *DAG.getContext()); |
352 | |
353 | // Analyze return values. |
354 | CCInfo.AnalyzeReturn(Outs, Fn: RetCC_Sparc64); |
355 | |
356 | SDValue Glue; |
357 | SmallVector<SDValue, 4> RetOps(1, Chain); |
358 | |
359 | // The second operand on the return instruction is the return address offset. |
360 | // The return address is always %i7+8 with the 64-bit ABI. |
361 | RetOps.push_back(Elt: DAG.getConstant(Val: 8, DL, VT: MVT::i32)); |
362 | |
363 | // Copy the result values into the output registers. |
364 | for (unsigned i = 0; i != RVLocs.size(); ++i) { |
365 | CCValAssign &VA = RVLocs[i]; |
366 | assert(VA.isRegLoc() && "Can only return in registers!" ); |
367 | SDValue OutVal = OutVals[i]; |
368 | |
369 | // Integer return values must be sign or zero extended by the callee. |
370 | switch (VA.getLocInfo()) { |
371 | case CCValAssign::Full: break; |
372 | case CCValAssign::SExt: |
373 | OutVal = DAG.getNode(Opcode: ISD::SIGN_EXTEND, DL, VT: VA.getLocVT(), Operand: OutVal); |
374 | break; |
375 | case CCValAssign::ZExt: |
376 | OutVal = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL, VT: VA.getLocVT(), Operand: OutVal); |
377 | break; |
378 | case CCValAssign::AExt: |
379 | OutVal = DAG.getNode(Opcode: ISD::ANY_EXTEND, DL, VT: VA.getLocVT(), Operand: OutVal); |
380 | break; |
381 | default: |
382 | llvm_unreachable("Unknown loc info!" ); |
383 | } |
384 | |
385 | // The custom bit on an i32 return value indicates that it should be passed |
386 | // in the high bits of the register. |
387 | if (VA.getValVT() == MVT::i32 && VA.needsCustom()) { |
388 | OutVal = DAG.getNode(Opcode: ISD::SHL, DL, VT: MVT::i64, N1: OutVal, |
389 | N2: DAG.getConstant(Val: 32, DL, VT: MVT::i32)); |
390 | |
391 | // The next value may go in the low bits of the same register. |
392 | // Handle both at once. |
393 | if (i+1 < RVLocs.size() && RVLocs[i+1].getLocReg() == VA.getLocReg()) { |
394 | SDValue NV = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL, VT: MVT::i64, Operand: OutVals[i+1]); |
395 | OutVal = DAG.getNode(Opcode: ISD::OR, DL, VT: MVT::i64, N1: OutVal, N2: NV); |
396 | // Skip the next value, it's already done. |
397 | ++i; |
398 | } |
399 | } |
400 | |
401 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: VA.getLocReg(), N: OutVal, Glue); |
402 | |
403 | // Guarantee that all emitted copies are stuck together with flags. |
404 | Glue = Chain.getValue(R: 1); |
405 | RetOps.push_back(Elt: DAG.getRegister(Reg: VA.getLocReg(), VT: VA.getLocVT())); |
406 | } |
407 | |
408 | RetOps[0] = Chain; // Update chain. |
409 | |
410 | // Add the flag if we have it. |
411 | if (Glue.getNode()) |
412 | RetOps.push_back(Elt: Glue); |
413 | |
414 | return DAG.getNode(Opcode: SPISD::RET_GLUE, DL, VT: MVT::Other, Ops: RetOps); |
415 | } |
416 | |
417 | SDValue SparcTargetLowering::LowerFormalArguments( |
418 | SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, |
419 | const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, |
420 | SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { |
421 | if (Subtarget->is64Bit()) |
422 | return LowerFormalArguments_64(Chain, CallConv, isVarArg: IsVarArg, Ins, |
423 | dl: DL, DAG, InVals); |
424 | return LowerFormalArguments_32(Chain, CallConv, isVarArg: IsVarArg, Ins, |
425 | dl: DL, DAG, InVals); |
426 | } |
427 | |
428 | /// LowerFormalArguments32 - V8 uses a very simple ABI, where all values are |
429 | /// passed in either one or two GPRs, including FP values. TODO: we should |
430 | /// pass FP values in FP registers for fastcc functions. |
431 | SDValue SparcTargetLowering::LowerFormalArguments_32( |
432 | SDValue Chain, CallingConv::ID CallConv, bool isVarArg, |
433 | const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, |
434 | SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { |
435 | MachineFunction &MF = DAG.getMachineFunction(); |
436 | MachineRegisterInfo &RegInfo = MF.getRegInfo(); |
437 | SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); |
438 | |
439 | // Assign locations to all of the incoming arguments. |
440 | SmallVector<CCValAssign, 16> ArgLocs; |
441 | CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, |
442 | *DAG.getContext()); |
443 | CCInfo.AnalyzeFormalArguments(Ins, Fn: CC_Sparc32); |
444 | |
445 | const unsigned StackOffset = 92; |
446 | bool IsLittleEndian = DAG.getDataLayout().isLittleEndian(); |
447 | |
448 | unsigned InIdx = 0; |
449 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) { |
450 | CCValAssign &VA = ArgLocs[i]; |
451 | |
452 | if (Ins[InIdx].Flags.isSRet()) { |
453 | if (InIdx != 0) |
454 | report_fatal_error(reason: "sparc only supports sret on the first parameter" ); |
455 | // Get SRet from [%fp+64]. |
456 | int FrameIdx = MF.getFrameInfo().CreateFixedObject(Size: 4, SPOffset: 64, IsImmutable: true); |
457 | SDValue FIPtr = DAG.getFrameIndex(FI: FrameIdx, VT: MVT::i32); |
458 | SDValue Arg = |
459 | DAG.getLoad(VT: MVT::i32, dl, Chain, Ptr: FIPtr, PtrInfo: MachinePointerInfo()); |
460 | InVals.push_back(Elt: Arg); |
461 | continue; |
462 | } |
463 | |
464 | if (VA.isRegLoc()) { |
465 | if (VA.needsCustom()) { |
466 | assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32); |
467 | |
468 | Register VRegHi = RegInfo.createVirtualRegister(RegClass: &SP::IntRegsRegClass); |
469 | MF.getRegInfo().addLiveIn(Reg: VA.getLocReg(), vreg: VRegHi); |
470 | SDValue HiVal = DAG.getCopyFromReg(Chain, dl, Reg: VRegHi, VT: MVT::i32); |
471 | |
472 | assert(i+1 < e); |
473 | CCValAssign &NextVA = ArgLocs[++i]; |
474 | |
475 | SDValue LoVal; |
476 | if (NextVA.isMemLoc()) { |
477 | int FrameIdx = MF.getFrameInfo(). |
478 | CreateFixedObject(Size: 4, SPOffset: StackOffset+NextVA.getLocMemOffset(),IsImmutable: true); |
479 | SDValue FIPtr = DAG.getFrameIndex(FI: FrameIdx, VT: MVT::i32); |
480 | LoVal = DAG.getLoad(VT: MVT::i32, dl, Chain, Ptr: FIPtr, PtrInfo: MachinePointerInfo()); |
481 | } else { |
482 | Register loReg = MF.addLiveIn(PReg: NextVA.getLocReg(), |
483 | RC: &SP::IntRegsRegClass); |
484 | LoVal = DAG.getCopyFromReg(Chain, dl, Reg: loReg, VT: MVT::i32); |
485 | } |
486 | |
487 | if (IsLittleEndian) |
488 | std::swap(a&: LoVal, b&: HiVal); |
489 | |
490 | SDValue WholeValue = |
491 | DAG.getNode(Opcode: ISD::BUILD_PAIR, DL: dl, VT: MVT::i64, N1: LoVal, N2: HiVal); |
492 | WholeValue = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: VA.getLocVT(), Operand: WholeValue); |
493 | InVals.push_back(Elt: WholeValue); |
494 | continue; |
495 | } |
496 | Register VReg = RegInfo.createVirtualRegister(RegClass: &SP::IntRegsRegClass); |
497 | MF.getRegInfo().addLiveIn(Reg: VA.getLocReg(), vreg: VReg); |
498 | SDValue Arg = DAG.getCopyFromReg(Chain, dl, Reg: VReg, VT: MVT::i32); |
499 | if (VA.getLocVT() == MVT::f32) |
500 | Arg = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: MVT::f32, Operand: Arg); |
501 | else if (VA.getLocVT() != MVT::i32) { |
502 | Arg = DAG.getNode(Opcode: ISD::AssertSext, DL: dl, VT: MVT::i32, N1: Arg, |
503 | N2: DAG.getValueType(VA.getLocVT())); |
504 | Arg = DAG.getNode(Opcode: ISD::TRUNCATE, DL: dl, VT: VA.getLocVT(), Operand: Arg); |
505 | } |
506 | InVals.push_back(Elt: Arg); |
507 | continue; |
508 | } |
509 | |
510 | assert(VA.isMemLoc()); |
511 | |
512 | unsigned Offset = VA.getLocMemOffset()+StackOffset; |
513 | auto PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
514 | |
515 | if (VA.needsCustom()) { |
516 | assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32); |
517 | // If it is double-word aligned, just load. |
518 | if (Offset % 8 == 0) { |
519 | int FI = MF.getFrameInfo().CreateFixedObject(Size: 8, |
520 | SPOffset: Offset, |
521 | IsImmutable: true); |
522 | SDValue FIPtr = DAG.getFrameIndex(FI, VT: PtrVT); |
523 | SDValue Load = |
524 | DAG.getLoad(VT: VA.getValVT(), dl, Chain, Ptr: FIPtr, PtrInfo: MachinePointerInfo()); |
525 | InVals.push_back(Elt: Load); |
526 | continue; |
527 | } |
528 | |
529 | int FI = MF.getFrameInfo().CreateFixedObject(Size: 4, |
530 | SPOffset: Offset, |
531 | IsImmutable: true); |
532 | SDValue FIPtr = DAG.getFrameIndex(FI, VT: PtrVT); |
533 | SDValue HiVal = |
534 | DAG.getLoad(VT: MVT::i32, dl, Chain, Ptr: FIPtr, PtrInfo: MachinePointerInfo()); |
535 | int FI2 = MF.getFrameInfo().CreateFixedObject(Size: 4, |
536 | SPOffset: Offset+4, |
537 | IsImmutable: true); |
538 | SDValue FIPtr2 = DAG.getFrameIndex(FI: FI2, VT: PtrVT); |
539 | |
540 | SDValue LoVal = |
541 | DAG.getLoad(VT: MVT::i32, dl, Chain, Ptr: FIPtr2, PtrInfo: MachinePointerInfo()); |
542 | |
543 | if (IsLittleEndian) |
544 | std::swap(a&: LoVal, b&: HiVal); |
545 | |
546 | SDValue WholeValue = |
547 | DAG.getNode(Opcode: ISD::BUILD_PAIR, DL: dl, VT: MVT::i64, N1: LoVal, N2: HiVal); |
548 | WholeValue = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: VA.getValVT(), Operand: WholeValue); |
549 | InVals.push_back(Elt: WholeValue); |
550 | continue; |
551 | } |
552 | |
553 | int FI = MF.getFrameInfo().CreateFixedObject(Size: 4, |
554 | SPOffset: Offset, |
555 | IsImmutable: true); |
556 | SDValue FIPtr = DAG.getFrameIndex(FI, VT: PtrVT); |
557 | SDValue Load ; |
558 | if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { |
559 | Load = DAG.getLoad(VT: VA.getValVT(), dl, Chain, Ptr: FIPtr, PtrInfo: MachinePointerInfo()); |
560 | } else if (VA.getValVT() == MVT::f128) { |
561 | report_fatal_error(reason: "SPARCv8 does not handle f128 in calls; " |
562 | "pass indirectly" ); |
563 | } else { |
564 | // We shouldn't see any other value types here. |
565 | llvm_unreachable("Unexpected ValVT encountered in frame lowering." ); |
566 | } |
567 | InVals.push_back(Elt: Load); |
568 | } |
569 | |
570 | if (MF.getFunction().hasStructRetAttr()) { |
571 | // Copy the SRet Argument to SRetReturnReg. |
572 | SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>(); |
573 | Register Reg = SFI->getSRetReturnReg(); |
574 | if (!Reg) { |
575 | Reg = MF.getRegInfo().createVirtualRegister(RegClass: &SP::IntRegsRegClass); |
576 | SFI->setSRetReturnReg(Reg); |
577 | } |
578 | SDValue Copy = DAG.getCopyToReg(Chain: DAG.getEntryNode(), dl, Reg, N: InVals[0]); |
579 | Chain = DAG.getNode(Opcode: ISD::TokenFactor, DL: dl, VT: MVT::Other, N1: Copy, N2: Chain); |
580 | } |
581 | |
582 | // Store remaining ArgRegs to the stack if this is a varargs function. |
583 | if (isVarArg) { |
584 | static const MCPhysReg ArgRegs[] = { |
585 | SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 |
586 | }; |
587 | unsigned NumAllocated = CCInfo.getFirstUnallocated(Regs: ArgRegs); |
588 | const MCPhysReg *CurArgReg = ArgRegs+NumAllocated, *ArgRegEnd = ArgRegs+6; |
589 | unsigned ArgOffset = CCInfo.getStackSize(); |
590 | if (NumAllocated == 6) |
591 | ArgOffset += StackOffset; |
592 | else { |
593 | assert(!ArgOffset); |
594 | ArgOffset = 68+4*NumAllocated; |
595 | } |
596 | |
597 | // Remember the vararg offset for the va_start implementation. |
598 | FuncInfo->setVarArgsFrameOffset(ArgOffset); |
599 | |
600 | std::vector<SDValue> OutChains; |
601 | |
602 | for (; CurArgReg != ArgRegEnd; ++CurArgReg) { |
603 | Register VReg = RegInfo.createVirtualRegister(RegClass: &SP::IntRegsRegClass); |
604 | MF.getRegInfo().addLiveIn(Reg: *CurArgReg, vreg: VReg); |
605 | SDValue Arg = DAG.getCopyFromReg(Chain: DAG.getRoot(), dl, Reg: VReg, VT: MVT::i32); |
606 | |
607 | int FrameIdx = MF.getFrameInfo().CreateFixedObject(Size: 4, SPOffset: ArgOffset, |
608 | IsImmutable: true); |
609 | SDValue FIPtr = DAG.getFrameIndex(FI: FrameIdx, VT: MVT::i32); |
610 | |
611 | OutChains.push_back( |
612 | x: DAG.getStore(Chain: DAG.getRoot(), dl, Val: Arg, Ptr: FIPtr, PtrInfo: MachinePointerInfo())); |
613 | ArgOffset += 4; |
614 | } |
615 | |
616 | if (!OutChains.empty()) { |
617 | OutChains.push_back(x: Chain); |
618 | Chain = DAG.getNode(Opcode: ISD::TokenFactor, DL: dl, VT: MVT::Other, Ops: OutChains); |
619 | } |
620 | } |
621 | |
622 | return Chain; |
623 | } |
624 | |
625 | // Lower formal arguments for the 64 bit ABI. |
626 | SDValue SparcTargetLowering::LowerFormalArguments_64( |
627 | SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, |
628 | const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, |
629 | SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { |
630 | MachineFunction &MF = DAG.getMachineFunction(); |
631 | |
632 | // Analyze arguments according to CC_Sparc64. |
633 | SmallVector<CCValAssign, 16> ArgLocs; |
634 | CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, |
635 | *DAG.getContext()); |
636 | CCInfo.AnalyzeFormalArguments(Ins, Fn: CC_Sparc64); |
637 | |
638 | // The argument array begins at %fp+BIAS+128, after the register save area. |
639 | const unsigned ArgArea = 128; |
640 | |
641 | for (const CCValAssign &VA : ArgLocs) { |
642 | if (VA.isRegLoc()) { |
643 | // This argument is passed in a register. |
644 | // All integer register arguments are promoted by the caller to i64. |
645 | |
646 | // Create a virtual register for the promoted live-in value. |
647 | Register VReg = MF.addLiveIn(PReg: VA.getLocReg(), |
648 | RC: getRegClassFor(VT: VA.getLocVT())); |
649 | SDValue Arg = DAG.getCopyFromReg(Chain, dl: DL, Reg: VReg, VT: VA.getLocVT()); |
650 | |
651 | // Get the high bits for i32 struct elements. |
652 | if (VA.getValVT() == MVT::i32 && VA.needsCustom()) |
653 | Arg = DAG.getNode(Opcode: ISD::SRL, DL, VT: VA.getLocVT(), N1: Arg, |
654 | N2: DAG.getConstant(Val: 32, DL, VT: MVT::i32)); |
655 | |
656 | // The caller promoted the argument, so insert an Assert?ext SDNode so we |
657 | // won't promote the value again in this function. |
658 | switch (VA.getLocInfo()) { |
659 | case CCValAssign::SExt: |
660 | Arg = DAG.getNode(Opcode: ISD::AssertSext, DL, VT: VA.getLocVT(), N1: Arg, |
661 | N2: DAG.getValueType(VA.getValVT())); |
662 | break; |
663 | case CCValAssign::ZExt: |
664 | Arg = DAG.getNode(Opcode: ISD::AssertZext, DL, VT: VA.getLocVT(), N1: Arg, |
665 | N2: DAG.getValueType(VA.getValVT())); |
666 | break; |
667 | default: |
668 | break; |
669 | } |
670 | |
671 | // Truncate the register down to the argument type. |
672 | if (VA.isExtInLoc()) |
673 | Arg = DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT: VA.getValVT(), Operand: Arg); |
674 | |
675 | InVals.push_back(Elt: Arg); |
676 | continue; |
677 | } |
678 | |
679 | // The registers are exhausted. This argument was passed on the stack. |
680 | assert(VA.isMemLoc()); |
681 | // The CC_Sparc64_Full/Half functions compute stack offsets relative to the |
682 | // beginning of the arguments area at %fp+BIAS+128. |
683 | unsigned Offset = VA.getLocMemOffset() + ArgArea; |
684 | unsigned ValSize = VA.getValVT().getSizeInBits() / 8; |
685 | // Adjust offset for extended arguments, SPARC is big-endian. |
686 | // The caller will have written the full slot with extended bytes, but we |
687 | // prefer our own extending loads. |
688 | if (VA.isExtInLoc()) |
689 | Offset += 8 - ValSize; |
690 | int FI = MF.getFrameInfo().CreateFixedObject(Size: ValSize, SPOffset: Offset, IsImmutable: true); |
691 | InVals.push_back( |
692 | Elt: DAG.getLoad(VT: VA.getValVT(), dl: DL, Chain, |
693 | Ptr: DAG.getFrameIndex(FI, VT: getPointerTy(DL: MF.getDataLayout())), |
694 | PtrInfo: MachinePointerInfo::getFixedStack(MF, FI))); |
695 | } |
696 | |
697 | if (!IsVarArg) |
698 | return Chain; |
699 | |
700 | // This function takes variable arguments, some of which may have been passed |
701 | // in registers %i0-%i5. Variable floating point arguments are never passed |
702 | // in floating point registers. They go on %i0-%i5 or on the stack like |
703 | // integer arguments. |
704 | // |
705 | // The va_start intrinsic needs to know the offset to the first variable |
706 | // argument. |
707 | unsigned ArgOffset = CCInfo.getStackSize(); |
708 | SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); |
709 | // Skip the 128 bytes of register save area. |
710 | FuncInfo->setVarArgsFrameOffset(ArgOffset + ArgArea + |
711 | Subtarget->getStackPointerBias()); |
712 | |
713 | // Save the variable arguments that were passed in registers. |
714 | // The caller is required to reserve stack space for 6 arguments regardless |
715 | // of how many arguments were actually passed. |
716 | SmallVector<SDValue, 8> OutChains; |
717 | for (; ArgOffset < 6*8; ArgOffset += 8) { |
718 | Register VReg = MF.addLiveIn(PReg: SP::I0 + ArgOffset/8, RC: &SP::I64RegsRegClass); |
719 | SDValue VArg = DAG.getCopyFromReg(Chain, dl: DL, Reg: VReg, VT: MVT::i64); |
720 | int FI = MF.getFrameInfo().CreateFixedObject(Size: 8, SPOffset: ArgOffset + ArgArea, IsImmutable: true); |
721 | auto PtrVT = getPointerTy(DL: MF.getDataLayout()); |
722 | OutChains.push_back( |
723 | Elt: DAG.getStore(Chain, dl: DL, Val: VArg, Ptr: DAG.getFrameIndex(FI, VT: PtrVT), |
724 | PtrInfo: MachinePointerInfo::getFixedStack(MF, FI))); |
725 | } |
726 | |
727 | if (!OutChains.empty()) |
728 | Chain = DAG.getNode(Opcode: ISD::TokenFactor, DL, VT: MVT::Other, Ops: OutChains); |
729 | |
730 | return Chain; |
731 | } |
732 | |
733 | // Check whether any of the argument registers are reserved |
734 | static bool isAnyArgRegReserved(const SparcRegisterInfo *TRI, |
735 | const MachineFunction &MF) { |
736 | // The register window design means that outgoing parameters at O* |
737 | // will appear in the callee as I*. |
738 | // Be conservative and check both sides of the register names. |
739 | bool Outgoing = |
740 | llvm::any_of(Range: SP::GPROutgoingArgRegClass, P: [TRI, &MF](MCPhysReg r) { |
741 | return TRI->isReservedReg(MF, Reg: r); |
742 | }); |
743 | bool Incoming = |
744 | llvm::any_of(Range: SP::GPRIncomingArgRegClass, P: [TRI, &MF](MCPhysReg r) { |
745 | return TRI->isReservedReg(MF, Reg: r); |
746 | }); |
747 | return Outgoing || Incoming; |
748 | } |
749 | |
750 | static void emitReservedArgRegCallError(const MachineFunction &MF) { |
751 | const Function &F = MF.getFunction(); |
752 | F.getContext().diagnose(DI: DiagnosticInfoUnsupported{ |
753 | F, ("SPARC doesn't support" |
754 | " function calls if any of the argument registers is reserved." )}); |
755 | } |
756 | |
757 | SDValue |
758 | SparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, |
759 | SmallVectorImpl<SDValue> &InVals) const { |
760 | if (Subtarget->is64Bit()) |
761 | return LowerCall_64(CLI, InVals); |
762 | return LowerCall_32(CLI, InVals); |
763 | } |
764 | |
765 | static bool hasReturnsTwiceAttr(SelectionDAG &DAG, SDValue Callee, |
766 | const CallBase *Call) { |
767 | if (Call) |
768 | return Call->hasFnAttr(Kind: Attribute::ReturnsTwice); |
769 | |
770 | const Function *CalleeFn = nullptr; |
771 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Val&: Callee)) { |
772 | CalleeFn = dyn_cast<Function>(Val: G->getGlobal()); |
773 | } else if (ExternalSymbolSDNode *E = |
774 | dyn_cast<ExternalSymbolSDNode>(Val&: Callee)) { |
775 | const Function &Fn = DAG.getMachineFunction().getFunction(); |
776 | const Module *M = Fn.getParent(); |
777 | const char *CalleeName = E->getSymbol(); |
778 | CalleeFn = M->getFunction(Name: CalleeName); |
779 | } |
780 | |
781 | if (!CalleeFn) |
782 | return false; |
783 | return CalleeFn->hasFnAttribute(Kind: Attribute::ReturnsTwice); |
784 | } |
785 | |
786 | /// IsEligibleForTailCallOptimization - Check whether the call is eligible |
787 | /// for tail call optimization. |
788 | bool SparcTargetLowering::IsEligibleForTailCallOptimization( |
789 | CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF) const { |
790 | |
791 | auto &Outs = CLI.Outs; |
792 | auto &Caller = MF.getFunction(); |
793 | |
794 | // Do not tail call opt functions with "disable-tail-calls" attribute. |
795 | if (Caller.getFnAttribute(Kind: "disable-tail-calls" ).getValueAsString() == "true" ) |
796 | return false; |
797 | |
798 | // Do not tail call opt if the stack is used to pass parameters. |
799 | // 64-bit targets have a slightly higher limit since the ABI requires |
800 | // to allocate some space even when all the parameters fit inside registers. |
801 | unsigned StackSizeLimit = Subtarget->is64Bit() ? 48 : 0; |
802 | if (CCInfo.getStackSize() > StackSizeLimit) |
803 | return false; |
804 | |
805 | // Do not tail call opt if either the callee or caller returns |
806 | // a struct and the other does not. |
807 | if (!Outs.empty() && Caller.hasStructRetAttr() != Outs[0].Flags.isSRet()) |
808 | return false; |
809 | |
810 | // Byval parameters hand the function a pointer directly into the stack area |
811 | // we want to reuse during a tail call. |
812 | for (auto &Arg : Outs) |
813 | if (Arg.Flags.isByVal()) |
814 | return false; |
815 | |
816 | return true; |
817 | } |
818 | |
819 | // Lower a call for the 32-bit ABI. |
820 | SDValue |
821 | SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, |
822 | SmallVectorImpl<SDValue> &InVals) const { |
823 | SelectionDAG &DAG = CLI.DAG; |
824 | SDLoc &dl = CLI.DL; |
825 | SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; |
826 | SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; |
827 | SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; |
828 | SDValue Chain = CLI.Chain; |
829 | SDValue Callee = CLI.Callee; |
830 | bool &isTailCall = CLI.IsTailCall; |
831 | CallingConv::ID CallConv = CLI.CallConv; |
832 | bool isVarArg = CLI.IsVarArg; |
833 | MachineFunction &MF = DAG.getMachineFunction(); |
834 | |
835 | // Analyze operands of the call, assigning locations to each operand. |
836 | SmallVector<CCValAssign, 16> ArgLocs; |
837 | CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, |
838 | *DAG.getContext()); |
839 | CCInfo.AnalyzeCallOperands(Outs, Fn: CC_Sparc32); |
840 | |
841 | isTailCall = isTailCall && IsEligibleForTailCallOptimization( |
842 | CCInfo, CLI, MF&: DAG.getMachineFunction()); |
843 | |
844 | // Get the size of the outgoing arguments stack space requirement. |
845 | unsigned ArgsSize = CCInfo.getStackSize(); |
846 | |
847 | // Keep stack frames 8-byte aligned. |
848 | ArgsSize = (ArgsSize+7) & ~7; |
849 | |
850 | MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); |
851 | |
852 | // Create local copies for byval args. |
853 | SmallVector<SDValue, 8> ByValArgs; |
854 | for (unsigned i = 0, e = Outs.size(); i != e; ++i) { |
855 | ISD::ArgFlagsTy Flags = Outs[i].Flags; |
856 | if (!Flags.isByVal()) |
857 | continue; |
858 | |
859 | SDValue Arg = OutVals[i]; |
860 | unsigned Size = Flags.getByValSize(); |
861 | Align Alignment = Flags.getNonZeroByValAlign(); |
862 | |
863 | if (Size > 0U) { |
864 | int FI = MFI.CreateStackObject(Size, Alignment, isSpillSlot: false); |
865 | SDValue FIPtr = DAG.getFrameIndex(FI, VT: getPointerTy(DL: DAG.getDataLayout())); |
866 | SDValue SizeNode = DAG.getConstant(Val: Size, DL: dl, VT: MVT::i32); |
867 | |
868 | Chain = DAG.getMemcpy(Chain, dl, Dst: FIPtr, Src: Arg, Size: SizeNode, Alignment, |
869 | isVol: false, // isVolatile, |
870 | AlwaysInline: (Size <= 32), // AlwaysInline if size <= 32, |
871 | /*CI=*/nullptr, OverrideTailCall: std::nullopt, DstPtrInfo: MachinePointerInfo(), |
872 | SrcPtrInfo: MachinePointerInfo()); |
873 | ByValArgs.push_back(Elt: FIPtr); |
874 | } |
875 | else { |
876 | SDValue nullVal; |
877 | ByValArgs.push_back(Elt: nullVal); |
878 | } |
879 | } |
880 | |
881 | assert(!isTailCall || ArgsSize == 0); |
882 | |
883 | if (!isTailCall) |
884 | Chain = DAG.getCALLSEQ_START(Chain, InSize: ArgsSize, OutSize: 0, DL: dl); |
885 | |
886 | SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; |
887 | SmallVector<SDValue, 8> MemOpChains; |
888 | |
889 | const unsigned StackOffset = 92; |
890 | bool hasStructRetAttr = false; |
891 | unsigned SRetArgSize = 0; |
892 | // Walk the register/memloc assignments, inserting copies/loads. |
893 | for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size(); |
894 | i != e; |
895 | ++i, ++realArgIdx) { |
896 | CCValAssign &VA = ArgLocs[i]; |
897 | SDValue Arg = OutVals[realArgIdx]; |
898 | |
899 | ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; |
900 | |
901 | // Use local copy if it is a byval arg. |
902 | if (Flags.isByVal()) { |
903 | Arg = ByValArgs[byvalArgIdx++]; |
904 | if (!Arg) { |
905 | continue; |
906 | } |
907 | } |
908 | |
909 | // Promote the value if needed. |
910 | switch (VA.getLocInfo()) { |
911 | default: llvm_unreachable("Unknown loc info!" ); |
912 | case CCValAssign::Full: break; |
913 | case CCValAssign::SExt: |
914 | Arg = DAG.getNode(Opcode: ISD::SIGN_EXTEND, DL: dl, VT: VA.getLocVT(), Operand: Arg); |
915 | break; |
916 | case CCValAssign::ZExt: |
917 | Arg = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL: dl, VT: VA.getLocVT(), Operand: Arg); |
918 | break; |
919 | case CCValAssign::AExt: |
920 | Arg = DAG.getNode(Opcode: ISD::ANY_EXTEND, DL: dl, VT: VA.getLocVT(), Operand: Arg); |
921 | break; |
922 | case CCValAssign::BCvt: |
923 | Arg = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: VA.getLocVT(), Operand: Arg); |
924 | break; |
925 | } |
926 | |
927 | if (Flags.isSRet()) { |
928 | assert(VA.needsCustom()); |
929 | |
930 | if (isTailCall) |
931 | continue; |
932 | |
933 | // store SRet argument in %sp+64 |
934 | SDValue StackPtr = DAG.getRegister(Reg: SP::O6, VT: MVT::i32); |
935 | SDValue PtrOff = DAG.getIntPtrConstant(Val: 64, DL: dl); |
936 | PtrOff = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: MVT::i32, N1: StackPtr, N2: PtrOff); |
937 | MemOpChains.push_back( |
938 | Elt: DAG.getStore(Chain, dl, Val: Arg, Ptr: PtrOff, PtrInfo: MachinePointerInfo())); |
939 | hasStructRetAttr = true; |
940 | // sret only allowed on first argument |
941 | assert(Outs[realArgIdx].OrigArgIndex == 0); |
942 | SRetArgSize = |
943 | DAG.getDataLayout().getTypeAllocSize(Ty: CLI.getArgs()[0].IndirectType); |
944 | continue; |
945 | } |
946 | |
947 | if (VA.needsCustom()) { |
948 | assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32); |
949 | |
950 | if (VA.isMemLoc()) { |
951 | unsigned Offset = VA.getLocMemOffset() + StackOffset; |
952 | // if it is double-word aligned, just store. |
953 | if (Offset % 8 == 0) { |
954 | SDValue StackPtr = DAG.getRegister(Reg: SP::O6, VT: MVT::i32); |
955 | SDValue PtrOff = DAG.getIntPtrConstant(Val: Offset, DL: dl); |
956 | PtrOff = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: MVT::i32, N1: StackPtr, N2: PtrOff); |
957 | MemOpChains.push_back( |
958 | Elt: DAG.getStore(Chain, dl, Val: Arg, Ptr: PtrOff, PtrInfo: MachinePointerInfo())); |
959 | continue; |
960 | } |
961 | } |
962 | |
963 | if (VA.getLocVT() == MVT::f64) { |
964 | // Move from the float value from float registers into the |
965 | // integer registers. |
966 | if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Val&: Arg)) |
967 | Arg = bitcastConstantFPToInt(C, DL: dl, DAG); |
968 | else |
969 | Arg = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: MVT::v2i32, Operand: Arg); |
970 | } |
971 | |
972 | SDValue Part0 = DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL: dl, VT: MVT::i32, |
973 | N1: Arg, |
974 | N2: DAG.getConstant(Val: 0, DL: dl, VT: getVectorIdxTy(DL: DAG.getDataLayout()))); |
975 | SDValue Part1 = DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL: dl, VT: MVT::i32, |
976 | N1: Arg, |
977 | N2: DAG.getConstant(Val: 1, DL: dl, VT: getVectorIdxTy(DL: DAG.getDataLayout()))); |
978 | |
979 | if (VA.isRegLoc()) { |
980 | RegsToPass.push_back(Elt: std::make_pair(x: VA.getLocReg(), y&: Part0)); |
981 | assert(i+1 != e); |
982 | CCValAssign &NextVA = ArgLocs[++i]; |
983 | if (NextVA.isRegLoc()) { |
984 | RegsToPass.push_back(Elt: std::make_pair(x: NextVA.getLocReg(), y&: Part1)); |
985 | } else { |
986 | // Store the second part in stack. |
987 | unsigned Offset = NextVA.getLocMemOffset() + StackOffset; |
988 | SDValue StackPtr = DAG.getRegister(Reg: SP::O6, VT: MVT::i32); |
989 | SDValue PtrOff = DAG.getIntPtrConstant(Val: Offset, DL: dl); |
990 | PtrOff = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: MVT::i32, N1: StackPtr, N2: PtrOff); |
991 | MemOpChains.push_back( |
992 | Elt: DAG.getStore(Chain, dl, Val: Part1, Ptr: PtrOff, PtrInfo: MachinePointerInfo())); |
993 | } |
994 | } else { |
995 | unsigned Offset = VA.getLocMemOffset() + StackOffset; |
996 | // Store the first part. |
997 | SDValue StackPtr = DAG.getRegister(Reg: SP::O6, VT: MVT::i32); |
998 | SDValue PtrOff = DAG.getIntPtrConstant(Val: Offset, DL: dl); |
999 | PtrOff = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: MVT::i32, N1: StackPtr, N2: PtrOff); |
1000 | MemOpChains.push_back( |
1001 | Elt: DAG.getStore(Chain, dl, Val: Part0, Ptr: PtrOff, PtrInfo: MachinePointerInfo())); |
1002 | // Store the second part. |
1003 | PtrOff = DAG.getIntPtrConstant(Val: Offset + 4, DL: dl); |
1004 | PtrOff = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: MVT::i32, N1: StackPtr, N2: PtrOff); |
1005 | MemOpChains.push_back( |
1006 | Elt: DAG.getStore(Chain, dl, Val: Part1, Ptr: PtrOff, PtrInfo: MachinePointerInfo())); |
1007 | } |
1008 | continue; |
1009 | } |
1010 | |
1011 | // Arguments that can be passed on register must be kept at |
1012 | // RegsToPass vector |
1013 | if (VA.isRegLoc()) { |
1014 | if (VA.getLocVT() != MVT::f32) { |
1015 | RegsToPass.push_back(Elt: std::make_pair(x: VA.getLocReg(), y&: Arg)); |
1016 | continue; |
1017 | } |
1018 | Arg = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: MVT::i32, Operand: Arg); |
1019 | RegsToPass.push_back(Elt: std::make_pair(x: VA.getLocReg(), y&: Arg)); |
1020 | continue; |
1021 | } |
1022 | |
1023 | assert(VA.isMemLoc()); |
1024 | |
1025 | // Create a store off the stack pointer for this argument. |
1026 | SDValue StackPtr = DAG.getRegister(Reg: SP::O6, VT: MVT::i32); |
1027 | SDValue PtrOff = DAG.getIntPtrConstant(Val: VA.getLocMemOffset() + StackOffset, |
1028 | DL: dl); |
1029 | PtrOff = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: MVT::i32, N1: StackPtr, N2: PtrOff); |
1030 | MemOpChains.push_back( |
1031 | Elt: DAG.getStore(Chain, dl, Val: Arg, Ptr: PtrOff, PtrInfo: MachinePointerInfo())); |
1032 | } |
1033 | |
1034 | |
1035 | // Emit all stores, make sure the occur before any copies into physregs. |
1036 | if (!MemOpChains.empty()) |
1037 | Chain = DAG.getNode(Opcode: ISD::TokenFactor, DL: dl, VT: MVT::Other, Ops: MemOpChains); |
1038 | |
1039 | // Build a sequence of copy-to-reg nodes chained together with token |
1040 | // chain and flag operands which copy the outgoing args into registers. |
1041 | // The InGlue in necessary since all emitted instructions must be |
1042 | // stuck together. |
1043 | SDValue InGlue; |
1044 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { |
1045 | Register Reg = RegsToPass[i].first; |
1046 | if (!isTailCall) |
1047 | Reg = toCallerWindow(Reg); |
1048 | Chain = DAG.getCopyToReg(Chain, dl, Reg, N: RegsToPass[i].second, Glue: InGlue); |
1049 | InGlue = Chain.getValue(R: 1); |
1050 | } |
1051 | |
1052 | bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, Call: CLI.CB); |
1053 | |
1054 | // If the callee is a GlobalAddress node (quite common, every direct call is) |
1055 | // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. |
1056 | // Likewise ExternalSymbol -> TargetExternalSymbol. |
1057 | unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30 |
1058 | : SparcMCExpr::VK_Sparc_WDISP30; |
1059 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Val&: Callee)) |
1060 | Callee = DAG.getTargetGlobalAddress(GV: G->getGlobal(), DL: dl, VT: MVT::i32, offset: 0, TargetFlags: TF); |
1061 | else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Val&: Callee)) |
1062 | Callee = DAG.getTargetExternalSymbol(Sym: E->getSymbol(), VT: MVT::i32, TargetFlags: TF); |
1063 | |
1064 | // Returns a chain & a flag for retval copy to use |
1065 | SDVTList NodeTys = DAG.getVTList(VT1: MVT::Other, VT2: MVT::Glue); |
1066 | SmallVector<SDValue, 8> Ops; |
1067 | Ops.push_back(Elt: Chain); |
1068 | Ops.push_back(Elt: Callee); |
1069 | if (hasStructRetAttr) |
1070 | Ops.push_back(Elt: DAG.getTargetConstant(Val: SRetArgSize, DL: dl, VT: MVT::i32)); |
1071 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { |
1072 | Register Reg = RegsToPass[i].first; |
1073 | if (!isTailCall) |
1074 | Reg = toCallerWindow(Reg); |
1075 | Ops.push_back(Elt: DAG.getRegister(Reg, VT: RegsToPass[i].second.getValueType())); |
1076 | } |
1077 | |
1078 | // Add a register mask operand representing the call-preserved registers. |
1079 | const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo(); |
1080 | const uint32_t *Mask = |
1081 | ((hasReturnsTwice) |
1082 | ? TRI->getRTCallPreservedMask(CC: CallConv) |
1083 | : TRI->getCallPreservedMask(MF: DAG.getMachineFunction(), CC: CallConv)); |
1084 | |
1085 | if (isAnyArgRegReserved(TRI, MF)) |
1086 | emitReservedArgRegCallError(MF); |
1087 | |
1088 | assert(Mask && "Missing call preserved mask for calling convention" ); |
1089 | Ops.push_back(Elt: DAG.getRegisterMask(RegMask: Mask)); |
1090 | |
1091 | if (InGlue.getNode()) |
1092 | Ops.push_back(Elt: InGlue); |
1093 | |
1094 | if (isTailCall) { |
1095 | DAG.getMachineFunction().getFrameInfo().setHasTailCall(); |
1096 | return DAG.getNode(Opcode: SPISD::TAIL_CALL, DL: dl, VT: MVT::Other, Ops); |
1097 | } |
1098 | |
1099 | Chain = DAG.getNode(Opcode: SPISD::CALL, DL: dl, VTList: NodeTys, Ops); |
1100 | InGlue = Chain.getValue(R: 1); |
1101 | |
1102 | Chain = DAG.getCALLSEQ_END(Chain, Size1: ArgsSize, Size2: 0, Glue: InGlue, DL: dl); |
1103 | InGlue = Chain.getValue(R: 1); |
1104 | |
1105 | // Assign locations to each value returned by this call. |
1106 | SmallVector<CCValAssign, 16> RVLocs; |
1107 | CCState RVInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, |
1108 | *DAG.getContext()); |
1109 | |
1110 | RVInfo.AnalyzeCallResult(Ins, Fn: RetCC_Sparc32); |
1111 | |
1112 | // Copy all of the result registers out of their specified physreg. |
1113 | for (unsigned i = 0; i != RVLocs.size(); ++i) { |
1114 | assert(RVLocs[i].isRegLoc() && "Can only return in registers!" ); |
1115 | if (RVLocs[i].getLocVT() == MVT::v2i32) { |
1116 | SDValue Vec = DAG.getNode(Opcode: ISD::UNDEF, DL: dl, VT: MVT::v2i32); |
1117 | SDValue Lo = DAG.getCopyFromReg( |
1118 | Chain, dl, Reg: toCallerWindow(Reg: RVLocs[i++].getLocReg()), VT: MVT::i32, Glue: InGlue); |
1119 | Chain = Lo.getValue(R: 1); |
1120 | InGlue = Lo.getValue(R: 2); |
1121 | Vec = DAG.getNode(Opcode: ISD::INSERT_VECTOR_ELT, DL: dl, VT: MVT::v2i32, N1: Vec, N2: Lo, |
1122 | N3: DAG.getConstant(Val: 0, DL: dl, VT: MVT::i32)); |
1123 | SDValue Hi = DAG.getCopyFromReg( |
1124 | Chain, dl, Reg: toCallerWindow(Reg: RVLocs[i].getLocReg()), VT: MVT::i32, Glue: InGlue); |
1125 | Chain = Hi.getValue(R: 1); |
1126 | InGlue = Hi.getValue(R: 2); |
1127 | Vec = DAG.getNode(Opcode: ISD::INSERT_VECTOR_ELT, DL: dl, VT: MVT::v2i32, N1: Vec, N2: Hi, |
1128 | N3: DAG.getConstant(Val: 1, DL: dl, VT: MVT::i32)); |
1129 | InVals.push_back(Elt: Vec); |
1130 | } else { |
1131 | Chain = |
1132 | DAG.getCopyFromReg(Chain, dl, Reg: toCallerWindow(Reg: RVLocs[i].getLocReg()), |
1133 | VT: RVLocs[i].getValVT(), Glue: InGlue) |
1134 | .getValue(R: 1); |
1135 | InGlue = Chain.getValue(R: 2); |
1136 | InVals.push_back(Elt: Chain.getValue(R: 0)); |
1137 | } |
1138 | } |
1139 | |
1140 | return Chain; |
1141 | } |
1142 | |
1143 | // FIXME? Maybe this could be a TableGen attribute on some registers and |
1144 | // this table could be generated automatically from RegInfo. |
1145 | Register SparcTargetLowering::getRegisterByName(const char* RegName, LLT VT, |
1146 | const MachineFunction &MF) const { |
1147 | Register Reg = StringSwitch<Register>(RegName) |
1148 | .Case(S: "i0" , Value: SP::I0).Case(S: "i1" , Value: SP::I1).Case(S: "i2" , Value: SP::I2).Case(S: "i3" , Value: SP::I3) |
1149 | .Case(S: "i4" , Value: SP::I4).Case(S: "i5" , Value: SP::I5).Case(S: "i6" , Value: SP::I6).Case(S: "i7" , Value: SP::I7) |
1150 | .Case(S: "o0" , Value: SP::O0).Case(S: "o1" , Value: SP::O1).Case(S: "o2" , Value: SP::O2).Case(S: "o3" , Value: SP::O3) |
1151 | .Case(S: "o4" , Value: SP::O4).Case(S: "o5" , Value: SP::O5).Case(S: "o6" , Value: SP::O6).Case(S: "o7" , Value: SP::O7) |
1152 | .Case(S: "l0" , Value: SP::L0).Case(S: "l1" , Value: SP::L1).Case(S: "l2" , Value: SP::L2).Case(S: "l3" , Value: SP::L3) |
1153 | .Case(S: "l4" , Value: SP::L4).Case(S: "l5" , Value: SP::L5).Case(S: "l6" , Value: SP::L6).Case(S: "l7" , Value: SP::L7) |
1154 | .Case(S: "g0" , Value: SP::G0).Case(S: "g1" , Value: SP::G1).Case(S: "g2" , Value: SP::G2).Case(S: "g3" , Value: SP::G3) |
1155 | .Case(S: "g4" , Value: SP::G4).Case(S: "g5" , Value: SP::G5).Case(S: "g6" , Value: SP::G6).Case(S: "g7" , Value: SP::G7) |
1156 | .Default(Value: 0); |
1157 | |
1158 | // If we're directly referencing register names |
1159 | // (e.g in GCC C extension `register int r asm("g1");`), |
1160 | // make sure that said register is in the reserve list. |
1161 | const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo(); |
1162 | if (!TRI->isReservedReg(MF, Reg)) |
1163 | Reg = 0; |
1164 | |
1165 | if (Reg) |
1166 | return Reg; |
1167 | |
1168 | report_fatal_error(reason: "Invalid register name global variable" ); |
1169 | } |
1170 | |
1171 | // Fixup floating point arguments in the ... part of a varargs call. |
1172 | // |
1173 | // The SPARC v9 ABI requires that floating point arguments are treated the same |
1174 | // as integers when calling a varargs function. This does not apply to the |
1175 | // fixed arguments that are part of the function's prototype. |
1176 | // |
1177 | // This function post-processes a CCValAssign array created by |
1178 | // AnalyzeCallOperands(). |
1179 | static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs, |
1180 | ArrayRef<ISD::OutputArg> Outs) { |
1181 | for (CCValAssign &VA : ArgLocs) { |
1182 | MVT ValTy = VA.getLocVT(); |
1183 | // FIXME: What about f32 arguments? C promotes them to f64 when calling |
1184 | // varargs functions. |
1185 | if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128)) |
1186 | continue; |
1187 | // The fixed arguments to a varargs function still go in FP registers. |
1188 | if (Outs[VA.getValNo()].IsFixed) |
1189 | continue; |
1190 | |
1191 | // This floating point argument should be reassigned. |
1192 | // Determine the offset into the argument array. |
1193 | Register firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0; |
1194 | unsigned argSize = (ValTy == MVT::f64) ? 8 : 16; |
1195 | unsigned Offset = argSize * (VA.getLocReg() - firstReg); |
1196 | assert(Offset < 16*8 && "Offset out of range, bad register enum?" ); |
1197 | |
1198 | if (Offset < 6*8) { |
1199 | // This argument should go in %i0-%i5. |
1200 | unsigned IReg = SP::I0 + Offset/8; |
1201 | if (ValTy == MVT::f64) |
1202 | // Full register, just bitconvert into i64. |
1203 | VA = CCValAssign::getReg(ValNo: VA.getValNo(), ValVT: VA.getValVT(), RegNo: IReg, LocVT: MVT::i64, |
1204 | HTP: CCValAssign::BCvt); |
1205 | else { |
1206 | assert(ValTy == MVT::f128 && "Unexpected type!" ); |
1207 | // Full register, just bitconvert into i128 -- We will lower this into |
1208 | // two i64s in LowerCall_64. |
1209 | VA = CCValAssign::getCustomReg(ValNo: VA.getValNo(), ValVT: VA.getValVT(), RegNo: IReg, |
1210 | LocVT: MVT::i128, HTP: CCValAssign::BCvt); |
1211 | } |
1212 | } else { |
1213 | // This needs to go to memory, we're out of integer registers. |
1214 | VA = CCValAssign::getMem(ValNo: VA.getValNo(), ValVT: VA.getValVT(), Offset, |
1215 | LocVT: VA.getLocVT(), HTP: VA.getLocInfo()); |
1216 | } |
1217 | } |
1218 | } |
1219 | |
1220 | // Lower a call for the 64-bit ABI. |
1221 | SDValue |
1222 | SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, |
1223 | SmallVectorImpl<SDValue> &InVals) const { |
1224 | SelectionDAG &DAG = CLI.DAG; |
1225 | SDLoc DL = CLI.DL; |
1226 | SDValue Chain = CLI.Chain; |
1227 | auto PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
1228 | MachineFunction &MF = DAG.getMachineFunction(); |
1229 | |
1230 | // Analyze operands of the call, assigning locations to each operand. |
1231 | SmallVector<CCValAssign, 16> ArgLocs; |
1232 | CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs, |
1233 | *DAG.getContext()); |
1234 | CCInfo.AnalyzeCallOperands(Outs: CLI.Outs, Fn: CC_Sparc64); |
1235 | |
1236 | CLI.IsTailCall = CLI.IsTailCall && IsEligibleForTailCallOptimization( |
1237 | CCInfo, CLI, MF&: DAG.getMachineFunction()); |
1238 | |
1239 | // Get the size of the outgoing arguments stack space requirement. |
1240 | // The stack offset computed by CC_Sparc64 includes all arguments. |
1241 | // Called functions expect 6 argument words to exist in the stack frame, used |
1242 | // or not. |
1243 | unsigned StackReserved = 6 * 8u; |
1244 | unsigned ArgsSize = std::max<unsigned>(a: StackReserved, b: CCInfo.getStackSize()); |
1245 | |
1246 | // Keep stack frames 16-byte aligned. |
1247 | ArgsSize = alignTo(Value: ArgsSize, Align: 16); |
1248 | |
1249 | // Varargs calls require special treatment. |
1250 | if (CLI.IsVarArg) |
1251 | fixupVariableFloatArgs(ArgLocs, Outs: CLI.Outs); |
1252 | |
1253 | assert(!CLI.IsTailCall || ArgsSize == StackReserved); |
1254 | |
1255 | // Adjust the stack pointer to make room for the arguments. |
1256 | // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls |
1257 | // with more than 6 arguments. |
1258 | if (!CLI.IsTailCall) |
1259 | Chain = DAG.getCALLSEQ_START(Chain, InSize: ArgsSize, OutSize: 0, DL); |
1260 | |
1261 | // Collect the set of registers to pass to the function and their values. |
1262 | // This will be emitted as a sequence of CopyToReg nodes glued to the call |
1263 | // instruction. |
1264 | SmallVector<std::pair<Register, SDValue>, 8> RegsToPass; |
1265 | |
1266 | // Collect chains from all the memory opeations that copy arguments to the |
1267 | // stack. They must follow the stack pointer adjustment above and precede the |
1268 | // call instruction itself. |
1269 | SmallVector<SDValue, 8> MemOpChains; |
1270 | |
1271 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { |
1272 | const CCValAssign &VA = ArgLocs[i]; |
1273 | SDValue Arg = CLI.OutVals[i]; |
1274 | |
1275 | // Promote the value if needed. |
1276 | switch (VA.getLocInfo()) { |
1277 | default: |
1278 | llvm_unreachable("Unknown location info!" ); |
1279 | case CCValAssign::Full: |
1280 | break; |
1281 | case CCValAssign::SExt: |
1282 | Arg = DAG.getNode(Opcode: ISD::SIGN_EXTEND, DL, VT: VA.getLocVT(), Operand: Arg); |
1283 | break; |
1284 | case CCValAssign::ZExt: |
1285 | Arg = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL, VT: VA.getLocVT(), Operand: Arg); |
1286 | break; |
1287 | case CCValAssign::AExt: |
1288 | Arg = DAG.getNode(Opcode: ISD::ANY_EXTEND, DL, VT: VA.getLocVT(), Operand: Arg); |
1289 | break; |
1290 | case CCValAssign::BCvt: |
1291 | // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But |
1292 | // SPARC does not support i128 natively. Lower it into two i64, see below. |
1293 | if (!VA.needsCustom() || VA.getValVT() != MVT::f128 |
1294 | || VA.getLocVT() != MVT::i128) |
1295 | Arg = DAG.getNode(Opcode: ISD::BITCAST, DL, VT: VA.getLocVT(), Operand: Arg); |
1296 | break; |
1297 | } |
1298 | |
1299 | if (VA.isRegLoc()) { |
1300 | if (VA.needsCustom() && VA.getValVT() == MVT::f128 |
1301 | && VA.getLocVT() == MVT::i128) { |
1302 | // Store and reload into the integer register reg and reg+1. |
1303 | unsigned Offset = 8 * (VA.getLocReg() - SP::I0); |
1304 | unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128; |
1305 | SDValue StackPtr = DAG.getRegister(Reg: SP::O6, VT: PtrVT); |
1306 | SDValue HiPtrOff = DAG.getIntPtrConstant(Val: StackOffset, DL); |
1307 | HiPtrOff = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, N1: StackPtr, N2: HiPtrOff); |
1308 | SDValue LoPtrOff = DAG.getIntPtrConstant(Val: StackOffset + 8, DL); |
1309 | LoPtrOff = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, N1: StackPtr, N2: LoPtrOff); |
1310 | |
1311 | // Store to %sp+BIAS+128+Offset |
1312 | SDValue Store = |
1313 | DAG.getStore(Chain, dl: DL, Val: Arg, Ptr: HiPtrOff, PtrInfo: MachinePointerInfo()); |
1314 | // Load into Reg and Reg+1 |
1315 | SDValue Hi64 = |
1316 | DAG.getLoad(VT: MVT::i64, dl: DL, Chain: Store, Ptr: HiPtrOff, PtrInfo: MachinePointerInfo()); |
1317 | SDValue Lo64 = |
1318 | DAG.getLoad(VT: MVT::i64, dl: DL, Chain: Store, Ptr: LoPtrOff, PtrInfo: MachinePointerInfo()); |
1319 | |
1320 | Register HiReg = VA.getLocReg(); |
1321 | Register LoReg = VA.getLocReg() + 1; |
1322 | if (!CLI.IsTailCall) { |
1323 | HiReg = toCallerWindow(Reg: HiReg); |
1324 | LoReg = toCallerWindow(Reg: LoReg); |
1325 | } |
1326 | |
1327 | RegsToPass.push_back(Elt: std::make_pair(x&: HiReg, y&: Hi64)); |
1328 | RegsToPass.push_back(Elt: std::make_pair(x&: LoReg, y&: Lo64)); |
1329 | continue; |
1330 | } |
1331 | |
1332 | // The custom bit on an i32 return value indicates that it should be |
1333 | // passed in the high bits of the register. |
1334 | if (VA.getValVT() == MVT::i32 && VA.needsCustom()) { |
1335 | Arg = DAG.getNode(Opcode: ISD::SHL, DL, VT: MVT::i64, N1: Arg, |
1336 | N2: DAG.getConstant(Val: 32, DL, VT: MVT::i32)); |
1337 | |
1338 | // The next value may go in the low bits of the same register. |
1339 | // Handle both at once. |
1340 | if (i+1 < ArgLocs.size() && ArgLocs[i+1].isRegLoc() && |
1341 | ArgLocs[i+1].getLocReg() == VA.getLocReg()) { |
1342 | SDValue NV = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL, VT: MVT::i64, |
1343 | Operand: CLI.OutVals[i+1]); |
1344 | Arg = DAG.getNode(Opcode: ISD::OR, DL, VT: MVT::i64, N1: Arg, N2: NV); |
1345 | // Skip the next value, it's already done. |
1346 | ++i; |
1347 | } |
1348 | } |
1349 | |
1350 | Register Reg = VA.getLocReg(); |
1351 | if (!CLI.IsTailCall) |
1352 | Reg = toCallerWindow(Reg); |
1353 | RegsToPass.push_back(Elt: std::make_pair(x&: Reg, y&: Arg)); |
1354 | continue; |
1355 | } |
1356 | |
1357 | assert(VA.isMemLoc()); |
1358 | |
1359 | // Create a store off the stack pointer for this argument. |
1360 | SDValue StackPtr = DAG.getRegister(Reg: SP::O6, VT: PtrVT); |
1361 | // The argument area starts at %fp+BIAS+128 in the callee frame, |
1362 | // %sp+BIAS+128 in ours. |
1363 | SDValue PtrOff = DAG.getIntPtrConstant(Val: VA.getLocMemOffset() + |
1364 | Subtarget->getStackPointerBias() + |
1365 | 128, DL); |
1366 | PtrOff = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, N1: StackPtr, N2: PtrOff); |
1367 | MemOpChains.push_back( |
1368 | Elt: DAG.getStore(Chain, dl: DL, Val: Arg, Ptr: PtrOff, PtrInfo: MachinePointerInfo())); |
1369 | } |
1370 | |
1371 | // Emit all stores, make sure they occur before the call. |
1372 | if (!MemOpChains.empty()) |
1373 | Chain = DAG.getNode(Opcode: ISD::TokenFactor, DL, VT: MVT::Other, Ops: MemOpChains); |
1374 | |
1375 | // Build a sequence of CopyToReg nodes glued together with token chain and |
1376 | // glue operands which copy the outgoing args into registers. The InGlue is |
1377 | // necessary since all emitted instructions must be stuck together in order |
1378 | // to pass the live physical registers. |
1379 | SDValue InGlue; |
1380 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { |
1381 | Chain = DAG.getCopyToReg(Chain, dl: DL, |
1382 | Reg: RegsToPass[i].first, N: RegsToPass[i].second, Glue: InGlue); |
1383 | InGlue = Chain.getValue(R: 1); |
1384 | } |
1385 | |
1386 | // If the callee is a GlobalAddress node (quite common, every direct call is) |
1387 | // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. |
1388 | // Likewise ExternalSymbol -> TargetExternalSymbol. |
1389 | SDValue Callee = CLI.Callee; |
1390 | bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, Call: CLI.CB); |
1391 | unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30 |
1392 | : SparcMCExpr::VK_Sparc_WDISP30; |
1393 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Val&: Callee)) |
1394 | Callee = DAG.getTargetGlobalAddress(GV: G->getGlobal(), DL, VT: PtrVT, offset: 0, TargetFlags: TF); |
1395 | else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Val&: Callee)) |
1396 | Callee = DAG.getTargetExternalSymbol(Sym: E->getSymbol(), VT: PtrVT, TargetFlags: TF); |
1397 | |
1398 | // Build the operands for the call instruction itself. |
1399 | SmallVector<SDValue, 8> Ops; |
1400 | Ops.push_back(Elt: Chain); |
1401 | Ops.push_back(Elt: Callee); |
1402 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) |
1403 | Ops.push_back(Elt: DAG.getRegister(Reg: RegsToPass[i].first, |
1404 | VT: RegsToPass[i].second.getValueType())); |
1405 | |
1406 | // Add a register mask operand representing the call-preserved registers. |
1407 | const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo(); |
1408 | const uint32_t *Mask = |
1409 | ((hasReturnsTwice) ? TRI->getRTCallPreservedMask(CC: CLI.CallConv) |
1410 | : TRI->getCallPreservedMask(MF: DAG.getMachineFunction(), |
1411 | CC: CLI.CallConv)); |
1412 | |
1413 | if (isAnyArgRegReserved(TRI, MF)) |
1414 | emitReservedArgRegCallError(MF); |
1415 | |
1416 | assert(Mask && "Missing call preserved mask for calling convention" ); |
1417 | Ops.push_back(Elt: DAG.getRegisterMask(RegMask: Mask)); |
1418 | |
1419 | // Make sure the CopyToReg nodes are glued to the call instruction which |
1420 | // consumes the registers. |
1421 | if (InGlue.getNode()) |
1422 | Ops.push_back(Elt: InGlue); |
1423 | |
1424 | // Now the call itself. |
1425 | if (CLI.IsTailCall) { |
1426 | DAG.getMachineFunction().getFrameInfo().setHasTailCall(); |
1427 | return DAG.getNode(Opcode: SPISD::TAIL_CALL, DL, VT: MVT::Other, Ops); |
1428 | } |
1429 | SDVTList NodeTys = DAG.getVTList(VT1: MVT::Other, VT2: MVT::Glue); |
1430 | Chain = DAG.getNode(Opcode: SPISD::CALL, DL, VTList: NodeTys, Ops); |
1431 | InGlue = Chain.getValue(R: 1); |
1432 | |
1433 | // Revert the stack pointer immediately after the call. |
1434 | Chain = DAG.getCALLSEQ_END(Chain, Size1: ArgsSize, Size2: 0, Glue: InGlue, DL); |
1435 | InGlue = Chain.getValue(R: 1); |
1436 | |
1437 | // Now extract the return values. This is more or less the same as |
1438 | // LowerFormalArguments_64. |
1439 | |
1440 | // Assign locations to each value returned by this call. |
1441 | SmallVector<CCValAssign, 16> RVLocs; |
1442 | CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs, |
1443 | *DAG.getContext()); |
1444 | |
1445 | // Set inreg flag manually for codegen generated library calls that |
1446 | // return float. |
1447 | if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && !CLI.CB) |
1448 | CLI.Ins[0].Flags.setInReg(); |
1449 | |
1450 | RVInfo.AnalyzeCallResult(Ins: CLI.Ins, Fn: RetCC_Sparc64); |
1451 | |
1452 | // Copy all of the result registers out of their specified physreg. |
1453 | for (unsigned i = 0; i != RVLocs.size(); ++i) { |
1454 | CCValAssign &VA = RVLocs[i]; |
1455 | assert(VA.isRegLoc() && "Can only return in registers!" ); |
1456 | unsigned Reg = toCallerWindow(Reg: VA.getLocReg()); |
1457 | |
1458 | // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can |
1459 | // reside in the same register in the high and low bits. Reuse the |
1460 | // CopyFromReg previous node to avoid duplicate copies. |
1461 | SDValue RV; |
1462 | if (RegisterSDNode *SrcReg = dyn_cast<RegisterSDNode>(Val: Chain.getOperand(i: 1))) |
1463 | if (SrcReg->getReg() == Reg && Chain->getOpcode() == ISD::CopyFromReg) |
1464 | RV = Chain.getValue(R: 0); |
1465 | |
1466 | // But usually we'll create a new CopyFromReg for a different register. |
1467 | if (!RV.getNode()) { |
1468 | RV = DAG.getCopyFromReg(Chain, dl: DL, Reg, VT: RVLocs[i].getLocVT(), Glue: InGlue); |
1469 | Chain = RV.getValue(R: 1); |
1470 | InGlue = Chain.getValue(R: 2); |
1471 | } |
1472 | |
1473 | // Get the high bits for i32 struct elements. |
1474 | if (VA.getValVT() == MVT::i32 && VA.needsCustom()) |
1475 | RV = DAG.getNode(Opcode: ISD::SRL, DL, VT: VA.getLocVT(), N1: RV, |
1476 | N2: DAG.getConstant(Val: 32, DL, VT: MVT::i32)); |
1477 | |
1478 | // The callee promoted the return value, so insert an Assert?ext SDNode so |
1479 | // we won't promote the value again in this function. |
1480 | switch (VA.getLocInfo()) { |
1481 | case CCValAssign::SExt: |
1482 | RV = DAG.getNode(Opcode: ISD::AssertSext, DL, VT: VA.getLocVT(), N1: RV, |
1483 | N2: DAG.getValueType(VA.getValVT())); |
1484 | break; |
1485 | case CCValAssign::ZExt: |
1486 | RV = DAG.getNode(Opcode: ISD::AssertZext, DL, VT: VA.getLocVT(), N1: RV, |
1487 | N2: DAG.getValueType(VA.getValVT())); |
1488 | break; |
1489 | default: |
1490 | break; |
1491 | } |
1492 | |
1493 | // Truncate the register down to the return value type. |
1494 | if (VA.isExtInLoc()) |
1495 | RV = DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT: VA.getValVT(), Operand: RV); |
1496 | |
1497 | InVals.push_back(Elt: RV); |
1498 | } |
1499 | |
1500 | return Chain; |
1501 | } |
1502 | |
1503 | //===----------------------------------------------------------------------===// |
1504 | // TargetLowering Implementation |
1505 | //===----------------------------------------------------------------------===// |
1506 | |
1507 | TargetLowering::AtomicExpansionKind SparcTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { |
1508 | if (AI->getOperation() == AtomicRMWInst::Xchg && |
1509 | AI->getType()->getPrimitiveSizeInBits() == 32) |
1510 | return AtomicExpansionKind::None; // Uses xchg instruction |
1511 | |
1512 | return AtomicExpansionKind::CmpXChg; |
1513 | } |
1514 | |
1515 | /// intCondCCodeToRcond - Convert a DAG integer condition code to a SPARC |
1516 | /// rcond condition. |
1517 | static SPCC::CondCodes intCondCCodeToRcond(ISD::CondCode CC) { |
1518 | switch (CC) { |
1519 | default: |
1520 | llvm_unreachable("Unknown/unsigned integer condition code!" ); |
1521 | case ISD::SETEQ: |
1522 | return SPCC::REG_Z; |
1523 | case ISD::SETNE: |
1524 | return SPCC::REG_NZ; |
1525 | case ISD::SETLT: |
1526 | return SPCC::REG_LZ; |
1527 | case ISD::SETGT: |
1528 | return SPCC::REG_GZ; |
1529 | case ISD::SETLE: |
1530 | return SPCC::REG_LEZ; |
1531 | case ISD::SETGE: |
1532 | return SPCC::REG_GEZ; |
1533 | } |
1534 | } |
1535 | |
1536 | /// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC |
1537 | /// condition. |
1538 | static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { |
1539 | switch (CC) { |
1540 | default: llvm_unreachable("Unknown integer condition code!" ); |
1541 | case ISD::SETEQ: return SPCC::ICC_E; |
1542 | case ISD::SETNE: return SPCC::ICC_NE; |
1543 | case ISD::SETLT: return SPCC::ICC_L; |
1544 | case ISD::SETGT: return SPCC::ICC_G; |
1545 | case ISD::SETLE: return SPCC::ICC_LE; |
1546 | case ISD::SETGE: return SPCC::ICC_GE; |
1547 | case ISD::SETULT: return SPCC::ICC_CS; |
1548 | case ISD::SETULE: return SPCC::ICC_LEU; |
1549 | case ISD::SETUGT: return SPCC::ICC_GU; |
1550 | case ISD::SETUGE: return SPCC::ICC_CC; |
1551 | } |
1552 | } |
1553 | |
1554 | /// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC |
1555 | /// FCC condition. |
1556 | static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { |
1557 | switch (CC) { |
1558 | default: llvm_unreachable("Unknown fp condition code!" ); |
1559 | case ISD::SETEQ: |
1560 | case ISD::SETOEQ: return SPCC::FCC_E; |
1561 | case ISD::SETNE: |
1562 | case ISD::SETUNE: return SPCC::FCC_NE; |
1563 | case ISD::SETLT: |
1564 | case ISD::SETOLT: return SPCC::FCC_L; |
1565 | case ISD::SETGT: |
1566 | case ISD::SETOGT: return SPCC::FCC_G; |
1567 | case ISD::SETLE: |
1568 | case ISD::SETOLE: return SPCC::FCC_LE; |
1569 | case ISD::SETGE: |
1570 | case ISD::SETOGE: return SPCC::FCC_GE; |
1571 | case ISD::SETULT: return SPCC::FCC_UL; |
1572 | case ISD::SETULE: return SPCC::FCC_ULE; |
1573 | case ISD::SETUGT: return SPCC::FCC_UG; |
1574 | case ISD::SETUGE: return SPCC::FCC_UGE; |
1575 | case ISD::SETUO: return SPCC::FCC_U; |
1576 | case ISD::SETO: return SPCC::FCC_O; |
1577 | case ISD::SETONE: return SPCC::FCC_LG; |
1578 | case ISD::SETUEQ: return SPCC::FCC_UE; |
1579 | } |
1580 | } |
1581 | |
1582 | SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM, |
1583 | const SparcSubtarget &STI) |
1584 | : TargetLowering(TM), Subtarget(&STI) { |
1585 | MVT PtrVT = MVT::getIntegerVT(BitWidth: TM.getPointerSizeInBits(AS: 0)); |
1586 | |
1587 | // Instructions which use registers as conditionals examine all the |
1588 | // bits (as does the pseudo SELECT_CC expansion). I don't think it |
1589 | // matters much whether it's ZeroOrOneBooleanContent, or |
1590 | // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the |
1591 | // former. |
1592 | setBooleanContents(ZeroOrOneBooleanContent); |
1593 | setBooleanVectorContents(ZeroOrOneBooleanContent); |
1594 | |
1595 | // Set up the register classes. |
1596 | addRegisterClass(VT: MVT::i32, RC: &SP::IntRegsRegClass); |
1597 | if (!Subtarget->useSoftFloat()) { |
1598 | addRegisterClass(VT: MVT::f32, RC: &SP::FPRegsRegClass); |
1599 | addRegisterClass(VT: MVT::f64, RC: &SP::DFPRegsRegClass); |
1600 | addRegisterClass(VT: MVT::f128, RC: &SP::QFPRegsRegClass); |
1601 | } |
1602 | if (Subtarget->is64Bit()) { |
1603 | addRegisterClass(VT: MVT::i64, RC: &SP::I64RegsRegClass); |
1604 | } else { |
1605 | // On 32bit sparc, we define a double-register 32bit register |
1606 | // class, as well. This is modeled in LLVM as a 2-vector of i32. |
1607 | addRegisterClass(VT: MVT::v2i32, RC: &SP::IntPairRegClass); |
1608 | |
1609 | // ...but almost all operations must be expanded, so set that as |
1610 | // the default. |
1611 | for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) { |
1612 | setOperationAction(Op, VT: MVT::v2i32, Action: Expand); |
1613 | } |
1614 | // Truncating/extending stores/loads are also not supported. |
1615 | for (MVT VT : MVT::integer_fixedlen_vector_valuetypes()) { |
1616 | setLoadExtAction(ExtType: ISD::SEXTLOAD, ValVT: VT, MemVT: MVT::v2i32, Action: Expand); |
1617 | setLoadExtAction(ExtType: ISD::ZEXTLOAD, ValVT: VT, MemVT: MVT::v2i32, Action: Expand); |
1618 | setLoadExtAction(ExtType: ISD::EXTLOAD, ValVT: VT, MemVT: MVT::v2i32, Action: Expand); |
1619 | |
1620 | setLoadExtAction(ExtType: ISD::SEXTLOAD, ValVT: MVT::v2i32, MemVT: VT, Action: Expand); |
1621 | setLoadExtAction(ExtType: ISD::ZEXTLOAD, ValVT: MVT::v2i32, MemVT: VT, Action: Expand); |
1622 | setLoadExtAction(ExtType: ISD::EXTLOAD, ValVT: MVT::v2i32, MemVT: VT, Action: Expand); |
1623 | |
1624 | setTruncStoreAction(ValVT: VT, MemVT: MVT::v2i32, Action: Expand); |
1625 | setTruncStoreAction(ValVT: MVT::v2i32, MemVT: VT, Action: Expand); |
1626 | } |
1627 | // However, load and store *are* legal. |
1628 | setOperationAction(Op: ISD::LOAD, VT: MVT::v2i32, Action: Legal); |
1629 | setOperationAction(Op: ISD::STORE, VT: MVT::v2i32, Action: Legal); |
1630 | setOperationAction(Op: ISD::EXTRACT_VECTOR_ELT, VT: MVT::v2i32, Action: Legal); |
1631 | setOperationAction(Op: ISD::BUILD_VECTOR, VT: MVT::v2i32, Action: Legal); |
1632 | |
1633 | // And we need to promote i64 loads/stores into vector load/store |
1634 | setOperationAction(Op: ISD::LOAD, VT: MVT::i64, Action: Custom); |
1635 | setOperationAction(Op: ISD::STORE, VT: MVT::i64, Action: Custom); |
1636 | |
1637 | // Sadly, this doesn't work: |
1638 | // AddPromotedToType(ISD::LOAD, MVT::i64, MVT::v2i32); |
1639 | // AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32); |
1640 | } |
1641 | |
1642 | // Turn FP extload into load/fpextend |
1643 | for (MVT VT : MVT::fp_valuetypes()) { |
1644 | setLoadExtAction(ExtType: ISD::EXTLOAD, ValVT: VT, MemVT: MVT::f16, Action: Expand); |
1645 | setLoadExtAction(ExtType: ISD::EXTLOAD, ValVT: VT, MemVT: MVT::f32, Action: Expand); |
1646 | setLoadExtAction(ExtType: ISD::EXTLOAD, ValVT: VT, MemVT: MVT::f64, Action: Expand); |
1647 | } |
1648 | |
1649 | // Sparc doesn't have i1 sign extending load |
1650 | for (MVT VT : MVT::integer_valuetypes()) |
1651 | setLoadExtAction(ExtType: ISD::SEXTLOAD, ValVT: VT, MemVT: MVT::i1, Action: Promote); |
1652 | |
1653 | // Turn FP truncstore into trunc + store. |
1654 | setTruncStoreAction(ValVT: MVT::f32, MemVT: MVT::f16, Action: Expand); |
1655 | setTruncStoreAction(ValVT: MVT::f64, MemVT: MVT::f16, Action: Expand); |
1656 | setTruncStoreAction(ValVT: MVT::f64, MemVT: MVT::f32, Action: Expand); |
1657 | setTruncStoreAction(ValVT: MVT::f128, MemVT: MVT::f16, Action: Expand); |
1658 | setTruncStoreAction(ValVT: MVT::f128, MemVT: MVT::f32, Action: Expand); |
1659 | setTruncStoreAction(ValVT: MVT::f128, MemVT: MVT::f64, Action: Expand); |
1660 | |
1661 | // Custom legalize GlobalAddress nodes into LO/HI parts. |
1662 | setOperationAction(Op: ISD::GlobalAddress, VT: PtrVT, Action: Custom); |
1663 | setOperationAction(Op: ISD::GlobalTLSAddress, VT: PtrVT, Action: Custom); |
1664 | setOperationAction(Op: ISD::ConstantPool, VT: PtrVT, Action: Custom); |
1665 | setOperationAction(Op: ISD::BlockAddress, VT: PtrVT, Action: Custom); |
1666 | |
1667 | // Sparc doesn't have sext_inreg, replace them with shl/sra |
1668 | setOperationAction(Op: ISD::SIGN_EXTEND_INREG, VT: MVT::i16, Action: Expand); |
1669 | setOperationAction(Op: ISD::SIGN_EXTEND_INREG, VT: MVT::i8 , Action: Expand); |
1670 | setOperationAction(Op: ISD::SIGN_EXTEND_INREG, VT: MVT::i1 , Action: Expand); |
1671 | |
1672 | // Sparc has no REM or DIVREM operations. |
1673 | setOperationAction(Op: ISD::UREM, VT: MVT::i32, Action: Expand); |
1674 | setOperationAction(Op: ISD::SREM, VT: MVT::i32, Action: Expand); |
1675 | setOperationAction(Op: ISD::SDIVREM, VT: MVT::i32, Action: Expand); |
1676 | setOperationAction(Op: ISD::UDIVREM, VT: MVT::i32, Action: Expand); |
1677 | |
1678 | // ... nor does SparcV9. |
1679 | if (Subtarget->is64Bit()) { |
1680 | setOperationAction(Op: ISD::UREM, VT: MVT::i64, Action: Expand); |
1681 | setOperationAction(Op: ISD::SREM, VT: MVT::i64, Action: Expand); |
1682 | setOperationAction(Op: ISD::SDIVREM, VT: MVT::i64, Action: Expand); |
1683 | setOperationAction(Op: ISD::UDIVREM, VT: MVT::i64, Action: Expand); |
1684 | } |
1685 | |
1686 | // Custom expand fp<->sint |
1687 | setOperationAction(Op: ISD::FP_TO_SINT, VT: MVT::i32, Action: Custom); |
1688 | setOperationAction(Op: ISD::SINT_TO_FP, VT: MVT::i32, Action: Custom); |
1689 | setOperationAction(Op: ISD::FP_TO_SINT, VT: MVT::i64, Action: Custom); |
1690 | setOperationAction(Op: ISD::SINT_TO_FP, VT: MVT::i64, Action: Custom); |
1691 | |
1692 | // Custom Expand fp<->uint |
1693 | setOperationAction(Op: ISD::FP_TO_UINT, VT: MVT::i32, Action: Custom); |
1694 | setOperationAction(Op: ISD::UINT_TO_FP, VT: MVT::i32, Action: Custom); |
1695 | setOperationAction(Op: ISD::FP_TO_UINT, VT: MVT::i64, Action: Custom); |
1696 | setOperationAction(Op: ISD::UINT_TO_FP, VT: MVT::i64, Action: Custom); |
1697 | |
1698 | // Lower f16 conversion operations into library calls |
1699 | setOperationAction(Op: ISD::FP16_TO_FP, VT: MVT::f32, Action: Expand); |
1700 | setOperationAction(Op: ISD::FP_TO_FP16, VT: MVT::f32, Action: Expand); |
1701 | setOperationAction(Op: ISD::FP16_TO_FP, VT: MVT::f64, Action: Expand); |
1702 | setOperationAction(Op: ISD::FP_TO_FP16, VT: MVT::f64, Action: Expand); |
1703 | setOperationAction(Op: ISD::FP16_TO_FP, VT: MVT::f128, Action: Expand); |
1704 | setOperationAction(Op: ISD::FP_TO_FP16, VT: MVT::f128, Action: Expand); |
1705 | |
1706 | setOperationAction(Op: ISD::BITCAST, VT: MVT::f32, Action: Expand); |
1707 | setOperationAction(Op: ISD::BITCAST, VT: MVT::i32, Action: Expand); |
1708 | |
1709 | // Sparc has no select or setcc: expand to SELECT_CC. |
1710 | setOperationAction(Op: ISD::SELECT, VT: MVT::i32, Action: Expand); |
1711 | setOperationAction(Op: ISD::SELECT, VT: MVT::f32, Action: Expand); |
1712 | setOperationAction(Op: ISD::SELECT, VT: MVT::f64, Action: Expand); |
1713 | setOperationAction(Op: ISD::SELECT, VT: MVT::f128, Action: Expand); |
1714 | |
1715 | setOperationAction(Op: ISD::SETCC, VT: MVT::i32, Action: Expand); |
1716 | setOperationAction(Op: ISD::SETCC, VT: MVT::f32, Action: Expand); |
1717 | setOperationAction(Op: ISD::SETCC, VT: MVT::f64, Action: Expand); |
1718 | setOperationAction(Op: ISD::SETCC, VT: MVT::f128, Action: Expand); |
1719 | |
1720 | // Sparc doesn't have BRCOND either, it has BR_CC. |
1721 | setOperationAction(Op: ISD::BRCOND, VT: MVT::Other, Action: Expand); |
1722 | setOperationAction(Op: ISD::BRIND, VT: MVT::Other, Action: Expand); |
1723 | setOperationAction(Op: ISD::BR_JT, VT: MVT::Other, Action: Expand); |
1724 | setOperationAction(Op: ISD::BR_CC, VT: MVT::i32, Action: Custom); |
1725 | setOperationAction(Op: ISD::BR_CC, VT: MVT::f32, Action: Custom); |
1726 | setOperationAction(Op: ISD::BR_CC, VT: MVT::f64, Action: Custom); |
1727 | setOperationAction(Op: ISD::BR_CC, VT: MVT::f128, Action: Custom); |
1728 | |
1729 | setOperationAction(Op: ISD::SELECT_CC, VT: MVT::i32, Action: Custom); |
1730 | setOperationAction(Op: ISD::SELECT_CC, VT: MVT::f32, Action: Custom); |
1731 | setOperationAction(Op: ISD::SELECT_CC, VT: MVT::f64, Action: Custom); |
1732 | setOperationAction(Op: ISD::SELECT_CC, VT: MVT::f128, Action: Custom); |
1733 | |
1734 | setOperationAction(Op: ISD::ADDC, VT: MVT::i32, Action: Custom); |
1735 | setOperationAction(Op: ISD::ADDE, VT: MVT::i32, Action: Custom); |
1736 | setOperationAction(Op: ISD::SUBC, VT: MVT::i32, Action: Custom); |
1737 | setOperationAction(Op: ISD::SUBE, VT: MVT::i32, Action: Custom); |
1738 | |
1739 | if (Subtarget->is64Bit()) { |
1740 | setOperationAction(Op: ISD::ADDC, VT: MVT::i64, Action: Custom); |
1741 | setOperationAction(Op: ISD::ADDE, VT: MVT::i64, Action: Custom); |
1742 | setOperationAction(Op: ISD::SUBC, VT: MVT::i64, Action: Custom); |
1743 | setOperationAction(Op: ISD::SUBE, VT: MVT::i64, Action: Custom); |
1744 | setOperationAction(Op: ISD::BITCAST, VT: MVT::f64, Action: Expand); |
1745 | setOperationAction(Op: ISD::BITCAST, VT: MVT::i64, Action: Expand); |
1746 | setOperationAction(Op: ISD::SELECT, VT: MVT::i64, Action: Expand); |
1747 | setOperationAction(Op: ISD::SETCC, VT: MVT::i64, Action: Expand); |
1748 | setOperationAction(Op: ISD::BR_CC, VT: MVT::i64, Action: Custom); |
1749 | setOperationAction(Op: ISD::SELECT_CC, VT: MVT::i64, Action: Custom); |
1750 | |
1751 | setOperationAction(Op: ISD::CTPOP, VT: MVT::i64, |
1752 | Action: Subtarget->usePopc() ? Legal : Expand); |
1753 | setOperationAction(Op: ISD::CTTZ , VT: MVT::i64, Action: Expand); |
1754 | setOperationAction(Op: ISD::CTLZ , VT: MVT::i64, Action: Expand); |
1755 | setOperationAction(Op: ISD::BSWAP, VT: MVT::i64, Action: Expand); |
1756 | setOperationAction(Op: ISD::ROTL , VT: MVT::i64, Action: Expand); |
1757 | setOperationAction(Op: ISD::ROTR , VT: MVT::i64, Action: Expand); |
1758 | setOperationAction(Op: ISD::DYNAMIC_STACKALLOC, VT: MVT::i64, Action: Custom); |
1759 | } |
1760 | |
1761 | // ATOMICs. |
1762 | // Atomics are supported on SparcV9. 32-bit atomics are also |
1763 | // supported by some Leon SparcV8 variants. Otherwise, atomics |
1764 | // are unsupported. |
1765 | if (Subtarget->isV9()) { |
1766 | // TODO: we _ought_ to be able to support 64-bit atomics on 32-bit sparcv9, |
1767 | // but it hasn't been implemented in the backend yet. |
1768 | if (Subtarget->is64Bit()) |
1769 | setMaxAtomicSizeInBitsSupported(64); |
1770 | else |
1771 | setMaxAtomicSizeInBitsSupported(32); |
1772 | } else if (Subtarget->hasLeonCasa()) |
1773 | setMaxAtomicSizeInBitsSupported(32); |
1774 | else |
1775 | setMaxAtomicSizeInBitsSupported(0); |
1776 | |
1777 | setMinCmpXchgSizeInBits(32); |
1778 | |
1779 | setOperationAction(Op: ISD::ATOMIC_SWAP, VT: MVT::i32, Action: Legal); |
1780 | |
1781 | setOperationAction(Op: ISD::ATOMIC_FENCE, VT: MVT::Other, Action: Legal); |
1782 | |
1783 | // Custom Lower Atomic LOAD/STORE |
1784 | setOperationAction(Op: ISD::ATOMIC_LOAD, VT: MVT::i32, Action: Custom); |
1785 | setOperationAction(Op: ISD::ATOMIC_STORE, VT: MVT::i32, Action: Custom); |
1786 | |
1787 | if (Subtarget->is64Bit()) { |
1788 | setOperationAction(Op: ISD::ATOMIC_CMP_SWAP, VT: MVT::i64, Action: Legal); |
1789 | setOperationAction(Op: ISD::ATOMIC_SWAP, VT: MVT::i64, Action: Legal); |
1790 | setOperationAction(Op: ISD::ATOMIC_LOAD, VT: MVT::i64, Action: Custom); |
1791 | setOperationAction(Op: ISD::ATOMIC_STORE, VT: MVT::i64, Action: Custom); |
1792 | } |
1793 | |
1794 | if (!Subtarget->isV9()) { |
1795 | // SparcV8 does not have FNEGD and FABSD. |
1796 | setOperationAction(Op: ISD::FNEG, VT: MVT::f64, Action: Custom); |
1797 | setOperationAction(Op: ISD::FABS, VT: MVT::f64, Action: Custom); |
1798 | } |
1799 | |
1800 | setOperationAction(Op: ISD::FSIN , VT: MVT::f128, Action: Expand); |
1801 | setOperationAction(Op: ISD::FCOS , VT: MVT::f128, Action: Expand); |
1802 | setOperationAction(Op: ISD::FSINCOS, VT: MVT::f128, Action: Expand); |
1803 | setOperationAction(Op: ISD::FREM , VT: MVT::f128, Action: Expand); |
1804 | setOperationAction(Op: ISD::FMA , VT: MVT::f128, Action: Expand); |
1805 | setOperationAction(Op: ISD::FSIN , VT: MVT::f64, Action: Expand); |
1806 | setOperationAction(Op: ISD::FCOS , VT: MVT::f64, Action: Expand); |
1807 | setOperationAction(Op: ISD::FSINCOS, VT: MVT::f64, Action: Expand); |
1808 | setOperationAction(Op: ISD::FREM , VT: MVT::f64, Action: Expand); |
1809 | setOperationAction(Op: ISD::FMA , VT: MVT::f64, Action: Expand); |
1810 | setOperationAction(Op: ISD::FSIN , VT: MVT::f32, Action: Expand); |
1811 | setOperationAction(Op: ISD::FCOS , VT: MVT::f32, Action: Expand); |
1812 | setOperationAction(Op: ISD::FSINCOS, VT: MVT::f32, Action: Expand); |
1813 | setOperationAction(Op: ISD::FREM , VT: MVT::f32, Action: Expand); |
1814 | setOperationAction(Op: ISD::FMA , VT: MVT::f32, Action: Expand); |
1815 | setOperationAction(Op: ISD::CTTZ , VT: MVT::i32, Action: Expand); |
1816 | setOperationAction(Op: ISD::CTLZ , VT: MVT::i32, Action: Expand); |
1817 | setOperationAction(Op: ISD::ROTL , VT: MVT::i32, Action: Expand); |
1818 | setOperationAction(Op: ISD::ROTR , VT: MVT::i32, Action: Expand); |
1819 | setOperationAction(Op: ISD::BSWAP, VT: MVT::i32, Action: Expand); |
1820 | setOperationAction(Op: ISD::FCOPYSIGN, VT: MVT::f128, Action: Expand); |
1821 | setOperationAction(Op: ISD::FCOPYSIGN, VT: MVT::f64, Action: Expand); |
1822 | setOperationAction(Op: ISD::FCOPYSIGN, VT: MVT::f32, Action: Expand); |
1823 | setOperationAction(Op: ISD::FPOW , VT: MVT::f128, Action: Expand); |
1824 | setOperationAction(Op: ISD::FPOW , VT: MVT::f64, Action: Expand); |
1825 | setOperationAction(Op: ISD::FPOW , VT: MVT::f32, Action: Expand); |
1826 | |
1827 | setOperationAction(Op: ISD::SHL_PARTS, VT: MVT::i32, Action: Expand); |
1828 | setOperationAction(Op: ISD::SRA_PARTS, VT: MVT::i32, Action: Expand); |
1829 | setOperationAction(Op: ISD::SRL_PARTS, VT: MVT::i32, Action: Expand); |
1830 | |
1831 | // Expands to [SU]MUL_LOHI. |
1832 | setOperationAction(Op: ISD::MULHU, VT: MVT::i32, Action: Expand); |
1833 | setOperationAction(Op: ISD::MULHS, VT: MVT::i32, Action: Expand); |
1834 | setOperationAction(Op: ISD::MUL, VT: MVT::i32, Action: Expand); |
1835 | |
1836 | if (Subtarget->useSoftMulDiv()) { |
1837 | // .umul works for both signed and unsigned |
1838 | setOperationAction(Op: ISD::SMUL_LOHI, VT: MVT::i32, Action: Expand); |
1839 | setOperationAction(Op: ISD::UMUL_LOHI, VT: MVT::i32, Action: Expand); |
1840 | setLibcallName(Call: RTLIB::MUL_I32, Name: ".umul" ); |
1841 | |
1842 | setOperationAction(Op: ISD::SDIV, VT: MVT::i32, Action: Expand); |
1843 | setLibcallName(Call: RTLIB::SDIV_I32, Name: ".div" ); |
1844 | |
1845 | setOperationAction(Op: ISD::UDIV, VT: MVT::i32, Action: Expand); |
1846 | setLibcallName(Call: RTLIB::UDIV_I32, Name: ".udiv" ); |
1847 | |
1848 | setLibcallName(Call: RTLIB::SREM_I32, Name: ".rem" ); |
1849 | setLibcallName(Call: RTLIB::UREM_I32, Name: ".urem" ); |
1850 | } |
1851 | |
1852 | if (Subtarget->is64Bit()) { |
1853 | setOperationAction(Op: ISD::UMUL_LOHI, VT: MVT::i64, Action: Expand); |
1854 | setOperationAction(Op: ISD::SMUL_LOHI, VT: MVT::i64, Action: Expand); |
1855 | setOperationAction(Op: ISD::MULHU, VT: MVT::i64, Action: Expand); |
1856 | setOperationAction(Op: ISD::MULHS, VT: MVT::i64, Action: Expand); |
1857 | |
1858 | setOperationAction(Op: ISD::UMULO, VT: MVT::i64, Action: Custom); |
1859 | setOperationAction(Op: ISD::SMULO, VT: MVT::i64, Action: Custom); |
1860 | |
1861 | setOperationAction(Op: ISD::SHL_PARTS, VT: MVT::i64, Action: Expand); |
1862 | setOperationAction(Op: ISD::SRA_PARTS, VT: MVT::i64, Action: Expand); |
1863 | setOperationAction(Op: ISD::SRL_PARTS, VT: MVT::i64, Action: Expand); |
1864 | } |
1865 | |
1866 | // VASTART needs to be custom lowered to use the VarArgsFrameIndex. |
1867 | setOperationAction(Op: ISD::VASTART , VT: MVT::Other, Action: Custom); |
1868 | // VAARG needs to be lowered to not do unaligned accesses for doubles. |
1869 | setOperationAction(Op: ISD::VAARG , VT: MVT::Other, Action: Custom); |
1870 | |
1871 | setOperationAction(Op: ISD::TRAP , VT: MVT::Other, Action: Legal); |
1872 | setOperationAction(Op: ISD::DEBUGTRAP , VT: MVT::Other, Action: Legal); |
1873 | |
1874 | // Use the default implementation. |
1875 | setOperationAction(Op: ISD::VACOPY , VT: MVT::Other, Action: Expand); |
1876 | setOperationAction(Op: ISD::VAEND , VT: MVT::Other, Action: Expand); |
1877 | setOperationAction(Op: ISD::STACKSAVE , VT: MVT::Other, Action: Expand); |
1878 | setOperationAction(Op: ISD::STACKRESTORE , VT: MVT::Other, Action: Expand); |
1879 | setOperationAction(Op: ISD::DYNAMIC_STACKALLOC, VT: MVT::i32 , Action: Custom); |
1880 | |
1881 | setStackPointerRegisterToSaveRestore(SP::O6); |
1882 | |
1883 | setOperationAction(Op: ISD::CTPOP, VT: MVT::i32, |
1884 | Action: Subtarget->usePopc() ? Legal : Expand); |
1885 | |
1886 | if (Subtarget->isV9() && Subtarget->hasHardQuad()) { |
1887 | setOperationAction(Op: ISD::LOAD, VT: MVT::f128, Action: Legal); |
1888 | setOperationAction(Op: ISD::STORE, VT: MVT::f128, Action: Legal); |
1889 | } else { |
1890 | setOperationAction(Op: ISD::LOAD, VT: MVT::f128, Action: Custom); |
1891 | setOperationAction(Op: ISD::STORE, VT: MVT::f128, Action: Custom); |
1892 | } |
1893 | |
1894 | if (Subtarget->hasHardQuad()) { |
1895 | setOperationAction(Op: ISD::FADD, VT: MVT::f128, Action: Legal); |
1896 | setOperationAction(Op: ISD::FSUB, VT: MVT::f128, Action: Legal); |
1897 | setOperationAction(Op: ISD::FMUL, VT: MVT::f128, Action: Legal); |
1898 | setOperationAction(Op: ISD::FDIV, VT: MVT::f128, Action: Legal); |
1899 | setOperationAction(Op: ISD::FSQRT, VT: MVT::f128, Action: Legal); |
1900 | setOperationAction(Op: ISD::FP_EXTEND, VT: MVT::f128, Action: Legal); |
1901 | setOperationAction(Op: ISD::FP_ROUND, VT: MVT::f64, Action: Legal); |
1902 | if (Subtarget->isV9()) { |
1903 | setOperationAction(Op: ISD::FNEG, VT: MVT::f128, Action: Legal); |
1904 | setOperationAction(Op: ISD::FABS, VT: MVT::f128, Action: Legal); |
1905 | } else { |
1906 | setOperationAction(Op: ISD::FNEG, VT: MVT::f128, Action: Custom); |
1907 | setOperationAction(Op: ISD::FABS, VT: MVT::f128, Action: Custom); |
1908 | } |
1909 | |
1910 | if (!Subtarget->is64Bit()) { |
1911 | setLibcallName(Call: RTLIB::FPTOSINT_F128_I64, Name: "_Q_qtoll" ); |
1912 | setLibcallName(Call: RTLIB::FPTOUINT_F128_I64, Name: "_Q_qtoull" ); |
1913 | setLibcallName(Call: RTLIB::SINTTOFP_I64_F128, Name: "_Q_lltoq" ); |
1914 | setLibcallName(Call: RTLIB::UINTTOFP_I64_F128, Name: "_Q_ulltoq" ); |
1915 | } |
1916 | |
1917 | } else { |
1918 | // Custom legalize f128 operations. |
1919 | |
1920 | setOperationAction(Op: ISD::FADD, VT: MVT::f128, Action: Custom); |
1921 | setOperationAction(Op: ISD::FSUB, VT: MVT::f128, Action: Custom); |
1922 | setOperationAction(Op: ISD::FMUL, VT: MVT::f128, Action: Custom); |
1923 | setOperationAction(Op: ISD::FDIV, VT: MVT::f128, Action: Custom); |
1924 | setOperationAction(Op: ISD::FSQRT, VT: MVT::f128, Action: Custom); |
1925 | setOperationAction(Op: ISD::FNEG, VT: MVT::f128, Action: Custom); |
1926 | setOperationAction(Op: ISD::FABS, VT: MVT::f128, Action: Custom); |
1927 | |
1928 | setOperationAction(Op: ISD::FP_EXTEND, VT: MVT::f128, Action: Custom); |
1929 | setOperationAction(Op: ISD::FP_ROUND, VT: MVT::f64, Action: Custom); |
1930 | setOperationAction(Op: ISD::FP_ROUND, VT: MVT::f32, Action: Custom); |
1931 | |
1932 | // Setup Runtime library names. |
1933 | if (Subtarget->is64Bit() && !Subtarget->useSoftFloat()) { |
1934 | setLibcallName(Call: RTLIB::ADD_F128, Name: "_Qp_add" ); |
1935 | setLibcallName(Call: RTLIB::SUB_F128, Name: "_Qp_sub" ); |
1936 | setLibcallName(Call: RTLIB::MUL_F128, Name: "_Qp_mul" ); |
1937 | setLibcallName(Call: RTLIB::DIV_F128, Name: "_Qp_div" ); |
1938 | setLibcallName(Call: RTLIB::SQRT_F128, Name: "_Qp_sqrt" ); |
1939 | setLibcallName(Call: RTLIB::FPTOSINT_F128_I32, Name: "_Qp_qtoi" ); |
1940 | setLibcallName(Call: RTLIB::FPTOUINT_F128_I32, Name: "_Qp_qtoui" ); |
1941 | setLibcallName(Call: RTLIB::SINTTOFP_I32_F128, Name: "_Qp_itoq" ); |
1942 | setLibcallName(Call: RTLIB::UINTTOFP_I32_F128, Name: "_Qp_uitoq" ); |
1943 | setLibcallName(Call: RTLIB::FPTOSINT_F128_I64, Name: "_Qp_qtox" ); |
1944 | setLibcallName(Call: RTLIB::FPTOUINT_F128_I64, Name: "_Qp_qtoux" ); |
1945 | setLibcallName(Call: RTLIB::SINTTOFP_I64_F128, Name: "_Qp_xtoq" ); |
1946 | setLibcallName(Call: RTLIB::UINTTOFP_I64_F128, Name: "_Qp_uxtoq" ); |
1947 | setLibcallName(Call: RTLIB::FPEXT_F32_F128, Name: "_Qp_stoq" ); |
1948 | setLibcallName(Call: RTLIB::FPEXT_F64_F128, Name: "_Qp_dtoq" ); |
1949 | setLibcallName(Call: RTLIB::FPROUND_F128_F32, Name: "_Qp_qtos" ); |
1950 | setLibcallName(Call: RTLIB::FPROUND_F128_F64, Name: "_Qp_qtod" ); |
1951 | } else if (!Subtarget->useSoftFloat()) { |
1952 | setLibcallName(Call: RTLIB::ADD_F128, Name: "_Q_add" ); |
1953 | setLibcallName(Call: RTLIB::SUB_F128, Name: "_Q_sub" ); |
1954 | setLibcallName(Call: RTLIB::MUL_F128, Name: "_Q_mul" ); |
1955 | setLibcallName(Call: RTLIB::DIV_F128, Name: "_Q_div" ); |
1956 | setLibcallName(Call: RTLIB::SQRT_F128, Name: "_Q_sqrt" ); |
1957 | setLibcallName(Call: RTLIB::FPTOSINT_F128_I32, Name: "_Q_qtoi" ); |
1958 | setLibcallName(Call: RTLIB::FPTOUINT_F128_I32, Name: "_Q_qtou" ); |
1959 | setLibcallName(Call: RTLIB::SINTTOFP_I32_F128, Name: "_Q_itoq" ); |
1960 | setLibcallName(Call: RTLIB::UINTTOFP_I32_F128, Name: "_Q_utoq" ); |
1961 | setLibcallName(Call: RTLIB::FPTOSINT_F128_I64, Name: "_Q_qtoll" ); |
1962 | setLibcallName(Call: RTLIB::FPTOUINT_F128_I64, Name: "_Q_qtoull" ); |
1963 | setLibcallName(Call: RTLIB::SINTTOFP_I64_F128, Name: "_Q_lltoq" ); |
1964 | setLibcallName(Call: RTLIB::UINTTOFP_I64_F128, Name: "_Q_ulltoq" ); |
1965 | setLibcallName(Call: RTLIB::FPEXT_F32_F128, Name: "_Q_stoq" ); |
1966 | setLibcallName(Call: RTLIB::FPEXT_F64_F128, Name: "_Q_dtoq" ); |
1967 | setLibcallName(Call: RTLIB::FPROUND_F128_F32, Name: "_Q_qtos" ); |
1968 | setLibcallName(Call: RTLIB::FPROUND_F128_F64, Name: "_Q_qtod" ); |
1969 | } |
1970 | } |
1971 | |
1972 | if (Subtarget->fixAllFDIVSQRT()) { |
1973 | // Promote FDIVS and FSQRTS to FDIVD and FSQRTD instructions instead as |
1974 | // the former instructions generate errata on LEON processors. |
1975 | setOperationAction(Op: ISD::FDIV, VT: MVT::f32, Action: Promote); |
1976 | setOperationAction(Op: ISD::FSQRT, VT: MVT::f32, Action: Promote); |
1977 | } |
1978 | |
1979 | if (Subtarget->hasNoFMULS()) { |
1980 | setOperationAction(Op: ISD::FMUL, VT: MVT::f32, Action: Promote); |
1981 | } |
1982 | |
1983 | // Custom combine bitcast between f64 and v2i32 |
1984 | if (!Subtarget->is64Bit()) |
1985 | setTargetDAGCombine(ISD::BITCAST); |
1986 | |
1987 | if (Subtarget->hasLeonCycleCounter()) |
1988 | setOperationAction(Op: ISD::READCYCLECOUNTER, VT: MVT::i64, Action: Custom); |
1989 | |
1990 | setOperationAction(Op: ISD::INTRINSIC_WO_CHAIN, VT: MVT::Other, Action: Custom); |
1991 | |
1992 | setMinFunctionAlignment(Align(4)); |
1993 | |
1994 | computeRegisterProperties(TRI: Subtarget->getRegisterInfo()); |
1995 | } |
1996 | |
1997 | bool SparcTargetLowering::useSoftFloat() const { |
1998 | return Subtarget->useSoftFloat(); |
1999 | } |
2000 | |
2001 | const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { |
2002 | switch ((SPISD::NodeType)Opcode) { |
2003 | case SPISD::FIRST_NUMBER: break; |
2004 | case SPISD::CMPICC: return "SPISD::CMPICC" ; |
2005 | case SPISD::CMPFCC: return "SPISD::CMPFCC" ; |
2006 | case SPISD::CMPFCC_V9: |
2007 | return "SPISD::CMPFCC_V9" ; |
2008 | case SPISD::BRICC: return "SPISD::BRICC" ; |
2009 | case SPISD::BPICC: |
2010 | return "SPISD::BPICC" ; |
2011 | case SPISD::BPXCC: |
2012 | return "SPISD::BPXCC" ; |
2013 | case SPISD::BRFCC: return "SPISD::BRFCC" ; |
2014 | case SPISD::BRFCC_V9: |
2015 | return "SPISD::BRFCC_V9" ; |
2016 | case SPISD::BR_REG: |
2017 | return "SPISD::BR_REG" ; |
2018 | case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC" ; |
2019 | case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC" ; |
2020 | case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC" ; |
2021 | case SPISD::SELECT_REG: |
2022 | return "SPISD::SELECT_REG" ; |
2023 | case SPISD::Hi: return "SPISD::Hi" ; |
2024 | case SPISD::Lo: return "SPISD::Lo" ; |
2025 | case SPISD::FTOI: return "SPISD::FTOI" ; |
2026 | case SPISD::ITOF: return "SPISD::ITOF" ; |
2027 | case SPISD::FTOX: return "SPISD::FTOX" ; |
2028 | case SPISD::XTOF: return "SPISD::XTOF" ; |
2029 | case SPISD::CALL: return "SPISD::CALL" ; |
2030 | case SPISD::RET_GLUE: return "SPISD::RET_GLUE" ; |
2031 | case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG" ; |
2032 | case SPISD::FLUSHW: return "SPISD::FLUSHW" ; |
2033 | case SPISD::TLS_ADD: return "SPISD::TLS_ADD" ; |
2034 | case SPISD::TLS_LD: return "SPISD::TLS_LD" ; |
2035 | case SPISD::TLS_CALL: return "SPISD::TLS_CALL" ; |
2036 | case SPISD::TAIL_CALL: return "SPISD::TAIL_CALL" ; |
2037 | case SPISD::LOAD_GDOP: return "SPISD::LOAD_GDOP" ; |
2038 | } |
2039 | return nullptr; |
2040 | } |
2041 | |
2042 | EVT SparcTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, |
2043 | EVT VT) const { |
2044 | if (!VT.isVector()) |
2045 | return MVT::i32; |
2046 | return VT.changeVectorElementTypeToInteger(); |
2047 | } |
2048 | |
2049 | /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to |
2050 | /// be zero. Op is expected to be a target specific node. Used by DAG |
2051 | /// combiner. |
2052 | void SparcTargetLowering::computeKnownBitsForTargetNode |
2053 | (const SDValue Op, |
2054 | KnownBits &Known, |
2055 | const APInt &DemandedElts, |
2056 | const SelectionDAG &DAG, |
2057 | unsigned Depth) const { |
2058 | KnownBits Known2; |
2059 | Known.resetAll(); |
2060 | |
2061 | switch (Op.getOpcode()) { |
2062 | default: break; |
2063 | case SPISD::SELECT_ICC: |
2064 | case SPISD::SELECT_XCC: |
2065 | case SPISD::SELECT_FCC: |
2066 | Known = DAG.computeKnownBits(Op: Op.getOperand(i: 1), Depth: Depth + 1); |
2067 | Known2 = DAG.computeKnownBits(Op: Op.getOperand(i: 0), Depth: Depth + 1); |
2068 | |
2069 | // Only known if known in both the LHS and RHS. |
2070 | Known = Known.intersectWith(RHS: Known2); |
2071 | break; |
2072 | } |
2073 | } |
2074 | |
2075 | // Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so |
2076 | // set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition. |
2077 | static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, |
2078 | ISD::CondCode CC, unsigned &SPCC) { |
2079 | if (isNullConstant(V: RHS) && CC == ISD::SETNE && |
2080 | (((LHS.getOpcode() == SPISD::SELECT_ICC || |
2081 | LHS.getOpcode() == SPISD::SELECT_XCC) && |
2082 | LHS.getOperand(i: 3).getOpcode() == SPISD::CMPICC) || |
2083 | (LHS.getOpcode() == SPISD::SELECT_FCC && |
2084 | (LHS.getOperand(i: 3).getOpcode() == SPISD::CMPFCC || |
2085 | LHS.getOperand(i: 3).getOpcode() == SPISD::CMPFCC_V9))) && |
2086 | isOneConstant(V: LHS.getOperand(i: 0)) && isNullConstant(V: LHS.getOperand(i: 1))) { |
2087 | SDValue CMPCC = LHS.getOperand(i: 3); |
2088 | SPCC = LHS.getConstantOperandVal(i: 2); |
2089 | LHS = CMPCC.getOperand(i: 0); |
2090 | RHS = CMPCC.getOperand(i: 1); |
2091 | } |
2092 | } |
2093 | |
2094 | // Convert to a target node and set target flags. |
2095 | SDValue SparcTargetLowering::withTargetFlags(SDValue Op, unsigned TF, |
2096 | SelectionDAG &DAG) const { |
2097 | if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Val&: Op)) |
2098 | return DAG.getTargetGlobalAddress(GV: GA->getGlobal(), |
2099 | DL: SDLoc(GA), |
2100 | VT: GA->getValueType(ResNo: 0), |
2101 | offset: GA->getOffset(), TargetFlags: TF); |
2102 | |
2103 | if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Val&: Op)) |
2104 | return DAG.getTargetConstantPool(C: CP->getConstVal(), VT: CP->getValueType(ResNo: 0), |
2105 | Align: CP->getAlign(), Offset: CP->getOffset(), TargetFlags: TF); |
2106 | |
2107 | if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Val&: Op)) |
2108 | return DAG.getTargetBlockAddress(BA: BA->getBlockAddress(), |
2109 | VT: Op.getValueType(), |
2110 | Offset: 0, |
2111 | TargetFlags: TF); |
2112 | |
2113 | if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Val&: Op)) |
2114 | return DAG.getTargetExternalSymbol(Sym: ES->getSymbol(), |
2115 | VT: ES->getValueType(ResNo: 0), TargetFlags: TF); |
2116 | |
2117 | llvm_unreachable("Unhandled address SDNode" ); |
2118 | } |
2119 | |
2120 | // Split Op into high and low parts according to HiTF and LoTF. |
2121 | // Return an ADD node combining the parts. |
2122 | SDValue SparcTargetLowering::makeHiLoPair(SDValue Op, |
2123 | unsigned HiTF, unsigned LoTF, |
2124 | SelectionDAG &DAG) const { |
2125 | SDLoc DL(Op); |
2126 | EVT VT = Op.getValueType(); |
2127 | SDValue Hi = DAG.getNode(Opcode: SPISD::Hi, DL, VT, Operand: withTargetFlags(Op, TF: HiTF, DAG)); |
2128 | SDValue Lo = DAG.getNode(Opcode: SPISD::Lo, DL, VT, Operand: withTargetFlags(Op, TF: LoTF, DAG)); |
2129 | return DAG.getNode(Opcode: ISD::ADD, DL, VT, N1: Hi, N2: Lo); |
2130 | } |
2131 | |
2132 | // Build SDNodes for producing an address from a GlobalAddress, ConstantPool, |
2133 | // or ExternalSymbol SDNode. |
2134 | SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const { |
2135 | SDLoc DL(Op); |
2136 | EVT VT = getPointerTy(DL: DAG.getDataLayout()); |
2137 | |
2138 | // Handle PIC mode first. SPARC needs a got load for every variable! |
2139 | if (isPositionIndependent()) { |
2140 | const Module *M = DAG.getMachineFunction().getFunction().getParent(); |
2141 | PICLevel::Level picLevel = M->getPICLevel(); |
2142 | SDValue Idx; |
2143 | |
2144 | if (picLevel == PICLevel::SmallPIC) { |
2145 | // This is the pic13 code model, the GOT is known to be smaller than 8KiB. |
2146 | Idx = DAG.getNode(Opcode: SPISD::Lo, DL, VT: Op.getValueType(), |
2147 | Operand: withTargetFlags(Op, TF: SparcMCExpr::VK_Sparc_GOT13, DAG)); |
2148 | } else { |
2149 | // This is the pic32 code model, the GOT is known to be smaller than 4GB. |
2150 | Idx = makeHiLoPair(Op, HiTF: SparcMCExpr::VK_Sparc_GOT22, |
2151 | LoTF: SparcMCExpr::VK_Sparc_GOT10, DAG); |
2152 | } |
2153 | |
2154 | SDValue GlobalBase = DAG.getNode(Opcode: SPISD::GLOBAL_BASE_REG, DL, VT); |
2155 | SDValue AbsAddr = DAG.getNode(Opcode: ISD::ADD, DL, VT, N1: GlobalBase, N2: Idx); |
2156 | // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this |
2157 | // function has calls. |
2158 | MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); |
2159 | MFI.setHasCalls(true); |
2160 | return DAG.getLoad(VT, dl: DL, Chain: DAG.getEntryNode(), Ptr: AbsAddr, |
2161 | PtrInfo: MachinePointerInfo::getGOT(MF&: DAG.getMachineFunction())); |
2162 | } |
2163 | |
2164 | // This is one of the absolute code models. |
2165 | switch(getTargetMachine().getCodeModel()) { |
2166 | default: |
2167 | llvm_unreachable("Unsupported absolute code model" ); |
2168 | case CodeModel::Small: |
2169 | // abs32. |
2170 | return makeHiLoPair(Op, HiTF: SparcMCExpr::VK_Sparc_HI, |
2171 | LoTF: SparcMCExpr::VK_Sparc_LO, DAG); |
2172 | case CodeModel::Medium: { |
2173 | // abs44. |
2174 | SDValue H44 = makeHiLoPair(Op, HiTF: SparcMCExpr::VK_Sparc_H44, |
2175 | LoTF: SparcMCExpr::VK_Sparc_M44, DAG); |
2176 | H44 = DAG.getNode(Opcode: ISD::SHL, DL, VT, N1: H44, N2: DAG.getConstant(Val: 12, DL, VT: MVT::i32)); |
2177 | SDValue L44 = withTargetFlags(Op, TF: SparcMCExpr::VK_Sparc_L44, DAG); |
2178 | L44 = DAG.getNode(Opcode: SPISD::Lo, DL, VT, Operand: L44); |
2179 | return DAG.getNode(Opcode: ISD::ADD, DL, VT, N1: H44, N2: L44); |
2180 | } |
2181 | case CodeModel::Large: { |
2182 | // abs64. |
2183 | SDValue Hi = makeHiLoPair(Op, HiTF: SparcMCExpr::VK_Sparc_HH, |
2184 | LoTF: SparcMCExpr::VK_Sparc_HM, DAG); |
2185 | Hi = DAG.getNode(Opcode: ISD::SHL, DL, VT, N1: Hi, N2: DAG.getConstant(Val: 32, DL, VT: MVT::i32)); |
2186 | SDValue Lo = makeHiLoPair(Op, HiTF: SparcMCExpr::VK_Sparc_HI, |
2187 | LoTF: SparcMCExpr::VK_Sparc_LO, DAG); |
2188 | return DAG.getNode(Opcode: ISD::ADD, DL, VT, N1: Hi, N2: Lo); |
2189 | } |
2190 | } |
2191 | } |
2192 | |
2193 | SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op, |
2194 | SelectionDAG &DAG) const { |
2195 | return makeAddress(Op, DAG); |
2196 | } |
2197 | |
2198 | SDValue SparcTargetLowering::LowerConstantPool(SDValue Op, |
2199 | SelectionDAG &DAG) const { |
2200 | return makeAddress(Op, DAG); |
2201 | } |
2202 | |
2203 | SDValue SparcTargetLowering::LowerBlockAddress(SDValue Op, |
2204 | SelectionDAG &DAG) const { |
2205 | return makeAddress(Op, DAG); |
2206 | } |
2207 | |
2208 | SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op, |
2209 | SelectionDAG &DAG) const { |
2210 | |
2211 | GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Val&: Op); |
2212 | if (DAG.getTarget().useEmulatedTLS()) |
2213 | return LowerToTLSEmulatedModel(GA, DAG); |
2214 | |
2215 | SDLoc DL(GA); |
2216 | const GlobalValue *GV = GA->getGlobal(); |
2217 | EVT PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
2218 | |
2219 | TLSModel::Model model = getTargetMachine().getTLSModel(GV); |
2220 | |
2221 | if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { |
2222 | unsigned HiTF = ((model == TLSModel::GeneralDynamic) |
2223 | ? SparcMCExpr::VK_Sparc_TLS_GD_HI22 |
2224 | : SparcMCExpr::VK_Sparc_TLS_LDM_HI22); |
2225 | unsigned LoTF = ((model == TLSModel::GeneralDynamic) |
2226 | ? SparcMCExpr::VK_Sparc_TLS_GD_LO10 |
2227 | : SparcMCExpr::VK_Sparc_TLS_LDM_LO10); |
2228 | unsigned addTF = ((model == TLSModel::GeneralDynamic) |
2229 | ? SparcMCExpr::VK_Sparc_TLS_GD_ADD |
2230 | : SparcMCExpr::VK_Sparc_TLS_LDM_ADD); |
2231 | unsigned callTF = ((model == TLSModel::GeneralDynamic) |
2232 | ? SparcMCExpr::VK_Sparc_TLS_GD_CALL |
2233 | : SparcMCExpr::VK_Sparc_TLS_LDM_CALL); |
2234 | |
2235 | SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG); |
2236 | SDValue Base = DAG.getNode(Opcode: SPISD::GLOBAL_BASE_REG, DL, VT: PtrVT); |
2237 | SDValue Argument = DAG.getNode(Opcode: SPISD::TLS_ADD, DL, VT: PtrVT, N1: Base, N2: HiLo, |
2238 | N3: withTargetFlags(Op, TF: addTF, DAG)); |
2239 | |
2240 | SDValue Chain = DAG.getEntryNode(); |
2241 | SDValue InGlue; |
2242 | |
2243 | Chain = DAG.getCALLSEQ_START(Chain, InSize: 1, OutSize: 0, DL); |
2244 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: SP::O0, N: Argument, Glue: InGlue); |
2245 | InGlue = Chain.getValue(R: 1); |
2246 | SDValue Callee = DAG.getTargetExternalSymbol(Sym: "__tls_get_addr" , VT: PtrVT); |
2247 | SDValue Symbol = withTargetFlags(Op, TF: callTF, DAG); |
2248 | |
2249 | SDVTList NodeTys = DAG.getVTList(VT1: MVT::Other, VT2: MVT::Glue); |
2250 | const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask( |
2251 | MF: DAG.getMachineFunction(), CC: CallingConv::C); |
2252 | assert(Mask && "Missing call preserved mask for calling convention" ); |
2253 | SDValue Ops[] = {Chain, |
2254 | Callee, |
2255 | Symbol, |
2256 | DAG.getRegister(Reg: SP::O0, VT: PtrVT), |
2257 | DAG.getRegisterMask(RegMask: Mask), |
2258 | InGlue}; |
2259 | Chain = DAG.getNode(Opcode: SPISD::TLS_CALL, DL, VTList: NodeTys, Ops); |
2260 | InGlue = Chain.getValue(R: 1); |
2261 | Chain = DAG.getCALLSEQ_END(Chain, Size1: 1, Size2: 0, Glue: InGlue, DL); |
2262 | InGlue = Chain.getValue(R: 1); |
2263 | SDValue Ret = DAG.getCopyFromReg(Chain, dl: DL, Reg: SP::O0, VT: PtrVT, Glue: InGlue); |
2264 | |
2265 | if (model != TLSModel::LocalDynamic) |
2266 | return Ret; |
2267 | |
2268 | SDValue Hi = DAG.getNode(Opcode: SPISD::Hi, DL, VT: PtrVT, |
2269 | Operand: withTargetFlags(Op, TF: SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG)); |
2270 | SDValue Lo = DAG.getNode(Opcode: SPISD::Lo, DL, VT: PtrVT, |
2271 | Operand: withTargetFlags(Op, TF: SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG)); |
2272 | HiLo = DAG.getNode(Opcode: ISD::XOR, DL, VT: PtrVT, N1: Hi, N2: Lo); |
2273 | return DAG.getNode(Opcode: SPISD::TLS_ADD, DL, VT: PtrVT, N1: Ret, N2: HiLo, |
2274 | N3: withTargetFlags(Op, TF: SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG)); |
2275 | } |
2276 | |
2277 | if (model == TLSModel::InitialExec) { |
2278 | unsigned ldTF = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX |
2279 | : SparcMCExpr::VK_Sparc_TLS_IE_LD); |
2280 | |
2281 | SDValue Base = DAG.getNode(Opcode: SPISD::GLOBAL_BASE_REG, DL, VT: PtrVT); |
2282 | |
2283 | // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this |
2284 | // function has calls. |
2285 | MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); |
2286 | MFI.setHasCalls(true); |
2287 | |
2288 | SDValue TGA = makeHiLoPair(Op, |
2289 | HiTF: SparcMCExpr::VK_Sparc_TLS_IE_HI22, |
2290 | LoTF: SparcMCExpr::VK_Sparc_TLS_IE_LO10, DAG); |
2291 | SDValue Ptr = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, N1: Base, N2: TGA); |
2292 | SDValue Offset = DAG.getNode(Opcode: SPISD::TLS_LD, |
2293 | DL, VT: PtrVT, N1: Ptr, |
2294 | N2: withTargetFlags(Op, TF: ldTF, DAG)); |
2295 | return DAG.getNode(Opcode: SPISD::TLS_ADD, DL, VT: PtrVT, |
2296 | N1: DAG.getRegister(Reg: SP::G7, VT: PtrVT), N2: Offset, |
2297 | N3: withTargetFlags(Op, |
2298 | TF: SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG)); |
2299 | } |
2300 | |
2301 | assert(model == TLSModel::LocalExec); |
2302 | SDValue Hi = DAG.getNode(Opcode: SPISD::Hi, DL, VT: PtrVT, |
2303 | Operand: withTargetFlags(Op, TF: SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG)); |
2304 | SDValue Lo = DAG.getNode(Opcode: SPISD::Lo, DL, VT: PtrVT, |
2305 | Operand: withTargetFlags(Op, TF: SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG)); |
2306 | SDValue Offset = DAG.getNode(Opcode: ISD::XOR, DL, VT: PtrVT, N1: Hi, N2: Lo); |
2307 | |
2308 | return DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, |
2309 | N1: DAG.getRegister(Reg: SP::G7, VT: PtrVT), N2: Offset); |
2310 | } |
2311 | |
2312 | SDValue SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain, |
2313 | ArgListTy &Args, SDValue Arg, |
2314 | const SDLoc &DL, |
2315 | SelectionDAG &DAG) const { |
2316 | MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); |
2317 | EVT ArgVT = Arg.getValueType(); |
2318 | Type *ArgTy = ArgVT.getTypeForEVT(Context&: *DAG.getContext()); |
2319 | |
2320 | ArgListEntry Entry; |
2321 | Entry.Node = Arg; |
2322 | Entry.Ty = ArgTy; |
2323 | |
2324 | if (ArgTy->isFP128Ty()) { |
2325 | // Create a stack object and pass the pointer to the library function. |
2326 | int FI = MFI.CreateStackObject(Size: 16, Alignment: Align(8), isSpillSlot: false); |
2327 | SDValue FIPtr = DAG.getFrameIndex(FI, VT: getPointerTy(DL: DAG.getDataLayout())); |
2328 | Chain = DAG.getStore(Chain, dl: DL, Val: Entry.Node, Ptr: FIPtr, PtrInfo: MachinePointerInfo(), |
2329 | Alignment: Align(8)); |
2330 | |
2331 | Entry.Node = FIPtr; |
2332 | Entry.Ty = PointerType::getUnqual(ElementType: ArgTy); |
2333 | } |
2334 | Args.push_back(x: Entry); |
2335 | return Chain; |
2336 | } |
2337 | |
2338 | SDValue |
2339 | SparcTargetLowering::LowerF128Op(SDValue Op, SelectionDAG &DAG, |
2340 | const char *LibFuncName, |
2341 | unsigned numArgs) const { |
2342 | |
2343 | ArgListTy Args; |
2344 | |
2345 | MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); |
2346 | auto PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
2347 | |
2348 | SDValue Callee = DAG.getExternalSymbol(Sym: LibFuncName, VT: PtrVT); |
2349 | Type *RetTy = Op.getValueType().getTypeForEVT(Context&: *DAG.getContext()); |
2350 | Type *RetTyABI = RetTy; |
2351 | SDValue Chain = DAG.getEntryNode(); |
2352 | SDValue RetPtr; |
2353 | |
2354 | if (RetTy->isFP128Ty()) { |
2355 | // Create a Stack Object to receive the return value of type f128. |
2356 | ArgListEntry Entry; |
2357 | int RetFI = MFI.CreateStackObject(Size: 16, Alignment: Align(8), isSpillSlot: false); |
2358 | RetPtr = DAG.getFrameIndex(FI: RetFI, VT: PtrVT); |
2359 | Entry.Node = RetPtr; |
2360 | Entry.Ty = PointerType::getUnqual(ElementType: RetTy); |
2361 | if (!Subtarget->is64Bit()) { |
2362 | Entry.IsSRet = true; |
2363 | Entry.IndirectType = RetTy; |
2364 | } |
2365 | Entry.IsReturned = false; |
2366 | Args.push_back(x: Entry); |
2367 | RetTyABI = Type::getVoidTy(C&: *DAG.getContext()); |
2368 | } |
2369 | |
2370 | assert(Op->getNumOperands() >= numArgs && "Not enough operands!" ); |
2371 | for (unsigned i = 0, e = numArgs; i != e; ++i) { |
2372 | Chain = LowerF128_LibCallArg(Chain, Args, Arg: Op.getOperand(i), DL: SDLoc(Op), DAG); |
2373 | } |
2374 | TargetLowering::CallLoweringInfo CLI(DAG); |
2375 | CLI.setDebugLoc(SDLoc(Op)).setChain(Chain) |
2376 | .setCallee(CC: CallingConv::C, ResultType: RetTyABI, Target: Callee, ArgsList: std::move(Args)); |
2377 | |
2378 | std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI); |
2379 | |
2380 | // chain is in second result. |
2381 | if (RetTyABI == RetTy) |
2382 | return CallInfo.first; |
2383 | |
2384 | assert (RetTy->isFP128Ty() && "Unexpected return type!" ); |
2385 | |
2386 | Chain = CallInfo.second; |
2387 | |
2388 | // Load RetPtr to get the return value. |
2389 | return DAG.getLoad(VT: Op.getValueType(), dl: SDLoc(Op), Chain, Ptr: RetPtr, |
2390 | PtrInfo: MachinePointerInfo(), Alignment: Align(8)); |
2391 | } |
2392 | |
2393 | SDValue SparcTargetLowering::LowerF128Compare(SDValue LHS, SDValue RHS, |
2394 | unsigned &SPCC, const SDLoc &DL, |
2395 | SelectionDAG &DAG) const { |
2396 | |
2397 | const char *LibCall = nullptr; |
2398 | bool is64Bit = Subtarget->is64Bit(); |
2399 | switch(SPCC) { |
2400 | default: llvm_unreachable("Unhandled conditional code!" ); |
2401 | case SPCC::FCC_E : LibCall = is64Bit? "_Qp_feq" : "_Q_feq" ; break; |
2402 | case SPCC::FCC_NE : LibCall = is64Bit? "_Qp_fne" : "_Q_fne" ; break; |
2403 | case SPCC::FCC_L : LibCall = is64Bit? "_Qp_flt" : "_Q_flt" ; break; |
2404 | case SPCC::FCC_G : LibCall = is64Bit? "_Qp_fgt" : "_Q_fgt" ; break; |
2405 | case SPCC::FCC_LE : LibCall = is64Bit? "_Qp_fle" : "_Q_fle" ; break; |
2406 | case SPCC::FCC_GE : LibCall = is64Bit? "_Qp_fge" : "_Q_fge" ; break; |
2407 | case SPCC::FCC_UL : |
2408 | case SPCC::FCC_ULE: |
2409 | case SPCC::FCC_UG : |
2410 | case SPCC::FCC_UGE: |
2411 | case SPCC::FCC_U : |
2412 | case SPCC::FCC_O : |
2413 | case SPCC::FCC_LG : |
2414 | case SPCC::FCC_UE : LibCall = is64Bit? "_Qp_cmp" : "_Q_cmp" ; break; |
2415 | } |
2416 | |
2417 | auto PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
2418 | SDValue Callee = DAG.getExternalSymbol(Sym: LibCall, VT: PtrVT); |
2419 | Type *RetTy = Type::getInt32Ty(C&: *DAG.getContext()); |
2420 | ArgListTy Args; |
2421 | SDValue Chain = DAG.getEntryNode(); |
2422 | Chain = LowerF128_LibCallArg(Chain, Args, Arg: LHS, DL, DAG); |
2423 | Chain = LowerF128_LibCallArg(Chain, Args, Arg: RHS, DL, DAG); |
2424 | |
2425 | TargetLowering::CallLoweringInfo CLI(DAG); |
2426 | CLI.setDebugLoc(DL).setChain(Chain) |
2427 | .setCallee(CC: CallingConv::C, ResultType: RetTy, Target: Callee, ArgsList: std::move(Args)); |
2428 | |
2429 | std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI); |
2430 | |
2431 | // result is in first, and chain is in second result. |
2432 | SDValue Result = CallInfo.first; |
2433 | |
2434 | switch(SPCC) { |
2435 | default: { |
2436 | SDValue RHS = DAG.getConstant(Val: 0, DL, VT: Result.getValueType()); |
2437 | SPCC = SPCC::ICC_NE; |
2438 | return DAG.getNode(Opcode: SPISD::CMPICC, DL, VT: MVT::Glue, N1: Result, N2: RHS); |
2439 | } |
2440 | case SPCC::FCC_UL : { |
2441 | SDValue Mask = DAG.getConstant(Val: 1, DL, VT: Result.getValueType()); |
2442 | Result = DAG.getNode(Opcode: ISD::AND, DL, VT: Result.getValueType(), N1: Result, N2: Mask); |
2443 | SDValue RHS = DAG.getConstant(Val: 0, DL, VT: Result.getValueType()); |
2444 | SPCC = SPCC::ICC_NE; |
2445 | return DAG.getNode(Opcode: SPISD::CMPICC, DL, VT: MVT::Glue, N1: Result, N2: RHS); |
2446 | } |
2447 | case SPCC::FCC_ULE: { |
2448 | SDValue RHS = DAG.getConstant(Val: 2, DL, VT: Result.getValueType()); |
2449 | SPCC = SPCC::ICC_NE; |
2450 | return DAG.getNode(Opcode: SPISD::CMPICC, DL, VT: MVT::Glue, N1: Result, N2: RHS); |
2451 | } |
2452 | case SPCC::FCC_UG : { |
2453 | SDValue RHS = DAG.getConstant(Val: 1, DL, VT: Result.getValueType()); |
2454 | SPCC = SPCC::ICC_G; |
2455 | return DAG.getNode(Opcode: SPISD::CMPICC, DL, VT: MVT::Glue, N1: Result, N2: RHS); |
2456 | } |
2457 | case SPCC::FCC_UGE: { |
2458 | SDValue RHS = DAG.getConstant(Val: 1, DL, VT: Result.getValueType()); |
2459 | SPCC = SPCC::ICC_NE; |
2460 | return DAG.getNode(Opcode: SPISD::CMPICC, DL, VT: MVT::Glue, N1: Result, N2: RHS); |
2461 | } |
2462 | |
2463 | case SPCC::FCC_U : { |
2464 | SDValue RHS = DAG.getConstant(Val: 3, DL, VT: Result.getValueType()); |
2465 | SPCC = SPCC::ICC_E; |
2466 | return DAG.getNode(Opcode: SPISD::CMPICC, DL, VT: MVT::Glue, N1: Result, N2: RHS); |
2467 | } |
2468 | case SPCC::FCC_O : { |
2469 | SDValue RHS = DAG.getConstant(Val: 3, DL, VT: Result.getValueType()); |
2470 | SPCC = SPCC::ICC_NE; |
2471 | return DAG.getNode(Opcode: SPISD::CMPICC, DL, VT: MVT::Glue, N1: Result, N2: RHS); |
2472 | } |
2473 | case SPCC::FCC_LG : { |
2474 | SDValue Mask = DAG.getConstant(Val: 3, DL, VT: Result.getValueType()); |
2475 | Result = DAG.getNode(Opcode: ISD::AND, DL, VT: Result.getValueType(), N1: Result, N2: Mask); |
2476 | SDValue RHS = DAG.getConstant(Val: 0, DL, VT: Result.getValueType()); |
2477 | SPCC = SPCC::ICC_NE; |
2478 | return DAG.getNode(Opcode: SPISD::CMPICC, DL, VT: MVT::Glue, N1: Result, N2: RHS); |
2479 | } |
2480 | case SPCC::FCC_UE : { |
2481 | SDValue Mask = DAG.getConstant(Val: 3, DL, VT: Result.getValueType()); |
2482 | Result = DAG.getNode(Opcode: ISD::AND, DL, VT: Result.getValueType(), N1: Result, N2: Mask); |
2483 | SDValue RHS = DAG.getConstant(Val: 0, DL, VT: Result.getValueType()); |
2484 | SPCC = SPCC::ICC_E; |
2485 | return DAG.getNode(Opcode: SPISD::CMPICC, DL, VT: MVT::Glue, N1: Result, N2: RHS); |
2486 | } |
2487 | } |
2488 | } |
2489 | |
2490 | static SDValue |
2491 | LowerF128_FPEXTEND(SDValue Op, SelectionDAG &DAG, |
2492 | const SparcTargetLowering &TLI) { |
2493 | |
2494 | if (Op.getOperand(i: 0).getValueType() == MVT::f64) |
2495 | return TLI.LowerF128Op(Op, DAG, |
2496 | LibFuncName: TLI.getLibcallName(Call: RTLIB::FPEXT_F64_F128), numArgs: 1); |
2497 | |
2498 | if (Op.getOperand(i: 0).getValueType() == MVT::f32) |
2499 | return TLI.LowerF128Op(Op, DAG, |
2500 | LibFuncName: TLI.getLibcallName(Call: RTLIB::FPEXT_F32_F128), numArgs: 1); |
2501 | |
2502 | llvm_unreachable("fpextend with non-float operand!" ); |
2503 | return SDValue(); |
2504 | } |
2505 | |
2506 | static SDValue |
2507 | LowerF128_FPROUND(SDValue Op, SelectionDAG &DAG, |
2508 | const SparcTargetLowering &TLI) { |
2509 | // FP_ROUND on f64 and f32 are legal. |
2510 | if (Op.getOperand(i: 0).getValueType() != MVT::f128) |
2511 | return Op; |
2512 | |
2513 | if (Op.getValueType() == MVT::f64) |
2514 | return TLI.LowerF128Op(Op, DAG, |
2515 | LibFuncName: TLI.getLibcallName(Call: RTLIB::FPROUND_F128_F64), numArgs: 1); |
2516 | if (Op.getValueType() == MVT::f32) |
2517 | return TLI.LowerF128Op(Op, DAG, |
2518 | LibFuncName: TLI.getLibcallName(Call: RTLIB::FPROUND_F128_F32), numArgs: 1); |
2519 | |
2520 | llvm_unreachable("fpround to non-float!" ); |
2521 | return SDValue(); |
2522 | } |
2523 | |
2524 | static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG, |
2525 | const SparcTargetLowering &TLI, |
2526 | bool hasHardQuad) { |
2527 | SDLoc dl(Op); |
2528 | EVT VT = Op.getValueType(); |
2529 | assert(VT == MVT::i32 || VT == MVT::i64); |
2530 | |
2531 | // Expand f128 operations to fp128 abi calls. |
2532 | if (Op.getOperand(i: 0).getValueType() == MVT::f128 |
2533 | && (!hasHardQuad || !TLI.isTypeLegal(VT))) { |
2534 | const char *libName = TLI.getLibcallName(Call: VT == MVT::i32 |
2535 | ? RTLIB::FPTOSINT_F128_I32 |
2536 | : RTLIB::FPTOSINT_F128_I64); |
2537 | return TLI.LowerF128Op(Op, DAG, LibFuncName: libName, numArgs: 1); |
2538 | } |
2539 | |
2540 | // Expand if the resulting type is illegal. |
2541 | if (!TLI.isTypeLegal(VT)) |
2542 | return SDValue(); |
2543 | |
2544 | // Otherwise, Convert the fp value to integer in an FP register. |
2545 | if (VT == MVT::i32) |
2546 | Op = DAG.getNode(Opcode: SPISD::FTOI, DL: dl, VT: MVT::f32, Operand: Op.getOperand(i: 0)); |
2547 | else |
2548 | Op = DAG.getNode(Opcode: SPISD::FTOX, DL: dl, VT: MVT::f64, Operand: Op.getOperand(i: 0)); |
2549 | |
2550 | return DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT, Operand: Op); |
2551 | } |
2552 | |
2553 | static SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG, |
2554 | const SparcTargetLowering &TLI, |
2555 | bool hasHardQuad) { |
2556 | SDLoc dl(Op); |
2557 | EVT OpVT = Op.getOperand(i: 0).getValueType(); |
2558 | assert(OpVT == MVT::i32 || (OpVT == MVT::i64)); |
2559 | |
2560 | EVT floatVT = (OpVT == MVT::i32) ? MVT::f32 : MVT::f64; |
2561 | |
2562 | // Expand f128 operations to fp128 ABI calls. |
2563 | if (Op.getValueType() == MVT::f128 |
2564 | && (!hasHardQuad || !TLI.isTypeLegal(VT: OpVT))) { |
2565 | const char *libName = TLI.getLibcallName(Call: OpVT == MVT::i32 |
2566 | ? RTLIB::SINTTOFP_I32_F128 |
2567 | : RTLIB::SINTTOFP_I64_F128); |
2568 | return TLI.LowerF128Op(Op, DAG, LibFuncName: libName, numArgs: 1); |
2569 | } |
2570 | |
2571 | // Expand if the operand type is illegal. |
2572 | if (!TLI.isTypeLegal(VT: OpVT)) |
2573 | return SDValue(); |
2574 | |
2575 | // Otherwise, Convert the int value to FP in an FP register. |
2576 | SDValue Tmp = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: floatVT, Operand: Op.getOperand(i: 0)); |
2577 | unsigned opcode = (OpVT == MVT::i32)? SPISD::ITOF : SPISD::XTOF; |
2578 | return DAG.getNode(Opcode: opcode, DL: dl, VT: Op.getValueType(), Operand: Tmp); |
2579 | } |
2580 | |
2581 | static SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG, |
2582 | const SparcTargetLowering &TLI, |
2583 | bool hasHardQuad) { |
2584 | SDLoc dl(Op); |
2585 | EVT VT = Op.getValueType(); |
2586 | |
2587 | // Expand if it does not involve f128 or the target has support for |
2588 | // quad floating point instructions and the resulting type is legal. |
2589 | if (Op.getOperand(i: 0).getValueType() != MVT::f128 || |
2590 | (hasHardQuad && TLI.isTypeLegal(VT))) |
2591 | return SDValue(); |
2592 | |
2593 | assert(VT == MVT::i32 || VT == MVT::i64); |
2594 | |
2595 | return TLI.LowerF128Op(Op, DAG, |
2596 | LibFuncName: TLI.getLibcallName(Call: VT == MVT::i32 |
2597 | ? RTLIB::FPTOUINT_F128_I32 |
2598 | : RTLIB::FPTOUINT_F128_I64), |
2599 | numArgs: 1); |
2600 | } |
2601 | |
2602 | static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG, |
2603 | const SparcTargetLowering &TLI, |
2604 | bool hasHardQuad) { |
2605 | SDLoc dl(Op); |
2606 | EVT OpVT = Op.getOperand(i: 0).getValueType(); |
2607 | assert(OpVT == MVT::i32 || OpVT == MVT::i64); |
2608 | |
2609 | // Expand if it does not involve f128 or the target has support for |
2610 | // quad floating point instructions and the operand type is legal. |
2611 | if (Op.getValueType() != MVT::f128 || (hasHardQuad && TLI.isTypeLegal(VT: OpVT))) |
2612 | return SDValue(); |
2613 | |
2614 | return TLI.LowerF128Op(Op, DAG, |
2615 | LibFuncName: TLI.getLibcallName(Call: OpVT == MVT::i32 |
2616 | ? RTLIB::UINTTOFP_I32_F128 |
2617 | : RTLIB::UINTTOFP_I64_F128), |
2618 | numArgs: 1); |
2619 | } |
2620 | |
2621 | static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG, |
2622 | const SparcTargetLowering &TLI, bool hasHardQuad, |
2623 | bool isV9, bool is64Bit) { |
2624 | SDValue Chain = Op.getOperand(i: 0); |
2625 | ISD::CondCode CC = cast<CondCodeSDNode>(Val: Op.getOperand(i: 1))->get(); |
2626 | SDValue LHS = Op.getOperand(i: 2); |
2627 | SDValue RHS = Op.getOperand(i: 3); |
2628 | SDValue Dest = Op.getOperand(i: 4); |
2629 | SDLoc dl(Op); |
2630 | unsigned Opc, SPCC = ~0U; |
2631 | |
2632 | // If this is a br_cc of a "setcc", and if the setcc got lowered into |
2633 | // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. |
2634 | LookThroughSetCC(LHS, RHS, CC, SPCC); |
2635 | assert(LHS.getValueType() == RHS.getValueType()); |
2636 | |
2637 | // Get the condition flag. |
2638 | SDValue CompareFlag; |
2639 | if (LHS.getValueType().isInteger()) { |
2640 | // On V9 processors running in 64-bit mode, if CC compares two `i64`s |
2641 | // and the RHS is zero we might be able to use a specialized branch. |
2642 | if (is64Bit && isV9 && LHS.getValueType() == MVT::i64 && |
2643 | isNullConstant(V: RHS) && !ISD::isUnsignedIntSetCC(Code: CC)) |
2644 | return DAG.getNode(Opcode: SPISD::BR_REG, DL: dl, VT: MVT::Other, N1: Chain, N2: Dest, |
2645 | N3: DAG.getConstant(Val: intCondCCodeToRcond(CC), DL: dl, VT: MVT::i32), |
2646 | N4: LHS); |
2647 | |
2648 | CompareFlag = DAG.getNode(Opcode: SPISD::CMPICC, DL: dl, VT: MVT::Glue, N1: LHS, N2: RHS); |
2649 | if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); |
2650 | if (isV9) |
2651 | // 32-bit compares use the icc flags, 64-bit uses the xcc flags. |
2652 | Opc = LHS.getValueType() == MVT::i32 ? SPISD::BPICC : SPISD::BPXCC; |
2653 | else |
2654 | // Non-v9 targets don't have xcc. |
2655 | Opc = SPISD::BRICC; |
2656 | } else { |
2657 | if (!hasHardQuad && LHS.getValueType() == MVT::f128) { |
2658 | if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); |
2659 | CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, DL: dl, DAG); |
2660 | Opc = isV9 ? SPISD::BPICC : SPISD::BRICC; |
2661 | } else { |
2662 | unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC; |
2663 | CompareFlag = DAG.getNode(Opcode: CmpOpc, DL: dl, VT: MVT::Glue, N1: LHS, N2: RHS); |
2664 | if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); |
2665 | Opc = isV9 ? SPISD::BRFCC_V9 : SPISD::BRFCC; |
2666 | } |
2667 | } |
2668 | return DAG.getNode(Opcode: Opc, DL: dl, VT: MVT::Other, N1: Chain, N2: Dest, |
2669 | N3: DAG.getConstant(Val: SPCC, DL: dl, VT: MVT::i32), N4: CompareFlag); |
2670 | } |
2671 | |
2672 | static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG, |
2673 | const SparcTargetLowering &TLI, bool hasHardQuad, |
2674 | bool isV9, bool is64Bit) { |
2675 | SDValue LHS = Op.getOperand(i: 0); |
2676 | SDValue RHS = Op.getOperand(i: 1); |
2677 | ISD::CondCode CC = cast<CondCodeSDNode>(Val: Op.getOperand(i: 4))->get(); |
2678 | SDValue TrueVal = Op.getOperand(i: 2); |
2679 | SDValue FalseVal = Op.getOperand(i: 3); |
2680 | SDLoc dl(Op); |
2681 | unsigned Opc, SPCC = ~0U; |
2682 | |
2683 | // If this is a select_cc of a "setcc", and if the setcc got lowered into |
2684 | // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. |
2685 | LookThroughSetCC(LHS, RHS, CC, SPCC); |
2686 | assert(LHS.getValueType() == RHS.getValueType()); |
2687 | |
2688 | SDValue CompareFlag; |
2689 | if (LHS.getValueType().isInteger()) { |
2690 | // On V9 processors running in 64-bit mode, if CC compares two `i64`s |
2691 | // and the RHS is zero we might be able to use a specialized select. |
2692 | // All SELECT_CC between any two scalar integer types are eligible for |
2693 | // lowering to specialized instructions. Additionally, f32 and f64 types |
2694 | // are also eligible, but for f128 we can only use the specialized |
2695 | // instruction when we have hardquad. |
2696 | EVT ValType = TrueVal.getValueType(); |
2697 | bool IsEligibleType = ValType.isScalarInteger() || ValType == MVT::f32 || |
2698 | ValType == MVT::f64 || |
2699 | (ValType == MVT::f128 && hasHardQuad); |
2700 | if (is64Bit && isV9 && LHS.getValueType() == MVT::i64 && |
2701 | isNullConstant(V: RHS) && !ISD::isUnsignedIntSetCC(Code: CC) && IsEligibleType) |
2702 | return DAG.getNode( |
2703 | Opcode: SPISD::SELECT_REG, DL: dl, VT: TrueVal.getValueType(), N1: TrueVal, N2: FalseVal, |
2704 | N3: DAG.getConstant(Val: intCondCCodeToRcond(CC), DL: dl, VT: MVT::i32), N4: LHS); |
2705 | |
2706 | CompareFlag = DAG.getNode(Opcode: SPISD::CMPICC, DL: dl, VT: MVT::Glue, N1: LHS, N2: RHS); |
2707 | Opc = LHS.getValueType() == MVT::i32 ? |
2708 | SPISD::SELECT_ICC : SPISD::SELECT_XCC; |
2709 | if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); |
2710 | } else { |
2711 | if (!hasHardQuad && LHS.getValueType() == MVT::f128) { |
2712 | if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); |
2713 | CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, DL: dl, DAG); |
2714 | Opc = SPISD::SELECT_ICC; |
2715 | } else { |
2716 | unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC; |
2717 | CompareFlag = DAG.getNode(Opcode: CmpOpc, DL: dl, VT: MVT::Glue, N1: LHS, N2: RHS); |
2718 | Opc = SPISD::SELECT_FCC; |
2719 | if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); |
2720 | } |
2721 | } |
2722 | return DAG.getNode(Opcode: Opc, DL: dl, VT: TrueVal.getValueType(), N1: TrueVal, N2: FalseVal, |
2723 | N3: DAG.getConstant(Val: SPCC, DL: dl, VT: MVT::i32), N4: CompareFlag); |
2724 | } |
2725 | |
2726 | static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, |
2727 | const SparcTargetLowering &TLI) { |
2728 | MachineFunction &MF = DAG.getMachineFunction(); |
2729 | SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); |
2730 | auto PtrVT = TLI.getPointerTy(DL: DAG.getDataLayout()); |
2731 | |
2732 | // Need frame address to find the address of VarArgsFrameIndex. |
2733 | MF.getFrameInfo().setFrameAddressIsTaken(true); |
2734 | |
2735 | // vastart just stores the address of the VarArgsFrameIndex slot into the |
2736 | // memory location argument. |
2737 | SDLoc DL(Op); |
2738 | SDValue Offset = |
2739 | DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, N1: DAG.getRegister(Reg: SP::I6, VT: PtrVT), |
2740 | N2: DAG.getIntPtrConstant(Val: FuncInfo->getVarArgsFrameOffset(), DL)); |
2741 | const Value *SV = cast<SrcValueSDNode>(Val: Op.getOperand(i: 2))->getValue(); |
2742 | return DAG.getStore(Chain: Op.getOperand(i: 0), dl: DL, Val: Offset, Ptr: Op.getOperand(i: 1), |
2743 | PtrInfo: MachinePointerInfo(SV)); |
2744 | } |
2745 | |
2746 | static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { |
2747 | SDNode *Node = Op.getNode(); |
2748 | EVT VT = Node->getValueType(ResNo: 0); |
2749 | SDValue InChain = Node->getOperand(Num: 0); |
2750 | SDValue VAListPtr = Node->getOperand(Num: 1); |
2751 | EVT PtrVT = VAListPtr.getValueType(); |
2752 | const Value *SV = cast<SrcValueSDNode>(Val: Node->getOperand(Num: 2))->getValue(); |
2753 | SDLoc DL(Node); |
2754 | SDValue VAList = |
2755 | DAG.getLoad(VT: PtrVT, dl: DL, Chain: InChain, Ptr: VAListPtr, PtrInfo: MachinePointerInfo(SV)); |
2756 | // Increment the pointer, VAList, to the next vaarg. |
2757 | SDValue NextPtr = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, N1: VAList, |
2758 | N2: DAG.getIntPtrConstant(Val: VT.getSizeInBits()/8, |
2759 | DL)); |
2760 | // Store the incremented VAList to the legalized pointer. |
2761 | InChain = DAG.getStore(Chain: VAList.getValue(R: 1), dl: DL, Val: NextPtr, Ptr: VAListPtr, |
2762 | PtrInfo: MachinePointerInfo(SV)); |
2763 | // Load the actual argument out of the pointer VAList. |
2764 | // We can't count on greater alignment than the word size. |
2765 | return DAG.getLoad( |
2766 | VT, dl: DL, Chain: InChain, Ptr: VAList, PtrInfo: MachinePointerInfo(), |
2767 | Alignment: Align(std::min(a: PtrVT.getFixedSizeInBits(), b: VT.getFixedSizeInBits()) / 8)); |
2768 | } |
2769 | |
2770 | static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, |
2771 | const SparcSubtarget *Subtarget) { |
2772 | SDValue Chain = Op.getOperand(i: 0); // Legalize the chain. |
2773 | SDValue Size = Op.getOperand(i: 1); // Legalize the size. |
2774 | MaybeAlign Alignment = |
2775 | cast<ConstantSDNode>(Val: Op.getOperand(i: 2))->getMaybeAlignValue(); |
2776 | Align StackAlign = Subtarget->getFrameLowering()->getStackAlign(); |
2777 | EVT VT = Size->getValueType(ResNo: 0); |
2778 | SDLoc dl(Op); |
2779 | |
2780 | // TODO: implement over-aligned alloca. (Note: also implies |
2781 | // supporting support for overaligned function frames + dynamic |
2782 | // allocations, at all, which currently isn't supported) |
2783 | if (Alignment && *Alignment > StackAlign) { |
2784 | const MachineFunction &MF = DAG.getMachineFunction(); |
2785 | report_fatal_error(reason: "Function \"" + Twine(MF.getName()) + "\": " |
2786 | "over-aligned dynamic alloca not supported." ); |
2787 | } |
2788 | |
2789 | // The resultant pointer needs to be above the register spill area |
2790 | // at the bottom of the stack. |
2791 | unsigned regSpillArea; |
2792 | if (Subtarget->is64Bit()) { |
2793 | regSpillArea = 128; |
2794 | } else { |
2795 | // On Sparc32, the size of the spill area is 92. Unfortunately, |
2796 | // that's only 4-byte aligned, not 8-byte aligned (the stack |
2797 | // pointer is 8-byte aligned). So, if the user asked for an 8-byte |
2798 | // aligned dynamic allocation, we actually need to add 96 to the |
2799 | // bottom of the stack, instead of 92, to ensure 8-byte alignment. |
2800 | |
2801 | // That also means adding 4 to the size of the allocation -- |
2802 | // before applying the 8-byte rounding. Unfortunately, we the |
2803 | // value we get here has already had rounding applied. So, we need |
2804 | // to add 8, instead, wasting a bit more memory. |
2805 | |
2806 | // Further, this only actually needs to be done if the required |
2807 | // alignment is > 4, but, we've lost that info by this point, too, |
2808 | // so we always apply it. |
2809 | |
2810 | // (An alternative approach would be to always reserve 96 bytes |
2811 | // instead of the required 92, but then we'd waste 4 extra bytes |
2812 | // in every frame, not just those with dynamic stack allocations) |
2813 | |
2814 | // TODO: modify code in SelectionDAGBuilder to make this less sad. |
2815 | |
2816 | Size = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT, N1: Size, |
2817 | N2: DAG.getConstant(Val: 8, DL: dl, VT)); |
2818 | regSpillArea = 96; |
2819 | } |
2820 | |
2821 | unsigned SPReg = SP::O6; |
2822 | SDValue SP = DAG.getCopyFromReg(Chain, dl, Reg: SPReg, VT); |
2823 | SDValue NewSP = DAG.getNode(Opcode: ISD::SUB, DL: dl, VT, N1: SP, N2: Size); // Value |
2824 | Chain = DAG.getCopyToReg(Chain: SP.getValue(R: 1), dl, Reg: SPReg, N: NewSP); // Output chain |
2825 | |
2826 | regSpillArea += Subtarget->getStackPointerBias(); |
2827 | |
2828 | SDValue NewVal = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT, N1: NewSP, |
2829 | N2: DAG.getConstant(Val: regSpillArea, DL: dl, VT)); |
2830 | SDValue Ops[2] = { NewVal, Chain }; |
2831 | return DAG.getMergeValues(Ops, dl); |
2832 | } |
2833 | |
2834 | |
2835 | static SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) { |
2836 | SDLoc dl(Op); |
2837 | SDValue Chain = DAG.getNode(Opcode: SPISD::FLUSHW, |
2838 | DL: dl, VT: MVT::Other, Operand: DAG.getEntryNode()); |
2839 | return Chain; |
2840 | } |
2841 | |
2842 | static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG, |
2843 | const SparcSubtarget *Subtarget, |
2844 | bool AlwaysFlush = false) { |
2845 | MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); |
2846 | MFI.setFrameAddressIsTaken(true); |
2847 | |
2848 | EVT VT = Op.getValueType(); |
2849 | SDLoc dl(Op); |
2850 | unsigned FrameReg = SP::I6; |
2851 | unsigned stackBias = Subtarget->getStackPointerBias(); |
2852 | |
2853 | SDValue FrameAddr; |
2854 | SDValue Chain; |
2855 | |
2856 | // flush first to make sure the windowed registers' values are in stack |
2857 | Chain = (depth || AlwaysFlush) ? getFLUSHW(Op, DAG) : DAG.getEntryNode(); |
2858 | |
2859 | FrameAddr = DAG.getCopyFromReg(Chain, dl, Reg: FrameReg, VT); |
2860 | |
2861 | unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56; |
2862 | |
2863 | while (depth--) { |
2864 | SDValue Ptr = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT, N1: FrameAddr, |
2865 | N2: DAG.getIntPtrConstant(Val: Offset, DL: dl)); |
2866 | FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, PtrInfo: MachinePointerInfo()); |
2867 | } |
2868 | if (Subtarget->is64Bit()) |
2869 | FrameAddr = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT, N1: FrameAddr, |
2870 | N2: DAG.getIntPtrConstant(Val: stackBias, DL: dl)); |
2871 | return FrameAddr; |
2872 | } |
2873 | |
2874 | |
2875 | static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, |
2876 | const SparcSubtarget *Subtarget) { |
2877 | |
2878 | uint64_t depth = Op.getConstantOperandVal(i: 0); |
2879 | |
2880 | return getFRAMEADDR(depth, Op, DAG, Subtarget); |
2881 | |
2882 | } |
2883 | |
2884 | static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG, |
2885 | const SparcTargetLowering &TLI, |
2886 | const SparcSubtarget *Subtarget) { |
2887 | MachineFunction &MF = DAG.getMachineFunction(); |
2888 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
2889 | MFI.setReturnAddressIsTaken(true); |
2890 | |
2891 | if (TLI.verifyReturnAddressArgumentIsConstant(Op, DAG)) |
2892 | return SDValue(); |
2893 | |
2894 | EVT VT = Op.getValueType(); |
2895 | SDLoc dl(Op); |
2896 | uint64_t depth = Op.getConstantOperandVal(i: 0); |
2897 | |
2898 | SDValue RetAddr; |
2899 | if (depth == 0) { |
2900 | auto PtrVT = TLI.getPointerTy(DL: DAG.getDataLayout()); |
2901 | Register RetReg = MF.addLiveIn(PReg: SP::I7, RC: TLI.getRegClassFor(VT: PtrVT)); |
2902 | RetAddr = DAG.getCopyFromReg(Chain: DAG.getEntryNode(), dl, Reg: RetReg, VT); |
2903 | return RetAddr; |
2904 | } |
2905 | |
2906 | // Need frame address to find return address of the caller. |
2907 | SDValue FrameAddr = getFRAMEADDR(depth: depth - 1, Op, DAG, Subtarget, AlwaysFlush: true); |
2908 | |
2909 | unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60; |
2910 | SDValue Ptr = DAG.getNode(Opcode: ISD::ADD, |
2911 | DL: dl, VT, |
2912 | N1: FrameAddr, |
2913 | N2: DAG.getIntPtrConstant(Val: Offset, DL: dl)); |
2914 | RetAddr = DAG.getLoad(VT, dl, Chain: DAG.getEntryNode(), Ptr, PtrInfo: MachinePointerInfo()); |
2915 | |
2916 | return RetAddr; |
2917 | } |
2918 | |
2919 | static SDValue LowerF64Op(SDValue SrcReg64, const SDLoc &dl, SelectionDAG &DAG, |
2920 | unsigned opcode) { |
2921 | assert(SrcReg64.getValueType() == MVT::f64 && "LowerF64Op called on non-double!" ); |
2922 | assert(opcode == ISD::FNEG || opcode == ISD::FABS); |
2923 | |
2924 | // Lower fneg/fabs on f64 to fneg/fabs on f32. |
2925 | // fneg f64 => fneg f32:sub_even, fmov f32:sub_odd. |
2926 | // fabs f64 => fabs f32:sub_even, fmov f32:sub_odd. |
2927 | |
2928 | // Note: in little-endian, the floating-point value is stored in the |
2929 | // registers are in the opposite order, so the subreg with the sign |
2930 | // bit is the highest-numbered (odd), rather than the |
2931 | // lowest-numbered (even). |
2932 | |
2933 | SDValue Hi32 = DAG.getTargetExtractSubreg(SRIdx: SP::sub_even, DL: dl, VT: MVT::f32, |
2934 | Operand: SrcReg64); |
2935 | SDValue Lo32 = DAG.getTargetExtractSubreg(SRIdx: SP::sub_odd, DL: dl, VT: MVT::f32, |
2936 | Operand: SrcReg64); |
2937 | |
2938 | if (DAG.getDataLayout().isLittleEndian()) |
2939 | Lo32 = DAG.getNode(Opcode: opcode, DL: dl, VT: MVT::f32, Operand: Lo32); |
2940 | else |
2941 | Hi32 = DAG.getNode(Opcode: opcode, DL: dl, VT: MVT::f32, Operand: Hi32); |
2942 | |
2943 | SDValue DstReg64 = SDValue(DAG.getMachineNode(Opcode: TargetOpcode::IMPLICIT_DEF, |
2944 | dl, VT: MVT::f64), 0); |
2945 | DstReg64 = DAG.getTargetInsertSubreg(SRIdx: SP::sub_even, DL: dl, VT: MVT::f64, |
2946 | Operand: DstReg64, Subreg: Hi32); |
2947 | DstReg64 = DAG.getTargetInsertSubreg(SRIdx: SP::sub_odd, DL: dl, VT: MVT::f64, |
2948 | Operand: DstReg64, Subreg: Lo32); |
2949 | return DstReg64; |
2950 | } |
2951 | |
2952 | // Lower a f128 load into two f64 loads. |
2953 | static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG) |
2954 | { |
2955 | SDLoc dl(Op); |
2956 | LoadSDNode *LdNode = cast<LoadSDNode>(Val: Op.getNode()); |
2957 | assert(LdNode->getOffset().isUndef() && "Unexpected node type" ); |
2958 | |
2959 | Align Alignment = commonAlignment(A: LdNode->getOriginalAlign(), Offset: 8); |
2960 | |
2961 | SDValue Hi64 = |
2962 | DAG.getLoad(VT: MVT::f64, dl, Chain: LdNode->getChain(), Ptr: LdNode->getBasePtr(), |
2963 | PtrInfo: LdNode->getPointerInfo(), Alignment); |
2964 | EVT addrVT = LdNode->getBasePtr().getValueType(); |
2965 | SDValue LoPtr = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: addrVT, |
2966 | N1: LdNode->getBasePtr(), |
2967 | N2: DAG.getConstant(Val: 8, DL: dl, VT: addrVT)); |
2968 | SDValue Lo64 = DAG.getLoad(VT: MVT::f64, dl, Chain: LdNode->getChain(), Ptr: LoPtr, |
2969 | PtrInfo: LdNode->getPointerInfo().getWithOffset(O: 8), |
2970 | Alignment); |
2971 | |
2972 | SDValue SubRegEven = DAG.getTargetConstant(Val: SP::sub_even64, DL: dl, VT: MVT::i32); |
2973 | SDValue SubRegOdd = DAG.getTargetConstant(Val: SP::sub_odd64, DL: dl, VT: MVT::i32); |
2974 | |
2975 | SDNode *InFP128 = DAG.getMachineNode(Opcode: TargetOpcode::IMPLICIT_DEF, |
2976 | dl, VT: MVT::f128); |
2977 | InFP128 = DAG.getMachineNode(Opcode: TargetOpcode::INSERT_SUBREG, dl, |
2978 | VT: MVT::f128, |
2979 | Op1: SDValue(InFP128, 0), |
2980 | Op2: Hi64, |
2981 | Op3: SubRegEven); |
2982 | InFP128 = DAG.getMachineNode(Opcode: TargetOpcode::INSERT_SUBREG, dl, |
2983 | VT: MVT::f128, |
2984 | Op1: SDValue(InFP128, 0), |
2985 | Op2: Lo64, |
2986 | Op3: SubRegOdd); |
2987 | SDValue OutChains[2] = { SDValue(Hi64.getNode(), 1), |
2988 | SDValue(Lo64.getNode(), 1) }; |
2989 | SDValue OutChain = DAG.getNode(Opcode: ISD::TokenFactor, DL: dl, VT: MVT::Other, Ops: OutChains); |
2990 | SDValue Ops[2] = {SDValue(InFP128,0), OutChain}; |
2991 | return DAG.getMergeValues(Ops, dl); |
2992 | } |
2993 | |
2994 | static SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) |
2995 | { |
2996 | LoadSDNode *LdNode = cast<LoadSDNode>(Val: Op.getNode()); |
2997 | |
2998 | EVT MemVT = LdNode->getMemoryVT(); |
2999 | if (MemVT == MVT::f128) |
3000 | return LowerF128Load(Op, DAG); |
3001 | |
3002 | return Op; |
3003 | } |
3004 | |
3005 | // Lower a f128 store into two f64 stores. |
3006 | static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) { |
3007 | SDLoc dl(Op); |
3008 | StoreSDNode *StNode = cast<StoreSDNode>(Val: Op.getNode()); |
3009 | assert(StNode->getOffset().isUndef() && "Unexpected node type" ); |
3010 | |
3011 | SDValue SubRegEven = DAG.getTargetConstant(Val: SP::sub_even64, DL: dl, VT: MVT::i32); |
3012 | SDValue SubRegOdd = DAG.getTargetConstant(Val: SP::sub_odd64, DL: dl, VT: MVT::i32); |
3013 | |
3014 | SDNode *Hi64 = DAG.getMachineNode(Opcode: TargetOpcode::EXTRACT_SUBREG, |
3015 | dl, |
3016 | VT: MVT::f64, |
3017 | Op1: StNode->getValue(), |
3018 | Op2: SubRegEven); |
3019 | SDNode *Lo64 = DAG.getMachineNode(Opcode: TargetOpcode::EXTRACT_SUBREG, |
3020 | dl, |
3021 | VT: MVT::f64, |
3022 | Op1: StNode->getValue(), |
3023 | Op2: SubRegOdd); |
3024 | |
3025 | Align Alignment = commonAlignment(A: StNode->getOriginalAlign(), Offset: 8); |
3026 | |
3027 | SDValue OutChains[2]; |
3028 | OutChains[0] = |
3029 | DAG.getStore(Chain: StNode->getChain(), dl, Val: SDValue(Hi64, 0), |
3030 | Ptr: StNode->getBasePtr(), PtrInfo: StNode->getPointerInfo(), |
3031 | Alignment); |
3032 | EVT addrVT = StNode->getBasePtr().getValueType(); |
3033 | SDValue LoPtr = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: addrVT, |
3034 | N1: StNode->getBasePtr(), |
3035 | N2: DAG.getConstant(Val: 8, DL: dl, VT: addrVT)); |
3036 | OutChains[1] = DAG.getStore(Chain: StNode->getChain(), dl, Val: SDValue(Lo64, 0), Ptr: LoPtr, |
3037 | PtrInfo: StNode->getPointerInfo().getWithOffset(O: 8), |
3038 | Alignment); |
3039 | return DAG.getNode(Opcode: ISD::TokenFactor, DL: dl, VT: MVT::Other, Ops: OutChains); |
3040 | } |
3041 | |
3042 | static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) |
3043 | { |
3044 | SDLoc dl(Op); |
3045 | StoreSDNode *St = cast<StoreSDNode>(Val: Op.getNode()); |
3046 | |
3047 | EVT MemVT = St->getMemoryVT(); |
3048 | if (MemVT == MVT::f128) |
3049 | return LowerF128Store(Op, DAG); |
3050 | |
3051 | if (MemVT == MVT::i64) { |
3052 | // Custom handling for i64 stores: turn it into a bitcast and a |
3053 | // v2i32 store. |
3054 | SDValue Val = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: MVT::v2i32, Operand: St->getValue()); |
3055 | SDValue Chain = DAG.getStore( |
3056 | Chain: St->getChain(), dl, Val, Ptr: St->getBasePtr(), PtrInfo: St->getPointerInfo(), |
3057 | Alignment: St->getOriginalAlign(), MMOFlags: St->getMemOperand()->getFlags(), |
3058 | AAInfo: St->getAAInfo()); |
3059 | return Chain; |
3060 | } |
3061 | |
3062 | return SDValue(); |
3063 | } |
3064 | |
3065 | static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) { |
3066 | assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS) |
3067 | && "invalid opcode" ); |
3068 | |
3069 | SDLoc dl(Op); |
3070 | |
3071 | if (Op.getValueType() == MVT::f64) |
3072 | return LowerF64Op(SrcReg64: Op.getOperand(i: 0), dl, DAG, opcode: Op.getOpcode()); |
3073 | if (Op.getValueType() != MVT::f128) |
3074 | return Op; |
3075 | |
3076 | // Lower fabs/fneg on f128 to fabs/fneg on f64 |
3077 | // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64 |
3078 | // (As with LowerF64Op, on little-endian, we need to negate the odd |
3079 | // subreg) |
3080 | |
3081 | SDValue SrcReg128 = Op.getOperand(i: 0); |
3082 | SDValue Hi64 = DAG.getTargetExtractSubreg(SRIdx: SP::sub_even64, DL: dl, VT: MVT::f64, |
3083 | Operand: SrcReg128); |
3084 | SDValue Lo64 = DAG.getTargetExtractSubreg(SRIdx: SP::sub_odd64, DL: dl, VT: MVT::f64, |
3085 | Operand: SrcReg128); |
3086 | |
3087 | if (DAG.getDataLayout().isLittleEndian()) { |
3088 | if (isV9) |
3089 | Lo64 = DAG.getNode(Opcode: Op.getOpcode(), DL: dl, VT: MVT::f64, Operand: Lo64); |
3090 | else |
3091 | Lo64 = LowerF64Op(SrcReg64: Lo64, dl, DAG, opcode: Op.getOpcode()); |
3092 | } else { |
3093 | if (isV9) |
3094 | Hi64 = DAG.getNode(Opcode: Op.getOpcode(), DL: dl, VT: MVT::f64, Operand: Hi64); |
3095 | else |
3096 | Hi64 = LowerF64Op(SrcReg64: Hi64, dl, DAG, opcode: Op.getOpcode()); |
3097 | } |
3098 | |
3099 | SDValue DstReg128 = SDValue(DAG.getMachineNode(Opcode: TargetOpcode::IMPLICIT_DEF, |
3100 | dl, VT: MVT::f128), 0); |
3101 | DstReg128 = DAG.getTargetInsertSubreg(SRIdx: SP::sub_even64, DL: dl, VT: MVT::f128, |
3102 | Operand: DstReg128, Subreg: Hi64); |
3103 | DstReg128 = DAG.getTargetInsertSubreg(SRIdx: SP::sub_odd64, DL: dl, VT: MVT::f128, |
3104 | Operand: DstReg128, Subreg: Lo64); |
3105 | return DstReg128; |
3106 | } |
3107 | |
3108 | static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) { |
3109 | |
3110 | if (Op.getValueType() != MVT::i64) |
3111 | return Op; |
3112 | |
3113 | SDLoc dl(Op); |
3114 | SDValue Src1 = Op.getOperand(i: 0); |
3115 | SDValue Src1Lo = DAG.getNode(Opcode: ISD::TRUNCATE, DL: dl, VT: MVT::i32, Operand: Src1); |
3116 | SDValue Src1Hi = DAG.getNode(Opcode: ISD::SRL, DL: dl, VT: MVT::i64, N1: Src1, |
3117 | N2: DAG.getConstant(Val: 32, DL: dl, VT: MVT::i64)); |
3118 | Src1Hi = DAG.getNode(Opcode: ISD::TRUNCATE, DL: dl, VT: MVT::i32, Operand: Src1Hi); |
3119 | |
3120 | SDValue Src2 = Op.getOperand(i: 1); |
3121 | SDValue Src2Lo = DAG.getNode(Opcode: ISD::TRUNCATE, DL: dl, VT: MVT::i32, Operand: Src2); |
3122 | SDValue Src2Hi = DAG.getNode(Opcode: ISD::SRL, DL: dl, VT: MVT::i64, N1: Src2, |
3123 | N2: DAG.getConstant(Val: 32, DL: dl, VT: MVT::i64)); |
3124 | Src2Hi = DAG.getNode(Opcode: ISD::TRUNCATE, DL: dl, VT: MVT::i32, Operand: Src2Hi); |
3125 | |
3126 | |
3127 | bool hasChain = false; |
3128 | unsigned hiOpc = Op.getOpcode(); |
3129 | switch (Op.getOpcode()) { |
3130 | default: llvm_unreachable("Invalid opcode" ); |
3131 | case ISD::ADDC: hiOpc = ISD::ADDE; break; |
3132 | case ISD::ADDE: hasChain = true; break; |
3133 | case ISD::SUBC: hiOpc = ISD::SUBE; break; |
3134 | case ISD::SUBE: hasChain = true; break; |
3135 | } |
3136 | SDValue Lo; |
3137 | SDVTList VTs = DAG.getVTList(VT1: MVT::i32, VT2: MVT::Glue); |
3138 | if (hasChain) { |
3139 | Lo = DAG.getNode(Opcode: Op.getOpcode(), DL: dl, VTList: VTs, N1: Src1Lo, N2: Src2Lo, |
3140 | N3: Op.getOperand(i: 2)); |
3141 | } else { |
3142 | Lo = DAG.getNode(Opcode: Op.getOpcode(), DL: dl, VTList: VTs, N1: Src1Lo, N2: Src2Lo); |
3143 | } |
3144 | SDValue Hi = DAG.getNode(Opcode: hiOpc, DL: dl, VTList: VTs, N1: Src1Hi, N2: Src2Hi, N3: Lo.getValue(R: 1)); |
3145 | SDValue Carry = Hi.getValue(R: 1); |
3146 | |
3147 | Lo = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL: dl, VT: MVT::i64, Operand: Lo); |
3148 | Hi = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL: dl, VT: MVT::i64, Operand: Hi); |
3149 | Hi = DAG.getNode(Opcode: ISD::SHL, DL: dl, VT: MVT::i64, N1: Hi, |
3150 | N2: DAG.getConstant(Val: 32, DL: dl, VT: MVT::i64)); |
3151 | |
3152 | SDValue Dst = DAG.getNode(Opcode: ISD::OR, DL: dl, VT: MVT::i64, N1: Hi, N2: Lo); |
3153 | SDValue Ops[2] = { Dst, Carry }; |
3154 | return DAG.getMergeValues(Ops, dl); |
3155 | } |
3156 | |
3157 | // Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode() |
3158 | // in LegalizeDAG.cpp except the order of arguments to the library function. |
3159 | static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG, |
3160 | const SparcTargetLowering &TLI) |
3161 | { |
3162 | unsigned opcode = Op.getOpcode(); |
3163 | assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode." ); |
3164 | |
3165 | bool isSigned = (opcode == ISD::SMULO); |
3166 | EVT VT = MVT::i64; |
3167 | EVT WideVT = MVT::i128; |
3168 | SDLoc dl(Op); |
3169 | SDValue LHS = Op.getOperand(i: 0); |
3170 | |
3171 | if (LHS.getValueType() != VT) |
3172 | return Op; |
3173 | |
3174 | SDValue ShiftAmt = DAG.getConstant(Val: 63, DL: dl, VT); |
3175 | |
3176 | SDValue RHS = Op.getOperand(i: 1); |
3177 | SDValue HiLHS, HiRHS; |
3178 | if (isSigned) { |
3179 | HiLHS = DAG.getNode(Opcode: ISD::SRA, DL: dl, VT, N1: LHS, N2: ShiftAmt); |
3180 | HiRHS = DAG.getNode(Opcode: ISD::SRA, DL: dl, VT: MVT::i64, N1: RHS, N2: ShiftAmt); |
3181 | } else { |
3182 | HiLHS = DAG.getConstant(Val: 0, DL: dl, VT); |
3183 | HiRHS = DAG.getConstant(Val: 0, DL: dl, VT: MVT::i64); |
3184 | } |
3185 | |
3186 | SDValue Args[] = { HiLHS, LHS, HiRHS, RHS }; |
3187 | |
3188 | TargetLowering::MakeLibCallOptions CallOptions; |
3189 | CallOptions.setSExt(isSigned); |
3190 | SDValue MulResult = TLI.makeLibCall(DAG, |
3191 | LC: RTLIB::MUL_I128, RetVT: WideVT, |
3192 | Ops: Args, CallOptions, dl).first; |
3193 | SDValue BottomHalf, TopHalf; |
3194 | std::tie(args&: BottomHalf, args&: TopHalf) = DAG.SplitScalar(N: MulResult, DL: dl, LoVT: VT, HiVT: VT); |
3195 | if (isSigned) { |
3196 | SDValue Tmp1 = DAG.getNode(Opcode: ISD::SRA, DL: dl, VT, N1: BottomHalf, N2: ShiftAmt); |
3197 | TopHalf = DAG.getSetCC(DL: dl, VT: MVT::i32, LHS: TopHalf, RHS: Tmp1, Cond: ISD::SETNE); |
3198 | } else { |
3199 | TopHalf = DAG.getSetCC(DL: dl, VT: MVT::i32, LHS: TopHalf, RHS: DAG.getConstant(Val: 0, DL: dl, VT), |
3200 | Cond: ISD::SETNE); |
3201 | } |
3202 | // MulResult is a node with an illegal type. Because such things are not |
3203 | // generally permitted during this phase of legalization, ensure that |
3204 | // nothing is left using the node. The above EXTRACT_ELEMENT nodes should have |
3205 | // been folded. |
3206 | assert(MulResult->use_empty() && "Illegally typed node still in use!" ); |
3207 | |
3208 | SDValue Ops[2] = { BottomHalf, TopHalf } ; |
3209 | return DAG.getMergeValues(Ops, dl); |
3210 | } |
3211 | |
3212 | static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) { |
3213 | if (isStrongerThanMonotonic(AO: cast<AtomicSDNode>(Val&: Op)->getSuccessOrdering())) { |
3214 | // Expand with a fence. |
3215 | return SDValue(); |
3216 | } |
3217 | |
3218 | // Monotonic load/stores are legal. |
3219 | return Op; |
3220 | } |
3221 | |
3222 | SDValue SparcTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, |
3223 | SelectionDAG &DAG) const { |
3224 | unsigned IntNo = Op.getConstantOperandVal(i: 0); |
3225 | SDLoc dl(Op); |
3226 | switch (IntNo) { |
3227 | default: return SDValue(); // Don't custom lower most intrinsics. |
3228 | case Intrinsic::thread_pointer: { |
3229 | EVT PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
3230 | return DAG.getRegister(Reg: SP::G7, VT: PtrVT); |
3231 | } |
3232 | } |
3233 | } |
3234 | |
3235 | SDValue SparcTargetLowering:: |
3236 | LowerOperation(SDValue Op, SelectionDAG &DAG) const { |
3237 | |
3238 | bool hasHardQuad = Subtarget->hasHardQuad(); |
3239 | bool isV9 = Subtarget->isV9(); |
3240 | bool is64Bit = Subtarget->is64Bit(); |
3241 | |
3242 | switch (Op.getOpcode()) { |
3243 | default: llvm_unreachable("Should not custom lower this!" ); |
3244 | |
3245 | case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, TLI: *this, |
3246 | Subtarget); |
3247 | case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG, |
3248 | Subtarget); |
3249 | case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); |
3250 | case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); |
3251 | case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); |
3252 | case ISD::ConstantPool: return LowerConstantPool(Op, DAG); |
3253 | case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG, TLI: *this, |
3254 | hasHardQuad); |
3255 | case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG, TLI: *this, |
3256 | hasHardQuad); |
3257 | case ISD::FP_TO_UINT: return LowerFP_TO_UINT(Op, DAG, TLI: *this, |
3258 | hasHardQuad); |
3259 | case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG, TLI: *this, |
3260 | hasHardQuad); |
3261 | case ISD::BR_CC: |
3262 | return LowerBR_CC(Op, DAG, TLI: *this, hasHardQuad, isV9, is64Bit); |
3263 | case ISD::SELECT_CC: |
3264 | return LowerSELECT_CC(Op, DAG, TLI: *this, hasHardQuad, isV9, is64Bit); |
3265 | case ISD::VASTART: return LowerVASTART(Op, DAG, TLI: *this); |
3266 | case ISD::VAARG: return LowerVAARG(Op, DAG); |
3267 | case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG, |
3268 | Subtarget); |
3269 | |
3270 | case ISD::LOAD: return LowerLOAD(Op, DAG); |
3271 | case ISD::STORE: return LowerSTORE(Op, DAG); |
3272 | case ISD::FADD: return LowerF128Op(Op, DAG, |
3273 | LibFuncName: getLibcallName(Call: RTLIB::ADD_F128), numArgs: 2); |
3274 | case ISD::FSUB: return LowerF128Op(Op, DAG, |
3275 | LibFuncName: getLibcallName(Call: RTLIB::SUB_F128), numArgs: 2); |
3276 | case ISD::FMUL: return LowerF128Op(Op, DAG, |
3277 | LibFuncName: getLibcallName(Call: RTLIB::MUL_F128), numArgs: 2); |
3278 | case ISD::FDIV: return LowerF128Op(Op, DAG, |
3279 | LibFuncName: getLibcallName(Call: RTLIB::DIV_F128), numArgs: 2); |
3280 | case ISD::FSQRT: return LowerF128Op(Op, DAG, |
3281 | LibFuncName: getLibcallName(Call: RTLIB::SQRT_F128),numArgs: 1); |
3282 | case ISD::FABS: |
3283 | case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9); |
3284 | case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, TLI: *this); |
3285 | case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, TLI: *this); |
3286 | case ISD::ADDC: |
3287 | case ISD::ADDE: |
3288 | case ISD::SUBC: |
3289 | case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG); |
3290 | case ISD::UMULO: |
3291 | case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, TLI: *this); |
3292 | case ISD::ATOMIC_LOAD: |
3293 | case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG); |
3294 | case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); |
3295 | } |
3296 | } |
3297 | |
3298 | SDValue SparcTargetLowering::bitcastConstantFPToInt(ConstantFPSDNode *C, |
3299 | const SDLoc &DL, |
3300 | SelectionDAG &DAG) const { |
3301 | APInt V = C->getValueAPF().bitcastToAPInt(); |
3302 | SDValue Lo = DAG.getConstant(Val: V.zextOrTrunc(width: 32), DL, VT: MVT::i32); |
3303 | SDValue Hi = DAG.getConstant(Val: V.lshr(shiftAmt: 32).zextOrTrunc(width: 32), DL, VT: MVT::i32); |
3304 | if (DAG.getDataLayout().isLittleEndian()) |
3305 | std::swap(a&: Lo, b&: Hi); |
3306 | return DAG.getBuildVector(VT: MVT::v2i32, DL, Ops: {Hi, Lo}); |
3307 | } |
3308 | |
3309 | SDValue SparcTargetLowering::PerformBITCASTCombine(SDNode *N, |
3310 | DAGCombinerInfo &DCI) const { |
3311 | SDLoc dl(N); |
3312 | SDValue Src = N->getOperand(Num: 0); |
3313 | |
3314 | if (isa<ConstantFPSDNode>(Val: Src) && N->getSimpleValueType(ResNo: 0) == MVT::v2i32 && |
3315 | Src.getSimpleValueType() == MVT::f64) |
3316 | return bitcastConstantFPToInt(C: cast<ConstantFPSDNode>(Val&: Src), DL: dl, DAG&: DCI.DAG); |
3317 | |
3318 | return SDValue(); |
3319 | } |
3320 | |
3321 | SDValue SparcTargetLowering::PerformDAGCombine(SDNode *N, |
3322 | DAGCombinerInfo &DCI) const { |
3323 | switch (N->getOpcode()) { |
3324 | default: |
3325 | break; |
3326 | case ISD::BITCAST: |
3327 | return PerformBITCASTCombine(N, DCI); |
3328 | } |
3329 | return SDValue(); |
3330 | } |
3331 | |
3332 | MachineBasicBlock * |
3333 | SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, |
3334 | MachineBasicBlock *BB) const { |
3335 | switch (MI.getOpcode()) { |
3336 | default: llvm_unreachable("Unknown SELECT_CC!" ); |
3337 | case SP::SELECT_CC_Int_ICC: |
3338 | case SP::SELECT_CC_FP_ICC: |
3339 | case SP::SELECT_CC_DFP_ICC: |
3340 | case SP::SELECT_CC_QFP_ICC: |
3341 | if (Subtarget->isV9()) |
3342 | return expandSelectCC(MI, BB, BROpcode: SP::BPICC); |
3343 | return expandSelectCC(MI, BB, BROpcode: SP::BCOND); |
3344 | case SP::SELECT_CC_Int_XCC: |
3345 | case SP::SELECT_CC_FP_XCC: |
3346 | case SP::SELECT_CC_DFP_XCC: |
3347 | case SP::SELECT_CC_QFP_XCC: |
3348 | return expandSelectCC(MI, BB, BROpcode: SP::BPXCC); |
3349 | case SP::SELECT_CC_Int_FCC: |
3350 | case SP::SELECT_CC_FP_FCC: |
3351 | case SP::SELECT_CC_DFP_FCC: |
3352 | case SP::SELECT_CC_QFP_FCC: |
3353 | if (Subtarget->isV9()) |
3354 | return expandSelectCC(MI, BB, BROpcode: SP::FBCOND_V9); |
3355 | return expandSelectCC(MI, BB, BROpcode: SP::FBCOND); |
3356 | } |
3357 | } |
3358 | |
3359 | MachineBasicBlock * |
3360 | SparcTargetLowering::expandSelectCC(MachineInstr &MI, MachineBasicBlock *BB, |
3361 | unsigned BROpcode) const { |
3362 | const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); |
3363 | DebugLoc dl = MI.getDebugLoc(); |
3364 | unsigned CC = (SPCC::CondCodes)MI.getOperand(i: 3).getImm(); |
3365 | |
3366 | // To "insert" a SELECT_CC instruction, we actually have to insert the |
3367 | // triangle control-flow pattern. The incoming instruction knows the |
3368 | // destination vreg to set, the condition code register to branch on, the |
3369 | // true/false values to select between, and the condition code for the branch. |
3370 | // |
3371 | // We produce the following control flow: |
3372 | // ThisMBB |
3373 | // | \ |
3374 | // | IfFalseMBB |
3375 | // | / |
3376 | // SinkMBB |
3377 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); |
3378 | MachineFunction::iterator It = ++BB->getIterator(); |
3379 | |
3380 | MachineBasicBlock *ThisMBB = BB; |
3381 | MachineFunction *F = BB->getParent(); |
3382 | MachineBasicBlock *IfFalseMBB = F->CreateMachineBasicBlock(BB: LLVM_BB); |
3383 | MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(BB: LLVM_BB); |
3384 | F->insert(MBBI: It, MBB: IfFalseMBB); |
3385 | F->insert(MBBI: It, MBB: SinkMBB); |
3386 | |
3387 | // Transfer the remainder of ThisMBB and its successor edges to SinkMBB. |
3388 | SinkMBB->splice(Where: SinkMBB->begin(), Other: ThisMBB, |
3389 | From: std::next(x: MachineBasicBlock::iterator(MI)), To: ThisMBB->end()); |
3390 | SinkMBB->transferSuccessorsAndUpdatePHIs(FromMBB: ThisMBB); |
3391 | |
3392 | // Set the new successors for ThisMBB. |
3393 | ThisMBB->addSuccessor(Succ: IfFalseMBB); |
3394 | ThisMBB->addSuccessor(Succ: SinkMBB); |
3395 | |
3396 | BuildMI(BB: ThisMBB, MIMD: dl, MCID: TII.get(Opcode: BROpcode)) |
3397 | .addMBB(MBB: SinkMBB) |
3398 | .addImm(Val: CC); |
3399 | |
3400 | // IfFalseMBB just falls through to SinkMBB. |
3401 | IfFalseMBB->addSuccessor(Succ: SinkMBB); |
3402 | |
3403 | // %Result = phi [ %TrueValue, ThisMBB ], [ %FalseValue, IfFalseMBB ] |
3404 | BuildMI(BB&: *SinkMBB, I: SinkMBB->begin(), MIMD: dl, MCID: TII.get(Opcode: SP::PHI), |
3405 | DestReg: MI.getOperand(i: 0).getReg()) |
3406 | .addReg(RegNo: MI.getOperand(i: 1).getReg()) |
3407 | .addMBB(MBB: ThisMBB) |
3408 | .addReg(RegNo: MI.getOperand(i: 2).getReg()) |
3409 | .addMBB(MBB: IfFalseMBB); |
3410 | |
3411 | MI.eraseFromParent(); // The pseudo instruction is gone now. |
3412 | return SinkMBB; |
3413 | } |
3414 | |
3415 | //===----------------------------------------------------------------------===// |
3416 | // Sparc Inline Assembly Support |
3417 | //===----------------------------------------------------------------------===// |
3418 | |
3419 | /// getConstraintType - Given a constraint letter, return the type of |
3420 | /// constraint it is for this target. |
3421 | SparcTargetLowering::ConstraintType |
3422 | SparcTargetLowering::getConstraintType(StringRef Constraint) const { |
3423 | if (Constraint.size() == 1) { |
3424 | switch (Constraint[0]) { |
3425 | default: break; |
3426 | case 'r': |
3427 | case 'f': |
3428 | case 'e': |
3429 | return C_RegisterClass; |
3430 | case 'I': // SIMM13 |
3431 | return C_Immediate; |
3432 | } |
3433 | } |
3434 | |
3435 | return TargetLowering::getConstraintType(Constraint); |
3436 | } |
3437 | |
3438 | TargetLowering::ConstraintWeight SparcTargetLowering:: |
3439 | getSingleConstraintMatchWeight(AsmOperandInfo &info, |
3440 | const char *constraint) const { |
3441 | ConstraintWeight weight = CW_Invalid; |
3442 | Value *CallOperandVal = info.CallOperandVal; |
3443 | // If we don't have a value, we can't do a match, |
3444 | // but allow it at the lowest weight. |
3445 | if (!CallOperandVal) |
3446 | return CW_Default; |
3447 | |
3448 | // Look at the constraint type. |
3449 | switch (*constraint) { |
3450 | default: |
3451 | weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); |
3452 | break; |
3453 | case 'I': // SIMM13 |
3454 | if (ConstantInt *C = dyn_cast<ConstantInt>(Val: info.CallOperandVal)) { |
3455 | if (isInt<13>(x: C->getSExtValue())) |
3456 | weight = CW_Constant; |
3457 | } |
3458 | break; |
3459 | } |
3460 | return weight; |
3461 | } |
3462 | |
3463 | /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops |
3464 | /// vector. If it is invalid, don't add anything to Ops. |
3465 | void SparcTargetLowering::LowerAsmOperandForConstraint( |
3466 | SDValue Op, StringRef Constraint, std::vector<SDValue> &Ops, |
3467 | SelectionDAG &DAG) const { |
3468 | SDValue Result; |
3469 | |
3470 | // Only support length 1 constraints for now. |
3471 | if (Constraint.size() > 1) |
3472 | return; |
3473 | |
3474 | char ConstraintLetter = Constraint[0]; |
3475 | switch (ConstraintLetter) { |
3476 | default: break; |
3477 | case 'I': |
3478 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val&: Op)) { |
3479 | if (isInt<13>(x: C->getSExtValue())) { |
3480 | Result = DAG.getTargetConstant(Val: C->getSExtValue(), DL: SDLoc(Op), |
3481 | VT: Op.getValueType()); |
3482 | break; |
3483 | } |
3484 | return; |
3485 | } |
3486 | } |
3487 | |
3488 | if (Result.getNode()) { |
3489 | Ops.push_back(x: Result); |
3490 | return; |
3491 | } |
3492 | TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); |
3493 | } |
3494 | |
3495 | std::pair<unsigned, const TargetRegisterClass *> |
3496 | SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, |
3497 | StringRef Constraint, |
3498 | MVT VT) const { |
3499 | if (Constraint.empty()) |
3500 | return std::make_pair(x: 0U, y: nullptr); |
3501 | |
3502 | if (Constraint.size() == 1) { |
3503 | switch (Constraint[0]) { |
3504 | case 'r': |
3505 | if (VT == MVT::v2i32) |
3506 | return std::make_pair(x: 0U, y: &SP::IntPairRegClass); |
3507 | else if (Subtarget->is64Bit()) |
3508 | return std::make_pair(x: 0U, y: &SP::I64RegsRegClass); |
3509 | else |
3510 | return std::make_pair(x: 0U, y: &SP::IntRegsRegClass); |
3511 | case 'f': |
3512 | if (VT == MVT::f32 || VT == MVT::i32) |
3513 | return std::make_pair(x: 0U, y: &SP::FPRegsRegClass); |
3514 | else if (VT == MVT::f64 || VT == MVT::i64) |
3515 | return std::make_pair(x: 0U, y: &SP::LowDFPRegsRegClass); |
3516 | else if (VT == MVT::f128) |
3517 | return std::make_pair(x: 0U, y: &SP::LowQFPRegsRegClass); |
3518 | // This will generate an error message |
3519 | return std::make_pair(x: 0U, y: nullptr); |
3520 | case 'e': |
3521 | if (VT == MVT::f32 || VT == MVT::i32) |
3522 | return std::make_pair(x: 0U, y: &SP::FPRegsRegClass); |
3523 | else if (VT == MVT::f64 || VT == MVT::i64 ) |
3524 | return std::make_pair(x: 0U, y: &SP::DFPRegsRegClass); |
3525 | else if (VT == MVT::f128) |
3526 | return std::make_pair(x: 0U, y: &SP::QFPRegsRegClass); |
3527 | // This will generate an error message |
3528 | return std::make_pair(x: 0U, y: nullptr); |
3529 | } |
3530 | } |
3531 | |
3532 | if (Constraint.front() != '{') |
3533 | return std::make_pair(x: 0U, y: nullptr); |
3534 | |
3535 | assert(Constraint.back() == '}' && "Not a brace enclosed constraint?" ); |
3536 | StringRef RegName(Constraint.data() + 1, Constraint.size() - 2); |
3537 | if (RegName.empty()) |
3538 | return std::make_pair(x: 0U, y: nullptr); |
3539 | |
3540 | unsigned long long RegNo; |
3541 | // Handle numbered register aliases. |
3542 | if (RegName[0] == 'r' && |
3543 | getAsUnsignedInteger(Str: RegName.begin() + 1, Radix: 10, Result&: RegNo)) { |
3544 | // r0-r7 -> g0-g7 |
3545 | // r8-r15 -> o0-o7 |
3546 | // r16-r23 -> l0-l7 |
3547 | // r24-r31 -> i0-i7 |
3548 | if (RegNo > 31) |
3549 | return std::make_pair(x: 0U, y: nullptr); |
3550 | const char RegTypes[] = {'g', 'o', 'l', 'i'}; |
3551 | char RegType = RegTypes[RegNo / 8]; |
3552 | char RegIndex = '0' + (RegNo % 8); |
3553 | char Tmp[] = {'{', RegType, RegIndex, '}', 0}; |
3554 | return getRegForInlineAsmConstraint(TRI, Constraint: Tmp, VT); |
3555 | } |
3556 | |
3557 | // Rewrite the fN constraint according to the value type if needed. |
3558 | if (VT != MVT::f32 && VT != MVT::Other && RegName[0] == 'f' && |
3559 | getAsUnsignedInteger(Str: RegName.begin() + 1, Radix: 10, Result&: RegNo)) { |
3560 | if (VT == MVT::f64 && (RegNo % 2 == 0)) { |
3561 | return getRegForInlineAsmConstraint( |
3562 | TRI, Constraint: StringRef("{d" + utostr(X: RegNo / 2) + "}" ), VT); |
3563 | } else if (VT == MVT::f128 && (RegNo % 4 == 0)) { |
3564 | return getRegForInlineAsmConstraint( |
3565 | TRI, Constraint: StringRef("{q" + utostr(X: RegNo / 4) + "}" ), VT); |
3566 | } else { |
3567 | return std::make_pair(x: 0U, y: nullptr); |
3568 | } |
3569 | } |
3570 | |
3571 | auto ResultPair = |
3572 | TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); |
3573 | if (!ResultPair.second) |
3574 | return std::make_pair(x: 0U, y: nullptr); |
3575 | |
3576 | // Force the use of I64Regs over IntRegs for 64-bit values. |
3577 | if (Subtarget->is64Bit() && VT == MVT::i64) { |
3578 | assert(ResultPair.second == &SP::IntRegsRegClass && |
3579 | "Unexpected register class" ); |
3580 | return std::make_pair(x&: ResultPair.first, y: &SP::I64RegsRegClass); |
3581 | } |
3582 | |
3583 | return ResultPair; |
3584 | } |
3585 | |
3586 | bool |
3587 | SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { |
3588 | // The Sparc target isn't yet aware of offsets. |
3589 | return false; |
3590 | } |
3591 | |
3592 | void SparcTargetLowering::ReplaceNodeResults(SDNode *N, |
3593 | SmallVectorImpl<SDValue>& Results, |
3594 | SelectionDAG &DAG) const { |
3595 | |
3596 | SDLoc dl(N); |
3597 | |
3598 | RTLIB::Libcall libCall = RTLIB::UNKNOWN_LIBCALL; |
3599 | |
3600 | switch (N->getOpcode()) { |
3601 | default: |
3602 | llvm_unreachable("Do not know how to custom type legalize this operation!" ); |
3603 | |
3604 | case ISD::FP_TO_SINT: |
3605 | case ISD::FP_TO_UINT: |
3606 | // Custom lower only if it involves f128 or i64. |
3607 | if (N->getOperand(Num: 0).getValueType() != MVT::f128 |
3608 | || N->getValueType(ResNo: 0) != MVT::i64) |
3609 | return; |
3610 | libCall = ((N->getOpcode() == ISD::FP_TO_SINT) |
3611 | ? RTLIB::FPTOSINT_F128_I64 |
3612 | : RTLIB::FPTOUINT_F128_I64); |
3613 | |
3614 | Results.push_back(Elt: LowerF128Op(Op: SDValue(N, 0), |
3615 | DAG, |
3616 | LibFuncName: getLibcallName(Call: libCall), |
3617 | numArgs: 1)); |
3618 | return; |
3619 | case ISD::READCYCLECOUNTER: { |
3620 | assert(Subtarget->hasLeonCycleCounter()); |
3621 | SDValue Lo = DAG.getCopyFromReg(Chain: N->getOperand(Num: 0), dl, Reg: SP::ASR23, VT: MVT::i32); |
3622 | SDValue Hi = DAG.getCopyFromReg(Chain: Lo, dl, Reg: SP::G0, VT: MVT::i32); |
3623 | SDValue Ops[] = { Lo, Hi }; |
3624 | SDValue Pair = DAG.getNode(Opcode: ISD::BUILD_PAIR, DL: dl, VT: MVT::i64, Ops); |
3625 | Results.push_back(Elt: Pair); |
3626 | Results.push_back(Elt: N->getOperand(Num: 0)); |
3627 | return; |
3628 | } |
3629 | case ISD::SINT_TO_FP: |
3630 | case ISD::UINT_TO_FP: |
3631 | // Custom lower only if it involves f128 or i64. |
3632 | if (N->getValueType(ResNo: 0) != MVT::f128 |
3633 | || N->getOperand(Num: 0).getValueType() != MVT::i64) |
3634 | return; |
3635 | |
3636 | libCall = ((N->getOpcode() == ISD::SINT_TO_FP) |
3637 | ? RTLIB::SINTTOFP_I64_F128 |
3638 | : RTLIB::UINTTOFP_I64_F128); |
3639 | |
3640 | Results.push_back(Elt: LowerF128Op(Op: SDValue(N, 0), |
3641 | DAG, |
3642 | LibFuncName: getLibcallName(Call: libCall), |
3643 | numArgs: 1)); |
3644 | return; |
3645 | case ISD::LOAD: { |
3646 | LoadSDNode *Ld = cast<LoadSDNode>(Val: N); |
3647 | // Custom handling only for i64: turn i64 load into a v2i32 load, |
3648 | // and a bitcast. |
3649 | if (Ld->getValueType(ResNo: 0) != MVT::i64 || Ld->getMemoryVT() != MVT::i64) |
3650 | return; |
3651 | |
3652 | SDLoc dl(N); |
3653 | SDValue LoadRes = DAG.getExtLoad( |
3654 | ExtType: Ld->getExtensionType(), dl, VT: MVT::v2i32, Chain: Ld->getChain(), |
3655 | Ptr: Ld->getBasePtr(), PtrInfo: Ld->getPointerInfo(), MemVT: MVT::v2i32, |
3656 | Alignment: Ld->getOriginalAlign(), MMOFlags: Ld->getMemOperand()->getFlags(), |
3657 | AAInfo: Ld->getAAInfo()); |
3658 | |
3659 | SDValue Res = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: MVT::i64, Operand: LoadRes); |
3660 | Results.push_back(Elt: Res); |
3661 | Results.push_back(Elt: LoadRes.getValue(R: 1)); |
3662 | return; |
3663 | } |
3664 | } |
3665 | } |
3666 | |
3667 | // Override to enable LOAD_STACK_GUARD lowering on Linux. |
3668 | bool SparcTargetLowering::useLoadStackGuardNode() const { |
3669 | if (!Subtarget->isTargetLinux()) |
3670 | return TargetLowering::useLoadStackGuardNode(); |
3671 | return true; |
3672 | } |
3673 | |
3674 | // Override to disable global variable loading on Linux. |
3675 | void SparcTargetLowering::insertSSPDeclarations(Module &M) const { |
3676 | if (!Subtarget->isTargetLinux()) |
3677 | return TargetLowering::insertSSPDeclarations(M); |
3678 | } |
3679 | |
3680 | void SparcTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, |
3681 | SDNode *Node) const { |
3682 | assert(MI.getOpcode() == SP::SUBCCrr || MI.getOpcode() == SP::SUBCCri); |
3683 | // If the result is dead, replace it with %g0. |
3684 | if (!Node->hasAnyUseOfValue(Value: 0)) |
3685 | MI.getOperand(i: 0).setReg(SP::G0); |
3686 | } |
3687 | |