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