1 | //===-- M68kISelLowering.cpp - M68k DAG Lowering Impl -----------*- C++ -*-===// |
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 | /// \file |
10 | /// This file defines the interfaces that M68k uses to lower LLVM code into a |
11 | /// selection DAG. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "M68kISelLowering.h" |
16 | #include "M68kCallingConv.h" |
17 | #include "M68kMachineFunction.h" |
18 | #include "M68kSubtarget.h" |
19 | #include "M68kTargetMachine.h" |
20 | #include "M68kTargetObjectFile.h" |
21 | |
22 | #include "llvm/ADT/Statistic.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/MachineJumpTableInfo.h" |
28 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
29 | #include "llvm/CodeGen/SelectionDAG.h" |
30 | #include "llvm/CodeGen/ValueTypes.h" |
31 | #include "llvm/IR/CallingConv.h" |
32 | #include "llvm/IR/DerivedTypes.h" |
33 | #include "llvm/IR/GlobalVariable.h" |
34 | #include "llvm/Support/CommandLine.h" |
35 | #include "llvm/Support/Debug.h" |
36 | #include "llvm/Support/ErrorHandling.h" |
37 | #include "llvm/Support/KnownBits.h" |
38 | #include "llvm/Support/raw_ostream.h" |
39 | |
40 | using namespace llvm; |
41 | |
42 | #define DEBUG_TYPE "M68k-isel" |
43 | |
44 | STATISTIC(NumTailCalls, "Number of tail calls" ); |
45 | |
46 | M68kTargetLowering::M68kTargetLowering(const M68kTargetMachine &TM, |
47 | const M68kSubtarget &STI) |
48 | : TargetLowering(TM), Subtarget(STI), TM(TM) { |
49 | |
50 | MVT PtrVT = MVT::i32; |
51 | |
52 | setBooleanContents(ZeroOrOneBooleanContent); |
53 | |
54 | auto *RegInfo = Subtarget.getRegisterInfo(); |
55 | setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister()); |
56 | |
57 | // Set up the register classes. |
58 | addRegisterClass(MVT::VT: i8, RC: &M68k::DR8RegClass); |
59 | addRegisterClass(MVT::VT: i16, RC: &M68k::XR16RegClass); |
60 | addRegisterClass(MVT::VT: i32, RC: &M68k::XR32RegClass); |
61 | |
62 | for (auto VT : MVT::integer_valuetypes()) { |
63 | setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); |
64 | setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); |
65 | setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); |
66 | } |
67 | |
68 | // We don't accept any truncstore of integer registers. |
69 | setTruncStoreAction(MVT::ValVT: i64, MVT::MemVT: i32, Action: Expand); |
70 | setTruncStoreAction(MVT::ValVT: i64, MVT::MemVT: i16, Action: Expand); |
71 | setTruncStoreAction(MVT::ValVT: i64, MVT::MemVT: i8, Action: Expand); |
72 | setTruncStoreAction(MVT::ValVT: i32, MVT::MemVT: i16, Action: Expand); |
73 | setTruncStoreAction(MVT::ValVT: i32, MVT::MemVT: i8, Action: Expand); |
74 | setTruncStoreAction(MVT::ValVT: i16, MVT::MemVT: i8, Action: Expand); |
75 | |
76 | setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i8, Promote); |
77 | setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i16, Legal); |
78 | if (Subtarget.atLeastM68020()) |
79 | setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i32, Legal); |
80 | else |
81 | setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i32, LibCall); |
82 | setOperationAction(ISD::MUL, MVT::i64, LibCall); |
83 | |
84 | for (auto OP : |
85 | {ISD::SREM, ISD::UREM, ISD::UDIVREM, ISD::SDIVREM, |
86 | ISD::MULHS, ISD::MULHU, ISD::UMUL_LOHI, ISD::SMUL_LOHI}) { |
87 | setOperationAction(OP, MVT::i8, Promote); |
88 | setOperationAction(OP, MVT::i16, Legal); |
89 | setOperationAction(OP, MVT::i32, LibCall); |
90 | } |
91 | |
92 | for (auto OP : {ISD::UMUL_LOHI, ISD::SMUL_LOHI}) { |
93 | setOperationAction(OP, MVT::i8, Expand); |
94 | setOperationAction(OP, MVT::i16, Expand); |
95 | } |
96 | |
97 | for (auto OP : {ISD::SMULO, ISD::UMULO}) { |
98 | setOperationAction(OP, MVT::i8, Custom); |
99 | setOperationAction(OP, MVT::i16, Custom); |
100 | setOperationAction(OP, MVT::i32, Custom); |
101 | } |
102 | |
103 | for (auto OP : {ISD::SHL_PARTS, ISD::SRA_PARTS, ISD::SRL_PARTS}) |
104 | setOperationAction(OP, MVT::i32, Custom); |
105 | |
106 | // Add/Sub overflow ops with MVT::Glues are lowered to CCR dependences. |
107 | for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) { |
108 | setOperationAction(ISD::ADDC, VT, Custom); |
109 | setOperationAction(ISD::ADDE, VT, Custom); |
110 | setOperationAction(ISD::SUBC, VT, Custom); |
111 | setOperationAction(ISD::SUBE, VT, Custom); |
112 | } |
113 | |
114 | // SADDO and friends are legal with this setup, i hope |
115 | for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) { |
116 | setOperationAction(ISD::SADDO, VT, Custom); |
117 | setOperationAction(ISD::UADDO, VT, Custom); |
118 | setOperationAction(ISD::SSUBO, VT, Custom); |
119 | setOperationAction(ISD::USUBO, VT, Custom); |
120 | } |
121 | |
122 | setOperationAction(ISD::BR_JT, MVT::Other, Expand); |
123 | setOperationAction(ISD::BRCOND, MVT::Other, Custom); |
124 | |
125 | for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) { |
126 | setOperationAction(ISD::BR_CC, VT, Expand); |
127 | setOperationAction(ISD::SELECT, VT, Custom); |
128 | setOperationAction(ISD::SELECT_CC, VT, Expand); |
129 | setOperationAction(ISD::SETCC, VT, Custom); |
130 | setOperationAction(ISD::SETCCCARRY, VT, Custom); |
131 | } |
132 | |
133 | for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) { |
134 | setOperationAction(ISD::BSWAP, VT, Expand); |
135 | setOperationAction(ISD::CTTZ, VT, Expand); |
136 | setOperationAction(ISD::CTLZ, VT, Expand); |
137 | setOperationAction(ISD::CTPOP, VT, Expand); |
138 | } |
139 | |
140 | setOperationAction(ISD::ConstantPool, MVT::i32, Custom); |
141 | setOperationAction(ISD::JumpTable, MVT::i32, Custom); |
142 | setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); |
143 | setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); |
144 | setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom); |
145 | setOperationAction(ISD::BlockAddress, MVT::i32, Custom); |
146 | |
147 | setOperationAction(ISD::VASTART, MVT::Other, Custom); |
148 | setOperationAction(ISD::VAEND, MVT::Other, Expand); |
149 | setOperationAction(ISD::VAARG, MVT::Other, Expand); |
150 | setOperationAction(ISD::VACOPY, MVT::Other, Expand); |
151 | |
152 | setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); |
153 | setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); |
154 | |
155 | setOperationAction(Op: ISD::DYNAMIC_STACKALLOC, VT: PtrVT, Action: Custom); |
156 | |
157 | computeRegisterProperties(STI.getRegisterInfo()); |
158 | |
159 | // We lower the `atomic-compare-and-swap` to `__sync_val_compare_and_swap` |
160 | // for subtarget < M68020 |
161 | setMaxAtomicSizeInBitsSupported(32); |
162 | setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i8, MVT::i16, MVT::i32}, |
163 | Subtarget.atLeastM68020() ? Legal : LibCall); |
164 | |
165 | setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); |
166 | |
167 | // M68k does not have native read-modify-write support, so expand all of them |
168 | // to `__sync_fetch_*` for target < M68020, otherwise expand to CmpxChg. |
169 | // See `shouldExpandAtomicRMWInIR` below. |
170 | setOperationAction( |
171 | { |
172 | ISD::ATOMIC_LOAD_ADD, |
173 | ISD::ATOMIC_LOAD_SUB, |
174 | ISD::ATOMIC_LOAD_AND, |
175 | ISD::ATOMIC_LOAD_OR, |
176 | ISD::ATOMIC_LOAD_XOR, |
177 | ISD::ATOMIC_LOAD_NAND, |
178 | ISD::ATOMIC_LOAD_MIN, |
179 | ISD::ATOMIC_LOAD_MAX, |
180 | ISD::ATOMIC_LOAD_UMIN, |
181 | ISD::ATOMIC_LOAD_UMAX, |
182 | ISD::ATOMIC_SWAP, |
183 | }, |
184 | {MVT::i8, MVT::i16, MVT::i32}, LibCall); |
185 | |
186 | setMinFunctionAlignment(Align(2)); |
187 | } |
188 | |
189 | TargetLoweringBase::AtomicExpansionKind |
190 | M68kTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { |
191 | return Subtarget.atLeastM68020() |
192 | ? TargetLoweringBase::AtomicExpansionKind::CmpXChg |
193 | : TargetLoweringBase::AtomicExpansionKind::None; |
194 | } |
195 | |
196 | Register |
197 | M68kTargetLowering::getExceptionPointerRegister(const Constant *) const { |
198 | return M68k::D0; |
199 | } |
200 | |
201 | Register |
202 | M68kTargetLowering::getExceptionSelectorRegister(const Constant *) const { |
203 | return M68k::D1; |
204 | } |
205 | |
206 | InlineAsm::ConstraintCode |
207 | M68kTargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const { |
208 | return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode) |
209 | .Case(S: "Q" , Value: InlineAsm::ConstraintCode::Q) |
210 | // We borrow ConstraintCode::Um for 'U'. |
211 | .Case(S: "U" , Value: InlineAsm::ConstraintCode::Um) |
212 | .Default(Value: TargetLowering::getInlineAsmMemConstraint(ConstraintCode)); |
213 | } |
214 | |
215 | EVT M68kTargetLowering::getSetCCResultType(const DataLayout &DL, |
216 | LLVMContext &Context, EVT VT) const { |
217 | // M68k SETcc producess either 0x00 or 0xFF |
218 | return MVT::i8; |
219 | } |
220 | |
221 | MVT M68kTargetLowering::getScalarShiftAmountTy(const DataLayout &DL, |
222 | EVT Ty) const { |
223 | if (Ty.isSimple()) { |
224 | return Ty.getSimpleVT(); |
225 | } |
226 | return MVT::getIntegerVT(BitWidth: DL.getPointerSizeInBits(AS: 0)); |
227 | } |
228 | |
229 | #include "M68kGenCallingConv.inc" |
230 | |
231 | enum StructReturnType { NotStructReturn, RegStructReturn, StackStructReturn }; |
232 | |
233 | static StructReturnType |
234 | callIsStructReturn(const SmallVectorImpl<ISD::OutputArg> &Outs) { |
235 | if (Outs.empty()) |
236 | return NotStructReturn; |
237 | |
238 | const ISD::ArgFlagsTy &Flags = Outs[0].Flags; |
239 | if (!Flags.isSRet()) |
240 | return NotStructReturn; |
241 | if (Flags.isInReg()) |
242 | return RegStructReturn; |
243 | return StackStructReturn; |
244 | } |
245 | |
246 | /// Determines whether a function uses struct return semantics. |
247 | static StructReturnType |
248 | argsAreStructReturn(const SmallVectorImpl<ISD::InputArg> &Ins) { |
249 | if (Ins.empty()) |
250 | return NotStructReturn; |
251 | |
252 | const ISD::ArgFlagsTy &Flags = Ins[0].Flags; |
253 | if (!Flags.isSRet()) |
254 | return NotStructReturn; |
255 | if (Flags.isInReg()) |
256 | return RegStructReturn; |
257 | return StackStructReturn; |
258 | } |
259 | |
260 | /// Make a copy of an aggregate at address specified by "Src" to address |
261 | /// "Dst" with size and alignment information specified by the specific |
262 | /// parameter attribute. The copy will be passed as a byval function parameter. |
263 | static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, |
264 | SDValue Chain, ISD::ArgFlagsTy Flags, |
265 | SelectionDAG &DAG, const SDLoc &DL) { |
266 | SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), DL, MVT::i32); |
267 | |
268 | return DAG.getMemcpy( |
269 | Chain, dl: DL, Dst, Src, Size: SizeNode, Alignment: Flags.getNonZeroByValAlign(), |
270 | /*isVolatile=*/isVol: false, /*AlwaysInline=*/true, |
271 | /*isTailCall=*/false, DstPtrInfo: MachinePointerInfo(), SrcPtrInfo: MachinePointerInfo()); |
272 | } |
273 | |
274 | /// Return true if the calling convention is one that we can guarantee TCO for. |
275 | static bool canGuaranteeTCO(CallingConv::ID CC) { return false; } |
276 | |
277 | /// Return true if we might ever do TCO for calls with this calling convention. |
278 | static bool mayTailCallThisCC(CallingConv::ID CC) { |
279 | switch (CC) { |
280 | // C calling conventions: |
281 | case CallingConv::C: |
282 | return true; |
283 | default: |
284 | return canGuaranteeTCO(CC); |
285 | } |
286 | } |
287 | |
288 | /// Return true if the function is being made into a tailcall target by |
289 | /// changing its ABI. |
290 | static bool shouldGuaranteeTCO(CallingConv::ID CC, bool GuaranteedTailCallOpt) { |
291 | return GuaranteedTailCallOpt && canGuaranteeTCO(CC); |
292 | } |
293 | |
294 | /// Return true if the given stack call argument is already available in the |
295 | /// same position (relatively) of the caller's incoming argument stack. |
296 | static bool MatchingStackOffset(SDValue Arg, unsigned Offset, |
297 | ISD::ArgFlagsTy Flags, MachineFrameInfo &MFI, |
298 | const MachineRegisterInfo *MRI, |
299 | const M68kInstrInfo *TII, |
300 | const CCValAssign &VA) { |
301 | unsigned Bytes = Arg.getValueType().getSizeInBits() / 8; |
302 | |
303 | for (;;) { |
304 | // Look through nodes that don't alter the bits of the incoming value. |
305 | unsigned Op = Arg.getOpcode(); |
306 | if (Op == ISD::ZERO_EXTEND || Op == ISD::ANY_EXTEND || Op == ISD::BITCAST) { |
307 | Arg = Arg.getOperand(i: 0); |
308 | continue; |
309 | } |
310 | if (Op == ISD::TRUNCATE) { |
311 | const SDValue &TruncInput = Arg.getOperand(i: 0); |
312 | if (TruncInput.getOpcode() == ISD::AssertZext && |
313 | cast<VTSDNode>(Val: TruncInput.getOperand(i: 1))->getVT() == |
314 | Arg.getValueType()) { |
315 | Arg = TruncInput.getOperand(i: 0); |
316 | continue; |
317 | } |
318 | } |
319 | break; |
320 | } |
321 | |
322 | int FI = INT_MAX; |
323 | if (Arg.getOpcode() == ISD::CopyFromReg) { |
324 | Register VR = cast<RegisterSDNode>(Val: Arg.getOperand(i: 1))->getReg(); |
325 | if (!Register::isVirtualRegister(Reg: VR)) |
326 | return false; |
327 | MachineInstr *Def = MRI->getVRegDef(Reg: VR); |
328 | if (!Def) |
329 | return false; |
330 | if (!Flags.isByVal()) { |
331 | if (!TII->isLoadFromStackSlot(*Def, FI)) |
332 | return false; |
333 | } else { |
334 | unsigned Opcode = Def->getOpcode(); |
335 | if ((Opcode == M68k::LEA32p || Opcode == M68k::LEA32f) && |
336 | Def->getOperand(1).isFI()) { |
337 | FI = Def->getOperand(i: 1).getIndex(); |
338 | Bytes = Flags.getByValSize(); |
339 | } else |
340 | return false; |
341 | } |
342 | } else if (auto *Ld = dyn_cast<LoadSDNode>(Val&: Arg)) { |
343 | if (Flags.isByVal()) |
344 | // ByVal argument is passed in as a pointer but it's now being |
345 | // dereferenced. e.g. |
346 | // define @foo(%struct.X* %A) { |
347 | // tail call @bar(%struct.X* byval %A) |
348 | // } |
349 | return false; |
350 | SDValue Ptr = Ld->getBasePtr(); |
351 | FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(Val&: Ptr); |
352 | if (!FINode) |
353 | return false; |
354 | FI = FINode->getIndex(); |
355 | } else if (Arg.getOpcode() == ISD::FrameIndex && Flags.isByVal()) { |
356 | FrameIndexSDNode *FINode = cast<FrameIndexSDNode>(Val&: Arg); |
357 | FI = FINode->getIndex(); |
358 | Bytes = Flags.getByValSize(); |
359 | } else |
360 | return false; |
361 | |
362 | assert(FI != INT_MAX); |
363 | if (!MFI.isFixedObjectIndex(ObjectIdx: FI)) |
364 | return false; |
365 | |
366 | if (Offset != MFI.getObjectOffset(ObjectIdx: FI)) |
367 | return false; |
368 | |
369 | if (VA.getLocVT().getSizeInBits() > Arg.getValueType().getSizeInBits()) { |
370 | // If the argument location is wider than the argument type, check that any |
371 | // extension flags match. |
372 | if (Flags.isZExt() != MFI.isObjectZExt(ObjectIdx: FI) || |
373 | Flags.isSExt() != MFI.isObjectSExt(ObjectIdx: FI)) { |
374 | return false; |
375 | } |
376 | } |
377 | |
378 | return Bytes == MFI.getObjectSize(ObjectIdx: FI); |
379 | } |
380 | |
381 | SDValue |
382 | M68kTargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const { |
383 | MachineFunction &MF = DAG.getMachineFunction(); |
384 | M68kMachineFunctionInfo *FuncInfo = MF.getInfo<M68kMachineFunctionInfo>(); |
385 | int ReturnAddrIndex = FuncInfo->getRAIndex(); |
386 | |
387 | if (ReturnAddrIndex == 0) { |
388 | // Set up a frame object for the return address. |
389 | unsigned SlotSize = Subtarget.getSlotSize(); |
390 | ReturnAddrIndex = MF.getFrameInfo().CreateFixedObject( |
391 | Size: SlotSize, SPOffset: -(int64_t)SlotSize, IsImmutable: false); |
392 | FuncInfo->setRAIndex(ReturnAddrIndex); |
393 | } |
394 | |
395 | return DAG.getFrameIndex(FI: ReturnAddrIndex, VT: getPointerTy(DL: DAG.getDataLayout())); |
396 | } |
397 | |
398 | SDValue M68kTargetLowering::EmitTailCallLoadRetAddr(SelectionDAG &DAG, |
399 | SDValue &OutRetAddr, |
400 | SDValue Chain, |
401 | bool IsTailCall, int FPDiff, |
402 | const SDLoc &DL) const { |
403 | EVT VT = getPointerTy(DL: DAG.getDataLayout()); |
404 | OutRetAddr = getReturnAddressFrameIndex(DAG); |
405 | |
406 | // Load the "old" Return address. |
407 | OutRetAddr = DAG.getLoad(VT, dl: DL, Chain, Ptr: OutRetAddr, PtrInfo: MachinePointerInfo()); |
408 | return SDValue(OutRetAddr.getNode(), 1); |
409 | } |
410 | |
411 | SDValue M68kTargetLowering::EmitTailCallStoreRetAddr( |
412 | SelectionDAG &DAG, MachineFunction &MF, SDValue Chain, SDValue RetFI, |
413 | EVT PtrVT, unsigned SlotSize, int FPDiff, const SDLoc &DL) const { |
414 | if (!FPDiff) |
415 | return Chain; |
416 | |
417 | // Calculate the new stack slot for the return address. |
418 | int NewFO = MF.getFrameInfo().CreateFixedObject( |
419 | Size: SlotSize, SPOffset: (int64_t)FPDiff - SlotSize, IsImmutable: false); |
420 | |
421 | SDValue NewFI = DAG.getFrameIndex(FI: NewFO, VT: PtrVT); |
422 | // Store the return address to the appropriate stack slot. |
423 | Chain = DAG.getStore( |
424 | Chain, dl: DL, Val: RetFI, Ptr: NewFI, |
425 | PtrInfo: MachinePointerInfo::getFixedStack(MF&: DAG.getMachineFunction(), FI: NewFO)); |
426 | return Chain; |
427 | } |
428 | |
429 | SDValue |
430 | M68kTargetLowering::LowerMemArgument(SDValue Chain, CallingConv::ID CallConv, |
431 | const SmallVectorImpl<ISD::InputArg> &Ins, |
432 | const SDLoc &DL, SelectionDAG &DAG, |
433 | const CCValAssign &VA, |
434 | MachineFrameInfo &MFI, |
435 | unsigned ArgIdx) const { |
436 | // Create the nodes corresponding to a load from this parameter slot. |
437 | ISD::ArgFlagsTy Flags = Ins[ArgIdx].Flags; |
438 | EVT ValVT; |
439 | |
440 | // If value is passed by pointer we have address passed instead of the value |
441 | // itself. |
442 | if (VA.getLocInfo() == CCValAssign::Indirect) |
443 | ValVT = VA.getLocVT(); |
444 | else |
445 | ValVT = VA.getValVT(); |
446 | |
447 | // Because we are dealing with BE architecture we need to offset loading of |
448 | // partial types |
449 | int Offset = VA.getLocMemOffset(); |
450 | if (VA.getValVT() == MVT::i8) { |
451 | Offset += 3; |
452 | } else if (VA.getValVT() == MVT::i16) { |
453 | Offset += 2; |
454 | } |
455 | |
456 | // TODO Interrupt handlers |
457 | // Calculate SP offset of interrupt parameter, re-arrange the slot normally |
458 | // taken by a return address. |
459 | |
460 | // FIXME For now, all byval parameter objects are marked mutable. This can |
461 | // be changed with more analysis. In case of tail call optimization mark all |
462 | // arguments mutable. Since they could be overwritten by lowering of arguments |
463 | // in case of a tail call. |
464 | bool AlwaysUseMutable = shouldGuaranteeTCO( |
465 | CC: CallConv, GuaranteedTailCallOpt: DAG.getTarget().Options.GuaranteedTailCallOpt); |
466 | bool IsImmutable = !AlwaysUseMutable && !Flags.isByVal(); |
467 | |
468 | if (Flags.isByVal()) { |
469 | unsigned Bytes = Flags.getByValSize(); |
470 | if (Bytes == 0) |
471 | Bytes = 1; // Don't create zero-sized stack objects. |
472 | int FI = MFI.CreateFixedObject(Size: Bytes, SPOffset: Offset, IsImmutable); |
473 | // TODO Interrupt handlers |
474 | // Adjust SP offset of interrupt parameter. |
475 | return DAG.getFrameIndex(FI, VT: getPointerTy(DL: DAG.getDataLayout())); |
476 | } else { |
477 | int FI = |
478 | MFI.CreateFixedObject(Size: ValVT.getSizeInBits() / 8, SPOffset: Offset, IsImmutable); |
479 | |
480 | // Set SExt or ZExt flag. |
481 | if (VA.getLocInfo() == CCValAssign::ZExt) { |
482 | MFI.setObjectZExt(ObjectIdx: FI, IsZExt: true); |
483 | } else if (VA.getLocInfo() == CCValAssign::SExt) { |
484 | MFI.setObjectSExt(ObjectIdx: FI, IsSExt: true); |
485 | } |
486 | |
487 | // TODO Interrupt handlers |
488 | // Adjust SP offset of interrupt parameter. |
489 | |
490 | SDValue FIN = DAG.getFrameIndex(FI, VT: getPointerTy(DL: DAG.getDataLayout())); |
491 | SDValue Val = DAG.getLoad( |
492 | VT: ValVT, dl: DL, Chain, Ptr: FIN, |
493 | PtrInfo: MachinePointerInfo::getFixedStack(MF&: DAG.getMachineFunction(), FI)); |
494 | return VA.isExtInLoc() ? DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT: VA.getValVT(), Operand: Val) |
495 | : Val; |
496 | } |
497 | } |
498 | |
499 | SDValue M68kTargetLowering::LowerMemOpCallTo(SDValue Chain, SDValue StackPtr, |
500 | SDValue Arg, const SDLoc &DL, |
501 | SelectionDAG &DAG, |
502 | const CCValAssign &VA, |
503 | ISD::ArgFlagsTy Flags) const { |
504 | unsigned LocMemOffset = VA.getLocMemOffset(); |
505 | SDValue PtrOff = DAG.getIntPtrConstant(Val: LocMemOffset, DL); |
506 | PtrOff = DAG.getNode(Opcode: ISD::ADD, DL, VT: getPointerTy(DL: DAG.getDataLayout()), |
507 | N1: StackPtr, N2: PtrOff); |
508 | if (Flags.isByVal()) |
509 | return CreateCopyOfByValArgument(Src: Arg, Dst: PtrOff, Chain, Flags, DAG, DL); |
510 | |
511 | return DAG.getStore( |
512 | Chain, dl: DL, Val: Arg, Ptr: PtrOff, |
513 | PtrInfo: MachinePointerInfo::getStack(MF&: DAG.getMachineFunction(), Offset: LocMemOffset)); |
514 | } |
515 | |
516 | //===----------------------------------------------------------------------===// |
517 | // Call |
518 | //===----------------------------------------------------------------------===// |
519 | |
520 | SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, |
521 | SmallVectorImpl<SDValue> &InVals) const { |
522 | SelectionDAG &DAG = CLI.DAG; |
523 | SDLoc &DL = CLI.DL; |
524 | SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; |
525 | SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; |
526 | SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; |
527 | SDValue Chain = CLI.Chain; |
528 | SDValue Callee = CLI.Callee; |
529 | CallingConv::ID CallConv = CLI.CallConv; |
530 | bool &IsTailCall = CLI.IsTailCall; |
531 | bool IsVarArg = CLI.IsVarArg; |
532 | |
533 | MachineFunction &MF = DAG.getMachineFunction(); |
534 | StructReturnType SR = callIsStructReturn(Outs); |
535 | bool IsSibcall = false; |
536 | M68kMachineFunctionInfo *MFI = MF.getInfo<M68kMachineFunctionInfo>(); |
537 | // const M68kRegisterInfo *TRI = Subtarget.getRegisterInfo(); |
538 | |
539 | if (CallConv == CallingConv::M68k_INTR) |
540 | report_fatal_error(reason: "M68k interrupts may not be called directly" ); |
541 | |
542 | auto Attr = MF.getFunction().getFnAttribute(Kind: "disable-tail-calls" ); |
543 | if (Attr.getValueAsBool()) |
544 | IsTailCall = false; |
545 | |
546 | // FIXME Add tailcalls support |
547 | |
548 | bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall(); |
549 | if (IsMustTail) { |
550 | // Force this to be a tail call. The verifier rules are enough to ensure |
551 | // that we can lower this successfully without moving the return address |
552 | // around. |
553 | IsTailCall = true; |
554 | } else if (IsTailCall) { |
555 | // Check if it's really possible to do a tail call. |
556 | IsTailCall = IsEligibleForTailCallOptimization( |
557 | Callee, CalleeCC: CallConv, IsVarArg, IsCalleeStructRet: SR != NotStructReturn, |
558 | IsCallerStructRet: MF.getFunction().hasStructRetAttr(), RetTy: CLI.RetTy, Outs, OutVals, Ins, |
559 | DAG); |
560 | |
561 | // Sibcalls are automatically detected tailcalls which do not require |
562 | // ABI changes. |
563 | if (!MF.getTarget().Options.GuaranteedTailCallOpt && IsTailCall) |
564 | IsSibcall = true; |
565 | |
566 | if (IsTailCall) |
567 | ++NumTailCalls; |
568 | } |
569 | |
570 | assert(!(IsVarArg && canGuaranteeTCO(CallConv)) && |
571 | "Var args not supported with calling convention fastcc" ); |
572 | |
573 | // Analyze operands of the call, assigning locations to each operand. |
574 | SmallVector<CCValAssign, 16> ArgLocs; |
575 | SmallVector<Type *, 4> ArgTypes; |
576 | for (const auto &Arg : CLI.getArgs()) |
577 | ArgTypes.emplace_back(Args: Arg.Ty); |
578 | M68kCCState CCInfo(ArgTypes, CallConv, IsVarArg, MF, ArgLocs, |
579 | *DAG.getContext()); |
580 | CCInfo.AnalyzeCallOperands(Outs, CC_M68k); |
581 | |
582 | // Get a count of how many bytes are to be pushed on the stack. |
583 | unsigned NumBytes = CCInfo.getAlignedCallFrameSize(); |
584 | if (IsSibcall) { |
585 | // This is a sibcall. The memory operands are available in caller's |
586 | // own caller's stack. |
587 | NumBytes = 0; |
588 | } else if (MF.getTarget().Options.GuaranteedTailCallOpt && |
589 | canGuaranteeTCO(CC: CallConv)) { |
590 | NumBytes = GetAlignedArgumentStackSize(StackSize: NumBytes, DAG); |
591 | } |
592 | |
593 | int FPDiff = 0; |
594 | if (IsTailCall && !IsSibcall && !IsMustTail) { |
595 | // Lower arguments at fp - stackoffset + fpdiff. |
596 | unsigned NumBytesCallerPushed = MFI->getBytesToPopOnReturn(); |
597 | |
598 | FPDiff = NumBytesCallerPushed - NumBytes; |
599 | |
600 | // Set the delta of movement of the returnaddr stackslot. |
601 | // But only set if delta is greater than previous delta. |
602 | if (FPDiff < MFI->getTCReturnAddrDelta()) |
603 | MFI->setTCReturnAddrDelta(FPDiff); |
604 | } |
605 | |
606 | unsigned NumBytesToPush = NumBytes; |
607 | unsigned NumBytesToPop = NumBytes; |
608 | |
609 | // If we have an inalloca argument, all stack space has already been allocated |
610 | // for us and be right at the top of the stack. We don't support multiple |
611 | // arguments passed in memory when using inalloca. |
612 | if (!Outs.empty() && Outs.back().Flags.isInAlloca()) { |
613 | NumBytesToPush = 0; |
614 | if (!ArgLocs.back().isMemLoc()) |
615 | report_fatal_error(reason: "cannot use inalloca attribute on a register " |
616 | "parameter" ); |
617 | if (ArgLocs.back().getLocMemOffset() != 0) |
618 | report_fatal_error(reason: "any parameter with the inalloca attribute must be " |
619 | "the only memory argument" ); |
620 | } |
621 | |
622 | if (!IsSibcall) |
623 | Chain = DAG.getCALLSEQ_START(Chain, InSize: NumBytesToPush, |
624 | OutSize: NumBytes - NumBytesToPush, DL); |
625 | |
626 | SDValue RetFI; |
627 | // Load return address for tail calls. |
628 | if (IsTailCall && FPDiff) |
629 | Chain = EmitTailCallLoadRetAddr(DAG, OutRetAddr&: RetFI, Chain, IsTailCall, FPDiff, DL); |
630 | |
631 | SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; |
632 | SmallVector<SDValue, 8> MemOpChains; |
633 | SDValue StackPtr; |
634 | |
635 | // Walk the register/memloc assignments, inserting copies/loads. In the case |
636 | // of tail call optimization arguments are handle later. |
637 | const M68kRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); |
638 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { |
639 | ISD::ArgFlagsTy Flags = Outs[i].Flags; |
640 | |
641 | // Skip inalloca arguments, they have already been written. |
642 | if (Flags.isInAlloca()) |
643 | continue; |
644 | |
645 | CCValAssign &VA = ArgLocs[i]; |
646 | EVT RegVT = VA.getLocVT(); |
647 | SDValue Arg = OutVals[i]; |
648 | bool IsByVal = Flags.isByVal(); |
649 | |
650 | // Promote the value if needed. |
651 | switch (VA.getLocInfo()) { |
652 | default: |
653 | llvm_unreachable("Unknown loc info!" ); |
654 | case CCValAssign::Full: |
655 | break; |
656 | case CCValAssign::SExt: |
657 | Arg = DAG.getNode(Opcode: ISD::SIGN_EXTEND, DL, VT: RegVT, Operand: Arg); |
658 | break; |
659 | case CCValAssign::ZExt: |
660 | Arg = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL, VT: RegVT, Operand: Arg); |
661 | break; |
662 | case CCValAssign::AExt: |
663 | Arg = DAG.getNode(Opcode: ISD::ANY_EXTEND, DL, VT: RegVT, Operand: Arg); |
664 | break; |
665 | case CCValAssign::BCvt: |
666 | Arg = DAG.getBitcast(VT: RegVT, V: Arg); |
667 | break; |
668 | case CCValAssign::Indirect: { |
669 | // Store the argument. |
670 | SDValue SpillSlot = DAG.CreateStackTemporary(VT: VA.getValVT()); |
671 | int FI = cast<FrameIndexSDNode>(Val&: SpillSlot)->getIndex(); |
672 | Chain = DAG.getStore( |
673 | Chain, dl: DL, Val: Arg, Ptr: SpillSlot, |
674 | PtrInfo: MachinePointerInfo::getFixedStack(MF&: DAG.getMachineFunction(), FI)); |
675 | Arg = SpillSlot; |
676 | break; |
677 | } |
678 | } |
679 | |
680 | if (VA.isRegLoc()) { |
681 | RegsToPass.push_back(Elt: std::make_pair(x: VA.getLocReg(), y&: Arg)); |
682 | } else if (!IsSibcall && (!IsTailCall || IsByVal)) { |
683 | assert(VA.isMemLoc()); |
684 | if (!StackPtr.getNode()) { |
685 | StackPtr = DAG.getCopyFromReg(Chain, dl: DL, Reg: RegInfo->getStackRegister(), |
686 | VT: getPointerTy(DL: DAG.getDataLayout())); |
687 | } |
688 | MemOpChains.push_back( |
689 | Elt: LowerMemOpCallTo(Chain, StackPtr, Arg, DL, DAG, VA, Flags)); |
690 | } |
691 | } |
692 | |
693 | if (!MemOpChains.empty()) |
694 | Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); |
695 | |
696 | // FIXME Make sure PIC style GOT works as expected |
697 | // The only time GOT is really needed is for Medium-PIC static data |
698 | // otherwise we are happy with pc-rel or static references |
699 | |
700 | if (IsVarArg && IsMustTail) { |
701 | const auto &Forwards = MFI->getForwardedMustTailRegParms(); |
702 | for (const auto &F : Forwards) { |
703 | SDValue Val = DAG.getCopyFromReg(Chain, dl: DL, Reg: F.VReg, VT: F.VT); |
704 | RegsToPass.push_back(Elt: std::make_pair(x: unsigned(F.PReg), y&: Val)); |
705 | } |
706 | } |
707 | |
708 | // For tail calls lower the arguments to the 'real' stack slots. Sibcalls |
709 | // don't need this because the eligibility check rejects calls that require |
710 | // shuffling arguments passed in memory. |
711 | if (!IsSibcall && IsTailCall) { |
712 | // Force all the incoming stack arguments to be loaded from the stack |
713 | // before any new outgoing arguments are stored to the stack, because the |
714 | // outgoing stack slots may alias the incoming argument stack slots, and |
715 | // the alias isn't otherwise explicit. This is slightly more conservative |
716 | // than necessary, because it means that each store effectively depends |
717 | // on every argument instead of just those arguments it would clobber. |
718 | SDValue ArgChain = DAG.getStackArgumentTokenFactor(Chain); |
719 | |
720 | SmallVector<SDValue, 8> MemOpChains2; |
721 | SDValue FIN; |
722 | int FI = 0; |
723 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { |
724 | CCValAssign &VA = ArgLocs[i]; |
725 | if (VA.isRegLoc()) |
726 | continue; |
727 | assert(VA.isMemLoc()); |
728 | SDValue Arg = OutVals[i]; |
729 | ISD::ArgFlagsTy Flags = Outs[i].Flags; |
730 | // Skip inalloca arguments. They don't require any work. |
731 | if (Flags.isInAlloca()) |
732 | continue; |
733 | // Create frame index. |
734 | int32_t Offset = VA.getLocMemOffset() + FPDiff; |
735 | uint32_t OpSize = (VA.getLocVT().getSizeInBits() + 7) / 8; |
736 | FI = MF.getFrameInfo().CreateFixedObject(Size: OpSize, SPOffset: Offset, IsImmutable: true); |
737 | FIN = DAG.getFrameIndex(FI, VT: getPointerTy(DL: DAG.getDataLayout())); |
738 | |
739 | if (Flags.isByVal()) { |
740 | // Copy relative to framepointer. |
741 | SDValue Source = DAG.getIntPtrConstant(Val: VA.getLocMemOffset(), DL); |
742 | if (!StackPtr.getNode()) { |
743 | StackPtr = DAG.getCopyFromReg(Chain, dl: DL, Reg: RegInfo->getStackRegister(), |
744 | VT: getPointerTy(DL: DAG.getDataLayout())); |
745 | } |
746 | Source = DAG.getNode(Opcode: ISD::ADD, DL, VT: getPointerTy(DL: DAG.getDataLayout()), |
747 | N1: StackPtr, N2: Source); |
748 | |
749 | MemOpChains2.push_back( |
750 | Elt: CreateCopyOfByValArgument(Src: Source, Dst: FIN, Chain: ArgChain, Flags, DAG, DL)); |
751 | } else { |
752 | // Store relative to framepointer. |
753 | MemOpChains2.push_back(Elt: DAG.getStore( |
754 | Chain: ArgChain, dl: DL, Val: Arg, Ptr: FIN, |
755 | PtrInfo: MachinePointerInfo::getFixedStack(MF&: DAG.getMachineFunction(), FI))); |
756 | } |
757 | } |
758 | |
759 | if (!MemOpChains2.empty()) |
760 | Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains2); |
761 | |
762 | // Store the return address to the appropriate stack slot. |
763 | Chain = EmitTailCallStoreRetAddr(DAG, MF, Chain, RetFI, |
764 | PtrVT: getPointerTy(DL: DAG.getDataLayout()), |
765 | SlotSize: Subtarget.getSlotSize(), FPDiff, DL); |
766 | } |
767 | |
768 | // Build a sequence of copy-to-reg nodes chained together with token chain |
769 | // and flag operands which copy the outgoing args into registers. |
770 | SDValue InGlue; |
771 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { |
772 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: RegsToPass[i].first, |
773 | N: RegsToPass[i].second, Glue: InGlue); |
774 | InGlue = Chain.getValue(R: 1); |
775 | } |
776 | |
777 | if (Callee->getOpcode() == ISD::GlobalAddress) { |
778 | // If the callee is a GlobalAddress node (quite common, every direct call |
779 | // is) turn it into a TargetGlobalAddress node so that legalize doesn't hack |
780 | // it. |
781 | GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Val&: Callee); |
782 | |
783 | // We should use extra load for direct calls to dllimported functions in |
784 | // non-JIT mode. |
785 | const GlobalValue *GV = G->getGlobal(); |
786 | if (!GV->hasDLLImportStorageClass()) { |
787 | unsigned char OpFlags = Subtarget.classifyGlobalFunctionReference(GV); |
788 | |
789 | Callee = DAG.getTargetGlobalAddress( |
790 | GV, DL, VT: getPointerTy(DL: DAG.getDataLayout()), offset: G->getOffset(), TargetFlags: OpFlags); |
791 | |
792 | if (OpFlags == M68kII::MO_GOTPCREL) { |
793 | |
794 | // Add a wrapper. |
795 | Callee = DAG.getNode(Opcode: M68kISD::WrapperPC, DL, |
796 | VT: getPointerTy(DL: DAG.getDataLayout()), Operand: Callee); |
797 | |
798 | // Add extra indirection |
799 | Callee = DAG.getLoad( |
800 | VT: getPointerTy(DL: DAG.getDataLayout()), dl: DL, Chain: DAG.getEntryNode(), Ptr: Callee, |
801 | PtrInfo: MachinePointerInfo::getGOT(MF&: DAG.getMachineFunction())); |
802 | } |
803 | } |
804 | } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Val&: Callee)) { |
805 | const Module *Mod = DAG.getMachineFunction().getFunction().getParent(); |
806 | unsigned char OpFlags = |
807 | Subtarget.classifyGlobalFunctionReference(GV: nullptr, M: *Mod); |
808 | |
809 | Callee = DAG.getTargetExternalSymbol( |
810 | Sym: S->getSymbol(), VT: getPointerTy(DL: DAG.getDataLayout()), TargetFlags: OpFlags); |
811 | } |
812 | |
813 | // Returns a chain & a flag for retval copy to use. |
814 | SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); |
815 | SmallVector<SDValue, 8> Ops; |
816 | |
817 | if (!IsSibcall && IsTailCall) { |
818 | Chain = DAG.getCALLSEQ_END(Chain, Size1: NumBytesToPop, Size2: 0, Glue: InGlue, DL); |
819 | InGlue = Chain.getValue(R: 1); |
820 | } |
821 | |
822 | Ops.push_back(Elt: Chain); |
823 | Ops.push_back(Elt: Callee); |
824 | |
825 | if (IsTailCall) |
826 | Ops.push_back(DAG.getConstant(FPDiff, DL, MVT::i32)); |
827 | |
828 | // Add argument registers to the end of the list so that they are known live |
829 | // into the call. |
830 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) |
831 | Ops.push_back(Elt: DAG.getRegister(Reg: RegsToPass[i].first, |
832 | VT: RegsToPass[i].second.getValueType())); |
833 | |
834 | // Add a register mask operand representing the call-preserved registers. |
835 | const uint32_t *Mask = RegInfo->getCallPreservedMask(MF, CallConv); |
836 | assert(Mask && "Missing call preserved mask for calling convention" ); |
837 | |
838 | Ops.push_back(Elt: DAG.getRegisterMask(RegMask: Mask)); |
839 | |
840 | if (InGlue.getNode()) |
841 | Ops.push_back(Elt: InGlue); |
842 | |
843 | if (IsTailCall) { |
844 | MF.getFrameInfo().setHasTailCall(); |
845 | return DAG.getNode(Opcode: M68kISD::TC_RETURN, DL, VTList: NodeTys, Ops); |
846 | } |
847 | |
848 | Chain = DAG.getNode(Opcode: M68kISD::CALL, DL, VTList: NodeTys, Ops); |
849 | InGlue = Chain.getValue(R: 1); |
850 | |
851 | // Create the CALLSEQ_END node. |
852 | unsigned NumBytesForCalleeToPop; |
853 | if (M68k::isCalleePop(CallingConv: CallConv, IsVarArg, |
854 | GuaranteeTCO: DAG.getTarget().Options.GuaranteedTailCallOpt)) { |
855 | NumBytesForCalleeToPop = NumBytes; // Callee pops everything |
856 | } else if (!canGuaranteeTCO(CC: CallConv) && SR == StackStructReturn) { |
857 | // If this is a call to a struct-return function, the callee |
858 | // pops the hidden struct pointer, so we have to push it back. |
859 | NumBytesForCalleeToPop = 4; |
860 | } else { |
861 | NumBytesForCalleeToPop = 0; // Callee pops nothing. |
862 | } |
863 | |
864 | if (CLI.DoesNotReturn && !getTargetMachine().Options.TrapUnreachable) { |
865 | // No need to reset the stack after the call if the call doesn't return. To |
866 | // make the MI verify, we'll pretend the callee does it for us. |
867 | NumBytesForCalleeToPop = NumBytes; |
868 | } |
869 | |
870 | // Returns a flag for retval copy to use. |
871 | if (!IsSibcall) { |
872 | Chain = DAG.getCALLSEQ_END(Chain, Size1: NumBytesToPop, Size2: NumBytesForCalleeToPop, |
873 | Glue: InGlue, DL); |
874 | InGlue = Chain.getValue(R: 1); |
875 | } |
876 | |
877 | // Handle result values, copying them out of physregs into vregs that we |
878 | // return. |
879 | return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG, |
880 | InVals); |
881 | } |
882 | |
883 | SDValue M68kTargetLowering::LowerCallResult( |
884 | SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg, |
885 | const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, |
886 | SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { |
887 | |
888 | // Assign locations to each value returned by this call. |
889 | SmallVector<CCValAssign, 16> RVLocs; |
890 | CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, |
891 | *DAG.getContext()); |
892 | CCInfo.AnalyzeCallResult(Ins, RetCC_M68k); |
893 | |
894 | // Copy all of the result registers out of their specified physreg. |
895 | for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { |
896 | CCValAssign &VA = RVLocs[i]; |
897 | EVT CopyVT = VA.getLocVT(); |
898 | |
899 | /// ??? is this correct? |
900 | Chain = DAG.getCopyFromReg(Chain, dl: DL, Reg: VA.getLocReg(), VT: CopyVT, Glue: InGlue) |
901 | .getValue(R: 1); |
902 | SDValue Val = Chain.getValue(R: 0); |
903 | |
904 | if (VA.isExtInLoc() && VA.getValVT().getScalarType() == MVT::i1) |
905 | Val = DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT: VA.getValVT(), Operand: Val); |
906 | |
907 | InGlue = Chain.getValue(R: 2); |
908 | InVals.push_back(Elt: Val); |
909 | } |
910 | |
911 | return Chain; |
912 | } |
913 | |
914 | //===----------------------------------------------------------------------===// |
915 | // Formal Arguments Calling Convention Implementation |
916 | //===----------------------------------------------------------------------===// |
917 | |
918 | SDValue M68kTargetLowering::LowerFormalArguments( |
919 | SDValue Chain, CallingConv::ID CCID, bool IsVarArg, |
920 | const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, |
921 | SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { |
922 | MachineFunction &MF = DAG.getMachineFunction(); |
923 | M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>(); |
924 | // const TargetFrameLowering &TFL = *Subtarget.getFrameLowering(); |
925 | |
926 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
927 | |
928 | // Assign locations to all of the incoming arguments. |
929 | SmallVector<CCValAssign, 16> ArgLocs; |
930 | SmallVector<Type *, 4> ArgTypes; |
931 | for (const Argument &Arg : MF.getFunction().args()) |
932 | ArgTypes.emplace_back(Args: Arg.getType()); |
933 | M68kCCState CCInfo(ArgTypes, CCID, IsVarArg, MF, ArgLocs, *DAG.getContext()); |
934 | |
935 | CCInfo.AnalyzeFormalArguments(Ins, CC_M68k); |
936 | |
937 | unsigned LastVal = ~0U; |
938 | SDValue ArgValue; |
939 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { |
940 | CCValAssign &VA = ArgLocs[i]; |
941 | assert(VA.getValNo() != LastVal && "Same value in different locations" ); |
942 | (void)LastVal; |
943 | |
944 | LastVal = VA.getValNo(); |
945 | |
946 | if (VA.isRegLoc()) { |
947 | EVT RegVT = VA.getLocVT(); |
948 | const TargetRegisterClass *RC; |
949 | if (RegVT == MVT::i32) |
950 | RC = &M68k::XR32RegClass; |
951 | else |
952 | llvm_unreachable("Unknown argument type!" ); |
953 | |
954 | Register Reg = MF.addLiveIn(PReg: VA.getLocReg(), RC); |
955 | ArgValue = DAG.getCopyFromReg(Chain, dl: DL, Reg, VT: RegVT); |
956 | |
957 | // If this is an 8 or 16-bit value, it is really passed promoted to 32 |
958 | // bits. Insert an assert[sz]ext to capture this, then truncate to the |
959 | // right size. |
960 | if (VA.getLocInfo() == CCValAssign::SExt) { |
961 | ArgValue = DAG.getNode(Opcode: ISD::AssertSext, DL, VT: RegVT, N1: ArgValue, |
962 | N2: DAG.getValueType(VA.getValVT())); |
963 | } else if (VA.getLocInfo() == CCValAssign::ZExt) { |
964 | ArgValue = DAG.getNode(Opcode: ISD::AssertZext, DL, VT: RegVT, N1: ArgValue, |
965 | N2: DAG.getValueType(VA.getValVT())); |
966 | } else if (VA.getLocInfo() == CCValAssign::BCvt) { |
967 | ArgValue = DAG.getBitcast(VT: VA.getValVT(), V: ArgValue); |
968 | } |
969 | |
970 | if (VA.isExtInLoc()) { |
971 | ArgValue = DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT: VA.getValVT(), Operand: ArgValue); |
972 | } |
973 | } else { |
974 | assert(VA.isMemLoc()); |
975 | ArgValue = LowerMemArgument(Chain, CallConv: CCID, Ins, DL, DAG, VA, MFI, ArgIdx: i); |
976 | } |
977 | |
978 | // If value is passed via pointer - do a load. |
979 | // TODO Make sure this handling on indirect arguments is correct |
980 | if (VA.getLocInfo() == CCValAssign::Indirect) |
981 | ArgValue = |
982 | DAG.getLoad(VT: VA.getValVT(), dl: DL, Chain, Ptr: ArgValue, PtrInfo: MachinePointerInfo()); |
983 | |
984 | InVals.push_back(Elt: ArgValue); |
985 | } |
986 | |
987 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { |
988 | // Swift calling convention does not require we copy the sret argument |
989 | // into %D0 for the return. We don't set SRetReturnReg for Swift. |
990 | if (CCID == CallingConv::Swift) |
991 | continue; |
992 | |
993 | // ABI require that for returning structs by value we copy the sret argument |
994 | // into %D0 for the return. Save the argument into a virtual register so |
995 | // that we can access it from the return points. |
996 | if (Ins[i].Flags.isSRet()) { |
997 | unsigned Reg = MMFI->getSRetReturnReg(); |
998 | if (!Reg) { |
999 | MVT PtrTy = getPointerTy(DL: DAG.getDataLayout()); |
1000 | Reg = MF.getRegInfo().createVirtualRegister(RegClass: getRegClassFor(VT: PtrTy)); |
1001 | MMFI->setSRetReturnReg(Reg); |
1002 | } |
1003 | SDValue Copy = DAG.getCopyToReg(Chain: DAG.getEntryNode(), dl: DL, Reg, N: InVals[i]); |
1004 | Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain); |
1005 | break; |
1006 | } |
1007 | } |
1008 | |
1009 | unsigned StackSize = CCInfo.getStackSize(); |
1010 | // Align stack specially for tail calls. |
1011 | if (shouldGuaranteeTCO(CC: CCID, GuaranteedTailCallOpt: MF.getTarget().Options.GuaranteedTailCallOpt)) |
1012 | StackSize = GetAlignedArgumentStackSize(StackSize, DAG); |
1013 | |
1014 | // If the function takes variable number of arguments, make a frame index for |
1015 | // the start of the first vararg value... for expansion of llvm.va_start. We |
1016 | // can skip this if there are no va_start calls. |
1017 | if (MFI.hasVAStart()) { |
1018 | MMFI->setVarArgsFrameIndex(MFI.CreateFixedObject(Size: 1, SPOffset: StackSize, IsImmutable: true)); |
1019 | } |
1020 | |
1021 | if (IsVarArg && MFI.hasMustTailInVarArgFunc()) { |
1022 | // We forward some GPRs and some vector types. |
1023 | SmallVector<MVT, 2> RegParmTypes; |
1024 | MVT IntVT = MVT::i32; |
1025 | RegParmTypes.push_back(Elt: IntVT); |
1026 | |
1027 | // Compute the set of forwarded registers. The rest are scratch. |
1028 | // ??? what is this for? |
1029 | SmallVectorImpl<ForwardedRegister> &Forwards = |
1030 | MMFI->getForwardedMustTailRegParms(); |
1031 | CCInfo.analyzeMustTailForwardedRegisters(Forwards, RegParmTypes, CC_M68k); |
1032 | |
1033 | // Copy all forwards from physical to virtual registers. |
1034 | for (ForwardedRegister &F : Forwards) { |
1035 | // FIXME Can we use a less constrained schedule? |
1036 | SDValue RegVal = DAG.getCopyFromReg(Chain, dl: DL, Reg: F.VReg, VT: F.VT); |
1037 | F.VReg = MF.getRegInfo().createVirtualRegister(RegClass: getRegClassFor(VT: F.VT)); |
1038 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: F.VReg, N: RegVal); |
1039 | } |
1040 | } |
1041 | |
1042 | // Some CCs need callee pop. |
1043 | if (M68k::isCalleePop(CallingConv: CCID, IsVarArg, |
1044 | GuaranteeTCO: MF.getTarget().Options.GuaranteedTailCallOpt)) { |
1045 | MMFI->setBytesToPopOnReturn(StackSize); // Callee pops everything. |
1046 | } else { |
1047 | MMFI->setBytesToPopOnReturn(0); // Callee pops nothing. |
1048 | // If this is an sret function, the return should pop the hidden pointer. |
1049 | if (!canGuaranteeTCO(CC: CCID) && argsAreStructReturn(Ins) == StackStructReturn) |
1050 | MMFI->setBytesToPopOnReturn(4); |
1051 | } |
1052 | |
1053 | MMFI->setArgumentStackSize(StackSize); |
1054 | |
1055 | return Chain; |
1056 | } |
1057 | |
1058 | //===----------------------------------------------------------------------===// |
1059 | // Return Value Calling Convention Implementation |
1060 | //===----------------------------------------------------------------------===// |
1061 | |
1062 | bool M68kTargetLowering::CanLowerReturn( |
1063 | CallingConv::ID CCID, MachineFunction &MF, bool IsVarArg, |
1064 | const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { |
1065 | SmallVector<CCValAssign, 16> RVLocs; |
1066 | CCState CCInfo(CCID, IsVarArg, MF, RVLocs, Context); |
1067 | return CCInfo.CheckReturn(Outs, RetCC_M68k); |
1068 | } |
1069 | |
1070 | SDValue |
1071 | M68kTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CCID, |
1072 | bool IsVarArg, |
1073 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
1074 | const SmallVectorImpl<SDValue> &OutVals, |
1075 | const SDLoc &DL, SelectionDAG &DAG) const { |
1076 | MachineFunction &MF = DAG.getMachineFunction(); |
1077 | M68kMachineFunctionInfo *MFI = MF.getInfo<M68kMachineFunctionInfo>(); |
1078 | |
1079 | SmallVector<CCValAssign, 16> RVLocs; |
1080 | CCState CCInfo(CCID, IsVarArg, MF, RVLocs, *DAG.getContext()); |
1081 | CCInfo.AnalyzeReturn(Outs, RetCC_M68k); |
1082 | |
1083 | SDValue Glue; |
1084 | SmallVector<SDValue, 6> RetOps; |
1085 | // Operand #0 = Chain (updated below) |
1086 | RetOps.push_back(Elt: Chain); |
1087 | // Operand #1 = Bytes To Pop |
1088 | RetOps.push_back( |
1089 | DAG.getTargetConstant(MFI->getBytesToPopOnReturn(), DL, MVT::i32)); |
1090 | |
1091 | // Copy the result values into the output registers. |
1092 | for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { |
1093 | CCValAssign &VA = RVLocs[i]; |
1094 | assert(VA.isRegLoc() && "Can only return in registers!" ); |
1095 | SDValue ValToCopy = OutVals[i]; |
1096 | EVT ValVT = ValToCopy.getValueType(); |
1097 | |
1098 | // Promote values to the appropriate types. |
1099 | if (VA.getLocInfo() == CCValAssign::SExt) |
1100 | ValToCopy = DAG.getNode(Opcode: ISD::SIGN_EXTEND, DL, VT: VA.getLocVT(), Operand: ValToCopy); |
1101 | else if (VA.getLocInfo() == CCValAssign::ZExt) |
1102 | ValToCopy = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL, VT: VA.getLocVT(), Operand: ValToCopy); |
1103 | else if (VA.getLocInfo() == CCValAssign::AExt) { |
1104 | if (ValVT.isVector() && ValVT.getVectorElementType() == MVT::i1) |
1105 | ValToCopy = DAG.getNode(Opcode: ISD::SIGN_EXTEND, DL, VT: VA.getLocVT(), Operand: ValToCopy); |
1106 | else |
1107 | ValToCopy = DAG.getNode(Opcode: ISD::ANY_EXTEND, DL, VT: VA.getLocVT(), Operand: ValToCopy); |
1108 | } else if (VA.getLocInfo() == CCValAssign::BCvt) |
1109 | ValToCopy = DAG.getBitcast(VT: VA.getLocVT(), V: ValToCopy); |
1110 | |
1111 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: VA.getLocReg(), N: ValToCopy, Glue); |
1112 | Glue = Chain.getValue(R: 1); |
1113 | RetOps.push_back(Elt: DAG.getRegister(Reg: VA.getLocReg(), VT: VA.getLocVT())); |
1114 | } |
1115 | |
1116 | // Swift calling convention does not require we copy the sret argument |
1117 | // into %d0 for the return, and SRetReturnReg is not set for Swift. |
1118 | |
1119 | // ABI require that for returning structs by value we copy the sret argument |
1120 | // into %D0 for the return. Save the argument into a virtual register so that |
1121 | // we can access it from the return points. |
1122 | // |
1123 | // Checking Function.hasStructRetAttr() here is insufficient because the IR |
1124 | // may not have an explicit sret argument. If MFI.CanLowerReturn is |
1125 | // false, then an sret argument may be implicitly inserted in the SelDAG. In |
1126 | // either case MFI->setSRetReturnReg() will have been called. |
1127 | if (unsigned SRetReg = MFI->getSRetReturnReg()) { |
1128 | // ??? Can i just move this to the top and escape this explanation? |
1129 | // When we have both sret and another return value, we should use the |
1130 | // original Chain stored in RetOps[0], instead of the current Chain updated |
1131 | // in the above loop. If we only have sret, RetOps[0] equals to Chain. |
1132 | |
1133 | // For the case of sret and another return value, we have |
1134 | // Chain_0 at the function entry |
1135 | // Chain_1 = getCopyToReg(Chain_0) in the above loop |
1136 | // If we use Chain_1 in getCopyFromReg, we will have |
1137 | // Val = getCopyFromReg(Chain_1) |
1138 | // Chain_2 = getCopyToReg(Chain_1, Val) from below |
1139 | |
1140 | // getCopyToReg(Chain_0) will be glued together with |
1141 | // getCopyToReg(Chain_1, Val) into Unit A, getCopyFromReg(Chain_1) will be |
1142 | // in Unit B, and we will have cyclic dependency between Unit A and Unit B: |
1143 | // Data dependency from Unit B to Unit A due to usage of Val in |
1144 | // getCopyToReg(Chain_1, Val) |
1145 | // Chain dependency from Unit A to Unit B |
1146 | |
1147 | // So here, we use RetOps[0] (i.e Chain_0) for getCopyFromReg. |
1148 | SDValue Val = DAG.getCopyFromReg(Chain: RetOps[0], dl: DL, Reg: SRetReg, |
1149 | VT: getPointerTy(DL: MF.getDataLayout())); |
1150 | |
1151 | // ??? How will this work if CC does not use registers for args passing? |
1152 | // ??? What if I return multiple structs? |
1153 | unsigned RetValReg = M68k::D0; |
1154 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: RetValReg, N: Val, Glue); |
1155 | Glue = Chain.getValue(R: 1); |
1156 | |
1157 | RetOps.push_back( |
1158 | Elt: DAG.getRegister(Reg: RetValReg, VT: getPointerTy(DL: DAG.getDataLayout()))); |
1159 | } |
1160 | |
1161 | RetOps[0] = Chain; // Update chain. |
1162 | |
1163 | // Add the glue if we have it. |
1164 | if (Glue.getNode()) |
1165 | RetOps.push_back(Elt: Glue); |
1166 | |
1167 | return DAG.getNode(M68kISD::RET, DL, MVT::Other, RetOps); |
1168 | } |
1169 | |
1170 | //===----------------------------------------------------------------------===// |
1171 | // Fast Calling Convention (tail call) implementation |
1172 | //===----------------------------------------------------------------------===// |
1173 | |
1174 | // Like std call, callee cleans arguments, convention except that ECX is |
1175 | // reserved for storing the tail called function address. Only 2 registers are |
1176 | // free for argument passing (inreg). Tail call optimization is performed |
1177 | // provided: |
1178 | // * tailcallopt is enabled |
1179 | // * caller/callee are fastcc |
1180 | // On M68k_64 architecture with GOT-style position independent code only |
1181 | // local (within module) calls are supported at the moment. To keep the stack |
1182 | // aligned according to platform abi the function GetAlignedArgumentStackSize |
1183 | // ensures that argument delta is always multiples of stack alignment. (Dynamic |
1184 | // linkers need this - darwin's dyld for example) If a tail called function |
1185 | // callee has more arguments than the caller the caller needs to make sure that |
1186 | // there is room to move the RETADDR to. This is achieved by reserving an area |
1187 | // the size of the argument delta right after the original RETADDR, but before |
1188 | // the saved framepointer or the spilled registers e.g. caller(arg1, arg2) |
1189 | // calls callee(arg1, arg2,arg3,arg4) stack layout: |
1190 | // arg1 |
1191 | // arg2 |
1192 | // RETADDR |
1193 | // [ new RETADDR |
1194 | // move area ] |
1195 | // (possible EBP) |
1196 | // ESI |
1197 | // EDI |
1198 | // local1 .. |
1199 | |
1200 | /// Make the stack size align e.g 16n + 12 aligned for a 16-byte align |
1201 | /// requirement. |
1202 | unsigned |
1203 | M68kTargetLowering::GetAlignedArgumentStackSize(unsigned StackSize, |
1204 | SelectionDAG &DAG) const { |
1205 | const TargetFrameLowering &TFI = *Subtarget.getFrameLowering(); |
1206 | unsigned StackAlignment = TFI.getStackAlignment(); |
1207 | uint64_t AlignMask = StackAlignment - 1; |
1208 | int64_t Offset = StackSize; |
1209 | unsigned SlotSize = Subtarget.getSlotSize(); |
1210 | if ((Offset & AlignMask) <= (StackAlignment - SlotSize)) { |
1211 | // Number smaller than 12 so just add the difference. |
1212 | Offset += ((StackAlignment - SlotSize) - (Offset & AlignMask)); |
1213 | } else { |
1214 | // Mask out lower bits, add stackalignment once plus the 12 bytes. |
1215 | Offset = |
1216 | ((~AlignMask) & Offset) + StackAlignment + (StackAlignment - SlotSize); |
1217 | } |
1218 | return Offset; |
1219 | } |
1220 | |
1221 | /// Check whether the call is eligible for tail call optimization. Targets |
1222 | /// that want to do tail call optimization should implement this function. |
1223 | bool M68kTargetLowering::IsEligibleForTailCallOptimization( |
1224 | SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg, |
1225 | bool IsCalleeStructRet, bool IsCallerStructRet, Type *RetTy, |
1226 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
1227 | const SmallVectorImpl<SDValue> &OutVals, |
1228 | const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const { |
1229 | if (!mayTailCallThisCC(CC: CalleeCC)) |
1230 | return false; |
1231 | |
1232 | // If -tailcallopt is specified, make fastcc functions tail-callable. |
1233 | MachineFunction &MF = DAG.getMachineFunction(); |
1234 | const auto &CallerF = MF.getFunction(); |
1235 | |
1236 | CallingConv::ID CallerCC = CallerF.getCallingConv(); |
1237 | bool CCMatch = CallerCC == CalleeCC; |
1238 | |
1239 | if (DAG.getTarget().Options.GuaranteedTailCallOpt) { |
1240 | if (canGuaranteeTCO(CC: CalleeCC) && CCMatch) |
1241 | return true; |
1242 | return false; |
1243 | } |
1244 | |
1245 | // Look for obvious safe cases to perform tail call optimization that do not |
1246 | // require ABI changes. This is what gcc calls sibcall. |
1247 | |
1248 | // Can't do sibcall if stack needs to be dynamically re-aligned. PEI needs to |
1249 | // emit a special epilogue. |
1250 | const M68kRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); |
1251 | if (RegInfo->hasStackRealignment(MF)) |
1252 | return false; |
1253 | |
1254 | // Also avoid sibcall optimization if either caller or callee uses struct |
1255 | // return semantics. |
1256 | if (IsCalleeStructRet || IsCallerStructRet) |
1257 | return false; |
1258 | |
1259 | // Do not sibcall optimize vararg calls unless all arguments are passed via |
1260 | // registers. |
1261 | LLVMContext &C = *DAG.getContext(); |
1262 | if (IsVarArg && !Outs.empty()) { |
1263 | |
1264 | SmallVector<CCValAssign, 16> ArgLocs; |
1265 | CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, C); |
1266 | |
1267 | CCInfo.AnalyzeCallOperands(Outs, CC_M68k); |
1268 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) |
1269 | if (!ArgLocs[i].isRegLoc()) |
1270 | return false; |
1271 | } |
1272 | |
1273 | // Check that the call results are passed in the same way. |
1274 | if (!CCState::resultsCompatible(CalleeCC, CallerCC, MF, C, Ins, RetCC_M68k, |
1275 | RetCC_M68k)) |
1276 | return false; |
1277 | |
1278 | // The callee has to preserve all registers the caller needs to preserve. |
1279 | const M68kRegisterInfo *TRI = Subtarget.getRegisterInfo(); |
1280 | const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC); |
1281 | if (!CCMatch) { |
1282 | const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC); |
1283 | if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) |
1284 | return false; |
1285 | } |
1286 | |
1287 | unsigned StackArgsSize = 0; |
1288 | |
1289 | // If the callee takes no arguments then go on to check the results of the |
1290 | // call. |
1291 | if (!Outs.empty()) { |
1292 | // Check if stack adjustment is needed. For now, do not do this if any |
1293 | // argument is passed on the stack. |
1294 | SmallVector<CCValAssign, 16> ArgLocs; |
1295 | CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, C); |
1296 | |
1297 | CCInfo.AnalyzeCallOperands(Outs, CC_M68k); |
1298 | StackArgsSize = CCInfo.getStackSize(); |
1299 | |
1300 | if (StackArgsSize) { |
1301 | // Check if the arguments are already laid out in the right way as |
1302 | // the caller's fixed stack objects. |
1303 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
1304 | const MachineRegisterInfo *MRI = &MF.getRegInfo(); |
1305 | const M68kInstrInfo *TII = Subtarget.getInstrInfo(); |
1306 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { |
1307 | CCValAssign &VA = ArgLocs[i]; |
1308 | SDValue Arg = OutVals[i]; |
1309 | ISD::ArgFlagsTy Flags = Outs[i].Flags; |
1310 | if (VA.getLocInfo() == CCValAssign::Indirect) |
1311 | return false; |
1312 | if (!VA.isRegLoc()) { |
1313 | if (!MatchingStackOffset(Arg, Offset: VA.getLocMemOffset(), Flags, MFI, MRI, |
1314 | TII, VA)) |
1315 | return false; |
1316 | } |
1317 | } |
1318 | } |
1319 | |
1320 | bool PositionIndependent = isPositionIndependent(); |
1321 | // If the tailcall address may be in a register, then make sure it's |
1322 | // possible to register allocate for it. The call address can |
1323 | // only target %A0 or %A1 since the tail call must be scheduled after |
1324 | // callee-saved registers are restored. These happen to be the same |
1325 | // registers used to pass 'inreg' arguments so watch out for those. |
1326 | if ((!isa<GlobalAddressSDNode>(Val: Callee) && |
1327 | !isa<ExternalSymbolSDNode>(Val: Callee)) || |
1328 | PositionIndependent) { |
1329 | unsigned NumInRegs = 0; |
1330 | // In PIC we need an extra register to formulate the address computation |
1331 | // for the callee. |
1332 | unsigned MaxInRegs = PositionIndependent ? 1 : 2; |
1333 | |
1334 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { |
1335 | CCValAssign &VA = ArgLocs[i]; |
1336 | if (!VA.isRegLoc()) |
1337 | continue; |
1338 | Register Reg = VA.getLocReg(); |
1339 | switch (Reg) { |
1340 | default: |
1341 | break; |
1342 | case M68k::A0: |
1343 | case M68k::A1: |
1344 | if (++NumInRegs == MaxInRegs) |
1345 | return false; |
1346 | break; |
1347 | } |
1348 | } |
1349 | } |
1350 | |
1351 | const MachineRegisterInfo &MRI = MF.getRegInfo(); |
1352 | if (!parametersInCSRMatch(MRI, CallerPreservedMask: CallerPreserved, ArgLocs, OutVals)) |
1353 | return false; |
1354 | } |
1355 | |
1356 | bool CalleeWillPop = M68k::isCalleePop( |
1357 | CallingConv: CalleeCC, IsVarArg, GuaranteeTCO: MF.getTarget().Options.GuaranteedTailCallOpt); |
1358 | |
1359 | if (unsigned BytesToPop = |
1360 | MF.getInfo<M68kMachineFunctionInfo>()->getBytesToPopOnReturn()) { |
1361 | // If we have bytes to pop, the callee must pop them. |
1362 | bool CalleePopMatches = CalleeWillPop && BytesToPop == StackArgsSize; |
1363 | if (!CalleePopMatches) |
1364 | return false; |
1365 | } else if (CalleeWillPop && StackArgsSize > 0) { |
1366 | // If we don't have bytes to pop, make sure the callee doesn't pop any. |
1367 | return false; |
1368 | } |
1369 | |
1370 | return true; |
1371 | } |
1372 | |
1373 | //===----------------------------------------------------------------------===// |
1374 | // Custom Lower |
1375 | //===----------------------------------------------------------------------===// |
1376 | |
1377 | SDValue M68kTargetLowering::LowerOperation(SDValue Op, |
1378 | SelectionDAG &DAG) const { |
1379 | switch (Op.getOpcode()) { |
1380 | default: |
1381 | llvm_unreachable("Should not custom lower this!" ); |
1382 | case ISD::SADDO: |
1383 | case ISD::UADDO: |
1384 | case ISD::SSUBO: |
1385 | case ISD::USUBO: |
1386 | case ISD::SMULO: |
1387 | case ISD::UMULO: |
1388 | return LowerXALUO(Op, DAG); |
1389 | case ISD::SETCC: |
1390 | return LowerSETCC(Op, DAG); |
1391 | case ISD::SETCCCARRY: |
1392 | return LowerSETCCCARRY(Op, DAG); |
1393 | case ISD::SELECT: |
1394 | return LowerSELECT(Op, DAG); |
1395 | case ISD::BRCOND: |
1396 | return LowerBRCOND(Op, DAG); |
1397 | case ISD::ADDC: |
1398 | case ISD::ADDE: |
1399 | case ISD::SUBC: |
1400 | case ISD::SUBE: |
1401 | return LowerADDC_ADDE_SUBC_SUBE(Op, DAG); |
1402 | case ISD::ConstantPool: |
1403 | return LowerConstantPool(Op, DAG); |
1404 | case ISD::GlobalAddress: |
1405 | return LowerGlobalAddress(Op, DAG); |
1406 | case ISD::ExternalSymbol: |
1407 | return LowerExternalSymbol(Op, DAG); |
1408 | case ISD::BlockAddress: |
1409 | return LowerBlockAddress(Op, DAG); |
1410 | case ISD::JumpTable: |
1411 | return LowerJumpTable(Op, DAG); |
1412 | case ISD::VASTART: |
1413 | return LowerVASTART(Op, DAG); |
1414 | case ISD::DYNAMIC_STACKALLOC: |
1415 | return LowerDYNAMIC_STACKALLOC(Op, DAG); |
1416 | case ISD::SHL_PARTS: |
1417 | return LowerShiftLeftParts(Op, DAG); |
1418 | case ISD::SRA_PARTS: |
1419 | return LowerShiftRightParts(Op, DAG, IsSRA: true); |
1420 | case ISD::SRL_PARTS: |
1421 | return LowerShiftRightParts(Op, DAG, IsSRA: false); |
1422 | case ISD::ATOMIC_FENCE: |
1423 | return LowerATOMICFENCE(Op, DAG); |
1424 | case ISD::GlobalTLSAddress: |
1425 | return LowerGlobalTLSAddress(Op, DAG); |
1426 | } |
1427 | } |
1428 | |
1429 | SDValue M68kTargetLowering::LowerExternalSymbolCall(SelectionDAG &DAG, |
1430 | SDLoc Loc, |
1431 | llvm::StringRef SymbolName, |
1432 | ArgListTy &&ArgList) const { |
1433 | PointerType *PtrTy = PointerType::get(C&: *DAG.getContext(), AddressSpace: 0); |
1434 | CallLoweringInfo CLI(DAG); |
1435 | CLI.setDebugLoc(Loc) |
1436 | .setChain(DAG.getEntryNode()) |
1437 | .setLibCallee(CC: CallingConv::C, ResultType: PtrTy, |
1438 | Target: DAG.getExternalSymbol(Sym: SymbolName.data(), |
1439 | VT: getPointerMemTy(DL: DAG.getDataLayout())), |
1440 | ArgsList: std::move(ArgList)); |
1441 | return LowerCallTo(CLI).first; |
1442 | } |
1443 | |
1444 | SDValue M68kTargetLowering::getTLSGetAddr(GlobalAddressSDNode *GA, |
1445 | SelectionDAG &DAG, |
1446 | unsigned TargetFlags) const { |
1447 | SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); |
1448 | SDValue TGA = DAG.getTargetGlobalAddress( |
1449 | GV: GA->getGlobal(), DL: GA, VT: GA->getValueType(ResNo: 0), offset: GA->getOffset(), TargetFlags); |
1450 | SDValue Arg = DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, GOT, TGA); |
1451 | |
1452 | PointerType *PtrTy = PointerType::get(C&: *DAG.getContext(), AddressSpace: 0); |
1453 | |
1454 | ArgListTy Args; |
1455 | ArgListEntry Entry; |
1456 | Entry.Node = Arg; |
1457 | Entry.Ty = PtrTy; |
1458 | Args.push_back(x: Entry); |
1459 | return LowerExternalSymbolCall(DAG, Loc: SDLoc(GA), SymbolName: "__tls_get_addr" , |
1460 | ArgList: std::move(Args)); |
1461 | } |
1462 | |
1463 | SDValue M68kTargetLowering::getM68kReadTp(SDLoc Loc, SelectionDAG &DAG) const { |
1464 | return LowerExternalSymbolCall(DAG, Loc, SymbolName: "__m68k_read_tp" , ArgList: ArgListTy()); |
1465 | } |
1466 | |
1467 | SDValue M68kTargetLowering::LowerTLSGeneralDynamic(GlobalAddressSDNode *GA, |
1468 | SelectionDAG &DAG) const { |
1469 | return getTLSGetAddr(GA, DAG, TargetFlags: M68kII::MO_TLSGD); |
1470 | } |
1471 | |
1472 | SDValue M68kTargetLowering::LowerTLSLocalDynamic(GlobalAddressSDNode *GA, |
1473 | SelectionDAG &DAG) const { |
1474 | SDValue Addr = getTLSGetAddr(GA, DAG, TargetFlags: M68kII::MO_TLSLDM); |
1475 | SDValue TGA = |
1476 | DAG.getTargetGlobalAddress(GV: GA->getGlobal(), DL: GA, VT: GA->getValueType(ResNo: 0), |
1477 | offset: GA->getOffset(), TargetFlags: M68kII::MO_TLSLD); |
1478 | return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, Addr); |
1479 | } |
1480 | |
1481 | SDValue M68kTargetLowering::LowerTLSInitialExec(GlobalAddressSDNode *GA, |
1482 | SelectionDAG &DAG) const { |
1483 | SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); |
1484 | SDValue Tp = getM68kReadTp(Loc: SDLoc(GA), DAG); |
1485 | SDValue TGA = |
1486 | DAG.getTargetGlobalAddress(GV: GA->getGlobal(), DL: GA, VT: GA->getValueType(ResNo: 0), |
1487 | offset: GA->getOffset(), TargetFlags: M68kII::MO_TLSIE); |
1488 | SDValue Addr = DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, GOT); |
1489 | SDValue Offset = |
1490 | DAG.getLoad(MVT::i32, SDLoc(GA), DAG.getEntryNode(), Addr, |
1491 | MachinePointerInfo::getGOT(DAG.getMachineFunction())); |
1492 | |
1493 | return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, Offset, Tp); |
1494 | } |
1495 | |
1496 | SDValue M68kTargetLowering::LowerTLSLocalExec(GlobalAddressSDNode *GA, |
1497 | SelectionDAG &DAG) const { |
1498 | SDValue Tp = getM68kReadTp(Loc: SDLoc(GA), DAG); |
1499 | SDValue TGA = |
1500 | DAG.getTargetGlobalAddress(GV: GA->getGlobal(), DL: GA, VT: GA->getValueType(ResNo: 0), |
1501 | offset: GA->getOffset(), TargetFlags: M68kII::MO_TLSLE); |
1502 | return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, Tp); |
1503 | } |
1504 | |
1505 | SDValue M68kTargetLowering::LowerGlobalTLSAddress(SDValue Op, |
1506 | SelectionDAG &DAG) const { |
1507 | assert(Subtarget.isTargetELF()); |
1508 | |
1509 | auto *GA = cast<GlobalAddressSDNode>(Val&: Op); |
1510 | TLSModel::Model AccessModel = DAG.getTarget().getTLSModel(GV: GA->getGlobal()); |
1511 | |
1512 | switch (AccessModel) { |
1513 | case TLSModel::GeneralDynamic: |
1514 | return LowerTLSGeneralDynamic(GA, DAG); |
1515 | case TLSModel::LocalDynamic: |
1516 | return LowerTLSLocalDynamic(GA, DAG); |
1517 | case TLSModel::InitialExec: |
1518 | return LowerTLSInitialExec(GA, DAG); |
1519 | case TLSModel::LocalExec: |
1520 | return LowerTLSLocalExec(GA, DAG); |
1521 | } |
1522 | |
1523 | llvm_unreachable("Unexpected TLS access model type" ); |
1524 | } |
1525 | |
1526 | bool M68kTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT, |
1527 | SDValue C) const { |
1528 | // Shifts and add instructions in M68000 and M68010 support |
1529 | // up to 32 bits, but mul only has 16-bit variant. So it's almost |
1530 | // certainly beneficial to lower 8/16/32-bit mul to their |
1531 | // add / shifts counterparts. But for 64-bits mul, it might be |
1532 | // safer to just leave it to compiler runtime implementations. |
1533 | return VT.bitsLE(MVT::i32) || Subtarget.atLeastM68020(); |
1534 | } |
1535 | |
1536 | static bool isOverflowArithmetic(unsigned Opcode) { |
1537 | switch (Opcode) { |
1538 | case ISD::UADDO: |
1539 | case ISD::SADDO: |
1540 | case ISD::USUBO: |
1541 | case ISD::SSUBO: |
1542 | case ISD::UMULO: |
1543 | case ISD::SMULO: |
1544 | return true; |
1545 | default: |
1546 | return false; |
1547 | } |
1548 | } |
1549 | |
1550 | static void lowerOverflowArithmetic(SDValue Op, SelectionDAG &DAG, |
1551 | SDValue &Result, SDValue &CCR, |
1552 | unsigned &CC) { |
1553 | SDNode *N = Op.getNode(); |
1554 | EVT VT = N->getValueType(ResNo: 0); |
1555 | SDValue LHS = N->getOperand(Num: 0); |
1556 | SDValue RHS = N->getOperand(Num: 1); |
1557 | SDLoc DL(Op); |
1558 | |
1559 | unsigned TruncOp = 0; |
1560 | auto PromoteMULO = [&](unsigned ExtOp) { |
1561 | // We don't have 8-bit multiplications, so promote i8 version of U/SMULO |
1562 | // to i16. |
1563 | // Ideally this should be done by legalizer but sadly there is no promotion |
1564 | // rule for U/SMULO at this moment. |
1565 | if (VT == MVT::i8) { |
1566 | LHS = DAG.getNode(ExtOp, DL, MVT::i16, LHS); |
1567 | RHS = DAG.getNode(ExtOp, DL, MVT::i16, RHS); |
1568 | VT = MVT::i16; |
1569 | TruncOp = ISD::TRUNCATE; |
1570 | } |
1571 | }; |
1572 | |
1573 | bool NoOverflow = false; |
1574 | unsigned BaseOp = 0; |
1575 | switch (Op.getOpcode()) { |
1576 | default: |
1577 | llvm_unreachable("Unknown ovf instruction!" ); |
1578 | case ISD::SADDO: |
1579 | BaseOp = M68kISD::ADD; |
1580 | CC = M68k::COND_VS; |
1581 | break; |
1582 | case ISD::UADDO: |
1583 | BaseOp = M68kISD::ADD; |
1584 | CC = M68k::COND_CS; |
1585 | break; |
1586 | case ISD::SSUBO: |
1587 | BaseOp = M68kISD::SUB; |
1588 | CC = M68k::COND_VS; |
1589 | break; |
1590 | case ISD::USUBO: |
1591 | BaseOp = M68kISD::SUB; |
1592 | CC = M68k::COND_CS; |
1593 | break; |
1594 | case ISD::UMULO: |
1595 | PromoteMULO(ISD::ZERO_EXTEND); |
1596 | NoOverflow = VT != MVT::i32; |
1597 | BaseOp = NoOverflow ? ISD::MUL : M68kISD::UMUL; |
1598 | CC = M68k::COND_VS; |
1599 | break; |
1600 | case ISD::SMULO: |
1601 | PromoteMULO(ISD::SIGN_EXTEND); |
1602 | NoOverflow = VT != MVT::i32; |
1603 | BaseOp = NoOverflow ? ISD::MUL : M68kISD::SMUL; |
1604 | CC = M68k::COND_VS; |
1605 | break; |
1606 | } |
1607 | |
1608 | SDVTList VTs; |
1609 | if (NoOverflow) |
1610 | VTs = DAG.getVTList(VT); |
1611 | else |
1612 | // Also sets CCR. |
1613 | VTs = DAG.getVTList(VT, MVT::i8); |
1614 | |
1615 | SDValue Arith = DAG.getNode(Opcode: BaseOp, DL, VTList: VTs, N1: LHS, N2: RHS); |
1616 | Result = Arith.getValue(R: 0); |
1617 | if (TruncOp) |
1618 | // Right now the only place to truncate is from i16 to i8. |
1619 | Result = DAG.getNode(TruncOp, DL, MVT::i8, Arith); |
1620 | |
1621 | if (NoOverflow) |
1622 | CCR = DAG.getConstant(Val: 0, DL, VT: N->getValueType(ResNo: 1)); |
1623 | else |
1624 | CCR = Arith.getValue(R: 1); |
1625 | } |
1626 | |
1627 | SDValue M68kTargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const { |
1628 | SDNode *N = Op.getNode(); |
1629 | SDLoc DL(Op); |
1630 | |
1631 | // Lower the "add/sub/mul with overflow" instruction into a regular ins plus |
1632 | // a "setcc" instruction that checks the overflow flag. |
1633 | SDValue Result, CCR; |
1634 | unsigned CC; |
1635 | lowerOverflowArithmetic(Op, DAG, Result, CCR, CC); |
1636 | |
1637 | SDValue Overflow; |
1638 | if (isa<ConstantSDNode>(Val: CCR)) { |
1639 | // It's likely a result of operations that will not overflow |
1640 | // hence no setcc is needed. |
1641 | Overflow = CCR; |
1642 | } else { |
1643 | // Generate a M68kISD::SETCC. |
1644 | Overflow = DAG.getNode(M68kISD::SETCC, DL, N->getValueType(1), |
1645 | DAG.getConstant(CC, DL, MVT::i8), CCR); |
1646 | } |
1647 | |
1648 | return DAG.getNode(Opcode: ISD::MERGE_VALUES, DL, VTList: N->getVTList(), N1: Result, N2: Overflow); |
1649 | } |
1650 | |
1651 | /// Create a BTST (Bit Test) node - Test bit \p BitNo in \p Src and set |
1652 | /// condition according to equal/not-equal condition code \p CC. |
1653 | static SDValue getBitTestCondition(SDValue Src, SDValue BitNo, ISD::CondCode CC, |
1654 | const SDLoc &DL, SelectionDAG &DAG) { |
1655 | // If Src is i8, promote it to i32 with any_extend. There is no i8 BTST |
1656 | // instruction. Since the shift amount is in-range-or-undefined, we know |
1657 | // that doing a bittest on the i32 value is ok. |
1658 | if (Src.getValueType() == MVT::i8 || Src.getValueType() == MVT::i16) |
1659 | Src = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Src); |
1660 | |
1661 | // If the operand types disagree, extend the shift amount to match. Since |
1662 | // BTST ignores high bits (like shifts) we can use anyextend. |
1663 | if (Src.getValueType() != BitNo.getValueType()) |
1664 | BitNo = DAG.getNode(Opcode: ISD::ANY_EXTEND, DL, VT: Src.getValueType(), Operand: BitNo); |
1665 | |
1666 | SDValue BTST = DAG.getNode(M68kISD::BTST, DL, MVT::i32, Src, BitNo); |
1667 | |
1668 | // NOTE BTST sets CCR.Z flag |
1669 | M68k::CondCode Cond = CC == ISD::SETEQ ? M68k::COND_NE : M68k::COND_EQ; |
1670 | return DAG.getNode(M68kISD::SETCC, DL, MVT::i8, |
1671 | DAG.getConstant(Cond, DL, MVT::i8), BTST); |
1672 | } |
1673 | |
1674 | /// Result of 'and' is compared against zero. Change to a BTST node if possible. |
1675 | static SDValue LowerAndToBTST(SDValue And, ISD::CondCode CC, const SDLoc &DL, |
1676 | SelectionDAG &DAG) { |
1677 | SDValue Op0 = And.getOperand(i: 0); |
1678 | SDValue Op1 = And.getOperand(i: 1); |
1679 | if (Op0.getOpcode() == ISD::TRUNCATE) |
1680 | Op0 = Op0.getOperand(i: 0); |
1681 | if (Op1.getOpcode() == ISD::TRUNCATE) |
1682 | Op1 = Op1.getOperand(i: 0); |
1683 | |
1684 | SDValue LHS, RHS; |
1685 | if (Op1.getOpcode() == ISD::SHL) |
1686 | std::swap(a&: Op0, b&: Op1); |
1687 | if (Op0.getOpcode() == ISD::SHL) { |
1688 | if (isOneConstant(V: Op0.getOperand(i: 0))) { |
1689 | // If we looked past a truncate, check that it's only truncating away |
1690 | // known zeros. |
1691 | unsigned BitWidth = Op0.getValueSizeInBits(); |
1692 | unsigned AndBitWidth = And.getValueSizeInBits(); |
1693 | if (BitWidth > AndBitWidth) { |
1694 | auto Known = DAG.computeKnownBits(Op: Op0); |
1695 | if (Known.countMinLeadingZeros() < BitWidth - AndBitWidth) |
1696 | return SDValue(); |
1697 | } |
1698 | LHS = Op1; |
1699 | RHS = Op0.getOperand(i: 1); |
1700 | } |
1701 | } else if (auto *AndRHS = dyn_cast<ConstantSDNode>(Val&: Op1)) { |
1702 | uint64_t AndRHSVal = AndRHS->getZExtValue(); |
1703 | SDValue AndLHS = Op0; |
1704 | |
1705 | if (AndRHSVal == 1 && AndLHS.getOpcode() == ISD::SRL) { |
1706 | LHS = AndLHS.getOperand(i: 0); |
1707 | RHS = AndLHS.getOperand(i: 1); |
1708 | } |
1709 | |
1710 | // Use BTST if the immediate can't be encoded in a TEST instruction. |
1711 | if (!isUInt<32>(x: AndRHSVal) && isPowerOf2_64(Value: AndRHSVal)) { |
1712 | LHS = AndLHS; |
1713 | RHS = DAG.getConstant(Val: Log2_64_Ceil(Value: AndRHSVal), DL, VT: LHS.getValueType()); |
1714 | } |
1715 | } |
1716 | |
1717 | if (LHS.getNode()) |
1718 | return getBitTestCondition(Src: LHS, BitNo: RHS, CC, DL, DAG); |
1719 | |
1720 | return SDValue(); |
1721 | } |
1722 | |
1723 | static M68k::CondCode TranslateIntegerM68kCC(ISD::CondCode SetCCOpcode) { |
1724 | switch (SetCCOpcode) { |
1725 | default: |
1726 | llvm_unreachable("Invalid integer condition!" ); |
1727 | case ISD::SETEQ: |
1728 | return M68k::COND_EQ; |
1729 | case ISD::SETGT: |
1730 | return M68k::COND_GT; |
1731 | case ISD::SETGE: |
1732 | return M68k::COND_GE; |
1733 | case ISD::SETLT: |
1734 | return M68k::COND_LT; |
1735 | case ISD::SETLE: |
1736 | return M68k::COND_LE; |
1737 | case ISD::SETNE: |
1738 | return M68k::COND_NE; |
1739 | case ISD::SETULT: |
1740 | return M68k::COND_CS; |
1741 | case ISD::SETUGE: |
1742 | return M68k::COND_CC; |
1743 | case ISD::SETUGT: |
1744 | return M68k::COND_HI; |
1745 | case ISD::SETULE: |
1746 | return M68k::COND_LS; |
1747 | } |
1748 | } |
1749 | |
1750 | /// Do a one-to-one translation of a ISD::CondCode to the M68k-specific |
1751 | /// condition code, returning the condition code and the LHS/RHS of the |
1752 | /// comparison to make. |
1753 | static unsigned TranslateM68kCC(ISD::CondCode SetCCOpcode, const SDLoc &DL, |
1754 | bool IsFP, SDValue &LHS, SDValue &RHS, |
1755 | SelectionDAG &DAG) { |
1756 | if (!IsFP) { |
1757 | if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(Val&: RHS)) { |
1758 | if (SetCCOpcode == ISD::SETGT && RHSC->isAllOnes()) { |
1759 | // X > -1 -> X == 0, jump !sign. |
1760 | RHS = DAG.getConstant(Val: 0, DL, VT: RHS.getValueType()); |
1761 | return M68k::COND_PL; |
1762 | } |
1763 | if (SetCCOpcode == ISD::SETLT && RHSC->isZero()) { |
1764 | // X < 0 -> X == 0, jump on sign. |
1765 | return M68k::COND_MI; |
1766 | } |
1767 | if (SetCCOpcode == ISD::SETLT && RHSC->getZExtValue() == 1) { |
1768 | // X < 1 -> X <= 0 |
1769 | RHS = DAG.getConstant(Val: 0, DL, VT: RHS.getValueType()); |
1770 | return M68k::COND_LE; |
1771 | } |
1772 | } |
1773 | |
1774 | return TranslateIntegerM68kCC(SetCCOpcode); |
1775 | } |
1776 | |
1777 | // First determine if it is required or is profitable to flip the operands. |
1778 | |
1779 | // If LHS is a foldable load, but RHS is not, flip the condition. |
1780 | if (ISD::isNON_EXTLoad(N: LHS.getNode()) && !ISD::isNON_EXTLoad(N: RHS.getNode())) { |
1781 | SetCCOpcode = getSetCCSwappedOperands(Operation: SetCCOpcode); |
1782 | std::swap(a&: LHS, b&: RHS); |
1783 | } |
1784 | |
1785 | switch (SetCCOpcode) { |
1786 | default: |
1787 | break; |
1788 | case ISD::SETOLT: |
1789 | case ISD::SETOLE: |
1790 | case ISD::SETUGT: |
1791 | case ISD::SETUGE: |
1792 | std::swap(a&: LHS, b&: RHS); |
1793 | break; |
1794 | } |
1795 | |
1796 | // On a floating point condition, the flags are set as follows: |
1797 | // ZF PF CF op |
1798 | // 0 | 0 | 0 | X > Y |
1799 | // 0 | 0 | 1 | X < Y |
1800 | // 1 | 0 | 0 | X == Y |
1801 | // 1 | 1 | 1 | unordered |
1802 | switch (SetCCOpcode) { |
1803 | default: |
1804 | llvm_unreachable("Condcode should be pre-legalized away" ); |
1805 | case ISD::SETUEQ: |
1806 | case ISD::SETEQ: |
1807 | return M68k::COND_EQ; |
1808 | case ISD::SETOLT: // flipped |
1809 | case ISD::SETOGT: |
1810 | case ISD::SETGT: |
1811 | return M68k::COND_HI; |
1812 | case ISD::SETOLE: // flipped |
1813 | case ISD::SETOGE: |
1814 | case ISD::SETGE: |
1815 | return M68k::COND_CC; |
1816 | case ISD::SETUGT: // flipped |
1817 | case ISD::SETULT: |
1818 | case ISD::SETLT: |
1819 | return M68k::COND_CS; |
1820 | case ISD::SETUGE: // flipped |
1821 | case ISD::SETULE: |
1822 | case ISD::SETLE: |
1823 | return M68k::COND_LS; |
1824 | case ISD::SETONE: |
1825 | case ISD::SETNE: |
1826 | return M68k::COND_NE; |
1827 | case ISD::SETOEQ: |
1828 | case ISD::SETUNE: |
1829 | return M68k::COND_INVALID; |
1830 | } |
1831 | } |
1832 | |
1833 | // Convert (truncate (srl X, N) to i1) to (bt X, N) |
1834 | static SDValue LowerTruncateToBTST(SDValue Op, ISD::CondCode CC, |
1835 | const SDLoc &DL, SelectionDAG &DAG) { |
1836 | |
1837 | assert(Op.getOpcode() == ISD::TRUNCATE && Op.getValueType() == MVT::i1 && |
1838 | "Expected TRUNCATE to i1 node" ); |
1839 | |
1840 | if (Op.getOperand(i: 0).getOpcode() != ISD::SRL) |
1841 | return SDValue(); |
1842 | |
1843 | SDValue ShiftRight = Op.getOperand(i: 0); |
1844 | return getBitTestCondition(Src: ShiftRight.getOperand(i: 0), BitNo: ShiftRight.getOperand(i: 1), |
1845 | CC, DL, DAG); |
1846 | } |
1847 | |
1848 | /// \brief return true if \c Op has a use that doesn't just read flags. |
1849 | static bool hasNonFlagsUse(SDValue Op) { |
1850 | for (SDNode::use_iterator UI = Op->use_begin(), UE = Op->use_end(); UI != UE; |
1851 | ++UI) { |
1852 | SDNode *User = *UI; |
1853 | unsigned UOpNo = UI.getOperandNo(); |
1854 | if (User->getOpcode() == ISD::TRUNCATE && User->hasOneUse()) { |
1855 | // Look pass truncate. |
1856 | UOpNo = User->use_begin().getOperandNo(); |
1857 | User = *User->use_begin(); |
1858 | } |
1859 | |
1860 | if (User->getOpcode() != ISD::BRCOND && User->getOpcode() != ISD::SETCC && |
1861 | !(User->getOpcode() == ISD::SELECT && UOpNo == 0)) |
1862 | return true; |
1863 | } |
1864 | return false; |
1865 | } |
1866 | |
1867 | SDValue M68kTargetLowering::EmitTest(SDValue Op, unsigned M68kCC, |
1868 | const SDLoc &DL, SelectionDAG &DAG) const { |
1869 | |
1870 | // CF and OF aren't always set the way we want. Determine which |
1871 | // of these we need. |
1872 | bool NeedCF = false; |
1873 | bool NeedOF = false; |
1874 | switch (M68kCC) { |
1875 | default: |
1876 | break; |
1877 | case M68k::COND_HI: |
1878 | case M68k::COND_CC: |
1879 | case M68k::COND_CS: |
1880 | case M68k::COND_LS: |
1881 | NeedCF = true; |
1882 | break; |
1883 | case M68k::COND_GT: |
1884 | case M68k::COND_GE: |
1885 | case M68k::COND_LT: |
1886 | case M68k::COND_LE: |
1887 | case M68k::COND_VS: |
1888 | case M68k::COND_VC: { |
1889 | // Check if we really need to set the |
1890 | // Overflow flag. If NoSignedWrap is present |
1891 | // that is not actually needed. |
1892 | switch (Op->getOpcode()) { |
1893 | case ISD::ADD: |
1894 | case ISD::SUB: |
1895 | case ISD::MUL: |
1896 | case ISD::SHL: { |
1897 | if (Op.getNode()->getFlags().hasNoSignedWrap()) |
1898 | break; |
1899 | [[fallthrough]]; |
1900 | } |
1901 | default: |
1902 | NeedOF = true; |
1903 | break; |
1904 | } |
1905 | break; |
1906 | } |
1907 | } |
1908 | // See if we can use the CCR value from the operand instead of |
1909 | // doing a separate TEST. TEST always sets OF and CF to 0, so unless |
1910 | // we prove that the arithmetic won't overflow, we can't use OF or CF. |
1911 | if (Op.getResNo() != 0 || NeedOF || NeedCF) { |
1912 | // Emit a CMP with 0, which is the TEST pattern. |
1913 | return DAG.getNode(M68kISD::CMP, DL, MVT::i8, |
1914 | DAG.getConstant(0, DL, Op.getValueType()), Op); |
1915 | } |
1916 | unsigned Opcode = 0; |
1917 | unsigned NumOperands = 0; |
1918 | |
1919 | // Truncate operations may prevent the merge of the SETCC instruction |
1920 | // and the arithmetic instruction before it. Attempt to truncate the operands |
1921 | // of the arithmetic instruction and use a reduced bit-width instruction. |
1922 | bool NeedTruncation = false; |
1923 | SDValue ArithOp = Op; |
1924 | if (Op->getOpcode() == ISD::TRUNCATE && Op->hasOneUse()) { |
1925 | SDValue Arith = Op->getOperand(Num: 0); |
1926 | // Both the trunc and the arithmetic op need to have one user each. |
1927 | if (Arith->hasOneUse()) |
1928 | switch (Arith.getOpcode()) { |
1929 | default: |
1930 | break; |
1931 | case ISD::ADD: |
1932 | case ISD::SUB: |
1933 | case ISD::AND: |
1934 | case ISD::OR: |
1935 | case ISD::XOR: { |
1936 | NeedTruncation = true; |
1937 | ArithOp = Arith; |
1938 | } |
1939 | } |
1940 | } |
1941 | |
1942 | // NOTICE: In the code below we use ArithOp to hold the arithmetic operation |
1943 | // which may be the result of a CAST. We use the variable 'Op', which is the |
1944 | // non-casted variable when we check for possible users. |
1945 | switch (ArithOp.getOpcode()) { |
1946 | case ISD::ADD: |
1947 | Opcode = M68kISD::ADD; |
1948 | NumOperands = 2; |
1949 | break; |
1950 | case ISD::SHL: |
1951 | case ISD::SRL: |
1952 | // If we have a constant logical shift that's only used in a comparison |
1953 | // against zero turn it into an equivalent AND. This allows turning it into |
1954 | // a TEST instruction later. |
1955 | if ((M68kCC == M68k::COND_EQ || M68kCC == M68k::COND_NE) && |
1956 | Op->hasOneUse() && isa<ConstantSDNode>(Val: Op->getOperand(Num: 1)) && |
1957 | !hasNonFlagsUse(Op)) { |
1958 | EVT VT = Op.getValueType(); |
1959 | unsigned BitWidth = VT.getSizeInBits(); |
1960 | unsigned ShAmt = Op->getConstantOperandVal(Num: 1); |
1961 | if (ShAmt >= BitWidth) // Avoid undefined shifts. |
1962 | break; |
1963 | APInt Mask = ArithOp.getOpcode() == ISD::SRL |
1964 | ? APInt::getHighBitsSet(numBits: BitWidth, hiBitsSet: BitWidth - ShAmt) |
1965 | : APInt::getLowBitsSet(numBits: BitWidth, loBitsSet: BitWidth - ShAmt); |
1966 | if (!Mask.isSignedIntN(N: 32)) // Avoid large immediates. |
1967 | break; |
1968 | Op = DAG.getNode(Opcode: ISD::AND, DL, VT, N1: Op->getOperand(Num: 0), |
1969 | N2: DAG.getConstant(Val: Mask, DL, VT)); |
1970 | } |
1971 | break; |
1972 | |
1973 | case ISD::AND: |
1974 | // If the primary 'and' result isn't used, don't bother using |
1975 | // M68kISD::AND, because a TEST instruction will be better. |
1976 | if (!hasNonFlagsUse(Op)) { |
1977 | SDValue Op0 = ArithOp->getOperand(Num: 0); |
1978 | SDValue Op1 = ArithOp->getOperand(Num: 1); |
1979 | EVT VT = ArithOp.getValueType(); |
1980 | bool IsAndn = isBitwiseNot(V: Op0) || isBitwiseNot(V: Op1); |
1981 | bool IsLegalAndnType = VT == MVT::i32 || VT == MVT::i64; |
1982 | |
1983 | // But if we can combine this into an ANDN operation, then create an AND |
1984 | // now and allow it to be pattern matched into an ANDN. |
1985 | if (/*!Subtarget.hasBMI() ||*/ !IsAndn || !IsLegalAndnType) |
1986 | break; |
1987 | } |
1988 | [[fallthrough]]; |
1989 | case ISD::SUB: |
1990 | case ISD::OR: |
1991 | case ISD::XOR: |
1992 | // Due to the ISEL shortcoming noted above, be conservative if this op is |
1993 | // likely to be selected as part of a load-modify-store instruction. |
1994 | for (const auto *U : Op.getNode()->uses()) |
1995 | if (U->getOpcode() == ISD::STORE) |
1996 | goto default_case; |
1997 | |
1998 | // Otherwise use a regular CCR-setting instruction. |
1999 | switch (ArithOp.getOpcode()) { |
2000 | default: |
2001 | llvm_unreachable("unexpected operator!" ); |
2002 | case ISD::SUB: |
2003 | Opcode = M68kISD::SUB; |
2004 | break; |
2005 | case ISD::XOR: |
2006 | Opcode = M68kISD::XOR; |
2007 | break; |
2008 | case ISD::AND: |
2009 | Opcode = M68kISD::AND; |
2010 | break; |
2011 | case ISD::OR: |
2012 | Opcode = M68kISD::OR; |
2013 | break; |
2014 | } |
2015 | |
2016 | NumOperands = 2; |
2017 | break; |
2018 | case M68kISD::ADD: |
2019 | case M68kISD::SUB: |
2020 | case M68kISD::OR: |
2021 | case M68kISD::XOR: |
2022 | case M68kISD::AND: |
2023 | return SDValue(Op.getNode(), 1); |
2024 | default: |
2025 | default_case: |
2026 | break; |
2027 | } |
2028 | |
2029 | // If we found that truncation is beneficial, perform the truncation and |
2030 | // update 'Op'. |
2031 | if (NeedTruncation) { |
2032 | EVT VT = Op.getValueType(); |
2033 | SDValue WideVal = Op->getOperand(Num: 0); |
2034 | EVT WideVT = WideVal.getValueType(); |
2035 | unsigned ConvertedOp = 0; |
2036 | // Use a target machine opcode to prevent further DAGCombine |
2037 | // optimizations that may separate the arithmetic operations |
2038 | // from the setcc node. |
2039 | switch (WideVal.getOpcode()) { |
2040 | default: |
2041 | break; |
2042 | case ISD::ADD: |
2043 | ConvertedOp = M68kISD::ADD; |
2044 | break; |
2045 | case ISD::SUB: |
2046 | ConvertedOp = M68kISD::SUB; |
2047 | break; |
2048 | case ISD::AND: |
2049 | ConvertedOp = M68kISD::AND; |
2050 | break; |
2051 | case ISD::OR: |
2052 | ConvertedOp = M68kISD::OR; |
2053 | break; |
2054 | case ISD::XOR: |
2055 | ConvertedOp = M68kISD::XOR; |
2056 | break; |
2057 | } |
2058 | |
2059 | if (ConvertedOp) { |
2060 | const TargetLowering &TLI = DAG.getTargetLoweringInfo(); |
2061 | if (TLI.isOperationLegal(Op: WideVal.getOpcode(), VT: WideVT)) { |
2062 | SDValue V0 = DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT, Operand: WideVal.getOperand(i: 0)); |
2063 | SDValue V1 = DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT, Operand: WideVal.getOperand(i: 1)); |
2064 | Op = DAG.getNode(Opcode: ConvertedOp, DL, VT, N1: V0, N2: V1); |
2065 | } |
2066 | } |
2067 | } |
2068 | |
2069 | if (Opcode == 0) { |
2070 | // Emit a CMP with 0, which is the TEST pattern. |
2071 | return DAG.getNode(M68kISD::CMP, DL, MVT::i8, |
2072 | DAG.getConstant(0, DL, Op.getValueType()), Op); |
2073 | } |
2074 | SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::i8); |
2075 | SmallVector<SDValue, 4> Ops(Op->op_begin(), Op->op_begin() + NumOperands); |
2076 | |
2077 | SDValue New = DAG.getNode(Opcode, DL, VTList: VTs, Ops); |
2078 | DAG.ReplaceAllUsesWith(From: Op, To: New); |
2079 | return SDValue(New.getNode(), 1); |
2080 | } |
2081 | |
2082 | /// \brief Return true if the condition is an unsigned comparison operation. |
2083 | static bool isM68kCCUnsigned(unsigned M68kCC) { |
2084 | switch (M68kCC) { |
2085 | default: |
2086 | llvm_unreachable("Invalid integer condition!" ); |
2087 | case M68k::COND_EQ: |
2088 | case M68k::COND_NE: |
2089 | case M68k::COND_CS: |
2090 | case M68k::COND_HI: |
2091 | case M68k::COND_LS: |
2092 | case M68k::COND_CC: |
2093 | return true; |
2094 | case M68k::COND_GT: |
2095 | case M68k::COND_GE: |
2096 | case M68k::COND_LT: |
2097 | case M68k::COND_LE: |
2098 | return false; |
2099 | } |
2100 | } |
2101 | |
2102 | SDValue M68kTargetLowering::EmitCmp(SDValue Op0, SDValue Op1, unsigned M68kCC, |
2103 | const SDLoc &DL, SelectionDAG &DAG) const { |
2104 | if (isNullConstant(V: Op1)) |
2105 | return EmitTest(Op: Op0, M68kCC, DL, DAG); |
2106 | |
2107 | assert(!(isa<ConstantSDNode>(Op1) && Op0.getValueType() == MVT::i1) && |
2108 | "Unexpected comparison operation for MVT::i1 operands" ); |
2109 | |
2110 | if ((Op0.getValueType() == MVT::i8 || Op0.getValueType() == MVT::i16 || |
2111 | Op0.getValueType() == MVT::i32 || Op0.getValueType() == MVT::i64)) { |
2112 | // Only promote the compare up to I32 if it is a 16 bit operation |
2113 | // with an immediate. 16 bit immediates are to be avoided. |
2114 | if ((Op0.getValueType() == MVT::i16 && |
2115 | (isa<ConstantSDNode>(Op0) || isa<ConstantSDNode>(Op1))) && |
2116 | !DAG.getMachineFunction().getFunction().hasMinSize()) { |
2117 | unsigned ExtendOp = |
2118 | isM68kCCUnsigned(M68kCC) ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND; |
2119 | Op0 = DAG.getNode(ExtendOp, DL, MVT::i32, Op0); |
2120 | Op1 = DAG.getNode(ExtendOp, DL, MVT::i32, Op1); |
2121 | } |
2122 | // Use SUB instead of CMP to enable CSE between SUB and CMP. |
2123 | SDVTList VTs = DAG.getVTList(Op0.getValueType(), MVT::i8); |
2124 | SDValue Sub = DAG.getNode(Opcode: M68kISD::SUB, DL, VTList: VTs, N1: Op0, N2: Op1); |
2125 | return SDValue(Sub.getNode(), 1); |
2126 | } |
2127 | return DAG.getNode(M68kISD::CMP, DL, MVT::i8, Op0, Op1); |
2128 | } |
2129 | |
2130 | /// Result of 'and' or 'trunc to i1' is compared against zero. |
2131 | /// Change to a BTST node if possible. |
2132 | SDValue M68kTargetLowering::LowerToBTST(SDValue Op, ISD::CondCode CC, |
2133 | const SDLoc &DL, |
2134 | SelectionDAG &DAG) const { |
2135 | if (Op.getOpcode() == ISD::AND) |
2136 | return LowerAndToBTST(And: Op, CC, DL, DAG); |
2137 | if (Op.getOpcode() == ISD::TRUNCATE && Op.getValueType() == MVT::i1) |
2138 | return LowerTruncateToBTST(Op, CC, DL, DAG); |
2139 | return SDValue(); |
2140 | } |
2141 | |
2142 | SDValue M68kTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { |
2143 | MVT VT = Op.getSimpleValueType(); |
2144 | assert(VT == MVT::i8 && "SetCC type must be 8-bit integer" ); |
2145 | |
2146 | SDValue Op0 = Op.getOperand(i: 0); |
2147 | SDValue Op1 = Op.getOperand(i: 1); |
2148 | SDLoc DL(Op); |
2149 | ISD::CondCode CC = cast<CondCodeSDNode>(Val: Op.getOperand(i: 2))->get(); |
2150 | |
2151 | // Optimize to BTST if possible. |
2152 | // Lower (X & (1 << N)) == 0 to BTST(X, N). |
2153 | // Lower ((X >>u N) & 1) != 0 to BTST(X, N). |
2154 | // Lower ((X >>s N) & 1) != 0 to BTST(X, N). |
2155 | // Lower (trunc (X >> N) to i1) to BTST(X, N). |
2156 | if (Op0.hasOneUse() && isNullConstant(V: Op1) && |
2157 | (CC == ISD::SETEQ || CC == ISD::SETNE)) { |
2158 | if (SDValue NewSetCC = LowerToBTST(Op: Op0, CC, DL, DAG)) { |
2159 | if (VT == MVT::i1) |
2160 | return DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, NewSetCC); |
2161 | return NewSetCC; |
2162 | } |
2163 | } |
2164 | |
2165 | // Look for X == 0, X == 1, X != 0, or X != 1. We can simplify some forms of |
2166 | // these. |
2167 | if ((isOneConstant(V: Op1) || isNullConstant(V: Op1)) && |
2168 | (CC == ISD::SETEQ || CC == ISD::SETNE)) { |
2169 | |
2170 | // If the input is a setcc, then reuse the input setcc or use a new one with |
2171 | // the inverted condition. |
2172 | if (Op0.getOpcode() == M68kISD::SETCC) { |
2173 | M68k::CondCode CCode = (M68k::CondCode)Op0.getConstantOperandVal(i: 0); |
2174 | bool Invert = (CC == ISD::SETNE) ^ isNullConstant(V: Op1); |
2175 | if (!Invert) |
2176 | return Op0; |
2177 | |
2178 | CCode = M68k::GetOppositeBranchCondition(CC: CCode); |
2179 | SDValue SetCC = |
2180 | DAG.getNode(M68kISD::SETCC, DL, MVT::i8, |
2181 | DAG.getConstant(CCode, DL, MVT::i8), Op0.getOperand(1)); |
2182 | if (VT == MVT::i1) |
2183 | return DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, SetCC); |
2184 | return SetCC; |
2185 | } |
2186 | } |
2187 | if (Op0.getValueType() == MVT::i1 && (CC == ISD::SETEQ || CC == ISD::SETNE)) { |
2188 | if (isOneConstant(V: Op1)) { |
2189 | ISD::CondCode NewCC = ISD::GlobalISel::getSetCCInverse(Operation: CC, isIntegerLike: true); |
2190 | return DAG.getSetCC(DL, VT, Op0, DAG.getConstant(0, DL, MVT::i1), NewCC); |
2191 | } |
2192 | if (!isNullConstant(V: Op1)) { |
2193 | SDValue Xor = DAG.getNode(ISD::XOR, DL, MVT::i1, Op0, Op1); |
2194 | return DAG.getSetCC(DL, VT, Xor, DAG.getConstant(0, DL, MVT::i1), CC); |
2195 | } |
2196 | } |
2197 | |
2198 | bool IsFP = Op1.getSimpleValueType().isFloatingPoint(); |
2199 | unsigned M68kCC = TranslateM68kCC(SetCCOpcode: CC, DL, IsFP, LHS&: Op0, RHS&: Op1, DAG); |
2200 | if (M68kCC == M68k::COND_INVALID) |
2201 | return SDValue(); |
2202 | |
2203 | SDValue CCR = EmitCmp(Op0, Op1, M68kCC, DL, DAG); |
2204 | return DAG.getNode(M68kISD::SETCC, DL, MVT::i8, |
2205 | DAG.getConstant(M68kCC, DL, MVT::i8), CCR); |
2206 | } |
2207 | |
2208 | SDValue M68kTargetLowering::LowerSETCCCARRY(SDValue Op, |
2209 | SelectionDAG &DAG) const { |
2210 | SDValue LHS = Op.getOperand(i: 0); |
2211 | SDValue RHS = Op.getOperand(i: 1); |
2212 | SDValue Carry = Op.getOperand(i: 2); |
2213 | SDValue Cond = Op.getOperand(i: 3); |
2214 | SDLoc DL(Op); |
2215 | |
2216 | assert(LHS.getSimpleValueType().isInteger() && "SETCCCARRY is integer only." ); |
2217 | M68k::CondCode CC = TranslateIntegerM68kCC(SetCCOpcode: cast<CondCodeSDNode>(Val&: Cond)->get()); |
2218 | |
2219 | EVT CarryVT = Carry.getValueType(); |
2220 | APInt NegOne = APInt::getAllOnes(numBits: CarryVT.getScalarSizeInBits()); |
2221 | Carry = DAG.getNode(M68kISD::ADD, DL, DAG.getVTList(CarryVT, MVT::i32), Carry, |
2222 | DAG.getConstant(NegOne, DL, CarryVT)); |
2223 | |
2224 | SDVTList VTs = DAG.getVTList(LHS.getValueType(), MVT::i32); |
2225 | SDValue Cmp = |
2226 | DAG.getNode(Opcode: M68kISD::SUBX, DL, VTList: VTs, N1: LHS, N2: RHS, N3: Carry.getValue(R: 1)); |
2227 | |
2228 | return DAG.getNode(M68kISD::SETCC, DL, MVT::i8, |
2229 | DAG.getConstant(CC, DL, MVT::i8), Cmp.getValue(1)); |
2230 | } |
2231 | |
2232 | /// Return true if opcode is a M68k logical comparison. |
2233 | static bool isM68kLogicalCmp(SDValue Op) { |
2234 | unsigned Opc = Op.getNode()->getOpcode(); |
2235 | if (Opc == M68kISD::CMP) |
2236 | return true; |
2237 | if (Op.getResNo() == 1 && |
2238 | (Opc == M68kISD::ADD || Opc == M68kISD::SUB || Opc == M68kISD::ADDX || |
2239 | Opc == M68kISD::SUBX || Opc == M68kISD::SMUL || Opc == M68kISD::UMUL || |
2240 | Opc == M68kISD::OR || Opc == M68kISD::XOR || Opc == M68kISD::AND)) |
2241 | return true; |
2242 | |
2243 | if (Op.getResNo() == 2 && Opc == M68kISD::UMUL) |
2244 | return true; |
2245 | |
2246 | return false; |
2247 | } |
2248 | |
2249 | static bool isTruncWithZeroHighBitsInput(SDValue V, SelectionDAG &DAG) { |
2250 | if (V.getOpcode() != ISD::TRUNCATE) |
2251 | return false; |
2252 | |
2253 | SDValue VOp0 = V.getOperand(i: 0); |
2254 | unsigned InBits = VOp0.getValueSizeInBits(); |
2255 | unsigned Bits = V.getValueSizeInBits(); |
2256 | return DAG.MaskedValueIsZero(Op: VOp0, |
2257 | Mask: APInt::getHighBitsSet(numBits: InBits, hiBitsSet: InBits - Bits)); |
2258 | } |
2259 | |
2260 | SDValue M68kTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { |
2261 | bool addTest = true; |
2262 | SDValue Cond = Op.getOperand(i: 0); |
2263 | SDValue Op1 = Op.getOperand(i: 1); |
2264 | SDValue Op2 = Op.getOperand(i: 2); |
2265 | SDLoc DL(Op); |
2266 | SDValue CC; |
2267 | |
2268 | if (Cond.getOpcode() == ISD::SETCC) { |
2269 | if (SDValue NewCond = LowerSETCC(Op: Cond, DAG)) |
2270 | Cond = NewCond; |
2271 | } |
2272 | |
2273 | // (select (x == 0), -1, y) -> (sign_bit (x - 1)) | y |
2274 | // (select (x == 0), y, -1) -> ~(sign_bit (x - 1)) | y |
2275 | // (select (x != 0), y, -1) -> (sign_bit (x - 1)) | y |
2276 | // (select (x != 0), -1, y) -> ~(sign_bit (x - 1)) | y |
2277 | if (Cond.getOpcode() == M68kISD::SETCC && |
2278 | Cond.getOperand(i: 1).getOpcode() == M68kISD::CMP && |
2279 | isNullConstant(V: Cond.getOperand(i: 1).getOperand(i: 0))) { |
2280 | SDValue Cmp = Cond.getOperand(i: 1); |
2281 | |
2282 | unsigned CondCode = Cond.getConstantOperandVal(i: 0); |
2283 | |
2284 | if ((isAllOnesConstant(V: Op1) || isAllOnesConstant(V: Op2)) && |
2285 | (CondCode == M68k::COND_EQ || CondCode == M68k::COND_NE)) { |
2286 | SDValue Y = isAllOnesConstant(V: Op2) ? Op1 : Op2; |
2287 | |
2288 | SDValue CmpOp0 = Cmp.getOperand(i: 1); |
2289 | // Apply further optimizations for special cases |
2290 | // (select (x != 0), -1, 0) -> neg & sbb |
2291 | // (select (x == 0), 0, -1) -> neg & sbb |
2292 | if (isNullConstant(V: Y) && |
2293 | (isAllOnesConstant(V: Op1) == (CondCode == M68k::COND_NE))) { |
2294 | |
2295 | SDVTList VTs = DAG.getVTList(CmpOp0.getValueType(), MVT::i32); |
2296 | |
2297 | SDValue Neg = |
2298 | DAG.getNode(Opcode: M68kISD::SUB, DL, VTList: VTs, |
2299 | N1: DAG.getConstant(Val: 0, DL, VT: CmpOp0.getValueType()), N2: CmpOp0); |
2300 | |
2301 | SDValue Res = DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(), |
2302 | DAG.getConstant(M68k::COND_CS, DL, MVT::i8), |
2303 | SDValue(Neg.getNode(), 1)); |
2304 | return Res; |
2305 | } |
2306 | |
2307 | Cmp = DAG.getNode(M68kISD::CMP, DL, MVT::i8, |
2308 | DAG.getConstant(1, DL, CmpOp0.getValueType()), CmpOp0); |
2309 | |
2310 | SDValue Res = // Res = 0 or -1. |
2311 | DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(), |
2312 | DAG.getConstant(M68k::COND_CS, DL, MVT::i8), Cmp); |
2313 | |
2314 | if (isAllOnesConstant(V: Op1) != (CondCode == M68k::COND_EQ)) |
2315 | Res = DAG.getNOT(DL, Val: Res, VT: Res.getValueType()); |
2316 | |
2317 | if (!isNullConstant(V: Op2)) |
2318 | Res = DAG.getNode(Opcode: ISD::OR, DL, VT: Res.getValueType(), N1: Res, N2: Y); |
2319 | return Res; |
2320 | } |
2321 | } |
2322 | |
2323 | // Look past (and (setcc_carry (cmp ...)), 1). |
2324 | if (Cond.getOpcode() == ISD::AND && |
2325 | Cond.getOperand(i: 0).getOpcode() == M68kISD::SETCC_CARRY && |
2326 | isOneConstant(V: Cond.getOperand(i: 1))) |
2327 | Cond = Cond.getOperand(i: 0); |
2328 | |
2329 | // If condition flag is set by a M68kISD::CMP, then use it as the condition |
2330 | // setting operand in place of the M68kISD::SETCC. |
2331 | unsigned CondOpcode = Cond.getOpcode(); |
2332 | if (CondOpcode == M68kISD::SETCC || CondOpcode == M68kISD::SETCC_CARRY) { |
2333 | CC = Cond.getOperand(i: 0); |
2334 | |
2335 | SDValue Cmp = Cond.getOperand(i: 1); |
2336 | unsigned Opc = Cmp.getOpcode(); |
2337 | |
2338 | bool IllegalFPCMov = false; |
2339 | |
2340 | if ((isM68kLogicalCmp(Op: Cmp) && !IllegalFPCMov) || Opc == M68kISD::BTST) { |
2341 | Cond = Cmp; |
2342 | addTest = false; |
2343 | } |
2344 | } else if (isOverflowArithmetic(Opcode: CondOpcode)) { |
2345 | // Result is unused here. |
2346 | SDValue Result; |
2347 | unsigned CCode; |
2348 | lowerOverflowArithmetic(Op: Cond, DAG, Result, CCR&: Cond, CC&: CCode); |
2349 | CC = DAG.getConstant(CCode, DL, MVT::i8); |
2350 | addTest = false; |
2351 | } |
2352 | |
2353 | if (addTest) { |
2354 | // Look past the truncate if the high bits are known zero. |
2355 | if (isTruncWithZeroHighBitsInput(V: Cond, DAG)) |
2356 | Cond = Cond.getOperand(i: 0); |
2357 | |
2358 | // We know the result of AND is compared against zero. Try to match |
2359 | // it to BT. |
2360 | if (Cond.getOpcode() == ISD::AND && Cond.hasOneUse()) { |
2361 | if (SDValue NewSetCC = LowerToBTST(Op: Cond, CC: ISD::SETNE, DL, DAG)) { |
2362 | CC = NewSetCC.getOperand(i: 0); |
2363 | Cond = NewSetCC.getOperand(i: 1); |
2364 | addTest = false; |
2365 | } |
2366 | } |
2367 | } |
2368 | |
2369 | if (addTest) { |
2370 | CC = DAG.getConstant(M68k::COND_NE, DL, MVT::i8); |
2371 | Cond = EmitTest(Op: Cond, M68kCC: M68k::COND_NE, DL, DAG); |
2372 | } |
2373 | |
2374 | // a < b ? -1 : 0 -> RES = ~setcc_carry |
2375 | // a < b ? 0 : -1 -> RES = setcc_carry |
2376 | // a >= b ? -1 : 0 -> RES = setcc_carry |
2377 | // a >= b ? 0 : -1 -> RES = ~setcc_carry |
2378 | if (Cond.getOpcode() == M68kISD::SUB) { |
2379 | unsigned CondCode = CC->getAsZExtVal(); |
2380 | |
2381 | if ((CondCode == M68k::COND_CC || CondCode == M68k::COND_CS) && |
2382 | (isAllOnesConstant(V: Op1) || isAllOnesConstant(V: Op2)) && |
2383 | (isNullConstant(V: Op1) || isNullConstant(V: Op2))) { |
2384 | SDValue Res = |
2385 | DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(), |
2386 | DAG.getConstant(M68k::COND_CS, DL, MVT::i8), Cond); |
2387 | if (isAllOnesConstant(V: Op1) != (CondCode == M68k::COND_CS)) |
2388 | return DAG.getNOT(DL, Val: Res, VT: Res.getValueType()); |
2389 | return Res; |
2390 | } |
2391 | } |
2392 | |
2393 | // M68k doesn't have an i8 cmov. If both operands are the result of a |
2394 | // truncate widen the cmov and push the truncate through. This avoids |
2395 | // introducing a new branch during isel and doesn't add any extensions. |
2396 | if (Op.getValueType() == MVT::i8 && Op1.getOpcode() == ISD::TRUNCATE && |
2397 | Op2.getOpcode() == ISD::TRUNCATE) { |
2398 | SDValue T1 = Op1.getOperand(i: 0), T2 = Op2.getOperand(i: 0); |
2399 | if (T1.getValueType() == T2.getValueType() && |
2400 | // Block CopyFromReg so partial register stalls are avoided. |
2401 | T1.getOpcode() != ISD::CopyFromReg && |
2402 | T2.getOpcode() != ISD::CopyFromReg) { |
2403 | SDVTList VTs = DAG.getVTList(T1.getValueType(), MVT::Glue); |
2404 | SDValue Cmov = DAG.getNode(Opcode: M68kISD::CMOV, DL, VTList: VTs, N1: T2, N2: T1, N3: CC, N4: Cond); |
2405 | return DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT: Op.getValueType(), Operand: Cmov); |
2406 | } |
2407 | } |
2408 | |
2409 | // Simple optimization when Cond is a constant to avoid generating |
2410 | // M68kISD::CMOV if possible. |
2411 | // TODO: Generalize this to use SelectionDAG::computeKnownBits. |
2412 | if (auto *Const = dyn_cast<ConstantSDNode>(Val: Cond.getNode())) { |
2413 | const APInt &C = Const->getAPIntValue(); |
2414 | if (C.countr_zero() >= 5) |
2415 | return Op2; |
2416 | else if (C.countr_one() >= 5) |
2417 | return Op1; |
2418 | } |
2419 | |
2420 | // M68kISD::CMOV means set the result (which is operand 1) to the RHS if |
2421 | // condition is true. |
2422 | SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); |
2423 | SDValue Ops[] = {Op2, Op1, CC, Cond}; |
2424 | return DAG.getNode(Opcode: M68kISD::CMOV, DL, VTList: VTs, Ops); |
2425 | } |
2426 | |
2427 | /// Return true if node is an ISD::AND or ISD::OR of two M68k::SETcc nodes |
2428 | /// each of which has no other use apart from the AND / OR. |
2429 | static bool isAndOrOfSetCCs(SDValue Op, unsigned &Opc) { |
2430 | Opc = Op.getOpcode(); |
2431 | if (Opc != ISD::OR && Opc != ISD::AND) |
2432 | return false; |
2433 | return (M68k::IsSETCC(SETCC: Op.getOperand(i: 0).getOpcode()) && |
2434 | Op.getOperand(i: 0).hasOneUse() && |
2435 | M68k::IsSETCC(SETCC: Op.getOperand(i: 1).getOpcode()) && |
2436 | Op.getOperand(i: 1).hasOneUse()); |
2437 | } |
2438 | |
2439 | /// Return true if node is an ISD::XOR of a M68kISD::SETCC and 1 and that the |
2440 | /// SETCC node has a single use. |
2441 | static bool isXor1OfSetCC(SDValue Op) { |
2442 | if (Op.getOpcode() != ISD::XOR) |
2443 | return false; |
2444 | if (isOneConstant(V: Op.getOperand(i: 1))) |
2445 | return Op.getOperand(i: 0).getOpcode() == M68kISD::SETCC && |
2446 | Op.getOperand(i: 0).hasOneUse(); |
2447 | return false; |
2448 | } |
2449 | |
2450 | SDValue M68kTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { |
2451 | bool AddTest = true; |
2452 | SDValue Chain = Op.getOperand(i: 0); |
2453 | SDValue Cond = Op.getOperand(i: 1); |
2454 | SDValue Dest = Op.getOperand(i: 2); |
2455 | SDLoc DL(Op); |
2456 | SDValue CC; |
2457 | bool Inverted = false; |
2458 | |
2459 | if (Cond.getOpcode() == ISD::SETCC) { |
2460 | // Check for setcc([su]{add,sub}o == 0). |
2461 | if (cast<CondCodeSDNode>(Val: Cond.getOperand(i: 2))->get() == ISD::SETEQ && |
2462 | isNullConstant(V: Cond.getOperand(i: 1)) && |
2463 | Cond.getOperand(i: 0).getResNo() == 1 && |
2464 | (Cond.getOperand(i: 0).getOpcode() == ISD::SADDO || |
2465 | Cond.getOperand(i: 0).getOpcode() == ISD::UADDO || |
2466 | Cond.getOperand(i: 0).getOpcode() == ISD::SSUBO || |
2467 | Cond.getOperand(i: 0).getOpcode() == ISD::USUBO)) { |
2468 | Inverted = true; |
2469 | Cond = Cond.getOperand(i: 0); |
2470 | } else { |
2471 | if (SDValue NewCond = LowerSETCC(Op: Cond, DAG)) |
2472 | Cond = NewCond; |
2473 | } |
2474 | } |
2475 | |
2476 | // Look pass (and (setcc_carry (cmp ...)), 1). |
2477 | if (Cond.getOpcode() == ISD::AND && |
2478 | Cond.getOperand(i: 0).getOpcode() == M68kISD::SETCC_CARRY && |
2479 | isOneConstant(V: Cond.getOperand(i: 1))) |
2480 | Cond = Cond.getOperand(i: 0); |
2481 | |
2482 | // If condition flag is set by a M68kISD::CMP, then use it as the condition |
2483 | // setting operand in place of the M68kISD::SETCC. |
2484 | unsigned CondOpcode = Cond.getOpcode(); |
2485 | if (CondOpcode == M68kISD::SETCC || CondOpcode == M68kISD::SETCC_CARRY) { |
2486 | CC = Cond.getOperand(i: 0); |
2487 | |
2488 | SDValue Cmp = Cond.getOperand(i: 1); |
2489 | unsigned Opc = Cmp.getOpcode(); |
2490 | |
2491 | if (isM68kLogicalCmp(Op: Cmp) || Opc == M68kISD::BTST) { |
2492 | Cond = Cmp; |
2493 | AddTest = false; |
2494 | } else { |
2495 | switch (CC->getAsZExtVal()) { |
2496 | default: |
2497 | break; |
2498 | case M68k::COND_VS: |
2499 | case M68k::COND_CS: |
2500 | // These can only come from an arithmetic instruction with overflow, |
2501 | // e.g. SADDO, UADDO. |
2502 | Cond = Cond.getNode()->getOperand(Num: 1); |
2503 | AddTest = false; |
2504 | break; |
2505 | } |
2506 | } |
2507 | } |
2508 | CondOpcode = Cond.getOpcode(); |
2509 | if (isOverflowArithmetic(Opcode: CondOpcode)) { |
2510 | SDValue Result; |
2511 | unsigned CCode; |
2512 | lowerOverflowArithmetic(Op: Cond, DAG, Result, CCR&: Cond, CC&: CCode); |
2513 | |
2514 | if (Inverted) |
2515 | CCode = M68k::GetOppositeBranchCondition(CC: (M68k::CondCode)CCode); |
2516 | CC = DAG.getConstant(CCode, DL, MVT::i8); |
2517 | |
2518 | AddTest = false; |
2519 | } else { |
2520 | unsigned CondOpc; |
2521 | if (Cond.hasOneUse() && isAndOrOfSetCCs(Op: Cond, Opc&: CondOpc)) { |
2522 | SDValue Cmp = Cond.getOperand(i: 0).getOperand(i: 1); |
2523 | if (CondOpc == ISD::OR) { |
2524 | // Also, recognize the pattern generated by an FCMP_UNE. We can emit |
2525 | // two branches instead of an explicit OR instruction with a |
2526 | // separate test. |
2527 | if (Cmp == Cond.getOperand(i: 1).getOperand(i: 1) && isM68kLogicalCmp(Op: Cmp)) { |
2528 | CC = Cond.getOperand(i: 0).getOperand(i: 0); |
2529 | Chain = DAG.getNode(Opcode: M68kISD::BRCOND, DL, VT: Op.getValueType(), N1: Chain, |
2530 | N2: Dest, N3: CC, N4: Cmp); |
2531 | CC = Cond.getOperand(i: 1).getOperand(i: 0); |
2532 | Cond = Cmp; |
2533 | AddTest = false; |
2534 | } |
2535 | } else { // ISD::AND |
2536 | // Also, recognize the pattern generated by an FCMP_OEQ. We can emit |
2537 | // two branches instead of an explicit AND instruction with a |
2538 | // separate test. However, we only do this if this block doesn't |
2539 | // have a fall-through edge, because this requires an explicit |
2540 | // jmp when the condition is false. |
2541 | if (Cmp == Cond.getOperand(i: 1).getOperand(i: 1) && isM68kLogicalCmp(Op: Cmp) && |
2542 | Op.getNode()->hasOneUse()) { |
2543 | M68k::CondCode CCode = |
2544 | (M68k::CondCode)Cond.getOperand(i: 0).getConstantOperandVal(i: 0); |
2545 | CCode = M68k::GetOppositeBranchCondition(CC: CCode); |
2546 | CC = DAG.getConstant(CCode, DL, MVT::i8); |
2547 | SDNode *User = *Op.getNode()->use_begin(); |
2548 | // Look for an unconditional branch following this conditional branch. |
2549 | // We need this because we need to reverse the successors in order |
2550 | // to implement FCMP_OEQ. |
2551 | if (User->getOpcode() == ISD::BR) { |
2552 | SDValue FalseBB = User->getOperand(Num: 1); |
2553 | SDNode *NewBR = |
2554 | DAG.UpdateNodeOperands(N: User, Op1: User->getOperand(Num: 0), Op2: Dest); |
2555 | assert(NewBR == User); |
2556 | (void)NewBR; |
2557 | Dest = FalseBB; |
2558 | |
2559 | Chain = DAG.getNode(Opcode: M68kISD::BRCOND, DL, VT: Op.getValueType(), N1: Chain, |
2560 | N2: Dest, N3: CC, N4: Cmp); |
2561 | M68k::CondCode CCode = |
2562 | (M68k::CondCode)Cond.getOperand(i: 1).getConstantOperandVal(i: 0); |
2563 | CCode = M68k::GetOppositeBranchCondition(CC: CCode); |
2564 | CC = DAG.getConstant(CCode, DL, MVT::i8); |
2565 | Cond = Cmp; |
2566 | AddTest = false; |
2567 | } |
2568 | } |
2569 | } |
2570 | } else if (Cond.hasOneUse() && isXor1OfSetCC(Op: Cond)) { |
2571 | // Recognize for xorb (setcc), 1 patterns. The xor inverts the condition. |
2572 | // It should be transformed during dag combiner except when the condition |
2573 | // is set by a arithmetics with overflow node. |
2574 | M68k::CondCode CCode = |
2575 | (M68k::CondCode)Cond.getOperand(i: 0).getConstantOperandVal(i: 0); |
2576 | CCode = M68k::GetOppositeBranchCondition(CC: CCode); |
2577 | CC = DAG.getConstant(CCode, DL, MVT::i8); |
2578 | Cond = Cond.getOperand(i: 0).getOperand(i: 1); |
2579 | AddTest = false; |
2580 | } |
2581 | } |
2582 | |
2583 | if (AddTest) { |
2584 | // Look pass the truncate if the high bits are known zero. |
2585 | if (isTruncWithZeroHighBitsInput(V: Cond, DAG)) |
2586 | Cond = Cond.getOperand(i: 0); |
2587 | |
2588 | // We know the result is compared against zero. Try to match it to BT. |
2589 | if (Cond.hasOneUse()) { |
2590 | if (SDValue NewSetCC = LowerToBTST(Op: Cond, CC: ISD::SETNE, DL, DAG)) { |
2591 | CC = NewSetCC.getOperand(i: 0); |
2592 | Cond = NewSetCC.getOperand(i: 1); |
2593 | AddTest = false; |
2594 | } |
2595 | } |
2596 | } |
2597 | |
2598 | if (AddTest) { |
2599 | M68k::CondCode MxCond = Inverted ? M68k::COND_EQ : M68k::COND_NE; |
2600 | CC = DAG.getConstant(MxCond, DL, MVT::i8); |
2601 | Cond = EmitTest(Op: Cond, M68kCC: MxCond, DL, DAG); |
2602 | } |
2603 | return DAG.getNode(Opcode: M68kISD::BRCOND, DL, VT: Op.getValueType(), N1: Chain, N2: Dest, N3: CC, |
2604 | N4: Cond); |
2605 | } |
2606 | |
2607 | SDValue M68kTargetLowering::LowerADDC_ADDE_SUBC_SUBE(SDValue Op, |
2608 | SelectionDAG &DAG) const { |
2609 | MVT VT = Op.getNode()->getSimpleValueType(ResNo: 0); |
2610 | |
2611 | // Let legalize expand this if it isn't a legal type yet. |
2612 | if (!DAG.getTargetLoweringInfo().isTypeLegal(VT)) |
2613 | return SDValue(); |
2614 | |
2615 | SDVTList VTs = DAG.getVTList(VT, MVT::i8); |
2616 | |
2617 | unsigned Opc; |
2618 | bool = false; |
2619 | switch (Op.getOpcode()) { |
2620 | default: |
2621 | llvm_unreachable("Invalid code" ); |
2622 | case ISD::ADDC: |
2623 | Opc = M68kISD::ADD; |
2624 | break; |
2625 | case ISD::ADDE: |
2626 | Opc = M68kISD::ADDX; |
2627 | ExtraOp = true; |
2628 | break; |
2629 | case ISD::SUBC: |
2630 | Opc = M68kISD::SUB; |
2631 | break; |
2632 | case ISD::SUBE: |
2633 | Opc = M68kISD::SUBX; |
2634 | ExtraOp = true; |
2635 | break; |
2636 | } |
2637 | |
2638 | if (!ExtraOp) |
2639 | return DAG.getNode(Opcode: Opc, DL: SDLoc(Op), VTList: VTs, N1: Op.getOperand(i: 0), N2: Op.getOperand(i: 1)); |
2640 | return DAG.getNode(Opcode: Opc, DL: SDLoc(Op), VTList: VTs, N1: Op.getOperand(i: 0), N2: Op.getOperand(i: 1), |
2641 | N3: Op.getOperand(i: 2)); |
2642 | } |
2643 | |
2644 | // ConstantPool, JumpTable, GlobalAddress, and ExternalSymbol are lowered as |
2645 | // their target countpart wrapped in the M68kISD::Wrapper node. Suppose N is |
2646 | // one of the above mentioned nodes. It has to be wrapped because otherwise |
2647 | // Select(N) returns N. So the raw TargetGlobalAddress nodes, etc. can only |
2648 | // be used to form addressing mode. These wrapped nodes will be selected |
2649 | // into MOV32ri. |
2650 | SDValue M68kTargetLowering::LowerConstantPool(SDValue Op, |
2651 | SelectionDAG &DAG) const { |
2652 | ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Val&: Op); |
2653 | |
2654 | // In PIC mode (unless we're in PCRel PIC mode) we add an offset to the |
2655 | // global base reg. |
2656 | unsigned char OpFlag = Subtarget.classifyLocalReference(GV: nullptr); |
2657 | |
2658 | unsigned WrapperKind = M68kISD::Wrapper; |
2659 | if (M68kII::isPCRelGlobalReference(Flag: OpFlag)) { |
2660 | WrapperKind = M68kISD::WrapperPC; |
2661 | } |
2662 | |
2663 | MVT PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
2664 | SDValue Result = DAG.getTargetConstantPool( |
2665 | C: CP->getConstVal(), VT: PtrVT, Align: CP->getAlign(), Offset: CP->getOffset(), TargetFlags: OpFlag); |
2666 | |
2667 | SDLoc DL(CP); |
2668 | Result = DAG.getNode(Opcode: WrapperKind, DL, VT: PtrVT, Operand: Result); |
2669 | |
2670 | // With PIC, the address is actually $g + Offset. |
2671 | if (M68kII::isGlobalRelativeToPICBase(TargetFlag: OpFlag)) { |
2672 | Result = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, |
2673 | N1: DAG.getNode(Opcode: M68kISD::GLOBAL_BASE_REG, DL: SDLoc(), VT: PtrVT), |
2674 | N2: Result); |
2675 | } |
2676 | |
2677 | return Result; |
2678 | } |
2679 | |
2680 | SDValue M68kTargetLowering::LowerExternalSymbol(SDValue Op, |
2681 | SelectionDAG &DAG) const { |
2682 | const char *Sym = cast<ExternalSymbolSDNode>(Val&: Op)->getSymbol(); |
2683 | |
2684 | // In PIC mode (unless we're in PCRel PIC mode) we add an offset to the |
2685 | // global base reg. |
2686 | const Module *Mod = DAG.getMachineFunction().getFunction().getParent(); |
2687 | unsigned char OpFlag = Subtarget.classifyExternalReference(M: *Mod); |
2688 | |
2689 | unsigned WrapperKind = M68kISD::Wrapper; |
2690 | if (M68kII::isPCRelGlobalReference(Flag: OpFlag)) { |
2691 | WrapperKind = M68kISD::WrapperPC; |
2692 | } |
2693 | |
2694 | auto PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
2695 | SDValue Result = DAG.getTargetExternalSymbol(Sym, VT: PtrVT, TargetFlags: OpFlag); |
2696 | |
2697 | SDLoc DL(Op); |
2698 | Result = DAG.getNode(Opcode: WrapperKind, DL, VT: PtrVT, Operand: Result); |
2699 | |
2700 | // With PIC, the address is actually $g + Offset. |
2701 | if (M68kII::isGlobalRelativeToPICBase(TargetFlag: OpFlag)) { |
2702 | Result = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, |
2703 | N1: DAG.getNode(Opcode: M68kISD::GLOBAL_BASE_REG, DL: SDLoc(), VT: PtrVT), |
2704 | N2: Result); |
2705 | } |
2706 | |
2707 | // For symbols that require a load from a stub to get the address, emit the |
2708 | // load. |
2709 | if (M68kII::isGlobalStubReference(TargetFlag: OpFlag)) { |
2710 | Result = DAG.getLoad(VT: PtrVT, dl: DL, Chain: DAG.getEntryNode(), Ptr: Result, |
2711 | PtrInfo: MachinePointerInfo::getGOT(MF&: DAG.getMachineFunction())); |
2712 | } |
2713 | |
2714 | return Result; |
2715 | } |
2716 | |
2717 | SDValue M68kTargetLowering::LowerBlockAddress(SDValue Op, |
2718 | SelectionDAG &DAG) const { |
2719 | unsigned char OpFlags = Subtarget.classifyBlockAddressReference(); |
2720 | const BlockAddress *BA = cast<BlockAddressSDNode>(Val&: Op)->getBlockAddress(); |
2721 | int64_t Offset = cast<BlockAddressSDNode>(Val&: Op)->getOffset(); |
2722 | SDLoc DL(Op); |
2723 | auto PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
2724 | |
2725 | // Create the TargetBlockAddressAddress node. |
2726 | SDValue Result = DAG.getTargetBlockAddress(BA, VT: PtrVT, Offset, TargetFlags: OpFlags); |
2727 | |
2728 | if (M68kII::isPCRelBlockReference(Flag: OpFlags)) { |
2729 | Result = DAG.getNode(Opcode: M68kISD::WrapperPC, DL, VT: PtrVT, Operand: Result); |
2730 | } else { |
2731 | Result = DAG.getNode(Opcode: M68kISD::Wrapper, DL, VT: PtrVT, Operand: Result); |
2732 | } |
2733 | |
2734 | // With PIC, the address is actually $g + Offset. |
2735 | if (M68kII::isGlobalRelativeToPICBase(TargetFlag: OpFlags)) { |
2736 | Result = |
2737 | DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, |
2738 | N1: DAG.getNode(Opcode: M68kISD::GLOBAL_BASE_REG, DL, VT: PtrVT), N2: Result); |
2739 | } |
2740 | |
2741 | return Result; |
2742 | } |
2743 | |
2744 | SDValue M68kTargetLowering::LowerGlobalAddress(const GlobalValue *GV, |
2745 | const SDLoc &DL, int64_t Offset, |
2746 | SelectionDAG &DAG) const { |
2747 | unsigned char OpFlags = Subtarget.classifyGlobalReference(GV); |
2748 | auto PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
2749 | |
2750 | // Create the TargetGlobalAddress node, folding in the constant |
2751 | // offset if it is legal. |
2752 | SDValue Result; |
2753 | if (M68kII::isDirectGlobalReference(Flag: OpFlags)) { |
2754 | Result = DAG.getTargetGlobalAddress(GV, DL, VT: PtrVT, offset: Offset); |
2755 | Offset = 0; |
2756 | } else { |
2757 | Result = DAG.getTargetGlobalAddress(GV, DL, VT: PtrVT, offset: 0, TargetFlags: OpFlags); |
2758 | } |
2759 | |
2760 | if (M68kII::isPCRelGlobalReference(Flag: OpFlags)) |
2761 | Result = DAG.getNode(Opcode: M68kISD::WrapperPC, DL, VT: PtrVT, Operand: Result); |
2762 | else |
2763 | Result = DAG.getNode(Opcode: M68kISD::Wrapper, DL, VT: PtrVT, Operand: Result); |
2764 | |
2765 | // With PIC, the address is actually $g + Offset. |
2766 | if (M68kII::isGlobalRelativeToPICBase(TargetFlag: OpFlags)) { |
2767 | Result = |
2768 | DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, |
2769 | N1: DAG.getNode(Opcode: M68kISD::GLOBAL_BASE_REG, DL, VT: PtrVT), N2: Result); |
2770 | } |
2771 | |
2772 | // For globals that require a load from a stub to get the address, emit the |
2773 | // load. |
2774 | if (M68kII::isGlobalStubReference(TargetFlag: OpFlags)) { |
2775 | Result = DAG.getLoad(VT: PtrVT, dl: DL, Chain: DAG.getEntryNode(), Ptr: Result, |
2776 | PtrInfo: MachinePointerInfo::getGOT(MF&: DAG.getMachineFunction())); |
2777 | } |
2778 | |
2779 | // If there was a non-zero offset that we didn't fold, create an explicit |
2780 | // addition for it. |
2781 | if (Offset != 0) { |
2782 | Result = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, N1: Result, |
2783 | N2: DAG.getConstant(Val: Offset, DL, VT: PtrVT)); |
2784 | } |
2785 | |
2786 | return Result; |
2787 | } |
2788 | |
2789 | SDValue M68kTargetLowering::LowerGlobalAddress(SDValue Op, |
2790 | SelectionDAG &DAG) const { |
2791 | const GlobalValue *GV = cast<GlobalAddressSDNode>(Val&: Op)->getGlobal(); |
2792 | int64_t Offset = cast<GlobalAddressSDNode>(Val&: Op)->getOffset(); |
2793 | return LowerGlobalAddress(GV, DL: SDLoc(Op), Offset, DAG); |
2794 | } |
2795 | |
2796 | //===----------------------------------------------------------------------===// |
2797 | // Custom Lower Jump Table |
2798 | //===----------------------------------------------------------------------===// |
2799 | |
2800 | SDValue M68kTargetLowering::LowerJumpTable(SDValue Op, |
2801 | SelectionDAG &DAG) const { |
2802 | JumpTableSDNode *JT = cast<JumpTableSDNode>(Val&: Op); |
2803 | |
2804 | // In PIC mode (unless we're in PCRel PIC mode) we add an offset to the |
2805 | // global base reg. |
2806 | unsigned char OpFlag = Subtarget.classifyLocalReference(GV: nullptr); |
2807 | |
2808 | unsigned WrapperKind = M68kISD::Wrapper; |
2809 | if (M68kII::isPCRelGlobalReference(Flag: OpFlag)) { |
2810 | WrapperKind = M68kISD::WrapperPC; |
2811 | } |
2812 | |
2813 | auto PtrVT = getPointerTy(DL: DAG.getDataLayout()); |
2814 | SDValue Result = DAG.getTargetJumpTable(JTI: JT->getIndex(), VT: PtrVT, TargetFlags: OpFlag); |
2815 | SDLoc DL(JT); |
2816 | Result = DAG.getNode(Opcode: WrapperKind, DL, VT: PtrVT, Operand: Result); |
2817 | |
2818 | // With PIC, the address is actually $g + Offset. |
2819 | if (M68kII::isGlobalRelativeToPICBase(TargetFlag: OpFlag)) { |
2820 | Result = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, |
2821 | N1: DAG.getNode(Opcode: M68kISD::GLOBAL_BASE_REG, DL: SDLoc(), VT: PtrVT), |
2822 | N2: Result); |
2823 | } |
2824 | |
2825 | return Result; |
2826 | } |
2827 | |
2828 | unsigned M68kTargetLowering::getJumpTableEncoding() const { |
2829 | return Subtarget.getJumpTableEncoding(); |
2830 | } |
2831 | |
2832 | const MCExpr *M68kTargetLowering::LowerCustomJumpTableEntry( |
2833 | const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, |
2834 | unsigned uid, MCContext &Ctx) const { |
2835 | return MCSymbolRefExpr::create(Symbol: MBB->getSymbol(), Kind: MCSymbolRefExpr::VK_GOTOFF, |
2836 | Ctx); |
2837 | } |
2838 | |
2839 | SDValue M68kTargetLowering::getPICJumpTableRelocBase(SDValue Table, |
2840 | SelectionDAG &DAG) const { |
2841 | if (getJumpTableEncoding() == MachineJumpTableInfo::EK_Custom32) |
2842 | return DAG.getNode(Opcode: M68kISD::GLOBAL_BASE_REG, DL: SDLoc(), |
2843 | VT: getPointerTy(DL: DAG.getDataLayout())); |
2844 | |
2845 | // MachineJumpTableInfo::EK_LabelDifference32 entry |
2846 | return Table; |
2847 | } |
2848 | |
2849 | // NOTE This only used for MachineJumpTableInfo::EK_LabelDifference32 entries |
2850 | const MCExpr *M68kTargetLowering::getPICJumpTableRelocBaseExpr( |
2851 | const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const { |
2852 | return MCSymbolRefExpr::create(Symbol: MF->getJTISymbol(JTI, Ctx), Ctx); |
2853 | } |
2854 | |
2855 | M68kTargetLowering::ConstraintType |
2856 | M68kTargetLowering::getConstraintType(StringRef Constraint) const { |
2857 | if (Constraint.size() > 0) { |
2858 | switch (Constraint[0]) { |
2859 | case 'a': |
2860 | case 'd': |
2861 | return C_RegisterClass; |
2862 | case 'I': |
2863 | case 'J': |
2864 | case 'K': |
2865 | case 'L': |
2866 | case 'M': |
2867 | case 'N': |
2868 | case 'O': |
2869 | case 'P': |
2870 | return C_Immediate; |
2871 | case 'C': |
2872 | if (Constraint.size() == 2) |
2873 | switch (Constraint[1]) { |
2874 | case '0': |
2875 | case 'i': |
2876 | case 'j': |
2877 | return C_Immediate; |
2878 | default: |
2879 | break; |
2880 | } |
2881 | break; |
2882 | case 'Q': |
2883 | case 'U': |
2884 | return C_Memory; |
2885 | default: |
2886 | break; |
2887 | } |
2888 | } |
2889 | |
2890 | return TargetLowering::getConstraintType(Constraint); |
2891 | } |
2892 | |
2893 | void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op, |
2894 | StringRef Constraint, |
2895 | std::vector<SDValue> &Ops, |
2896 | SelectionDAG &DAG) const { |
2897 | SDValue Result; |
2898 | |
2899 | if (Constraint.size() == 1) { |
2900 | // Constant constraints |
2901 | switch (Constraint[0]) { |
2902 | case 'I': |
2903 | case 'J': |
2904 | case 'K': |
2905 | case 'L': |
2906 | case 'M': |
2907 | case 'N': |
2908 | case 'O': |
2909 | case 'P': { |
2910 | auto *C = dyn_cast<ConstantSDNode>(Val&: Op); |
2911 | if (!C) |
2912 | return; |
2913 | |
2914 | int64_t Val = C->getSExtValue(); |
2915 | switch (Constraint[0]) { |
2916 | case 'I': // constant integer in the range [1,8] |
2917 | if (Val > 0 && Val <= 8) |
2918 | break; |
2919 | return; |
2920 | case 'J': // constant signed 16-bit integer |
2921 | if (isInt<16>(x: Val)) |
2922 | break; |
2923 | return; |
2924 | case 'K': // constant that is NOT in the range of [-0x80, 0x80) |
2925 | if (Val < -0x80 || Val >= 0x80) |
2926 | break; |
2927 | return; |
2928 | case 'L': // constant integer in the range [-8,-1] |
2929 | if (Val < 0 && Val >= -8) |
2930 | break; |
2931 | return; |
2932 | case 'M': // constant that is NOT in the range of [-0x100, 0x100] |
2933 | if (Val < -0x100 || Val >= 0x100) |
2934 | break; |
2935 | return; |
2936 | case 'N': // constant integer in the range [24,31] |
2937 | if (Val >= 24 && Val <= 31) |
2938 | break; |
2939 | return; |
2940 | case 'O': // constant integer 16 |
2941 | if (Val == 16) |
2942 | break; |
2943 | return; |
2944 | case 'P': // constant integer in the range [8,15] |
2945 | if (Val >= 8 && Val <= 15) |
2946 | break; |
2947 | return; |
2948 | default: |
2949 | llvm_unreachable("Unhandled constant constraint" ); |
2950 | } |
2951 | |
2952 | Result = DAG.getTargetConstant(Val, DL: SDLoc(Op), VT: Op.getValueType()); |
2953 | break; |
2954 | } |
2955 | default: |
2956 | break; |
2957 | } |
2958 | } |
2959 | |
2960 | if (Constraint.size() == 2) { |
2961 | switch (Constraint[0]) { |
2962 | case 'C': |
2963 | // Constant constraints start with 'C' |
2964 | switch (Constraint[1]) { |
2965 | case '0': |
2966 | case 'i': |
2967 | case 'j': { |
2968 | auto *C = dyn_cast<ConstantSDNode>(Val&: Op); |
2969 | if (!C) |
2970 | break; |
2971 | |
2972 | int64_t Val = C->getSExtValue(); |
2973 | switch (Constraint[1]) { |
2974 | case '0': // constant integer 0 |
2975 | if (!Val) |
2976 | break; |
2977 | return; |
2978 | case 'i': // constant integer |
2979 | break; |
2980 | case 'j': // integer constant that doesn't fit in 16 bits |
2981 | if (!isInt<16>(x: C->getSExtValue())) |
2982 | break; |
2983 | return; |
2984 | default: |
2985 | llvm_unreachable("Unhandled constant constraint" ); |
2986 | } |
2987 | |
2988 | Result = DAG.getTargetConstant(Val, DL: SDLoc(Op), VT: Op.getValueType()); |
2989 | break; |
2990 | } |
2991 | default: |
2992 | break; |
2993 | } |
2994 | break; |
2995 | default: |
2996 | break; |
2997 | } |
2998 | } |
2999 | |
3000 | if (Result.getNode()) { |
3001 | Ops.push_back(x: Result); |
3002 | return; |
3003 | } |
3004 | |
3005 | TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); |
3006 | } |
3007 | |
3008 | std::pair<unsigned, const TargetRegisterClass *> |
3009 | M68kTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, |
3010 | StringRef Constraint, |
3011 | MVT VT) const { |
3012 | if (Constraint.size() == 1) { |
3013 | switch (Constraint[0]) { |
3014 | case 'r': |
3015 | case 'd': |
3016 | switch (VT.SimpleTy) { |
3017 | case MVT::i8: |
3018 | return std::make_pair(0U, &M68k::DR8RegClass); |
3019 | case MVT::i16: |
3020 | return std::make_pair(0U, &M68k::DR16RegClass); |
3021 | case MVT::i32: |
3022 | return std::make_pair(0U, &M68k::DR32RegClass); |
3023 | default: |
3024 | break; |
3025 | } |
3026 | break; |
3027 | case 'a': |
3028 | switch (VT.SimpleTy) { |
3029 | case MVT::i16: |
3030 | return std::make_pair(0U, &M68k::AR16RegClass); |
3031 | case MVT::i32: |
3032 | return std::make_pair(0U, &M68k::AR32RegClass); |
3033 | default: |
3034 | break; |
3035 | } |
3036 | break; |
3037 | default: |
3038 | break; |
3039 | } |
3040 | } |
3041 | |
3042 | return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); |
3043 | } |
3044 | |
3045 | /// Determines whether the callee is required to pop its own arguments. |
3046 | /// Callee pop is necessary to support tail calls. |
3047 | bool M68k::isCalleePop(CallingConv::ID CC, bool IsVarArg, bool GuaranteeTCO) { |
3048 | return CC == CallingConv::M68k_RTD && !IsVarArg; |
3049 | } |
3050 | |
3051 | // Return true if it is OK for this CMOV pseudo-opcode to be cascaded |
3052 | // together with other CMOV pseudo-opcodes into a single basic-block with |
3053 | // conditional jump around it. |
3054 | static bool isCMOVPseudo(MachineInstr &MI) { |
3055 | switch (MI.getOpcode()) { |
3056 | case M68k::CMOV8d: |
3057 | case M68k::CMOV16d: |
3058 | case M68k::CMOV32r: |
3059 | return true; |
3060 | |
3061 | default: |
3062 | return false; |
3063 | } |
3064 | } |
3065 | |
3066 | // The CCR operand of SelectItr might be missing a kill marker |
3067 | // because there were multiple uses of CCR, and ISel didn't know |
3068 | // which to mark. Figure out whether SelectItr should have had a |
3069 | // kill marker, and set it if it should. Returns the correct kill |
3070 | // marker value. |
3071 | static bool checkAndUpdateCCRKill(MachineBasicBlock::iterator SelectItr, |
3072 | MachineBasicBlock *BB, |
3073 | const TargetRegisterInfo *TRI) { |
3074 | // Scan forward through BB for a use/def of CCR. |
3075 | MachineBasicBlock::iterator miI(std::next(x: SelectItr)); |
3076 | for (MachineBasicBlock::iterator miE = BB->end(); miI != miE; ++miI) { |
3077 | const MachineInstr &mi = *miI; |
3078 | if (mi.readsRegister(M68k::CCR, /*TRI=*/nullptr)) |
3079 | return false; |
3080 | if (mi.definesRegister(M68k::CCR, /*TRI=*/nullptr)) |
3081 | break; // Should have kill-flag - update below. |
3082 | } |
3083 | |
3084 | // If we hit the end of the block, check whether CCR is live into a |
3085 | // successor. |
3086 | if (miI == BB->end()) |
3087 | for (const auto *SBB : BB->successors()) |
3088 | if (SBB->isLiveIn(M68k::CCR)) |
3089 | return false; |
3090 | |
3091 | // We found a def, or hit the end of the basic block and CCR wasn't live |
3092 | // out. SelectMI should have a kill flag on CCR. |
3093 | SelectItr->addRegisterKilled(M68k::CCR, TRI); |
3094 | return true; |
3095 | } |
3096 | |
3097 | MachineBasicBlock * |
3098 | M68kTargetLowering::EmitLoweredSelect(MachineInstr &MI, |
3099 | MachineBasicBlock *MBB) const { |
3100 | const TargetInstrInfo *TII = Subtarget.getInstrInfo(); |
3101 | DebugLoc DL = MI.getDebugLoc(); |
3102 | |
3103 | // To "insert" a SELECT_CC instruction, we actually have to insert the |
3104 | // diamond control-flow pattern. The incoming instruction knows the |
3105 | // destination vreg to set, the condition code register to branch on, the |
3106 | // true/false values to select between, and a branch opcode to use. |
3107 | const BasicBlock *BB = MBB->getBasicBlock(); |
3108 | MachineFunction::iterator It = ++MBB->getIterator(); |
3109 | |
3110 | // ThisMBB: |
3111 | // ... |
3112 | // TrueVal = ... |
3113 | // cmp ccX, r1, r2 |
3114 | // bcc Copy1MBB |
3115 | // fallthrough --> Copy0MBB |
3116 | MachineBasicBlock *ThisMBB = MBB; |
3117 | MachineFunction *F = MBB->getParent(); |
3118 | |
3119 | // This code lowers all pseudo-CMOV instructions. Generally it lowers these |
3120 | // as described above, by inserting a MBB, and then making a PHI at the join |
3121 | // point to select the true and false operands of the CMOV in the PHI. |
3122 | // |
3123 | // The code also handles two different cases of multiple CMOV opcodes |
3124 | // in a row. |
3125 | // |
3126 | // Case 1: |
3127 | // In this case, there are multiple CMOVs in a row, all which are based on |
3128 | // the same condition setting (or the exact opposite condition setting). |
3129 | // In this case we can lower all the CMOVs using a single inserted MBB, and |
3130 | // then make a number of PHIs at the join point to model the CMOVs. The only |
3131 | // trickiness here, is that in a case like: |
3132 | // |
3133 | // t2 = CMOV cond1 t1, f1 |
3134 | // t3 = CMOV cond1 t2, f2 |
3135 | // |
3136 | // when rewriting this into PHIs, we have to perform some renaming on the |
3137 | // temps since you cannot have a PHI operand refer to a PHI result earlier |
3138 | // in the same block. The "simple" but wrong lowering would be: |
3139 | // |
3140 | // t2 = PHI t1(BB1), f1(BB2) |
3141 | // t3 = PHI t2(BB1), f2(BB2) |
3142 | // |
3143 | // but clearly t2 is not defined in BB1, so that is incorrect. The proper |
3144 | // renaming is to note that on the path through BB1, t2 is really just a |
3145 | // copy of t1, and do that renaming, properly generating: |
3146 | // |
3147 | // t2 = PHI t1(BB1), f1(BB2) |
3148 | // t3 = PHI t1(BB1), f2(BB2) |
3149 | // |
3150 | // Case 2, we lower cascaded CMOVs such as |
3151 | // |
3152 | // (CMOV (CMOV F, T, cc1), T, cc2) |
3153 | // |
3154 | // to two successives branches. |
3155 | MachineInstr *CascadedCMOV = nullptr; |
3156 | MachineInstr *LastCMOV = &MI; |
3157 | M68k::CondCode CC = M68k::CondCode(MI.getOperand(i: 3).getImm()); |
3158 | M68k::CondCode OppCC = M68k::GetOppositeBranchCondition(CC); |
3159 | MachineBasicBlock::iterator NextMIIt = |
3160 | std::next(x: MachineBasicBlock::iterator(MI)); |
3161 | |
3162 | // Check for case 1, where there are multiple CMOVs with the same condition |
3163 | // first. Of the two cases of multiple CMOV lowerings, case 1 reduces the |
3164 | // number of jumps the most. |
3165 | |
3166 | if (isCMOVPseudo(MI)) { |
3167 | // See if we have a string of CMOVS with the same condition. |
3168 | while (NextMIIt != MBB->end() && isCMOVPseudo(MI&: *NextMIIt) && |
3169 | (NextMIIt->getOperand(i: 3).getImm() == CC || |
3170 | NextMIIt->getOperand(i: 3).getImm() == OppCC)) { |
3171 | LastCMOV = &*NextMIIt; |
3172 | ++NextMIIt; |
3173 | } |
3174 | } |
3175 | |
3176 | // This checks for case 2, but only do this if we didn't already find |
3177 | // case 1, as indicated by LastCMOV == MI. |
3178 | if (LastCMOV == &MI && NextMIIt != MBB->end() && |
3179 | NextMIIt->getOpcode() == MI.getOpcode() && |
3180 | NextMIIt->getOperand(i: 2).getReg() == MI.getOperand(i: 2).getReg() && |
3181 | NextMIIt->getOperand(i: 1).getReg() == MI.getOperand(i: 0).getReg() && |
3182 | NextMIIt->getOperand(i: 1).isKill()) { |
3183 | CascadedCMOV = &*NextMIIt; |
3184 | } |
3185 | |
3186 | MachineBasicBlock *Jcc1MBB = nullptr; |
3187 | |
3188 | // If we have a cascaded CMOV, we lower it to two successive branches to |
3189 | // the same block. CCR is used by both, so mark it as live in the second. |
3190 | if (CascadedCMOV) { |
3191 | Jcc1MBB = F->CreateMachineBasicBlock(BB); |
3192 | F->insert(MBBI: It, MBB: Jcc1MBB); |
3193 | Jcc1MBB->addLiveIn(M68k::CCR); |
3194 | } |
3195 | |
3196 | MachineBasicBlock *Copy0MBB = F->CreateMachineBasicBlock(BB); |
3197 | MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(BB); |
3198 | F->insert(MBBI: It, MBB: Copy0MBB); |
3199 | F->insert(MBBI: It, MBB: SinkMBB); |
3200 | |
3201 | // Set the call frame size on entry to the new basic blocks. |
3202 | unsigned CallFrameSize = TII->getCallFrameSizeAt(MI); |
3203 | Copy0MBB->setCallFrameSize(CallFrameSize); |
3204 | SinkMBB->setCallFrameSize(CallFrameSize); |
3205 | |
3206 | // If the CCR register isn't dead in the terminator, then claim that it's |
3207 | // live into the sink and copy blocks. |
3208 | const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); |
3209 | |
3210 | MachineInstr *LastCCRSUser = CascadedCMOV ? CascadedCMOV : LastCMOV; |
3211 | if (!LastCCRSUser->killsRegister(M68k::CCR) && |
3212 | !checkAndUpdateCCRKill(LastCCRSUser, MBB, TRI)) { |
3213 | Copy0MBB->addLiveIn(M68k::CCR); |
3214 | SinkMBB->addLiveIn(M68k::CCR); |
3215 | } |
3216 | |
3217 | // Transfer the remainder of MBB and its successor edges to SinkMBB. |
3218 | SinkMBB->splice(Where: SinkMBB->begin(), Other: MBB, |
3219 | From: std::next(x: MachineBasicBlock::iterator(LastCMOV)), To: MBB->end()); |
3220 | SinkMBB->transferSuccessorsAndUpdatePHIs(FromMBB: MBB); |
3221 | |
3222 | // Add the true and fallthrough blocks as its successors. |
3223 | if (CascadedCMOV) { |
3224 | // The fallthrough block may be Jcc1MBB, if we have a cascaded CMOV. |
3225 | MBB->addSuccessor(Succ: Jcc1MBB); |
3226 | |
3227 | // In that case, Jcc1MBB will itself fallthrough the Copy0MBB, and |
3228 | // jump to the SinkMBB. |
3229 | Jcc1MBB->addSuccessor(Succ: Copy0MBB); |
3230 | Jcc1MBB->addSuccessor(Succ: SinkMBB); |
3231 | } else { |
3232 | MBB->addSuccessor(Succ: Copy0MBB); |
3233 | } |
3234 | |
3235 | // The true block target of the first (or only) branch is always SinkMBB. |
3236 | MBB->addSuccessor(Succ: SinkMBB); |
3237 | |
3238 | // Create the conditional branch instruction. |
3239 | unsigned Opc = M68k::GetCondBranchFromCond(CC); |
3240 | BuildMI(BB: MBB, MIMD: DL, MCID: TII->get(Opcode: Opc)).addMBB(MBB: SinkMBB); |
3241 | |
3242 | if (CascadedCMOV) { |
3243 | unsigned Opc2 = M68k::GetCondBranchFromCond( |
3244 | CC: (M68k::CondCode)CascadedCMOV->getOperand(i: 3).getImm()); |
3245 | BuildMI(BB: Jcc1MBB, MIMD: DL, MCID: TII->get(Opcode: Opc2)).addMBB(MBB: SinkMBB); |
3246 | } |
3247 | |
3248 | // Copy0MBB: |
3249 | // %FalseValue = ... |
3250 | // # fallthrough to SinkMBB |
3251 | Copy0MBB->addSuccessor(Succ: SinkMBB); |
3252 | |
3253 | // SinkMBB: |
3254 | // %Result = phi [ %FalseValue, Copy0MBB ], [ %TrueValue, ThisMBB ] |
3255 | // ... |
3256 | MachineBasicBlock::iterator MIItBegin = MachineBasicBlock::iterator(MI); |
3257 | MachineBasicBlock::iterator MIItEnd = |
3258 | std::next(x: MachineBasicBlock::iterator(LastCMOV)); |
3259 | MachineBasicBlock::iterator SinkInsertionPoint = SinkMBB->begin(); |
3260 | DenseMap<unsigned, std::pair<unsigned, unsigned>> RegRewriteTable; |
3261 | MachineInstrBuilder MIB; |
3262 | |
3263 | // As we are creating the PHIs, we have to be careful if there is more than |
3264 | // one. Later CMOVs may reference the results of earlier CMOVs, but later |
3265 | // PHIs have to reference the individual true/false inputs from earlier PHIs. |
3266 | // That also means that PHI construction must work forward from earlier to |
3267 | // later, and that the code must maintain a mapping from earlier PHI's |
3268 | // destination registers, and the registers that went into the PHI. |
3269 | |
3270 | for (MachineBasicBlock::iterator MIIt = MIItBegin; MIIt != MIItEnd; ++MIIt) { |
3271 | Register DestReg = MIIt->getOperand(i: 0).getReg(); |
3272 | Register Op1Reg = MIIt->getOperand(i: 1).getReg(); |
3273 | Register Op2Reg = MIIt->getOperand(i: 2).getReg(); |
3274 | |
3275 | // If this CMOV we are generating is the opposite condition from |
3276 | // the jump we generated, then we have to swap the operands for the |
3277 | // PHI that is going to be generated. |
3278 | if (MIIt->getOperand(i: 3).getImm() == OppCC) |
3279 | std::swap(a&: Op1Reg, b&: Op2Reg); |
3280 | |
3281 | if (RegRewriteTable.find(Val: Op1Reg) != RegRewriteTable.end()) |
3282 | Op1Reg = RegRewriteTable[Op1Reg].first; |
3283 | |
3284 | if (RegRewriteTable.find(Val: Op2Reg) != RegRewriteTable.end()) |
3285 | Op2Reg = RegRewriteTable[Op2Reg].second; |
3286 | |
3287 | MIB = |
3288 | BuildMI(*SinkMBB, SinkInsertionPoint, DL, TII->get(M68k::PHI), DestReg) |
3289 | .addReg(Op1Reg) |
3290 | .addMBB(Copy0MBB) |
3291 | .addReg(Op2Reg) |
3292 | .addMBB(ThisMBB); |
3293 | |
3294 | // Add this PHI to the rewrite table. |
3295 | RegRewriteTable[DestReg] = std::make_pair(x&: Op1Reg, y&: Op2Reg); |
3296 | } |
3297 | |
3298 | // If we have a cascaded CMOV, the second Jcc provides the same incoming |
3299 | // value as the first Jcc (the True operand of the SELECT_CC/CMOV nodes). |
3300 | if (CascadedCMOV) { |
3301 | MIB.addReg(RegNo: MI.getOperand(i: 2).getReg()).addMBB(MBB: Jcc1MBB); |
3302 | // Copy the PHI result to the register defined by the second CMOV. |
3303 | BuildMI(BB&: *SinkMBB, I: std::next(x: MachineBasicBlock::iterator(MIB.getInstr())), |
3304 | MIMD: DL, MCID: TII->get(Opcode: TargetOpcode::COPY), |
3305 | DestReg: CascadedCMOV->getOperand(i: 0).getReg()) |
3306 | .addReg(RegNo: MI.getOperand(i: 0).getReg()); |
3307 | CascadedCMOV->eraseFromParent(); |
3308 | } |
3309 | |
3310 | // Now remove the CMOV(s). |
3311 | for (MachineBasicBlock::iterator MIIt = MIItBegin; MIIt != MIItEnd;) |
3312 | (MIIt++)->eraseFromParent(); |
3313 | |
3314 | return SinkMBB; |
3315 | } |
3316 | |
3317 | MachineBasicBlock * |
3318 | M68kTargetLowering::EmitLoweredSegAlloca(MachineInstr &MI, |
3319 | MachineBasicBlock *BB) const { |
3320 | llvm_unreachable("Cannot lower Segmented Stack Alloca with stack-split on" ); |
3321 | } |
3322 | |
3323 | MachineBasicBlock * |
3324 | M68kTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, |
3325 | MachineBasicBlock *BB) const { |
3326 | switch (MI.getOpcode()) { |
3327 | default: |
3328 | llvm_unreachable("Unexpected instr type to insert" ); |
3329 | case M68k::CMOV8d: |
3330 | case M68k::CMOV16d: |
3331 | case M68k::CMOV32r: |
3332 | return EmitLoweredSelect(MI, MBB: BB); |
3333 | case M68k::SALLOCA: |
3334 | return EmitLoweredSegAlloca(MI, BB); |
3335 | } |
3336 | } |
3337 | |
3338 | SDValue M68kTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { |
3339 | MachineFunction &MF = DAG.getMachineFunction(); |
3340 | auto PtrVT = getPointerTy(DL: MF.getDataLayout()); |
3341 | M68kMachineFunctionInfo *FuncInfo = MF.getInfo<M68kMachineFunctionInfo>(); |
3342 | |
3343 | const Value *SV = cast<SrcValueSDNode>(Val: Op.getOperand(i: 2))->getValue(); |
3344 | SDLoc DL(Op); |
3345 | |
3346 | // vastart just stores the address of the VarArgsFrameIndex slot into the |
3347 | // memory location argument. |
3348 | SDValue FR = DAG.getFrameIndex(FI: FuncInfo->getVarArgsFrameIndex(), VT: PtrVT); |
3349 | return DAG.getStore(Chain: Op.getOperand(i: 0), dl: DL, Val: FR, Ptr: Op.getOperand(i: 1), |
3350 | PtrInfo: MachinePointerInfo(SV)); |
3351 | } |
3352 | |
3353 | SDValue M68kTargetLowering::LowerATOMICFENCE(SDValue Op, |
3354 | SelectionDAG &DAG) const { |
3355 | // Lower to a memory barrier created from inline asm. |
3356 | const TargetLowering &TLI = DAG.getTargetLoweringInfo(); |
3357 | LLVMContext &Ctx = *DAG.getContext(); |
3358 | |
3359 | const unsigned Flags = InlineAsm::Extra_MayLoad | InlineAsm::Extra_MayStore | |
3360 | InlineAsm::Extra_HasSideEffects; |
3361 | const SDValue AsmOperands[4] = { |
3362 | Op.getOperand(i: 0), // Input chain |
3363 | DAG.getTargetExternalSymbol( |
3364 | Sym: "" , VT: TLI.getProgramPointerTy( |
3365 | DL: DAG.getDataLayout())), // Empty inline asm string |
3366 | DAG.getMDNode(MD: MDNode::get(Context&: Ctx, MDs: {})), // (empty) srcloc |
3367 | DAG.getTargetConstant(Val: Flags, DL: SDLoc(Op), |
3368 | VT: TLI.getPointerTy(DL: DAG.getDataLayout())), // Flags |
3369 | }; |
3370 | |
3371 | return DAG.getNode(ISD::INLINEASM, SDLoc(Op), |
3372 | DAG.getVTList(MVT::Other, MVT::Glue), AsmOperands); |
3373 | } |
3374 | |
3375 | // Lower dynamic stack allocation to _alloca call for Cygwin/Mingw targets. |
3376 | // Calls to _alloca are needed to probe the stack when allocating more than 4k |
3377 | // bytes in one go. Touching the stack at 4K increments is necessary to ensure |
3378 | // that the guard pages used by the OS virtual memory manager are allocated in |
3379 | // correct sequence. |
3380 | SDValue M68kTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, |
3381 | SelectionDAG &DAG) const { |
3382 | MachineFunction &MF = DAG.getMachineFunction(); |
3383 | bool SplitStack = MF.shouldSplitStack(); |
3384 | |
3385 | SDLoc DL(Op); |
3386 | |
3387 | // Get the inputs. |
3388 | SDNode *Node = Op.getNode(); |
3389 | SDValue Chain = Op.getOperand(i: 0); |
3390 | SDValue Size = Op.getOperand(i: 1); |
3391 | unsigned Align = Op.getConstantOperandVal(i: 2); |
3392 | EVT VT = Node->getValueType(ResNo: 0); |
3393 | |
3394 | // Chain the dynamic stack allocation so that it doesn't modify the stack |
3395 | // pointer when other instructions are using the stack. |
3396 | Chain = DAG.getCALLSEQ_START(Chain, InSize: 0, OutSize: 0, DL); |
3397 | |
3398 | SDValue Result; |
3399 | if (SplitStack) { |
3400 | auto &MRI = MF.getRegInfo(); |
3401 | auto SPTy = getPointerTy(DL: DAG.getDataLayout()); |
3402 | auto *ARClass = getRegClassFor(VT: SPTy); |
3403 | Register Vreg = MRI.createVirtualRegister(RegClass: ARClass); |
3404 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: Vreg, N: Size); |
3405 | Result = DAG.getNode(Opcode: M68kISD::SEG_ALLOCA, DL, VT: SPTy, N1: Chain, |
3406 | N2: DAG.getRegister(Reg: Vreg, VT: SPTy)); |
3407 | } else { |
3408 | auto &TLI = DAG.getTargetLoweringInfo(); |
3409 | Register SPReg = TLI.getStackPointerRegisterToSaveRestore(); |
3410 | assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and" |
3411 | " not tell us which reg is the stack pointer!" ); |
3412 | |
3413 | SDValue SP = DAG.getCopyFromReg(Chain, dl: DL, Reg: SPReg, VT); |
3414 | Chain = SP.getValue(R: 1); |
3415 | const TargetFrameLowering &TFI = *Subtarget.getFrameLowering(); |
3416 | unsigned StackAlign = TFI.getStackAlignment(); |
3417 | Result = DAG.getNode(Opcode: ISD::SUB, DL, VT, N1: SP, N2: Size); // Value |
3418 | if (Align > StackAlign) |
3419 | Result = DAG.getNode(Opcode: ISD::AND, DL, VT, N1: Result, |
3420 | N2: DAG.getConstant(Val: -(uint64_t)Align, DL, VT)); |
3421 | Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: SPReg, N: Result); // Output chain |
3422 | } |
3423 | |
3424 | Chain = DAG.getCALLSEQ_END(Chain, Size1: 0, Size2: 0, Glue: SDValue(), DL); |
3425 | |
3426 | SDValue Ops[2] = {Result, Chain}; |
3427 | return DAG.getMergeValues(Ops, dl: DL); |
3428 | } |
3429 | |
3430 | SDValue M68kTargetLowering::LowerShiftLeftParts(SDValue Op, |
3431 | SelectionDAG &DAG) const { |
3432 | SDLoc DL(Op); |
3433 | SDValue Lo = Op.getOperand(i: 0); |
3434 | SDValue Hi = Op.getOperand(i: 1); |
3435 | SDValue Shamt = Op.getOperand(i: 2); |
3436 | EVT VT = Lo.getValueType(); |
3437 | |
3438 | // if Shamt - register size < 0: // Shamt < register size |
3439 | // Lo = Lo << Shamt |
3440 | // Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (register size - 1 ^ Shamt)) |
3441 | // else: |
3442 | // Lo = 0 |
3443 | // Hi = Lo << (Shamt - register size) |
3444 | |
3445 | SDValue Zero = DAG.getConstant(Val: 0, DL, VT); |
3446 | SDValue One = DAG.getConstant(Val: 1, DL, VT); |
3447 | SDValue MinusRegisterSize = DAG.getConstant(Val: -32, DL, VT); |
3448 | SDValue RegisterSizeMinus1 = DAG.getConstant(Val: 32 - 1, DL, VT); |
3449 | SDValue ShamtMinusRegisterSize = |
3450 | DAG.getNode(Opcode: ISD::ADD, DL, VT, N1: Shamt, N2: MinusRegisterSize); |
3451 | SDValue RegisterSizeMinus1Shamt = |
3452 | DAG.getNode(Opcode: ISD::XOR, DL, VT, N1: RegisterSizeMinus1, N2: Shamt); |
3453 | |
3454 | SDValue LoTrue = DAG.getNode(Opcode: ISD::SHL, DL, VT, N1: Lo, N2: Shamt); |
3455 | SDValue ShiftRight1Lo = DAG.getNode(Opcode: ISD::SRL, DL, VT, N1: Lo, N2: One); |
3456 | SDValue ShiftRightLo = |
3457 | DAG.getNode(Opcode: ISD::SRL, DL, VT, N1: ShiftRight1Lo, N2: RegisterSizeMinus1Shamt); |
3458 | SDValue ShiftLeftHi = DAG.getNode(Opcode: ISD::SHL, DL, VT, N1: Hi, N2: Shamt); |
3459 | SDValue HiTrue = DAG.getNode(Opcode: ISD::OR, DL, VT, N1: ShiftLeftHi, N2: ShiftRightLo); |
3460 | SDValue HiFalse = DAG.getNode(Opcode: ISD::SHL, DL, VT, N1: Lo, N2: ShamtMinusRegisterSize); |
3461 | |
3462 | SDValue CC = |
3463 | DAG.getSetCC(DL, MVT::i8, ShamtMinusRegisterSize, Zero, ISD::SETLT); |
3464 | |
3465 | Lo = DAG.getNode(Opcode: ISD::SELECT, DL, VT, N1: CC, N2: LoTrue, N3: Zero); |
3466 | Hi = DAG.getNode(Opcode: ISD::SELECT, DL, VT, N1: CC, N2: HiTrue, N3: HiFalse); |
3467 | |
3468 | return DAG.getMergeValues(Ops: {Lo, Hi}, dl: DL); |
3469 | } |
3470 | |
3471 | SDValue M68kTargetLowering::LowerShiftRightParts(SDValue Op, SelectionDAG &DAG, |
3472 | bool IsSRA) const { |
3473 | SDLoc DL(Op); |
3474 | SDValue Lo = Op.getOperand(i: 0); |
3475 | SDValue Hi = Op.getOperand(i: 1); |
3476 | SDValue Shamt = Op.getOperand(i: 2); |
3477 | EVT VT = Lo.getValueType(); |
3478 | |
3479 | // SRA expansion: |
3480 | // if Shamt - register size < 0: // Shamt < register size |
3481 | // Lo = (Lo >>u Shamt) | ((Hi << 1) << (register size - 1 ^ Shamt)) |
3482 | // Hi = Hi >>s Shamt |
3483 | // else: |
3484 | // Lo = Hi >>s (Shamt - register size); |
3485 | // Hi = Hi >>s (register size - 1) |
3486 | // |
3487 | // SRL expansion: |
3488 | // if Shamt - register size < 0: // Shamt < register size |
3489 | // Lo = (Lo >>u Shamt) | ((Hi << 1) << (register size - 1 ^ Shamt)) |
3490 | // Hi = Hi >>u Shamt |
3491 | // else: |
3492 | // Lo = Hi >>u (Shamt - register size); |
3493 | // Hi = 0; |
3494 | |
3495 | unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL; |
3496 | |
3497 | SDValue Zero = DAG.getConstant(Val: 0, DL, VT); |
3498 | SDValue One = DAG.getConstant(Val: 1, DL, VT); |
3499 | SDValue MinusRegisterSize = DAG.getConstant(Val: -32, DL, VT); |
3500 | SDValue RegisterSizeMinus1 = DAG.getConstant(Val: 32 - 1, DL, VT); |
3501 | SDValue ShamtMinusRegisterSize = |
3502 | DAG.getNode(Opcode: ISD::ADD, DL, VT, N1: Shamt, N2: MinusRegisterSize); |
3503 | SDValue RegisterSizeMinus1Shamt = |
3504 | DAG.getNode(Opcode: ISD::XOR, DL, VT, N1: RegisterSizeMinus1, N2: Shamt); |
3505 | |
3506 | SDValue ShiftRightLo = DAG.getNode(Opcode: ISD::SRL, DL, VT, N1: Lo, N2: Shamt); |
3507 | SDValue ShiftLeftHi1 = DAG.getNode(Opcode: ISD::SHL, DL, VT, N1: Hi, N2: One); |
3508 | SDValue ShiftLeftHi = |
3509 | DAG.getNode(Opcode: ISD::SHL, DL, VT, N1: ShiftLeftHi1, N2: RegisterSizeMinus1Shamt); |
3510 | SDValue LoTrue = DAG.getNode(Opcode: ISD::OR, DL, VT, N1: ShiftRightLo, N2: ShiftLeftHi); |
3511 | SDValue HiTrue = DAG.getNode(Opcode: ShiftRightOp, DL, VT, N1: Hi, N2: Shamt); |
3512 | SDValue LoFalse = |
3513 | DAG.getNode(Opcode: ShiftRightOp, DL, VT, N1: Hi, N2: ShamtMinusRegisterSize); |
3514 | SDValue HiFalse = |
3515 | IsSRA ? DAG.getNode(Opcode: ISD::SRA, DL, VT, N1: Hi, N2: RegisterSizeMinus1) : Zero; |
3516 | |
3517 | SDValue CC = |
3518 | DAG.getSetCC(DL, MVT::i8, ShamtMinusRegisterSize, Zero, ISD::SETLT); |
3519 | |
3520 | Lo = DAG.getNode(Opcode: ISD::SELECT, DL, VT, N1: CC, N2: LoTrue, N3: LoFalse); |
3521 | Hi = DAG.getNode(Opcode: ISD::SELECT, DL, VT, N1: CC, N2: HiTrue, N3: HiFalse); |
3522 | |
3523 | return DAG.getMergeValues(Ops: {Lo, Hi}, dl: DL); |
3524 | } |
3525 | |
3526 | //===----------------------------------------------------------------------===// |
3527 | // DAG Combine |
3528 | //===----------------------------------------------------------------------===// |
3529 | |
3530 | static SDValue getSETCC(M68k::CondCode Cond, SDValue CCR, const SDLoc &dl, |
3531 | SelectionDAG &DAG) { |
3532 | return DAG.getNode(M68kISD::SETCC, dl, MVT::i8, |
3533 | DAG.getConstant(Cond, dl, MVT::i8), CCR); |
3534 | } |
3535 | // When legalizing carry, we create carries via add X, -1 |
3536 | // If that comes from an actual carry, via setcc, we use the |
3537 | // carry directly. |
3538 | static SDValue combineCarryThroughADD(SDValue CCR) { |
3539 | if (CCR.getOpcode() == M68kISD::ADD) { |
3540 | if (isAllOnesConstant(V: CCR.getOperand(i: 1))) { |
3541 | SDValue Carry = CCR.getOperand(i: 0); |
3542 | while (Carry.getOpcode() == ISD::TRUNCATE || |
3543 | Carry.getOpcode() == ISD::ZERO_EXTEND || |
3544 | Carry.getOpcode() == ISD::SIGN_EXTEND || |
3545 | Carry.getOpcode() == ISD::ANY_EXTEND || |
3546 | (Carry.getOpcode() == ISD::AND && |
3547 | isOneConstant(V: Carry.getOperand(i: 1)))) |
3548 | Carry = Carry.getOperand(i: 0); |
3549 | if (Carry.getOpcode() == M68kISD::SETCC || |
3550 | Carry.getOpcode() == M68kISD::SETCC_CARRY) { |
3551 | if (Carry.getConstantOperandVal(i: 0) == M68k::COND_CS) |
3552 | return Carry.getOperand(i: 1); |
3553 | } |
3554 | } |
3555 | } |
3556 | |
3557 | return SDValue(); |
3558 | } |
3559 | |
3560 | /// Optimize a CCR definition used according to the condition code \p CC into |
3561 | /// a simpler CCR value, potentially returning a new \p CC and replacing uses |
3562 | /// of chain values. |
3563 | static SDValue combineSetCCCCR(SDValue CCR, M68k::CondCode &CC, |
3564 | SelectionDAG &DAG, |
3565 | const M68kSubtarget &Subtarget) { |
3566 | if (CC == M68k::COND_CS) |
3567 | if (SDValue Flags = combineCarryThroughADD(CCR)) |
3568 | return Flags; |
3569 | |
3570 | return SDValue(); |
3571 | } |
3572 | |
3573 | // Optimize RES = M68kISD::SETCC CONDCODE, CCR_INPUT |
3574 | static SDValue combineM68kSetCC(SDNode *N, SelectionDAG &DAG, |
3575 | const M68kSubtarget &Subtarget) { |
3576 | SDLoc DL(N); |
3577 | M68k::CondCode CC = M68k::CondCode(N->getConstantOperandVal(Num: 0)); |
3578 | SDValue CCR = N->getOperand(Num: 1); |
3579 | |
3580 | // Try to simplify the CCR and condition code operands. |
3581 | if (SDValue Flags = combineSetCCCCR(CCR, CC, DAG, Subtarget)) |
3582 | return getSETCC(Cond: CC, CCR: Flags, dl: DL, DAG); |
3583 | |
3584 | return SDValue(); |
3585 | } |
3586 | static SDValue combineM68kBrCond(SDNode *N, SelectionDAG &DAG, |
3587 | const M68kSubtarget &Subtarget) { |
3588 | SDLoc DL(N); |
3589 | M68k::CondCode CC = M68k::CondCode(N->getConstantOperandVal(Num: 2)); |
3590 | SDValue CCR = N->getOperand(Num: 3); |
3591 | |
3592 | // Try to simplify the CCR and condition code operands. |
3593 | // Make sure to not keep references to operands, as combineSetCCCCR can |
3594 | // RAUW them under us. |
3595 | if (SDValue Flags = combineSetCCCCR(CCR, CC, DAG, Subtarget)) { |
3596 | SDValue Cond = DAG.getConstant(CC, DL, MVT::i8); |
3597 | return DAG.getNode(Opcode: M68kISD::BRCOND, DL, VTList: N->getVTList(), N1: N->getOperand(Num: 0), |
3598 | N2: N->getOperand(Num: 1), N3: Cond, N4: Flags); |
3599 | } |
3600 | |
3601 | return SDValue(); |
3602 | } |
3603 | |
3604 | static SDValue combineSUBX(SDNode *N, SelectionDAG &DAG) { |
3605 | if (SDValue Flags = combineCarryThroughADD(CCR: N->getOperand(Num: 2))) { |
3606 | MVT VT = N->getSimpleValueType(ResNo: 0); |
3607 | SDVTList VTs = DAG.getVTList(VT, MVT::i32); |
3608 | return DAG.getNode(Opcode: M68kISD::SUBX, DL: SDLoc(N), VTList: VTs, N1: N->getOperand(Num: 0), |
3609 | N2: N->getOperand(Num: 1), N3: Flags); |
3610 | } |
3611 | |
3612 | return SDValue(); |
3613 | } |
3614 | |
3615 | // Optimize RES, CCR = M68kISD::ADDX LHS, RHS, CCR |
3616 | static SDValue combineADDX(SDNode *N, SelectionDAG &DAG, |
3617 | TargetLowering::DAGCombinerInfo &DCI) { |
3618 | if (SDValue Flags = combineCarryThroughADD(CCR: N->getOperand(Num: 2))) { |
3619 | MVT VT = N->getSimpleValueType(ResNo: 0); |
3620 | SDVTList VTs = DAG.getVTList(VT, MVT::i32); |
3621 | return DAG.getNode(Opcode: M68kISD::ADDX, DL: SDLoc(N), VTList: VTs, N1: N->getOperand(Num: 0), |
3622 | N2: N->getOperand(Num: 1), N3: Flags); |
3623 | } |
3624 | |
3625 | return SDValue(); |
3626 | } |
3627 | |
3628 | SDValue M68kTargetLowering::PerformDAGCombine(SDNode *N, |
3629 | DAGCombinerInfo &DCI) const { |
3630 | SelectionDAG &DAG = DCI.DAG; |
3631 | switch (N->getOpcode()) { |
3632 | case M68kISD::SUBX: |
3633 | return combineSUBX(N, DAG); |
3634 | case M68kISD::ADDX: |
3635 | return combineADDX(N, DAG, DCI); |
3636 | case M68kISD::SETCC: |
3637 | return combineM68kSetCC(N, DAG, Subtarget); |
3638 | case M68kISD::BRCOND: |
3639 | return combineM68kBrCond(N, DAG, Subtarget); |
3640 | } |
3641 | |
3642 | return SDValue(); |
3643 | } |
3644 | |
3645 | //===----------------------------------------------------------------------===// |
3646 | // M68kISD Node Names |
3647 | //===----------------------------------------------------------------------===// |
3648 | const char *M68kTargetLowering::getTargetNodeName(unsigned Opcode) const { |
3649 | switch (Opcode) { |
3650 | case M68kISD::CALL: |
3651 | return "M68kISD::CALL" ; |
3652 | case M68kISD::TAIL_CALL: |
3653 | return "M68kISD::TAIL_CALL" ; |
3654 | case M68kISD::RET: |
3655 | return "M68kISD::RET" ; |
3656 | case M68kISD::TC_RETURN: |
3657 | return "M68kISD::TC_RETURN" ; |
3658 | case M68kISD::ADD: |
3659 | return "M68kISD::ADD" ; |
3660 | case M68kISD::SUB: |
3661 | return "M68kISD::SUB" ; |
3662 | case M68kISD::ADDX: |
3663 | return "M68kISD::ADDX" ; |
3664 | case M68kISD::SUBX: |
3665 | return "M68kISD::SUBX" ; |
3666 | case M68kISD::SMUL: |
3667 | return "M68kISD::SMUL" ; |
3668 | case M68kISD::UMUL: |
3669 | return "M68kISD::UMUL" ; |
3670 | case M68kISD::OR: |
3671 | return "M68kISD::OR" ; |
3672 | case M68kISD::XOR: |
3673 | return "M68kISD::XOR" ; |
3674 | case M68kISD::AND: |
3675 | return "M68kISD::AND" ; |
3676 | case M68kISD::CMP: |
3677 | return "M68kISD::CMP" ; |
3678 | case M68kISD::BTST: |
3679 | return "M68kISD::BTST" ; |
3680 | case M68kISD::SELECT: |
3681 | return "M68kISD::SELECT" ; |
3682 | case M68kISD::CMOV: |
3683 | return "M68kISD::CMOV" ; |
3684 | case M68kISD::BRCOND: |
3685 | return "M68kISD::BRCOND" ; |
3686 | case M68kISD::SETCC: |
3687 | return "M68kISD::SETCC" ; |
3688 | case M68kISD::SETCC_CARRY: |
3689 | return "M68kISD::SETCC_CARRY" ; |
3690 | case M68kISD::GLOBAL_BASE_REG: |
3691 | return "M68kISD::GLOBAL_BASE_REG" ; |
3692 | case M68kISD::Wrapper: |
3693 | return "M68kISD::Wrapper" ; |
3694 | case M68kISD::WrapperPC: |
3695 | return "M68kISD::WrapperPC" ; |
3696 | case M68kISD::SEG_ALLOCA: |
3697 | return "M68kISD::SEG_ALLOCA" ; |
3698 | default: |
3699 | return NULL; |
3700 | } |
3701 | } |
3702 | |
3703 | CCAssignFn *M68kTargetLowering::getCCAssignFn(CallingConv::ID CC, bool Return, |
3704 | bool IsVarArg) const { |
3705 | if (Return) |
3706 | return RetCC_M68k_C; |
3707 | else |
3708 | return CC_M68k_C; |
3709 | } |
3710 | |