| //===-- M68kISelLowering.cpp - M68k DAG Lowering Impl -----------*- C++ -*-===// | 
 | // | 
 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
 | // See https://llvm.org/LICENSE.txt for license information. | 
 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | /// | 
 | /// \file | 
 | /// This file defines the interfaces that M68k uses to lower LLVM code into a | 
 | /// selection DAG. | 
 | /// | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "M68kISelLowering.h" | 
 | #include "M68kCallingConv.h" | 
 | #include "M68kMachineFunction.h" | 
 | #include "M68kSubtarget.h" | 
 | #include "M68kTargetMachine.h" | 
 | #include "M68kTargetObjectFile.h" | 
 | #include "MCTargetDesc/M68kMCExpr.h" | 
 |  | 
 | #include "llvm/ADT/Statistic.h" | 
 | #include "llvm/CodeGen/CallingConvLower.h" | 
 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
 | #include "llvm/CodeGen/MachineFunction.h" | 
 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
 | #include "llvm/CodeGen/MachineJumpTableInfo.h" | 
 | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
 | #include "llvm/CodeGen/SelectionDAG.h" | 
 | #include "llvm/CodeGen/ValueTypes.h" | 
 | #include "llvm/IR/CallingConv.h" | 
 | #include "llvm/IR/DerivedTypes.h" | 
 | #include "llvm/IR/GlobalVariable.h" | 
 | #include "llvm/Support/CommandLine.h" | 
 | #include "llvm/Support/Debug.h" | 
 | #include "llvm/Support/ErrorHandling.h" | 
 | #include "llvm/Support/KnownBits.h" | 
 | #include "llvm/Support/raw_ostream.h" | 
 |  | 
 | using namespace llvm; | 
 |  | 
 | #define DEBUG_TYPE "M68k-isel" | 
 |  | 
 | STATISTIC(NumTailCalls, "Number of tail calls"); | 
 |  | 
 | M68kTargetLowering::M68kTargetLowering(const M68kTargetMachine &TM, | 
 |                                        const M68kSubtarget &STI) | 
 |     : TargetLowering(TM), Subtarget(STI), TM(TM) { | 
 |  | 
 |   MVT PtrVT = MVT::i32; | 
 |  | 
 |   setBooleanContents(ZeroOrOneBooleanContent); | 
 |  | 
 |   auto *RegInfo = Subtarget.getRegisterInfo(); | 
 |   setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister()); | 
 |  | 
 |   // Set up the register classes. | 
 |   addRegisterClass(MVT::i8, &M68k::DR8RegClass); | 
 |   addRegisterClass(MVT::i16, &M68k::XR16RegClass); | 
 |   addRegisterClass(MVT::i32, &M68k::XR32RegClass); | 
 |  | 
 |   for (auto VT : MVT::integer_valuetypes()) { | 
 |     setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); | 
 |     setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); | 
 |     setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); | 
 |   } | 
 |  | 
 |   // We don't accept any truncstore of integer registers. | 
 |   setTruncStoreAction(MVT::i64, MVT::i32, Expand); | 
 |   setTruncStoreAction(MVT::i64, MVT::i16, Expand); | 
 |   setTruncStoreAction(MVT::i64, MVT::i8, Expand); | 
 |   setTruncStoreAction(MVT::i32, MVT::i16, Expand); | 
 |   setTruncStoreAction(MVT::i32, MVT::i8, Expand); | 
 |   setTruncStoreAction(MVT::i16, MVT::i8, Expand); | 
 |  | 
 |   setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i8, Promote); | 
 |   setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i16, Legal); | 
 |   if (Subtarget.atLeastM68020()) | 
 |     setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i32, Legal); | 
 |   else | 
 |     setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i32, LibCall); | 
 |   setOperationAction(ISD::MUL, MVT::i64, LibCall); | 
 |  | 
 |   for (auto OP : | 
 |        {ISD::SREM, ISD::UREM, ISD::UDIVREM, ISD::SDIVREM, | 
 |         ISD::MULHS, ISD::MULHU, ISD::UMUL_LOHI, ISD::SMUL_LOHI}) { | 
 |     setOperationAction(OP, MVT::i8, Promote); | 
 |     setOperationAction(OP, MVT::i16, Legal); | 
 |     setOperationAction(OP, MVT::i32, LibCall); | 
 |   } | 
 |  | 
 |   for (auto OP : {ISD::UMUL_LOHI, ISD::SMUL_LOHI}) { | 
 |     setOperationAction(OP, MVT::i8, Expand); | 
 |     setOperationAction(OP, MVT::i16, Expand); | 
 |   } | 
 |  | 
 |   for (auto OP : {ISD::SMULO, ISD::UMULO}) { | 
 |     setOperationAction(OP, MVT::i8,  Custom); | 
 |     setOperationAction(OP, MVT::i16, Custom); | 
 |     setOperationAction(OP, MVT::i32, Custom); | 
 |   } | 
 |  | 
 |   for (auto OP : {ISD::SHL_PARTS, ISD::SRA_PARTS, ISD::SRL_PARTS}) | 
 |     setOperationAction(OP, MVT::i32, Custom); | 
 |  | 
 |   // Add/Sub overflow ops with MVT::Glues are lowered to CCR dependences. | 
 |   for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) { | 
 |     setOperationAction(ISD::ADDC, VT, Custom); | 
 |     setOperationAction(ISD::ADDE, VT, Custom); | 
 |     setOperationAction(ISD::SUBC, VT, Custom); | 
 |     setOperationAction(ISD::SUBE, VT, Custom); | 
 |   } | 
 |  | 
 |   // SADDO and friends are legal with this setup, i hope | 
 |   for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) { | 
 |     setOperationAction(ISD::SADDO, VT, Custom); | 
 |     setOperationAction(ISD::UADDO, VT, Custom); | 
 |     setOperationAction(ISD::SSUBO, VT, Custom); | 
 |     setOperationAction(ISD::USUBO, VT, Custom); | 
 |   } | 
 |  | 
 |   setOperationAction(ISD::BR_JT, MVT::Other, Expand); | 
 |   setOperationAction(ISD::BRCOND, MVT::Other, Custom); | 
 |  | 
 |   for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) { | 
 |     setOperationAction(ISD::BR_CC, VT, Expand); | 
 |     setOperationAction(ISD::SELECT, VT, Custom); | 
 |     setOperationAction(ISD::SELECT_CC, VT, Expand); | 
 |     setOperationAction(ISD::SETCC, VT, Custom); | 
 |     setOperationAction(ISD::SETCCCARRY, VT, Custom); | 
 |   } | 
 |  | 
 |   for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) { | 
 |     setOperationAction(ISD::BSWAP, VT, Expand); | 
 |     setOperationAction(ISD::CTTZ, VT, Expand); | 
 |     setOperationAction(ISD::CTLZ, VT, Expand); | 
 |     setOperationAction(ISD::CTPOP, VT, Expand); | 
 |   } | 
 |  | 
 |   setOperationAction(ISD::ConstantPool, MVT::i32, Custom); | 
 |   setOperationAction(ISD::JumpTable, MVT::i32, Custom); | 
 |   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); | 
 |   setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); | 
 |   setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom); | 
 |   setOperationAction(ISD::BlockAddress, MVT::i32, Custom); | 
 |  | 
 |   setOperationAction(ISD::VASTART, MVT::Other, Custom); | 
 |   setOperationAction(ISD::VAEND, MVT::Other, Expand); | 
 |   setOperationAction(ISD::VAARG, MVT::Other, Expand); | 
 |   setOperationAction(ISD::VACOPY, MVT::Other, Expand); | 
 |  | 
 |   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); | 
 |   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); | 
 |  | 
 |   setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom); | 
 |  | 
 |   computeRegisterProperties(STI.getRegisterInfo()); | 
 |  | 
 |   // We lower the `atomic-compare-and-swap` to `__sync_val_compare_and_swap` | 
 |   // for subtarget < M68020 | 
 |   setMaxAtomicSizeInBitsSupported(32); | 
 |   setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i8, MVT::i16, MVT::i32}, | 
 |                      Subtarget.atLeastM68020() ? Legal : LibCall); | 
 |  | 
 |   setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); | 
 |  | 
 |   // M68k does not have native read-modify-write support, so expand all of them | 
 |   // to `__sync_fetch_*` for target < M68020, otherwise expand to CmpxChg. | 
 |   // See `shouldExpandAtomicRMWInIR` below. | 
 |   setOperationAction( | 
 |       { | 
 |           ISD::ATOMIC_LOAD_ADD, | 
 |           ISD::ATOMIC_LOAD_SUB, | 
 |           ISD::ATOMIC_LOAD_AND, | 
 |           ISD::ATOMIC_LOAD_OR, | 
 |           ISD::ATOMIC_LOAD_XOR, | 
 |           ISD::ATOMIC_LOAD_NAND, | 
 |           ISD::ATOMIC_LOAD_MIN, | 
 |           ISD::ATOMIC_LOAD_MAX, | 
 |           ISD::ATOMIC_LOAD_UMIN, | 
 |           ISD::ATOMIC_LOAD_UMAX, | 
 |           ISD::ATOMIC_SWAP, | 
 |       }, | 
 |       {MVT::i8, MVT::i16, MVT::i32}, LibCall); | 
 |  | 
 |   setMinFunctionAlignment(Align(2)); | 
 | } | 
 |  | 
 | TargetLoweringBase::AtomicExpansionKind | 
 | M68kTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { | 
 |   return Subtarget.atLeastM68020() | 
 |              ? TargetLoweringBase::AtomicExpansionKind::CmpXChg | 
 |              : TargetLoweringBase::AtomicExpansionKind::None; | 
 | } | 
 |  | 
 | Register | 
 | M68kTargetLowering::getExceptionPointerRegister(const Constant *) const { | 
 |   return M68k::D0; | 
 | } | 
 |  | 
 | Register | 
 | M68kTargetLowering::getExceptionSelectorRegister(const Constant *) const { | 
 |   return M68k::D1; | 
 | } | 
 |  | 
 | InlineAsm::ConstraintCode | 
 | M68kTargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const { | 
 |   return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode) | 
 |       .Case("Q", InlineAsm::ConstraintCode::Q) | 
 |       // We borrow ConstraintCode::Um for 'U'. | 
 |       .Case("U", InlineAsm::ConstraintCode::Um) | 
 |       .Default(TargetLowering::getInlineAsmMemConstraint(ConstraintCode)); | 
 | } | 
 |  | 
 | EVT M68kTargetLowering::getSetCCResultType(const DataLayout &DL, | 
 |                                            LLVMContext &Context, EVT VT) const { | 
 |   // M68k SETcc producess either 0x00 or 0xFF | 
 |   return MVT::i8; | 
 | } | 
 |  | 
 | MVT M68kTargetLowering::getScalarShiftAmountTy(const DataLayout &DL, | 
 |                                                EVT Ty) const { | 
 |   if (Ty.isSimple()) { | 
 |     return Ty.getSimpleVT(); | 
 |   } | 
 |   return MVT::getIntegerVT(DL.getPointerSizeInBits(0)); | 
 | } | 
 |  | 
 | #include "M68kGenCallingConv.inc" | 
 |  | 
 | enum StructReturnType { NotStructReturn, RegStructReturn, StackStructReturn }; | 
 |  | 
 | static StructReturnType | 
 | callIsStructReturn(const SmallVectorImpl<ISD::OutputArg> &Outs) { | 
 |   if (Outs.empty()) | 
 |     return NotStructReturn; | 
 |  | 
 |   const ISD::ArgFlagsTy &Flags = Outs[0].Flags; | 
 |   if (!Flags.isSRet()) | 
 |     return NotStructReturn; | 
 |   if (Flags.isInReg()) | 
 |     return RegStructReturn; | 
 |   return StackStructReturn; | 
 | } | 
 |  | 
 | /// Determines whether a function uses struct return semantics. | 
 | static StructReturnType | 
 | argsAreStructReturn(const SmallVectorImpl<ISD::InputArg> &Ins) { | 
 |   if (Ins.empty()) | 
 |     return NotStructReturn; | 
 |  | 
 |   const ISD::ArgFlagsTy &Flags = Ins[0].Flags; | 
 |   if (!Flags.isSRet()) | 
 |     return NotStructReturn; | 
 |   if (Flags.isInReg()) | 
 |     return RegStructReturn; | 
 |   return StackStructReturn; | 
 | } | 
 |  | 
 | /// Make a copy of an aggregate at address specified by "Src" to address | 
 | /// "Dst" with size and alignment information specified by the specific | 
 | /// parameter attribute. The copy will be passed as a byval function parameter. | 
 | static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, | 
 |                                          SDValue Chain, ISD::ArgFlagsTy Flags, | 
 |                                          SelectionDAG &DAG, const SDLoc &DL) { | 
 |   SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), DL, MVT::i32); | 
 |  | 
 |   return DAG.getMemcpy( | 
 |       Chain, DL, Dst, Src, SizeNode, Flags.getNonZeroByValAlign(), | 
 |       /*isVolatile=*/false, /*AlwaysInline=*/true, | 
 |       /*CI=*/nullptr, std::nullopt, MachinePointerInfo(), MachinePointerInfo()); | 
 | } | 
 |  | 
 | /// Return true if the calling convention is one that we can guarantee TCO for. | 
 | static bool canGuaranteeTCO(CallingConv::ID CC) { return false; } | 
 |  | 
 | /// Return true if we might ever do TCO for calls with this calling convention. | 
 | static bool mayTailCallThisCC(CallingConv::ID CC) { | 
 |   switch (CC) { | 
 |   // C calling conventions: | 
 |   case CallingConv::C: | 
 |     return true; | 
 |   default: | 
 |     return canGuaranteeTCO(CC); | 
 |   } | 
 | } | 
 |  | 
 | /// Return true if the function is being made into a tailcall target by | 
 | /// changing its ABI. | 
 | static bool shouldGuaranteeTCO(CallingConv::ID CC, bool GuaranteedTailCallOpt) { | 
 |   return GuaranteedTailCallOpt && canGuaranteeTCO(CC); | 
 | } | 
 |  | 
 | /// Return true if the given stack call argument is already available in the | 
 | /// same position (relatively) of the caller's incoming argument stack. | 
 | static bool MatchingStackOffset(SDValue Arg, unsigned Offset, | 
 |                                 ISD::ArgFlagsTy Flags, MachineFrameInfo &MFI, | 
 |                                 const MachineRegisterInfo *MRI, | 
 |                                 const M68kInstrInfo *TII, | 
 |                                 const CCValAssign &VA) { | 
 |   unsigned Bytes = Arg.getValueType().getSizeInBits() / 8; | 
 |  | 
 |   for (;;) { | 
 |     // Look through nodes that don't alter the bits of the incoming value. | 
 |     unsigned Op = Arg.getOpcode(); | 
 |     if (Op == ISD::ZERO_EXTEND || Op == ISD::ANY_EXTEND || Op == ISD::BITCAST) { | 
 |       Arg = Arg.getOperand(0); | 
 |       continue; | 
 |     } | 
 |     if (Op == ISD::TRUNCATE) { | 
 |       const SDValue &TruncInput = Arg.getOperand(0); | 
 |       if (TruncInput.getOpcode() == ISD::AssertZext && | 
 |           cast<VTSDNode>(TruncInput.getOperand(1))->getVT() == | 
 |               Arg.getValueType()) { | 
 |         Arg = TruncInput.getOperand(0); | 
 |         continue; | 
 |       } | 
 |     } | 
 |     break; | 
 |   } | 
 |  | 
 |   int FI = INT_MAX; | 
 |   if (Arg.getOpcode() == ISD::CopyFromReg) { | 
 |     Register VR = cast<RegisterSDNode>(Arg.getOperand(1))->getReg(); | 
 |     if (!Register::isVirtualRegister(VR)) | 
 |       return false; | 
 |     MachineInstr *Def = MRI->getVRegDef(VR); | 
 |     if (!Def) | 
 |       return false; | 
 |     if (!Flags.isByVal()) { | 
 |       if (!TII->isLoadFromStackSlot(*Def, FI)) | 
 |         return false; | 
 |     } else { | 
 |       unsigned Opcode = Def->getOpcode(); | 
 |       if ((Opcode == M68k::LEA32p || Opcode == M68k::LEA32f) && | 
 |           Def->getOperand(1).isFI()) { | 
 |         FI = Def->getOperand(1).getIndex(); | 
 |         Bytes = Flags.getByValSize(); | 
 |       } else | 
 |         return false; | 
 |     } | 
 |   } else if (auto *Ld = dyn_cast<LoadSDNode>(Arg)) { | 
 |     if (Flags.isByVal()) | 
 |       // ByVal argument is passed in as a pointer but it's now being | 
 |       // dereferenced. e.g. | 
 |       // define @foo(%struct.X* %A) { | 
 |       //   tail call @bar(%struct.X* byval %A) | 
 |       // } | 
 |       return false; | 
 |     SDValue Ptr = Ld->getBasePtr(); | 
 |     FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(Ptr); | 
 |     if (!FINode) | 
 |       return false; | 
 |     FI = FINode->getIndex(); | 
 |   } else if (Arg.getOpcode() == ISD::FrameIndex && Flags.isByVal()) { | 
 |     FrameIndexSDNode *FINode = cast<FrameIndexSDNode>(Arg); | 
 |     FI = FINode->getIndex(); | 
 |     Bytes = Flags.getByValSize(); | 
 |   } else | 
 |     return false; | 
 |  | 
 |   assert(FI != INT_MAX); | 
 |   if (!MFI.isFixedObjectIndex(FI)) | 
 |     return false; | 
 |  | 
 |   if (Offset != MFI.getObjectOffset(FI)) | 
 |     return false; | 
 |  | 
 |   if (VA.getLocVT().getSizeInBits() > Arg.getValueType().getSizeInBits()) { | 
 |     // If the argument location is wider than the argument type, check that any | 
 |     // extension flags match. | 
 |     if (Flags.isZExt() != MFI.isObjectZExt(FI) || | 
 |         Flags.isSExt() != MFI.isObjectSExt(FI)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   return Bytes == MFI.getObjectSize(FI); | 
 | } | 
 |  | 
 | SDValue | 
 | M68kTargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const { | 
 |   MachineFunction &MF = DAG.getMachineFunction(); | 
 |   M68kMachineFunctionInfo *FuncInfo = MF.getInfo<M68kMachineFunctionInfo>(); | 
 |   int ReturnAddrIndex = FuncInfo->getRAIndex(); | 
 |  | 
 |   if (ReturnAddrIndex == 0) { | 
 |     // Set up a frame object for the return address. | 
 |     unsigned SlotSize = Subtarget.getSlotSize(); | 
 |     ReturnAddrIndex = MF.getFrameInfo().CreateFixedObject( | 
 |         SlotSize, -(int64_t)SlotSize, false); | 
 |     FuncInfo->setRAIndex(ReturnAddrIndex); | 
 |   } | 
 |  | 
 |   return DAG.getFrameIndex(ReturnAddrIndex, getPointerTy(DAG.getDataLayout())); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::EmitTailCallLoadRetAddr(SelectionDAG &DAG, | 
 |                                                     SDValue &OutRetAddr, | 
 |                                                     SDValue Chain, | 
 |                                                     bool IsTailCall, int FPDiff, | 
 |                                                     const SDLoc &DL) const { | 
 |   EVT VT = getPointerTy(DAG.getDataLayout()); | 
 |   OutRetAddr = getReturnAddressFrameIndex(DAG); | 
 |  | 
 |   // Load the "old" Return address. | 
 |   OutRetAddr = DAG.getLoad(VT, DL, Chain, OutRetAddr, MachinePointerInfo()); | 
 |   return SDValue(OutRetAddr.getNode(), 1); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::EmitTailCallStoreRetAddr( | 
 |     SelectionDAG &DAG, MachineFunction &MF, SDValue Chain, SDValue RetFI, | 
 |     EVT PtrVT, unsigned SlotSize, int FPDiff, const SDLoc &DL) const { | 
 |   if (!FPDiff) | 
 |     return Chain; | 
 |  | 
 |   // Calculate the new stack slot for the return address. | 
 |   int NewFO = MF.getFrameInfo().CreateFixedObject( | 
 |       SlotSize, (int64_t)FPDiff - SlotSize, false); | 
 |  | 
 |   SDValue NewFI = DAG.getFrameIndex(NewFO, PtrVT); | 
 |   // Store the return address to the appropriate stack slot. | 
 |   Chain = DAG.getStore( | 
 |       Chain, DL, RetFI, NewFI, | 
 |       MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), NewFO)); | 
 |   return Chain; | 
 | } | 
 |  | 
 | SDValue | 
 | M68kTargetLowering::LowerMemArgument(SDValue Chain, CallingConv::ID CallConv, | 
 |                                      const SmallVectorImpl<ISD::InputArg> &Ins, | 
 |                                      const SDLoc &DL, SelectionDAG &DAG, | 
 |                                      const CCValAssign &VA, | 
 |                                      MachineFrameInfo &MFI, | 
 |                                      unsigned ArgIdx) const { | 
 |   // Create the nodes corresponding to a load from this parameter slot. | 
 |   ISD::ArgFlagsTy Flags = Ins[ArgIdx].Flags; | 
 |   EVT ValVT; | 
 |  | 
 |   // If value is passed by pointer we have address passed instead of the value | 
 |   // itself. | 
 |   if (VA.getLocInfo() == CCValAssign::Indirect) | 
 |     ValVT = VA.getLocVT(); | 
 |   else | 
 |     ValVT = VA.getValVT(); | 
 |  | 
 |   // Because we are dealing with BE architecture we need to offset loading of | 
 |   // partial types | 
 |   int Offset = VA.getLocMemOffset(); | 
 |   if (VA.getValVT() == MVT::i8) { | 
 |     Offset += 3; | 
 |   } else if (VA.getValVT() == MVT::i16) { | 
 |     Offset += 2; | 
 |   } | 
 |  | 
 |   // TODO Interrupt handlers | 
 |   // Calculate SP offset of interrupt parameter, re-arrange the slot normally | 
 |   // taken by a return address. | 
 |  | 
 |   // FIXME For now, all byval parameter objects are marked mutable. This can | 
 |   // be changed with more analysis. In case of tail call optimization mark all | 
 |   // arguments mutable. Since they could be overwritten by lowering of arguments | 
 |   // in case of a tail call. | 
 |   bool AlwaysUseMutable = shouldGuaranteeTCO( | 
 |       CallConv, DAG.getTarget().Options.GuaranteedTailCallOpt); | 
 |   bool IsImmutable = !AlwaysUseMutable && !Flags.isByVal(); | 
 |  | 
 |   if (Flags.isByVal()) { | 
 |     unsigned Bytes = Flags.getByValSize(); | 
 |     if (Bytes == 0) | 
 |       Bytes = 1; // Don't create zero-sized stack objects. | 
 |     int FI = MFI.CreateFixedObject(Bytes, Offset, IsImmutable); | 
 |     // TODO Interrupt handlers | 
 |     // Adjust SP offset of interrupt parameter. | 
 |     return DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); | 
 |   } else { | 
 |     int FI = | 
 |         MFI.CreateFixedObject(ValVT.getSizeInBits() / 8, Offset, IsImmutable); | 
 |  | 
 |     // Set SExt or ZExt flag. | 
 |     if (VA.getLocInfo() == CCValAssign::ZExt) { | 
 |       MFI.setObjectZExt(FI, true); | 
 |     } else if (VA.getLocInfo() == CCValAssign::SExt) { | 
 |       MFI.setObjectSExt(FI, true); | 
 |     } | 
 |  | 
 |     // TODO Interrupt handlers | 
 |     // Adjust SP offset of interrupt parameter. | 
 |  | 
 |     SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); | 
 |     SDValue Val = DAG.getLoad( | 
 |         ValVT, DL, Chain, FIN, | 
 |         MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); | 
 |     return VA.isExtInLoc() ? DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val) | 
 |                            : Val; | 
 |   } | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerMemOpCallTo(SDValue Chain, SDValue StackPtr, | 
 |                                              SDValue Arg, const SDLoc &DL, | 
 |                                              SelectionDAG &DAG, | 
 |                                              const CCValAssign &VA, | 
 |                                              ISD::ArgFlagsTy Flags) const { | 
 |   unsigned LocMemOffset = VA.getLocMemOffset(); | 
 |   SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset, DL); | 
 |   PtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), | 
 |                        StackPtr, PtrOff); | 
 |   if (Flags.isByVal()) | 
 |     return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG, DL); | 
 |  | 
 |   return DAG.getStore( | 
 |       Chain, DL, Arg, PtrOff, | 
 |       MachinePointerInfo::getStack(DAG.getMachineFunction(), LocMemOffset)); | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | //                                   Call | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, | 
 |                                       SmallVectorImpl<SDValue> &InVals) const { | 
 |   SelectionDAG &DAG = CLI.DAG; | 
 |   SDLoc &DL = CLI.DL; | 
 |   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; | 
 |   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; | 
 |   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; | 
 |   SDValue Chain = CLI.Chain; | 
 |   SDValue Callee = CLI.Callee; | 
 |   CallingConv::ID CallConv = CLI.CallConv; | 
 |   bool &IsTailCall = CLI.IsTailCall; | 
 |   bool IsVarArg = CLI.IsVarArg; | 
 |  | 
 |   MachineFunction &MF = DAG.getMachineFunction(); | 
 |   StructReturnType SR = callIsStructReturn(Outs); | 
 |   bool IsSibcall = false; | 
 |   M68kMachineFunctionInfo *MFI = MF.getInfo<M68kMachineFunctionInfo>(); | 
 |   // const M68kRegisterInfo *TRI = Subtarget.getRegisterInfo(); | 
 |  | 
 |   if (CallConv == CallingConv::M68k_INTR) | 
 |     report_fatal_error("M68k interrupts may not be called directly"); | 
 |  | 
 |   auto Attr = MF.getFunction().getFnAttribute("disable-tail-calls"); | 
 |   if (Attr.getValueAsBool()) | 
 |     IsTailCall = false; | 
 |  | 
 |   // FIXME Add tailcalls support | 
 |  | 
 |   bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall(); | 
 |   if (IsMustTail) { | 
 |     // Force this to be a tail call.  The verifier rules are enough to ensure | 
 |     // that we can lower this successfully without moving the return address | 
 |     // around. | 
 |     IsTailCall = true; | 
 |   } else if (IsTailCall) { | 
 |     // Check if it's really possible to do a tail call. | 
 |     IsTailCall = IsEligibleForTailCallOptimization( | 
 |         Callee, CallConv, IsVarArg, SR != NotStructReturn, | 
 |         MF.getFunction().hasStructRetAttr(), CLI.RetTy, Outs, OutVals, Ins, | 
 |         DAG); | 
 |  | 
 |     // Sibcalls are automatically detected tailcalls which do not require | 
 |     // ABI changes. | 
 |     if (!MF.getTarget().Options.GuaranteedTailCallOpt && IsTailCall) | 
 |       IsSibcall = true; | 
 |  | 
 |     if (IsTailCall) | 
 |       ++NumTailCalls; | 
 |   } | 
 |  | 
 |   assert(!(IsVarArg && canGuaranteeTCO(CallConv)) && | 
 |          "Var args not supported with calling convention fastcc"); | 
 |  | 
 |   // Analyze operands of the call, assigning locations to each operand. | 
 |   SmallVector<CCValAssign, 16> ArgLocs; | 
 |   SmallVector<Type *, 4> ArgTypes; | 
 |   for (const auto &Arg : CLI.getArgs()) | 
 |     ArgTypes.emplace_back(Arg.Ty); | 
 |   M68kCCState CCInfo(ArgTypes, CallConv, IsVarArg, MF, ArgLocs, | 
 |                      *DAG.getContext()); | 
 |   CCInfo.AnalyzeCallOperands(Outs, CC_M68k); | 
 |  | 
 |   // Get a count of how many bytes are to be pushed on the stack. | 
 |   unsigned NumBytes = CCInfo.getAlignedCallFrameSize(); | 
 |   if (IsSibcall) { | 
 |     // This is a sibcall. The memory operands are available in caller's | 
 |     // own caller's stack. | 
 |     NumBytes = 0; | 
 |   } else if (MF.getTarget().Options.GuaranteedTailCallOpt && | 
 |              canGuaranteeTCO(CallConv)) { | 
 |     NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG); | 
 |   } | 
 |  | 
 |   int FPDiff = 0; | 
 |   if (IsTailCall && !IsSibcall && !IsMustTail) { | 
 |     // Lower arguments at fp - stackoffset + fpdiff. | 
 |     unsigned NumBytesCallerPushed = MFI->getBytesToPopOnReturn(); | 
 |  | 
 |     FPDiff = NumBytesCallerPushed - NumBytes; | 
 |  | 
 |     // Set the delta of movement of the returnaddr stackslot. | 
 |     // But only set if delta is greater than previous delta. | 
 |     if (FPDiff < MFI->getTCReturnAddrDelta()) | 
 |       MFI->setTCReturnAddrDelta(FPDiff); | 
 |   } | 
 |  | 
 |   unsigned NumBytesToPush = NumBytes; | 
 |   unsigned NumBytesToPop = NumBytes; | 
 |  | 
 |   // If we have an inalloca argument, all stack space has already been allocated | 
 |   // for us and be right at the top of the stack.  We don't support multiple | 
 |   // arguments passed in memory when using inalloca. | 
 |   if (!Outs.empty() && Outs.back().Flags.isInAlloca()) { | 
 |     NumBytesToPush = 0; | 
 |     if (!ArgLocs.back().isMemLoc()) | 
 |       report_fatal_error("cannot use inalloca attribute on a register " | 
 |                          "parameter"); | 
 |     if (ArgLocs.back().getLocMemOffset() != 0) | 
 |       report_fatal_error("any parameter with the inalloca attribute must be " | 
 |                          "the only memory argument"); | 
 |   } | 
 |  | 
 |   if (!IsSibcall) | 
 |     Chain = DAG.getCALLSEQ_START(Chain, NumBytesToPush, | 
 |                                  NumBytes - NumBytesToPush, DL); | 
 |  | 
 |   SDValue RetFI; | 
 |   // Load return address for tail calls. | 
 |   if (IsTailCall && FPDiff) | 
 |     Chain = EmitTailCallLoadRetAddr(DAG, RetFI, Chain, IsTailCall, FPDiff, DL); | 
 |  | 
 |   SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; | 
 |   SmallVector<SDValue, 8> MemOpChains; | 
 |   SDValue StackPtr; | 
 |  | 
 |   // Walk the register/memloc assignments, inserting copies/loads.  In the case | 
 |   // of tail call optimization arguments are handle later. | 
 |   const M68kRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); | 
 |   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | 
 |     ISD::ArgFlagsTy Flags = Outs[i].Flags; | 
 |  | 
 |     // Skip inalloca arguments, they have already been written. | 
 |     if (Flags.isInAlloca()) | 
 |       continue; | 
 |  | 
 |     CCValAssign &VA = ArgLocs[i]; | 
 |     EVT RegVT = VA.getLocVT(); | 
 |     SDValue Arg = OutVals[i]; | 
 |     bool IsByVal = Flags.isByVal(); | 
 |  | 
 |     // Promote the value if needed. | 
 |     switch (VA.getLocInfo()) { | 
 |     default: | 
 |       llvm_unreachable("Unknown loc info!"); | 
 |     case CCValAssign::Full: | 
 |       break; | 
 |     case CCValAssign::SExt: | 
 |       Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, RegVT, Arg); | 
 |       break; | 
 |     case CCValAssign::ZExt: | 
 |       Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, RegVT, Arg); | 
 |       break; | 
 |     case CCValAssign::AExt: | 
 |       Arg = DAG.getNode(ISD::ANY_EXTEND, DL, RegVT, Arg); | 
 |       break; | 
 |     case CCValAssign::BCvt: | 
 |       Arg = DAG.getBitcast(RegVT, Arg); | 
 |       break; | 
 |     case CCValAssign::Indirect: { | 
 |       // Store the argument. | 
 |       SDValue SpillSlot = DAG.CreateStackTemporary(VA.getValVT()); | 
 |       int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex(); | 
 |       Chain = DAG.getStore( | 
 |           Chain, DL, Arg, SpillSlot, | 
 |           MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); | 
 |       Arg = SpillSlot; | 
 |       break; | 
 |     } | 
 |     } | 
 |  | 
 |     if (VA.isRegLoc()) { | 
 |       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); | 
 |     } else if (!IsSibcall && (!IsTailCall || IsByVal)) { | 
 |       assert(VA.isMemLoc()); | 
 |       if (!StackPtr.getNode()) { | 
 |         StackPtr = DAG.getCopyFromReg(Chain, DL, RegInfo->getStackRegister(), | 
 |                                       getPointerTy(DAG.getDataLayout())); | 
 |       } | 
 |       MemOpChains.push_back( | 
 |           LowerMemOpCallTo(Chain, StackPtr, Arg, DL, DAG, VA, Flags)); | 
 |     } | 
 |   } | 
 |  | 
 |   if (!MemOpChains.empty()) | 
 |     Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); | 
 |  | 
 |   // FIXME Make sure PIC style GOT works as expected | 
 |   // The only time GOT is really needed is for Medium-PIC static data | 
 |   // otherwise we are happy with pc-rel or static references | 
 |  | 
 |   if (IsVarArg && IsMustTail) { | 
 |     const auto &Forwards = MFI->getForwardedMustTailRegParms(); | 
 |     for (const auto &F : Forwards) { | 
 |       SDValue Val = DAG.getCopyFromReg(Chain, DL, F.VReg, F.VT); | 
 |       RegsToPass.push_back(std::make_pair(unsigned(F.PReg), Val)); | 
 |     } | 
 |   } | 
 |  | 
 |   // For tail calls lower the arguments to the 'real' stack slots.  Sibcalls | 
 |   // don't need this because the eligibility check rejects calls that require | 
 |   // shuffling arguments passed in memory. | 
 |   if (!IsSibcall && IsTailCall) { | 
 |     // Force all the incoming stack arguments to be loaded from the stack | 
 |     // before any new outgoing arguments are stored to the stack, because the | 
 |     // outgoing stack slots may alias the incoming argument stack slots, and | 
 |     // the alias isn't otherwise explicit. This is slightly more conservative | 
 |     // than necessary, because it means that each store effectively depends | 
 |     // on every argument instead of just those arguments it would clobber. | 
 |     SDValue ArgChain = DAG.getStackArgumentTokenFactor(Chain); | 
 |  | 
 |     SmallVector<SDValue, 8> MemOpChains2; | 
 |     SDValue FIN; | 
 |     int FI = 0; | 
 |     for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | 
 |       CCValAssign &VA = ArgLocs[i]; | 
 |       if (VA.isRegLoc()) | 
 |         continue; | 
 |       assert(VA.isMemLoc()); | 
 |       SDValue Arg = OutVals[i]; | 
 |       ISD::ArgFlagsTy Flags = Outs[i].Flags; | 
 |       // Skip inalloca arguments.  They don't require any work. | 
 |       if (Flags.isInAlloca()) | 
 |         continue; | 
 |       // Create frame index. | 
 |       int32_t Offset = VA.getLocMemOffset() + FPDiff; | 
 |       uint32_t OpSize = (VA.getLocVT().getSizeInBits() + 7) / 8; | 
 |       FI = MF.getFrameInfo().CreateFixedObject(OpSize, Offset, true); | 
 |       FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); | 
 |  | 
 |       if (Flags.isByVal()) { | 
 |         // Copy relative to framepointer. | 
 |         SDValue Source = DAG.getIntPtrConstant(VA.getLocMemOffset(), DL); | 
 |         if (!StackPtr.getNode()) { | 
 |           StackPtr = DAG.getCopyFromReg(Chain, DL, RegInfo->getStackRegister(), | 
 |                                         getPointerTy(DAG.getDataLayout())); | 
 |         } | 
 |         Source = DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), | 
 |                              StackPtr, Source); | 
 |  | 
 |         MemOpChains2.push_back( | 
 |             CreateCopyOfByValArgument(Source, FIN, ArgChain, Flags, DAG, DL)); | 
 |       } else { | 
 |         // Store relative to framepointer. | 
 |         MemOpChains2.push_back(DAG.getStore( | 
 |             ArgChain, DL, Arg, FIN, | 
 |             MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI))); | 
 |       } | 
 |     } | 
 |  | 
 |     if (!MemOpChains2.empty()) | 
 |       Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains2); | 
 |  | 
 |     // Store the return address to the appropriate stack slot. | 
 |     Chain = EmitTailCallStoreRetAddr(DAG, MF, Chain, RetFI, | 
 |                                      getPointerTy(DAG.getDataLayout()), | 
 |                                      Subtarget.getSlotSize(), FPDiff, DL); | 
 |   } | 
 |  | 
 |   // Build a sequence of copy-to-reg nodes chained together with token chain | 
 |   // and flag operands which copy the outgoing args into registers. | 
 |   SDValue InGlue; | 
 |   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { | 
 |     Chain = DAG.getCopyToReg(Chain, DL, RegsToPass[i].first, | 
 |                              RegsToPass[i].second, InGlue); | 
 |     InGlue = Chain.getValue(1); | 
 |   } | 
 |  | 
 |   if (Callee->getOpcode() == ISD::GlobalAddress) { | 
 |     // If the callee is a GlobalAddress node (quite common, every direct call | 
 |     // is) turn it into a TargetGlobalAddress node so that legalize doesn't hack | 
 |     // it. | 
 |     GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Callee); | 
 |  | 
 |     // We should use extra load for direct calls to dllimported functions in | 
 |     // non-JIT mode. | 
 |     const GlobalValue *GV = G->getGlobal(); | 
 |     if (!GV->hasDLLImportStorageClass()) { | 
 |       unsigned char OpFlags = Subtarget.classifyGlobalFunctionReference(GV); | 
 |  | 
 |       Callee = DAG.getTargetGlobalAddress( | 
 |           GV, DL, getPointerTy(DAG.getDataLayout()), G->getOffset(), OpFlags); | 
 |  | 
 |       if (OpFlags == M68kII::MO_GOTPCREL) { | 
 |  | 
 |         // Add a wrapper. | 
 |         Callee = DAG.getNode(M68kISD::WrapperPC, DL, | 
 |                              getPointerTy(DAG.getDataLayout()), Callee); | 
 |  | 
 |         // Add extra indirection | 
 |         Callee = DAG.getLoad( | 
 |             getPointerTy(DAG.getDataLayout()), DL, DAG.getEntryNode(), Callee, | 
 |             MachinePointerInfo::getGOT(DAG.getMachineFunction())); | 
 |       } | 
 |     } | 
 |   } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { | 
 |     const Module *Mod = DAG.getMachineFunction().getFunction().getParent(); | 
 |     unsigned char OpFlags = | 
 |         Subtarget.classifyGlobalFunctionReference(nullptr, *Mod); | 
 |  | 
 |     Callee = DAG.getTargetExternalSymbol( | 
 |         S->getSymbol(), getPointerTy(DAG.getDataLayout()), OpFlags); | 
 |   } | 
 |  | 
 |   SmallVector<SDValue, 8> Ops; | 
 |  | 
 |   if (!IsSibcall && IsTailCall) { | 
 |     Chain = DAG.getCALLSEQ_END(Chain, NumBytesToPop, 0, InGlue, DL); | 
 |     InGlue = Chain.getValue(1); | 
 |   } | 
 |  | 
 |   Ops.push_back(Chain); | 
 |   Ops.push_back(Callee); | 
 |  | 
 |   if (IsTailCall) | 
 |     Ops.push_back(DAG.getConstant(FPDiff, DL, MVT::i32)); | 
 |  | 
 |   // Add argument registers to the end of the list so that they are known live | 
 |   // into the call. | 
 |   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) | 
 |     Ops.push_back(DAG.getRegister(RegsToPass[i].first, | 
 |                                   RegsToPass[i].second.getValueType())); | 
 |  | 
 |   // Add a register mask operand representing the call-preserved registers. | 
 |   const uint32_t *Mask = RegInfo->getCallPreservedMask(MF, CallConv); | 
 |   assert(Mask && "Missing call preserved mask for calling convention"); | 
 |  | 
 |   Ops.push_back(DAG.getRegisterMask(Mask)); | 
 |  | 
 |   if (InGlue.getNode()) | 
 |     Ops.push_back(InGlue); | 
 |  | 
 |   if (IsTailCall) { | 
 |     MF.getFrameInfo().setHasTailCall(); | 
 |     return DAG.getNode(M68kISD::TC_RETURN, DL, MVT::Other, Ops); | 
 |   } | 
 |  | 
 |   // Returns a chain & a flag for retval copy to use. | 
 |   Chain = DAG.getNode(M68kISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops); | 
 |   InGlue = Chain.getValue(1); | 
 |  | 
 |   // Create the CALLSEQ_END node. | 
 |   unsigned NumBytesForCalleeToPop; | 
 |   if (M68k::isCalleePop(CallConv, IsVarArg, | 
 |                         DAG.getTarget().Options.GuaranteedTailCallOpt)) { | 
 |     NumBytesForCalleeToPop = NumBytes; // Callee pops everything | 
 |   } else if (!canGuaranteeTCO(CallConv) && SR == StackStructReturn) { | 
 |     // If this is a call to a struct-return function, the callee | 
 |     // pops the hidden struct pointer, so we have to push it back. | 
 |     NumBytesForCalleeToPop = 4; | 
 |   } else { | 
 |     NumBytesForCalleeToPop = 0; // Callee pops nothing. | 
 |   } | 
 |  | 
 |   if (CLI.DoesNotReturn && !getTargetMachine().Options.TrapUnreachable) { | 
 |     // No need to reset the stack after the call if the call doesn't return. To | 
 |     // make the MI verify, we'll pretend the callee does it for us. | 
 |     NumBytesForCalleeToPop = NumBytes; | 
 |   } | 
 |  | 
 |   // Returns a flag for retval copy to use. | 
 |   if (!IsSibcall) { | 
 |     Chain = DAG.getCALLSEQ_END(Chain, NumBytesToPop, NumBytesForCalleeToPop, | 
 |                                InGlue, DL); | 
 |     InGlue = Chain.getValue(1); | 
 |   } | 
 |  | 
 |   // Handle result values, copying them out of physregs into vregs that we | 
 |   // return. | 
 |   return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG, | 
 |                          InVals); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerCallResult( | 
 |     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg, | 
 |     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, | 
 |     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { | 
 |  | 
 |   // Assign locations to each value returned by this call. | 
 |   SmallVector<CCValAssign, 16> RVLocs; | 
 |   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, | 
 |                  *DAG.getContext()); | 
 |   CCInfo.AnalyzeCallResult(Ins, RetCC_M68k); | 
 |  | 
 |   // Copy all of the result registers out of their specified physreg. | 
 |   for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { | 
 |     CCValAssign &VA = RVLocs[i]; | 
 |     EVT CopyVT = VA.getLocVT(); | 
 |  | 
 |     /// ??? is this correct? | 
 |     Chain = DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), CopyVT, InGlue) | 
 |                 .getValue(1); | 
 |     SDValue Val = Chain.getValue(0); | 
 |  | 
 |     if (VA.isExtInLoc() && VA.getValVT().getScalarType() == MVT::i1) | 
 |       Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); | 
 |  | 
 |     InGlue = Chain.getValue(2); | 
 |     InVals.push_back(Val); | 
 |   } | 
 |  | 
 |   return Chain; | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | //            Formal Arguments Calling Convention Implementation | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | SDValue M68kTargetLowering::LowerFormalArguments( | 
 |     SDValue Chain, CallingConv::ID CCID, bool IsVarArg, | 
 |     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, | 
 |     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { | 
 |   MachineFunction &MF = DAG.getMachineFunction(); | 
 |   M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>(); | 
 |   // const TargetFrameLowering &TFL = *Subtarget.getFrameLowering(); | 
 |  | 
 |   MachineFrameInfo &MFI = MF.getFrameInfo(); | 
 |  | 
 |   // Assign locations to all of the incoming arguments. | 
 |   SmallVector<CCValAssign, 16> ArgLocs; | 
 |   SmallVector<Type *, 4> ArgTypes; | 
 |   for (const Argument &Arg : MF.getFunction().args()) | 
 |     ArgTypes.emplace_back(Arg.getType()); | 
 |   M68kCCState CCInfo(ArgTypes, CCID, IsVarArg, MF, ArgLocs, *DAG.getContext()); | 
 |  | 
 |   CCInfo.AnalyzeFormalArguments(Ins, CC_M68k); | 
 |  | 
 |   unsigned LastVal = ~0U; | 
 |   SDValue ArgValue; | 
 |   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | 
 |     CCValAssign &VA = ArgLocs[i]; | 
 |     assert(VA.getValNo() != LastVal && "Same value in different locations"); | 
 |     (void)LastVal; | 
 |  | 
 |     LastVal = VA.getValNo(); | 
 |  | 
 |     if (VA.isRegLoc()) { | 
 |       EVT RegVT = VA.getLocVT(); | 
 |       const TargetRegisterClass *RC; | 
 |       if (RegVT == MVT::i32) | 
 |         RC = &M68k::XR32RegClass; | 
 |       else | 
 |         llvm_unreachable("Unknown argument type!"); | 
 |  | 
 |       Register Reg = MF.addLiveIn(VA.getLocReg(), RC); | 
 |       ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); | 
 |  | 
 |       // If this is an 8 or 16-bit value, it is really passed promoted to 32 | 
 |       // bits.  Insert an assert[sz]ext to capture this, then truncate to the | 
 |       // right size. | 
 |       if (VA.getLocInfo() == CCValAssign::SExt) { | 
 |         ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue, | 
 |                                DAG.getValueType(VA.getValVT())); | 
 |       } else if (VA.getLocInfo() == CCValAssign::ZExt) { | 
 |         ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue, | 
 |                                DAG.getValueType(VA.getValVT())); | 
 |       } else if (VA.getLocInfo() == CCValAssign::BCvt) { | 
 |         ArgValue = DAG.getBitcast(VA.getValVT(), ArgValue); | 
 |       } | 
 |  | 
 |       if (VA.isExtInLoc()) { | 
 |         ArgValue = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), ArgValue); | 
 |       } | 
 |     } else { | 
 |       assert(VA.isMemLoc()); | 
 |       ArgValue = LowerMemArgument(Chain, CCID, Ins, DL, DAG, VA, MFI, i); | 
 |     } | 
 |  | 
 |     // If value is passed via pointer - do a load. | 
 |     // TODO Make sure this handling on indirect arguments is correct | 
 |     if (VA.getLocInfo() == CCValAssign::Indirect) | 
 |       ArgValue = | 
 |           DAG.getLoad(VA.getValVT(), DL, Chain, ArgValue, MachinePointerInfo()); | 
 |  | 
 |     InVals.push_back(ArgValue); | 
 |   } | 
 |  | 
 |   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | 
 |     // Swift calling convention does not require we copy the sret argument | 
 |     // into %D0 for the return. We don't set SRetReturnReg for Swift. | 
 |     if (CCID == CallingConv::Swift) | 
 |       continue; | 
 |  | 
 |     // ABI require that for returning structs by value we copy the sret argument | 
 |     // into %D0 for the return. Save the argument into a virtual register so | 
 |     // that we can access it from the return points. | 
 |     if (Ins[i].Flags.isSRet()) { | 
 |       unsigned Reg = MMFI->getSRetReturnReg(); | 
 |       if (!Reg) { | 
 |         MVT PtrTy = getPointerTy(DAG.getDataLayout()); | 
 |         Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(PtrTy)); | 
 |         MMFI->setSRetReturnReg(Reg); | 
 |       } | 
 |       SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]); | 
 |       Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain); | 
 |       break; | 
 |     } | 
 |   } | 
 |  | 
 |   unsigned StackSize = CCInfo.getStackSize(); | 
 |   // Align stack specially for tail calls. | 
 |   if (shouldGuaranteeTCO(CCID, MF.getTarget().Options.GuaranteedTailCallOpt)) | 
 |     StackSize = GetAlignedArgumentStackSize(StackSize, DAG); | 
 |  | 
 |   // If the function takes variable number of arguments, make a frame index for | 
 |   // the start of the first vararg value... for expansion of llvm.va_start. We | 
 |   // can skip this if there are no va_start calls. | 
 |   if (MFI.hasVAStart()) { | 
 |     MMFI->setVarArgsFrameIndex(MFI.CreateFixedObject(1, StackSize, true)); | 
 |   } | 
 |  | 
 |   if (IsVarArg && MFI.hasMustTailInVarArgFunc()) { | 
 |     // We forward some GPRs and some vector types. | 
 |     SmallVector<MVT, 2> RegParmTypes; | 
 |     MVT IntVT = MVT::i32; | 
 |     RegParmTypes.push_back(IntVT); | 
 |  | 
 |     // Compute the set of forwarded registers. The rest are scratch. | 
 |     // ??? what is this for? | 
 |     SmallVectorImpl<ForwardedRegister> &Forwards = | 
 |         MMFI->getForwardedMustTailRegParms(); | 
 |     CCInfo.analyzeMustTailForwardedRegisters(Forwards, RegParmTypes, CC_M68k); | 
 |  | 
 |     // Copy all forwards from physical to virtual registers. | 
 |     for (ForwardedRegister &F : Forwards) { | 
 |       // FIXME Can we use a less constrained schedule? | 
 |       SDValue RegVal = DAG.getCopyFromReg(Chain, DL, F.VReg, F.VT); | 
 |       F.VReg = MF.getRegInfo().createVirtualRegister(getRegClassFor(F.VT)); | 
 |       Chain = DAG.getCopyToReg(Chain, DL, F.VReg, RegVal); | 
 |     } | 
 |   } | 
 |  | 
 |   // Some CCs need callee pop. | 
 |   if (M68k::isCalleePop(CCID, IsVarArg, | 
 |                         MF.getTarget().Options.GuaranteedTailCallOpt)) { | 
 |     MMFI->setBytesToPopOnReturn(StackSize); // Callee pops everything. | 
 |   } else { | 
 |     MMFI->setBytesToPopOnReturn(0); // Callee pops nothing. | 
 |     // If this is an sret function, the return should pop the hidden pointer. | 
 |     if (!canGuaranteeTCO(CCID) && argsAreStructReturn(Ins) == StackStructReturn) | 
 |       MMFI->setBytesToPopOnReturn(4); | 
 |   } | 
 |  | 
 |   MMFI->setArgumentStackSize(StackSize); | 
 |  | 
 |   return Chain; | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | //              Return Value Calling Convention Implementation | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | bool M68kTargetLowering::CanLowerReturn( | 
 |     CallingConv::ID CCID, MachineFunction &MF, bool IsVarArg, | 
 |     const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context, | 
 |     const Type *RetTy) const { | 
 |   SmallVector<CCValAssign, 16> RVLocs; | 
 |   CCState CCInfo(CCID, IsVarArg, MF, RVLocs, Context); | 
 |   return CCInfo.CheckReturn(Outs, RetCC_M68k); | 
 | } | 
 |  | 
 | SDValue | 
 | M68kTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CCID, | 
 |                                 bool IsVarArg, | 
 |                                 const SmallVectorImpl<ISD::OutputArg> &Outs, | 
 |                                 const SmallVectorImpl<SDValue> &OutVals, | 
 |                                 const SDLoc &DL, SelectionDAG &DAG) const { | 
 |   MachineFunction &MF = DAG.getMachineFunction(); | 
 |   M68kMachineFunctionInfo *MFI = MF.getInfo<M68kMachineFunctionInfo>(); | 
 |  | 
 |   SmallVector<CCValAssign, 16> RVLocs; | 
 |   CCState CCInfo(CCID, IsVarArg, MF, RVLocs, *DAG.getContext()); | 
 |   CCInfo.AnalyzeReturn(Outs, RetCC_M68k); | 
 |  | 
 |   SDValue Glue; | 
 |   SmallVector<SDValue, 6> RetOps; | 
 |   // Operand #0 = Chain (updated below) | 
 |   RetOps.push_back(Chain); | 
 |   // Operand #1 = Bytes To Pop | 
 |   RetOps.push_back( | 
 |       DAG.getTargetConstant(MFI->getBytesToPopOnReturn(), DL, MVT::i32)); | 
 |  | 
 |   // Copy the result values into the output registers. | 
 |   for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { | 
 |     CCValAssign &VA = RVLocs[i]; | 
 |     assert(VA.isRegLoc() && "Can only return in registers!"); | 
 |     SDValue ValToCopy = OutVals[i]; | 
 |     EVT ValVT = ValToCopy.getValueType(); | 
 |  | 
 |     // Promote values to the appropriate types. | 
 |     if (VA.getLocInfo() == CCValAssign::SExt) | 
 |       ValToCopy = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), ValToCopy); | 
 |     else if (VA.getLocInfo() == CCValAssign::ZExt) | 
 |       ValToCopy = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), ValToCopy); | 
 |     else if (VA.getLocInfo() == CCValAssign::AExt) { | 
 |       if (ValVT.isVector() && ValVT.getVectorElementType() == MVT::i1) | 
 |         ValToCopy = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), ValToCopy); | 
 |       else | 
 |         ValToCopy = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), ValToCopy); | 
 |     } else if (VA.getLocInfo() == CCValAssign::BCvt) | 
 |       ValToCopy = DAG.getBitcast(VA.getLocVT(), ValToCopy); | 
 |  | 
 |     Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), ValToCopy, Glue); | 
 |     Glue = Chain.getValue(1); | 
 |     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); | 
 |   } | 
 |  | 
 |   // Swift calling convention does not require we copy the sret argument | 
 |   // into %d0 for the return, and SRetReturnReg is not set for Swift. | 
 |  | 
 |   // ABI require that for returning structs by value we copy the sret argument | 
 |   // into %D0 for the return. Save the argument into a virtual register so that | 
 |   // we can access it from the return points. | 
 |   // | 
 |   // Checking Function.hasStructRetAttr() here is insufficient because the IR | 
 |   // may not have an explicit sret argument. If MFI.CanLowerReturn is | 
 |   // false, then an sret argument may be implicitly inserted in the SelDAG. In | 
 |   // either case MFI->setSRetReturnReg() will have been called. | 
 |   if (unsigned SRetReg = MFI->getSRetReturnReg()) { | 
 |     // ??? Can i just move this to the top and escape this explanation? | 
 |     // When we have both sret and another return value, we should use the | 
 |     // original Chain stored in RetOps[0], instead of the current Chain updated | 
 |     // in the above loop. If we only have sret, RetOps[0] equals to Chain. | 
 |  | 
 |     // For the case of sret and another return value, we have | 
 |     //   Chain_0 at the function entry | 
 |     //   Chain_1 = getCopyToReg(Chain_0) in the above loop | 
 |     // If we use Chain_1 in getCopyFromReg, we will have | 
 |     //   Val = getCopyFromReg(Chain_1) | 
 |     //   Chain_2 = getCopyToReg(Chain_1, Val) from below | 
 |  | 
 |     // getCopyToReg(Chain_0) will be glued together with | 
 |     // getCopyToReg(Chain_1, Val) into Unit A, getCopyFromReg(Chain_1) will be | 
 |     // in Unit B, and we will have cyclic dependency between Unit A and Unit B: | 
 |     //   Data dependency from Unit B to Unit A due to usage of Val in | 
 |     //     getCopyToReg(Chain_1, Val) | 
 |     //   Chain dependency from Unit A to Unit B | 
 |  | 
 |     // So here, we use RetOps[0] (i.e Chain_0) for getCopyFromReg. | 
 |     SDValue Val = DAG.getCopyFromReg(RetOps[0], DL, SRetReg, | 
 |                                      getPointerTy(MF.getDataLayout())); | 
 |  | 
 |     // ??? How will this work if CC does not use registers for args passing? | 
 |     // ??? What if I return multiple structs? | 
 |     unsigned RetValReg = M68k::D0; | 
 |     Chain = DAG.getCopyToReg(Chain, DL, RetValReg, Val, Glue); | 
 |     Glue = Chain.getValue(1); | 
 |  | 
 |     RetOps.push_back( | 
 |         DAG.getRegister(RetValReg, getPointerTy(DAG.getDataLayout()))); | 
 |   } | 
 |  | 
 |   RetOps[0] = Chain; // Update chain. | 
 |  | 
 |   // Add the glue if we have it. | 
 |   if (Glue.getNode()) | 
 |     RetOps.push_back(Glue); | 
 |  | 
 |   return DAG.getNode(M68kISD::RET, DL, MVT::Other, RetOps); | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | //                Fast Calling Convention (tail call) implementation | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | //  Like std call, callee cleans arguments, convention except that ECX is | 
 | //  reserved for storing the tail called function address. Only 2 registers are | 
 | //  free for argument passing (inreg). Tail call optimization is performed | 
 | //  provided: | 
 | //                * tailcallopt is enabled | 
 | //                * caller/callee are fastcc | 
 | //  On M68k_64 architecture with GOT-style position independent code only | 
 | //  local (within module) calls are supported at the moment. To keep the stack | 
 | //  aligned according to platform abi the function GetAlignedArgumentStackSize | 
 | //  ensures that argument delta is always multiples of stack alignment. (Dynamic | 
 | //  linkers need this - darwin's dyld for example) If a tail called function | 
 | //  callee has more arguments than the caller the caller needs to make sure that | 
 | //  there is room to move the RETADDR to. This is achieved by reserving an area | 
 | //  the size of the argument delta right after the original RETADDR, but before | 
 | //  the saved framepointer or the spilled registers e.g. caller(arg1, arg2) | 
 | //  calls callee(arg1, arg2,arg3,arg4) stack layout: | 
 | //    arg1 | 
 | //    arg2 | 
 | //    RETADDR | 
 | //    [ new RETADDR | 
 | //      move area ] | 
 | //    (possible EBP) | 
 | //    ESI | 
 | //    EDI | 
 | //    local1 .. | 
 |  | 
 | /// Make the stack size align e.g 16n + 12 aligned for a 16-byte align | 
 | /// requirement. | 
 | unsigned | 
 | M68kTargetLowering::GetAlignedArgumentStackSize(unsigned StackSize, | 
 |                                                 SelectionDAG &DAG) const { | 
 |   const TargetFrameLowering &TFI = *Subtarget.getFrameLowering(); | 
 |   unsigned StackAlignment = TFI.getStackAlignment(); | 
 |   uint64_t AlignMask = StackAlignment - 1; | 
 |   int64_t Offset = StackSize; | 
 |   unsigned SlotSize = Subtarget.getSlotSize(); | 
 |   if ((Offset & AlignMask) <= (StackAlignment - SlotSize)) { | 
 |     // Number smaller than 12 so just add the difference. | 
 |     Offset += ((StackAlignment - SlotSize) - (Offset & AlignMask)); | 
 |   } else { | 
 |     // Mask out lower bits, add stackalignment once plus the 12 bytes. | 
 |     Offset = | 
 |         ((~AlignMask) & Offset) + StackAlignment + (StackAlignment - SlotSize); | 
 |   } | 
 |   return Offset; | 
 | } | 
 |  | 
 | /// Check whether the call is eligible for tail call optimization. Targets | 
 | /// that want to do tail call optimization should implement this function. | 
 | bool M68kTargetLowering::IsEligibleForTailCallOptimization( | 
 |     SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg, | 
 |     bool IsCalleeStructRet, bool IsCallerStructRet, Type *RetTy, | 
 |     const SmallVectorImpl<ISD::OutputArg> &Outs, | 
 |     const SmallVectorImpl<SDValue> &OutVals, | 
 |     const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const { | 
 |   if (!mayTailCallThisCC(CalleeCC)) | 
 |     return false; | 
 |  | 
 |   // If -tailcallopt is specified, make fastcc functions tail-callable. | 
 |   MachineFunction &MF = DAG.getMachineFunction(); | 
 |   const auto &CallerF = MF.getFunction(); | 
 |  | 
 |   CallingConv::ID CallerCC = CallerF.getCallingConv(); | 
 |   bool CCMatch = CallerCC == CalleeCC; | 
 |  | 
 |   if (DAG.getTarget().Options.GuaranteedTailCallOpt) { | 
 |     if (canGuaranteeTCO(CalleeCC) && CCMatch) | 
 |       return true; | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Look for obvious safe cases to perform tail call optimization that do not | 
 |   // require ABI changes. This is what gcc calls sibcall. | 
 |  | 
 |   // Can't do sibcall if stack needs to be dynamically re-aligned. PEI needs to | 
 |   // emit a special epilogue. | 
 |   const M68kRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); | 
 |   if (RegInfo->hasStackRealignment(MF)) | 
 |     return false; | 
 |  | 
 |   // Also avoid sibcall optimization if either caller or callee uses struct | 
 |   // return semantics. | 
 |   if (IsCalleeStructRet || IsCallerStructRet) | 
 |     return false; | 
 |  | 
 |   // Do not sibcall optimize vararg calls unless all arguments are passed via | 
 |   // registers. | 
 |   LLVMContext &C = *DAG.getContext(); | 
 |   if (IsVarArg && !Outs.empty()) { | 
 |  | 
 |     SmallVector<CCValAssign, 16> ArgLocs; | 
 |     CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, C); | 
 |  | 
 |     CCInfo.AnalyzeCallOperands(Outs, CC_M68k); | 
 |     for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) | 
 |       if (!ArgLocs[i].isRegLoc()) | 
 |         return false; | 
 |   } | 
 |  | 
 |   // Check that the call results are passed in the same way. | 
 |   if (!CCState::resultsCompatible(CalleeCC, CallerCC, MF, C, Ins, RetCC_M68k, | 
 |                                   RetCC_M68k)) | 
 |     return false; | 
 |  | 
 |   // The callee has to preserve all registers the caller needs to preserve. | 
 |   const M68kRegisterInfo *TRI = Subtarget.getRegisterInfo(); | 
 |   const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC); | 
 |   if (!CCMatch) { | 
 |     const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC); | 
 |     if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) | 
 |       return false; | 
 |   } | 
 |  | 
 |   unsigned StackArgsSize = 0; | 
 |  | 
 |   // If the callee takes no arguments then go on to check the results of the | 
 |   // call. | 
 |   if (!Outs.empty()) { | 
 |     // Check if stack adjustment is needed. For now, do not do this if any | 
 |     // argument is passed on the stack. | 
 |     SmallVector<CCValAssign, 16> ArgLocs; | 
 |     CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, C); | 
 |  | 
 |     CCInfo.AnalyzeCallOperands(Outs, CC_M68k); | 
 |     StackArgsSize = CCInfo.getStackSize(); | 
 |  | 
 |     if (StackArgsSize) { | 
 |       // Check if the arguments are already laid out in the right way as | 
 |       // the caller's fixed stack objects. | 
 |       MachineFrameInfo &MFI = MF.getFrameInfo(); | 
 |       const MachineRegisterInfo *MRI = &MF.getRegInfo(); | 
 |       const M68kInstrInfo *TII = Subtarget.getInstrInfo(); | 
 |       for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | 
 |         CCValAssign &VA = ArgLocs[i]; | 
 |         SDValue Arg = OutVals[i]; | 
 |         ISD::ArgFlagsTy Flags = Outs[i].Flags; | 
 |         if (VA.getLocInfo() == CCValAssign::Indirect) | 
 |           return false; | 
 |         if (!VA.isRegLoc()) { | 
 |           if (!MatchingStackOffset(Arg, VA.getLocMemOffset(), Flags, MFI, MRI, | 
 |                                    TII, VA)) | 
 |             return false; | 
 |         } | 
 |       } | 
 |     } | 
 |  | 
 |     bool PositionIndependent = isPositionIndependent(); | 
 |     // If the tailcall address may be in a register, then make sure it's | 
 |     // possible to register allocate for it. The call address can | 
 |     // only target %A0 or %A1 since the tail call must be scheduled after | 
 |     // callee-saved registers are restored. These happen to be the same | 
 |     // registers used to pass 'inreg' arguments so watch out for those. | 
 |     if ((!isa<GlobalAddressSDNode>(Callee) && | 
 |          !isa<ExternalSymbolSDNode>(Callee)) || | 
 |         PositionIndependent) { | 
 |       unsigned NumInRegs = 0; | 
 |       // In PIC we need an extra register to formulate the address computation | 
 |       // for the callee. | 
 |       unsigned MaxInRegs = PositionIndependent ? 1 : 2; | 
 |  | 
 |       for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | 
 |         CCValAssign &VA = ArgLocs[i]; | 
 |         if (!VA.isRegLoc()) | 
 |           continue; | 
 |         Register Reg = VA.getLocReg(); | 
 |         switch (Reg) { | 
 |         default: | 
 |           break; | 
 |         case M68k::A0: | 
 |         case M68k::A1: | 
 |           if (++NumInRegs == MaxInRegs) | 
 |             return false; | 
 |           break; | 
 |         } | 
 |       } | 
 |     } | 
 |  | 
 |     const MachineRegisterInfo &MRI = MF.getRegInfo(); | 
 |     if (!parametersInCSRMatch(MRI, CallerPreserved, ArgLocs, OutVals)) | 
 |       return false; | 
 |   } | 
 |  | 
 |   bool CalleeWillPop = M68k::isCalleePop( | 
 |       CalleeCC, IsVarArg, MF.getTarget().Options.GuaranteedTailCallOpt); | 
 |  | 
 |   if (unsigned BytesToPop = | 
 |           MF.getInfo<M68kMachineFunctionInfo>()->getBytesToPopOnReturn()) { | 
 |     // If we have bytes to pop, the callee must pop them. | 
 |     bool CalleePopMatches = CalleeWillPop && BytesToPop == StackArgsSize; | 
 |     if (!CalleePopMatches) | 
 |       return false; | 
 |   } else if (CalleeWillPop && StackArgsSize > 0) { | 
 |     // If we don't have bytes to pop, make sure the callee doesn't pop any. | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // Custom Lower | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | SDValue M68kTargetLowering::LowerOperation(SDValue Op, | 
 |                                            SelectionDAG &DAG) const { | 
 |   switch (Op.getOpcode()) { | 
 |   default: | 
 |     llvm_unreachable("Should not custom lower this!"); | 
 |   case ISD::SADDO: | 
 |   case ISD::UADDO: | 
 |   case ISD::SSUBO: | 
 |   case ISD::USUBO: | 
 |   case ISD::SMULO: | 
 |   case ISD::UMULO: | 
 |     return LowerXALUO(Op, DAG); | 
 |   case ISD::SETCC: | 
 |     return LowerSETCC(Op, DAG); | 
 |   case ISD::SETCCCARRY: | 
 |     return LowerSETCCCARRY(Op, DAG); | 
 |   case ISD::SELECT: | 
 |     return LowerSELECT(Op, DAG); | 
 |   case ISD::BRCOND: | 
 |     return LowerBRCOND(Op, DAG); | 
 |   case ISD::ADDC: | 
 |   case ISD::ADDE: | 
 |   case ISD::SUBC: | 
 |   case ISD::SUBE: | 
 |     return LowerADDC_ADDE_SUBC_SUBE(Op, DAG); | 
 |   case ISD::ConstantPool: | 
 |     return LowerConstantPool(Op, DAG); | 
 |   case ISD::GlobalAddress: | 
 |     return LowerGlobalAddress(Op, DAG); | 
 |   case ISD::ExternalSymbol: | 
 |     return LowerExternalSymbol(Op, DAG); | 
 |   case ISD::BlockAddress: | 
 |     return LowerBlockAddress(Op, DAG); | 
 |   case ISD::JumpTable: | 
 |     return LowerJumpTable(Op, DAG); | 
 |   case ISD::VASTART: | 
 |     return LowerVASTART(Op, DAG); | 
 |   case ISD::DYNAMIC_STACKALLOC: | 
 |     return LowerDYNAMIC_STACKALLOC(Op, DAG); | 
 |   case ISD::SHL_PARTS: | 
 |     return LowerShiftLeftParts(Op, DAG); | 
 |   case ISD::SRA_PARTS: | 
 |     return LowerShiftRightParts(Op, DAG, true); | 
 |   case ISD::SRL_PARTS: | 
 |     return LowerShiftRightParts(Op, DAG, false); | 
 |   case ISD::ATOMIC_FENCE: | 
 |     return LowerATOMICFENCE(Op, DAG); | 
 |   case ISD::GlobalTLSAddress: | 
 |     return LowerGlobalTLSAddress(Op, DAG); | 
 |   } | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerExternalSymbolCall(SelectionDAG &DAG, | 
 |                                                     SDLoc Loc, | 
 |                                                     llvm::StringRef SymbolName, | 
 |                                                     ArgListTy &&ArgList) const { | 
 |   PointerType *PtrTy = PointerType::get(*DAG.getContext(), 0); | 
 |   CallLoweringInfo CLI(DAG); | 
 |   CLI.setDebugLoc(Loc) | 
 |       .setChain(DAG.getEntryNode()) | 
 |       .setLibCallee(CallingConv::C, PtrTy, | 
 |                     DAG.getExternalSymbol(SymbolName.data(), | 
 |                                           getPointerMemTy(DAG.getDataLayout())), | 
 |                     std::move(ArgList)); | 
 |   return LowerCallTo(CLI).first; | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::getTLSGetAddr(GlobalAddressSDNode *GA, | 
 |                                           SelectionDAG &DAG, | 
 |                                           unsigned TargetFlags) const { | 
 |   SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); | 
 |   SDValue TGA = DAG.getTargetGlobalAddress( | 
 |       GA->getGlobal(), GA, GA->getValueType(0), GA->getOffset(), TargetFlags); | 
 |   SDValue Arg = DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, GOT, TGA); | 
 |  | 
 |   PointerType *PtrTy = PointerType::get(*DAG.getContext(), 0); | 
 |  | 
 |   ArgListTy Args; | 
 |   ArgListEntry Entry; | 
 |   Entry.Node = Arg; | 
 |   Entry.Ty = PtrTy; | 
 |   Args.push_back(Entry); | 
 |   return LowerExternalSymbolCall(DAG, SDLoc(GA), "__tls_get_addr", | 
 |                                  std::move(Args)); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::getM68kReadTp(SDLoc Loc, SelectionDAG &DAG) const { | 
 |   return LowerExternalSymbolCall(DAG, Loc, "__m68k_read_tp", ArgListTy()); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerTLSGeneralDynamic(GlobalAddressSDNode *GA, | 
 |                                                    SelectionDAG &DAG) const { | 
 |   return getTLSGetAddr(GA, DAG, M68kII::MO_TLSGD); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerTLSLocalDynamic(GlobalAddressSDNode *GA, | 
 |                                                  SelectionDAG &DAG) const { | 
 |   SDValue Addr = getTLSGetAddr(GA, DAG, M68kII::MO_TLSLDM); | 
 |   SDValue TGA = | 
 |       DAG.getTargetGlobalAddress(GA->getGlobal(), GA, GA->getValueType(0), | 
 |                                  GA->getOffset(), M68kII::MO_TLSLD); | 
 |   return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, Addr); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerTLSInitialExec(GlobalAddressSDNode *GA, | 
 |                                                 SelectionDAG &DAG) const { | 
 |   SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); | 
 |   SDValue Tp = getM68kReadTp(SDLoc(GA), DAG); | 
 |   SDValue TGA = | 
 |       DAG.getTargetGlobalAddress(GA->getGlobal(), GA, GA->getValueType(0), | 
 |                                  GA->getOffset(), M68kII::MO_TLSIE); | 
 |   SDValue Addr = DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, GOT); | 
 |   SDValue Offset = | 
 |       DAG.getLoad(MVT::i32, SDLoc(GA), DAG.getEntryNode(), Addr, | 
 |                   MachinePointerInfo::getGOT(DAG.getMachineFunction())); | 
 |  | 
 |   return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, Offset, Tp); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerTLSLocalExec(GlobalAddressSDNode *GA, | 
 |                                               SelectionDAG &DAG) const { | 
 |   SDValue Tp = getM68kReadTp(SDLoc(GA), DAG); | 
 |   SDValue TGA = | 
 |       DAG.getTargetGlobalAddress(GA->getGlobal(), GA, GA->getValueType(0), | 
 |                                  GA->getOffset(), M68kII::MO_TLSLE); | 
 |   return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, Tp); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerGlobalTLSAddress(SDValue Op, | 
 |                                                   SelectionDAG &DAG) const { | 
 |   assert(Subtarget.isTargetELF()); | 
 |  | 
 |   auto *GA = cast<GlobalAddressSDNode>(Op); | 
 |   TLSModel::Model AccessModel = DAG.getTarget().getTLSModel(GA->getGlobal()); | 
 |  | 
 |   switch (AccessModel) { | 
 |   case TLSModel::GeneralDynamic: | 
 |     return LowerTLSGeneralDynamic(GA, DAG); | 
 |   case TLSModel::LocalDynamic: | 
 |     return LowerTLSLocalDynamic(GA, DAG); | 
 |   case TLSModel::InitialExec: | 
 |     return LowerTLSInitialExec(GA, DAG); | 
 |   case TLSModel::LocalExec: | 
 |     return LowerTLSLocalExec(GA, DAG); | 
 |   } | 
 |  | 
 |   llvm_unreachable("Unexpected TLS access model type"); | 
 | } | 
 |  | 
 | bool M68kTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT, | 
 |                                                 SDValue C) const { | 
 |   // Shifts and add instructions in M68000 and M68010 support | 
 |   // up to 32 bits, but mul only has 16-bit variant. So it's almost | 
 |   // certainly beneficial to lower 8/16/32-bit mul to their | 
 |   // add / shifts counterparts. But for 64-bits mul, it might be | 
 |   // safer to just leave it to compiler runtime implementations. | 
 |   return VT.bitsLE(MVT::i32) || Subtarget.atLeastM68020(); | 
 | } | 
 |  | 
 | static bool isOverflowArithmetic(unsigned Opcode) { | 
 |   switch (Opcode) { | 
 |   case ISD::UADDO: | 
 |   case ISD::SADDO: | 
 |   case ISD::USUBO: | 
 |   case ISD::SSUBO: | 
 |   case ISD::UMULO: | 
 |   case ISD::SMULO: | 
 |     return true; | 
 |   default: | 
 |     return false; | 
 |   } | 
 | } | 
 |  | 
 | static void lowerOverflowArithmetic(SDValue Op, SelectionDAG &DAG, | 
 |                                     SDValue &Result, SDValue &CCR, | 
 |                                     unsigned &CC) { | 
 |   SDNode *N = Op.getNode(); | 
 |   EVT VT = N->getValueType(0); | 
 |   SDValue LHS = N->getOperand(0); | 
 |   SDValue RHS = N->getOperand(1); | 
 |   SDLoc DL(Op); | 
 |  | 
 |   unsigned TruncOp = 0; | 
 |   auto PromoteMULO = [&](unsigned ExtOp) { | 
 |     // We don't have 8-bit multiplications, so promote i8 version of U/SMULO | 
 |     // to i16. | 
 |     // Ideally this should be done by legalizer but sadly there is no promotion | 
 |     // rule for U/SMULO at this moment. | 
 |     if (VT == MVT::i8) { | 
 |       LHS = DAG.getNode(ExtOp, DL, MVT::i16, LHS); | 
 |       RHS = DAG.getNode(ExtOp, DL, MVT::i16, RHS); | 
 |       VT = MVT::i16; | 
 |       TruncOp = ISD::TRUNCATE; | 
 |     } | 
 |   }; | 
 |  | 
 |   bool NoOverflow = false; | 
 |   unsigned BaseOp = 0; | 
 |   switch (Op.getOpcode()) { | 
 |   default: | 
 |     llvm_unreachable("Unknown ovf instruction!"); | 
 |   case ISD::SADDO: | 
 |     BaseOp = M68kISD::ADD; | 
 |     CC = M68k::COND_VS; | 
 |     break; | 
 |   case ISD::UADDO: | 
 |     BaseOp = M68kISD::ADD; | 
 |     CC = M68k::COND_CS; | 
 |     break; | 
 |   case ISD::SSUBO: | 
 |     BaseOp = M68kISD::SUB; | 
 |     CC = M68k::COND_VS; | 
 |     break; | 
 |   case ISD::USUBO: | 
 |     BaseOp = M68kISD::SUB; | 
 |     CC = M68k::COND_CS; | 
 |     break; | 
 |   case ISD::UMULO: | 
 |     PromoteMULO(ISD::ZERO_EXTEND); | 
 |     NoOverflow = VT != MVT::i32; | 
 |     BaseOp = NoOverflow ? (unsigned)ISD::MUL : (unsigned)M68kISD::UMUL; | 
 |     CC = M68k::COND_VS; | 
 |     break; | 
 |   case ISD::SMULO: | 
 |     PromoteMULO(ISD::SIGN_EXTEND); | 
 |     NoOverflow = VT != MVT::i32; | 
 |     BaseOp = NoOverflow ? (unsigned)ISD::MUL : (unsigned)M68kISD::SMUL; | 
 |     CC = M68k::COND_VS; | 
 |     break; | 
 |   } | 
 |  | 
 |   SDVTList VTs; | 
 |   if (NoOverflow) | 
 |     VTs = DAG.getVTList(VT); | 
 |   else | 
 |     // Also sets CCR. | 
 |     VTs = DAG.getVTList(VT, MVT::i8); | 
 |  | 
 |   SDValue Arith = DAG.getNode(BaseOp, DL, VTs, LHS, RHS); | 
 |   Result = Arith.getValue(0); | 
 |   if (TruncOp) | 
 |     // Right now the only place to truncate is from i16 to i8. | 
 |     Result = DAG.getNode(TruncOp, DL, MVT::i8, Arith); | 
 |  | 
 |   if (NoOverflow) | 
 |     CCR = DAG.getConstant(0, DL, N->getValueType(1)); | 
 |   else | 
 |     CCR = Arith.getValue(1); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const { | 
 |   SDNode *N = Op.getNode(); | 
 |   SDLoc DL(Op); | 
 |  | 
 |   // Lower the "add/sub/mul with overflow" instruction into a regular ins plus | 
 |   // a "setcc" instruction that checks the overflow flag. | 
 |   SDValue Result, CCR; | 
 |   unsigned CC; | 
 |   lowerOverflowArithmetic(Op, DAG, Result, CCR, CC); | 
 |  | 
 |   SDValue Overflow; | 
 |   if (isa<ConstantSDNode>(CCR)) { | 
 |     // It's likely a result of operations that will not overflow | 
 |     // hence no setcc is needed. | 
 |     Overflow = CCR; | 
 |   } else { | 
 |     // Generate a M68kISD::SETCC. | 
 |     Overflow = DAG.getNode(M68kISD::SETCC, DL, N->getValueType(1), | 
 |                            DAG.getConstant(CC, DL, MVT::i8), CCR); | 
 |   } | 
 |  | 
 |   return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Result, Overflow); | 
 | } | 
 |  | 
 | /// Create a BTST (Bit Test) node - Test bit \p BitNo in \p Src and set | 
 | /// condition according to equal/not-equal condition code \p CC. | 
 | static SDValue getBitTestCondition(SDValue Src, SDValue BitNo, ISD::CondCode CC, | 
 |                                    const SDLoc &DL, SelectionDAG &DAG) { | 
 |   // If Src is i8, promote it to i32 with any_extend.  There is no i8 BTST | 
 |   // instruction.  Since the shift amount is in-range-or-undefined, we know | 
 |   // that doing a bittest on the i32 value is ok. | 
 |   if (Src.getValueType() == MVT::i8 || Src.getValueType() == MVT::i16) | 
 |     Src = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Src); | 
 |  | 
 |   // If the operand types disagree, extend the shift amount to match.  Since | 
 |   // BTST ignores high bits (like shifts) we can use anyextend. | 
 |   if (Src.getValueType() != BitNo.getValueType()) | 
 |     BitNo = DAG.getNode(ISD::ANY_EXTEND, DL, Src.getValueType(), BitNo); | 
 |  | 
 |   SDValue BTST = DAG.getNode(M68kISD::BTST, DL, MVT::i32, Src, BitNo); | 
 |  | 
 |   // NOTE BTST sets CCR.Z flag | 
 |   M68k::CondCode Cond = CC == ISD::SETEQ ? M68k::COND_NE : M68k::COND_EQ; | 
 |   return DAG.getNode(M68kISD::SETCC, DL, MVT::i8, | 
 |                      DAG.getConstant(Cond, DL, MVT::i8), BTST); | 
 | } | 
 |  | 
 | /// Result of 'and' is compared against zero. Change to a BTST node if possible. | 
 | static SDValue LowerAndToBTST(SDValue And, ISD::CondCode CC, const SDLoc &DL, | 
 |                               SelectionDAG &DAG) { | 
 |   SDValue Op0 = And.getOperand(0); | 
 |   SDValue Op1 = And.getOperand(1); | 
 |   if (Op0.getOpcode() == ISD::TRUNCATE) | 
 |     Op0 = Op0.getOperand(0); | 
 |   if (Op1.getOpcode() == ISD::TRUNCATE) | 
 |     Op1 = Op1.getOperand(0); | 
 |  | 
 |   SDValue LHS, RHS; | 
 |   if (Op1.getOpcode() == ISD::SHL) | 
 |     std::swap(Op0, Op1); | 
 |   if (Op0.getOpcode() == ISD::SHL) { | 
 |     if (isOneConstant(Op0.getOperand(0))) { | 
 |       // If we looked past a truncate, check that it's only truncating away | 
 |       // known zeros. | 
 |       unsigned BitWidth = Op0.getValueSizeInBits(); | 
 |       unsigned AndBitWidth = And.getValueSizeInBits(); | 
 |       if (BitWidth > AndBitWidth) { | 
 |         auto Known = DAG.computeKnownBits(Op0); | 
 |         if (Known.countMinLeadingZeros() < BitWidth - AndBitWidth) | 
 |           return SDValue(); | 
 |       } | 
 |       LHS = Op1; | 
 |       RHS = Op0.getOperand(1); | 
 |     } | 
 |   } else if (auto *AndRHS = dyn_cast<ConstantSDNode>(Op1)) { | 
 |     uint64_t AndRHSVal = AndRHS->getZExtValue(); | 
 |     SDValue AndLHS = Op0; | 
 |  | 
 |     if (AndRHSVal == 1 && AndLHS.getOpcode() == ISD::SRL) { | 
 |       LHS = AndLHS.getOperand(0); | 
 |       RHS = AndLHS.getOperand(1); | 
 |     } | 
 |  | 
 |     // Use BTST if the immediate can't be encoded in a TEST instruction. | 
 |     if (!isUInt<32>(AndRHSVal) && isPowerOf2_64(AndRHSVal)) { | 
 |       LHS = AndLHS; | 
 |       RHS = DAG.getConstant(Log2_64_Ceil(AndRHSVal), DL, LHS.getValueType()); | 
 |     } | 
 |   } | 
 |  | 
 |   if (LHS.getNode()) | 
 |     return getBitTestCondition(LHS, RHS, CC, DL, DAG); | 
 |  | 
 |   return SDValue(); | 
 | } | 
 |  | 
 | static M68k::CondCode TranslateIntegerM68kCC(ISD::CondCode SetCCOpcode) { | 
 |   switch (SetCCOpcode) { | 
 |   default: | 
 |     llvm_unreachable("Invalid integer condition!"); | 
 |   case ISD::SETEQ: | 
 |     return M68k::COND_EQ; | 
 |   case ISD::SETGT: | 
 |     return M68k::COND_GT; | 
 |   case ISD::SETGE: | 
 |     return M68k::COND_GE; | 
 |   case ISD::SETLT: | 
 |     return M68k::COND_LT; | 
 |   case ISD::SETLE: | 
 |     return M68k::COND_LE; | 
 |   case ISD::SETNE: | 
 |     return M68k::COND_NE; | 
 |   case ISD::SETULT: | 
 |     return M68k::COND_CS; | 
 |   case ISD::SETUGE: | 
 |     return M68k::COND_CC; | 
 |   case ISD::SETUGT: | 
 |     return M68k::COND_HI; | 
 |   case ISD::SETULE: | 
 |     return M68k::COND_LS; | 
 |   } | 
 | } | 
 |  | 
 | /// Do a one-to-one translation of a ISD::CondCode to the M68k-specific | 
 | /// condition code, returning the condition code and the LHS/RHS of the | 
 | /// comparison to make. | 
 | static unsigned TranslateM68kCC(ISD::CondCode SetCCOpcode, const SDLoc &DL, | 
 |                                 bool IsFP, SDValue &LHS, SDValue &RHS, | 
 |                                 SelectionDAG &DAG) { | 
 |   if (!IsFP) { | 
 |     if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) { | 
 |       if (SetCCOpcode == ISD::SETGT && RHSC->isAllOnes()) { | 
 |         // X > -1   -> X == 0, jump !sign. | 
 |         RHS = DAG.getConstant(0, DL, RHS.getValueType()); | 
 |         return M68k::COND_PL; | 
 |       } | 
 |       if (SetCCOpcode == ISD::SETLT && RHSC->isZero()) { | 
 |         // X < 0   -> X == 0, jump on sign. | 
 |         return M68k::COND_MI; | 
 |       } | 
 |       if (SetCCOpcode == ISD::SETLT && RHSC->getZExtValue() == 1) { | 
 |         // X < 1   -> X <= 0 | 
 |         RHS = DAG.getConstant(0, DL, RHS.getValueType()); | 
 |         return M68k::COND_LE; | 
 |       } | 
 |     } | 
 |  | 
 |     return TranslateIntegerM68kCC(SetCCOpcode); | 
 |   } | 
 |  | 
 |   // First determine if it is required or is profitable to flip the operands. | 
 |  | 
 |   // If LHS is a foldable load, but RHS is not, flip the condition. | 
 |   if (ISD::isNON_EXTLoad(LHS.getNode()) && !ISD::isNON_EXTLoad(RHS.getNode())) { | 
 |     SetCCOpcode = getSetCCSwappedOperands(SetCCOpcode); | 
 |     std::swap(LHS, RHS); | 
 |   } | 
 |  | 
 |   switch (SetCCOpcode) { | 
 |   default: | 
 |     break; | 
 |   case ISD::SETOLT: | 
 |   case ISD::SETOLE: | 
 |   case ISD::SETUGT: | 
 |   case ISD::SETUGE: | 
 |     std::swap(LHS, RHS); | 
 |     break; | 
 |   } | 
 |  | 
 |   // On a floating point condition, the flags are set as follows: | 
 |   // ZF  PF  CF   op | 
 |   //  0 | 0 | 0 | X > Y | 
 |   //  0 | 0 | 1 | X < Y | 
 |   //  1 | 0 | 0 | X == Y | 
 |   //  1 | 1 | 1 | unordered | 
 |   switch (SetCCOpcode) { | 
 |   default: | 
 |     llvm_unreachable("Condcode should be pre-legalized away"); | 
 |   case ISD::SETUEQ: | 
 |   case ISD::SETEQ: | 
 |     return M68k::COND_EQ; | 
 |   case ISD::SETOLT: // flipped | 
 |   case ISD::SETOGT: | 
 |   case ISD::SETGT: | 
 |     return M68k::COND_HI; | 
 |   case ISD::SETOLE: // flipped | 
 |   case ISD::SETOGE: | 
 |   case ISD::SETGE: | 
 |     return M68k::COND_CC; | 
 |   case ISD::SETUGT: // flipped | 
 |   case ISD::SETULT: | 
 |   case ISD::SETLT: | 
 |     return M68k::COND_CS; | 
 |   case ISD::SETUGE: // flipped | 
 |   case ISD::SETULE: | 
 |   case ISD::SETLE: | 
 |     return M68k::COND_LS; | 
 |   case ISD::SETONE: | 
 |   case ISD::SETNE: | 
 |     return M68k::COND_NE; | 
 |   case ISD::SETOEQ: | 
 |   case ISD::SETUNE: | 
 |     return M68k::COND_INVALID; | 
 |   } | 
 | } | 
 |  | 
 | // Convert (truncate (srl X, N) to i1) to (bt X, N) | 
 | static SDValue LowerTruncateToBTST(SDValue Op, ISD::CondCode CC, | 
 |                                    const SDLoc &DL, SelectionDAG &DAG) { | 
 |  | 
 |   assert(Op.getOpcode() == ISD::TRUNCATE && Op.getValueType() == MVT::i1 && | 
 |          "Expected TRUNCATE to i1 node"); | 
 |  | 
 |   if (Op.getOperand(0).getOpcode() != ISD::SRL) | 
 |     return SDValue(); | 
 |  | 
 |   SDValue ShiftRight = Op.getOperand(0); | 
 |   return getBitTestCondition(ShiftRight.getOperand(0), ShiftRight.getOperand(1), | 
 |                              CC, DL, DAG); | 
 | } | 
 |  | 
 | /// \brief return true if \c Op has a use that doesn't just read flags. | 
 | static bool hasNonFlagsUse(SDValue Op) { | 
 |   for (SDNode::use_iterator UI = Op->use_begin(), UE = Op->use_end(); UI != UE; | 
 |        ++UI) { | 
 |     SDNode *User = UI->getUser(); | 
 |     unsigned UOpNo = UI->getOperandNo(); | 
 |     if (User->getOpcode() == ISD::TRUNCATE && User->hasOneUse()) { | 
 |       // Look past truncate. | 
 |       UOpNo = User->use_begin()->getOperandNo(); | 
 |       User = User->use_begin()->getUser(); | 
 |     } | 
 |  | 
 |     if (User->getOpcode() != ISD::BRCOND && User->getOpcode() != ISD::SETCC && | 
 |         !(User->getOpcode() == ISD::SELECT && UOpNo == 0)) | 
 |       return true; | 
 |   } | 
 |   return false; | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::EmitTest(SDValue Op, unsigned M68kCC, | 
 |                                      const SDLoc &DL, SelectionDAG &DAG) const { | 
 |  | 
 |   // CF and OF aren't always set the way we want. Determine which | 
 |   // of these we need. | 
 |   bool NeedCF = false; | 
 |   bool NeedOF = false; | 
 |   switch (M68kCC) { | 
 |   default: | 
 |     break; | 
 |   case M68k::COND_HI: | 
 |   case M68k::COND_CC: | 
 |   case M68k::COND_CS: | 
 |   case M68k::COND_LS: | 
 |     NeedCF = true; | 
 |     break; | 
 |   case M68k::COND_GT: | 
 |   case M68k::COND_GE: | 
 |   case M68k::COND_LT: | 
 |   case M68k::COND_LE: | 
 |   case M68k::COND_VS: | 
 |   case M68k::COND_VC: { | 
 |     // Check if we really need to set the | 
 |     // Overflow flag. If NoSignedWrap is present | 
 |     // that is not actually needed. | 
 |     switch (Op->getOpcode()) { | 
 |     case ISD::ADD: | 
 |     case ISD::SUB: | 
 |     case ISD::MUL: | 
 |     case ISD::SHL: { | 
 |       if (Op.getNode()->getFlags().hasNoSignedWrap()) | 
 |         break; | 
 |       [[fallthrough]]; | 
 |     } | 
 |     default: | 
 |       NeedOF = true; | 
 |       break; | 
 |     } | 
 |     break; | 
 |   } | 
 |   } | 
 |   // See if we can use the CCR value from the operand instead of | 
 |   // doing a separate TEST. TEST always sets OF and CF to 0, so unless | 
 |   // we prove that the arithmetic won't overflow, we can't use OF or CF. | 
 |   if (Op.getResNo() != 0 || NeedOF || NeedCF) { | 
 |     // Emit a CMP with 0, which is the TEST pattern. | 
 |     return DAG.getNode(M68kISD::CMP, DL, MVT::i8, | 
 |                        DAG.getConstant(0, DL, Op.getValueType()), Op); | 
 |   } | 
 |   unsigned Opcode = 0; | 
 |   unsigned NumOperands = 0; | 
 |  | 
 |   // Truncate operations may prevent the merge of the SETCC instruction | 
 |   // and the arithmetic instruction before it. Attempt to truncate the operands | 
 |   // of the arithmetic instruction and use a reduced bit-width instruction. | 
 |   bool NeedTruncation = false; | 
 |   SDValue ArithOp = Op; | 
 |   if (Op->getOpcode() == ISD::TRUNCATE && Op->hasOneUse()) { | 
 |     SDValue Arith = Op->getOperand(0); | 
 |     // Both the trunc and the arithmetic op need to have one user each. | 
 |     if (Arith->hasOneUse()) | 
 |       switch (Arith.getOpcode()) { | 
 |       default: | 
 |         break; | 
 |       case ISD::ADD: | 
 |       case ISD::SUB: | 
 |       case ISD::AND: | 
 |       case ISD::OR: | 
 |       case ISD::XOR: { | 
 |         NeedTruncation = true; | 
 |         ArithOp = Arith; | 
 |       } | 
 |       } | 
 |   } | 
 |  | 
 |   // NOTICE: In the code below we use ArithOp to hold the arithmetic operation | 
 |   // which may be the result of a CAST.  We use the variable 'Op', which is the | 
 |   // non-casted variable when we check for possible users. | 
 |   switch (ArithOp.getOpcode()) { | 
 |   case ISD::ADD: | 
 |     Opcode = M68kISD::ADD; | 
 |     NumOperands = 2; | 
 |     break; | 
 |   case ISD::SHL: | 
 |   case ISD::SRL: | 
 |     // If we have a constant logical shift that's only used in a comparison | 
 |     // against zero turn it into an equivalent AND. This allows turning it into | 
 |     // a TEST instruction later. | 
 |     if ((M68kCC == M68k::COND_EQ || M68kCC == M68k::COND_NE) && | 
 |         Op->hasOneUse() && isa<ConstantSDNode>(Op->getOperand(1)) && | 
 |         !hasNonFlagsUse(Op)) { | 
 |       EVT VT = Op.getValueType(); | 
 |       unsigned BitWidth = VT.getSizeInBits(); | 
 |       unsigned ShAmt = Op->getConstantOperandVal(1); | 
 |       if (ShAmt >= BitWidth) // Avoid undefined shifts. | 
 |         break; | 
 |       APInt Mask = ArithOp.getOpcode() == ISD::SRL | 
 |                        ? APInt::getHighBitsSet(BitWidth, BitWidth - ShAmt) | 
 |                        : APInt::getLowBitsSet(BitWidth, BitWidth - ShAmt); | 
 |       if (!Mask.isSignedIntN(32)) // Avoid large immediates. | 
 |         break; | 
 |       Op = DAG.getNode(ISD::AND, DL, VT, Op->getOperand(0), | 
 |                        DAG.getConstant(Mask, DL, VT)); | 
 |     } | 
 |     break; | 
 |  | 
 |   case ISD::AND: | 
 |     // If the primary 'and' result isn't used, don't bother using | 
 |     // M68kISD::AND, because a TEST instruction will be better. | 
 |     if (!hasNonFlagsUse(Op)) { | 
 |       SDValue Op0 = ArithOp->getOperand(0); | 
 |       SDValue Op1 = ArithOp->getOperand(1); | 
 |       EVT VT = ArithOp.getValueType(); | 
 |       bool IsAndn = isBitwiseNot(Op0) || isBitwiseNot(Op1); | 
 |       bool IsLegalAndnType = VT == MVT::i32 || VT == MVT::i64; | 
 |  | 
 |       // But if we can combine this into an ANDN operation, then create an AND | 
 |       // now and allow it to be pattern matched into an ANDN. | 
 |       if (/*!Subtarget.hasBMI() ||*/ !IsAndn || !IsLegalAndnType) | 
 |         break; | 
 |     } | 
 |     [[fallthrough]]; | 
 |   case ISD::SUB: | 
 |   case ISD::OR: | 
 |   case ISD::XOR: | 
 |     // Due to the ISEL shortcoming noted above, be conservative if this op is | 
 |     // likely to be selected as part of a load-modify-store instruction. | 
 |     for (const auto *U : Op.getNode()->users()) | 
 |       if (U->getOpcode() == ISD::STORE) | 
 |         goto default_case; | 
 |  | 
 |     // Otherwise use a regular CCR-setting instruction. | 
 |     switch (ArithOp.getOpcode()) { | 
 |     default: | 
 |       llvm_unreachable("unexpected operator!"); | 
 |     case ISD::SUB: | 
 |       Opcode = M68kISD::SUB; | 
 |       break; | 
 |     case ISD::XOR: | 
 |       Opcode = M68kISD::XOR; | 
 |       break; | 
 |     case ISD::AND: | 
 |       Opcode = M68kISD::AND; | 
 |       break; | 
 |     case ISD::OR: | 
 |       Opcode = M68kISD::OR; | 
 |       break; | 
 |     } | 
 |  | 
 |     NumOperands = 2; | 
 |     break; | 
 |   case M68kISD::ADD: | 
 |   case M68kISD::SUB: | 
 |   case M68kISD::OR: | 
 |   case M68kISD::XOR: | 
 |   case M68kISD::AND: | 
 |     return SDValue(Op.getNode(), 1); | 
 |   default: | 
 |   default_case: | 
 |     break; | 
 |   } | 
 |  | 
 |   // If we found that truncation is beneficial, perform the truncation and | 
 |   // update 'Op'. | 
 |   if (NeedTruncation) { | 
 |     EVT VT = Op.getValueType(); | 
 |     SDValue WideVal = Op->getOperand(0); | 
 |     EVT WideVT = WideVal.getValueType(); | 
 |     unsigned ConvertedOp = 0; | 
 |     // Use a target machine opcode to prevent further DAGCombine | 
 |     // optimizations that may separate the arithmetic operations | 
 |     // from the setcc node. | 
 |     switch (WideVal.getOpcode()) { | 
 |     default: | 
 |       break; | 
 |     case ISD::ADD: | 
 |       ConvertedOp = M68kISD::ADD; | 
 |       break; | 
 |     case ISD::SUB: | 
 |       ConvertedOp = M68kISD::SUB; | 
 |       break; | 
 |     case ISD::AND: | 
 |       ConvertedOp = M68kISD::AND; | 
 |       break; | 
 |     case ISD::OR: | 
 |       ConvertedOp = M68kISD::OR; | 
 |       break; | 
 |     case ISD::XOR: | 
 |       ConvertedOp = M68kISD::XOR; | 
 |       break; | 
 |     } | 
 |  | 
 |     if (ConvertedOp) { | 
 |       const TargetLowering &TLI = DAG.getTargetLoweringInfo(); | 
 |       if (TLI.isOperationLegal(WideVal.getOpcode(), WideVT)) { | 
 |         SDValue V0 = DAG.getNode(ISD::TRUNCATE, DL, VT, WideVal.getOperand(0)); | 
 |         SDValue V1 = DAG.getNode(ISD::TRUNCATE, DL, VT, WideVal.getOperand(1)); | 
 |         Op = DAG.getNode(ConvertedOp, DL, VT, V0, V1); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   if (Opcode == 0) { | 
 |     // Emit a CMP with 0, which is the TEST pattern. | 
 |     return DAG.getNode(M68kISD::CMP, DL, MVT::i8, | 
 |                        DAG.getConstant(0, DL, Op.getValueType()), Op); | 
 |   } | 
 |   SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::i8); | 
 |   SmallVector<SDValue, 4> Ops(Op->op_begin(), Op->op_begin() + NumOperands); | 
 |  | 
 |   SDValue New = DAG.getNode(Opcode, DL, VTs, Ops); | 
 |   DAG.ReplaceAllUsesWith(Op, New); | 
 |   return SDValue(New.getNode(), 1); | 
 | } | 
 |  | 
 | /// \brief Return true if the condition is an unsigned comparison operation. | 
 | static bool isM68kCCUnsigned(unsigned M68kCC) { | 
 |   switch (M68kCC) { | 
 |   default: | 
 |     llvm_unreachable("Invalid integer condition!"); | 
 |   case M68k::COND_EQ: | 
 |   case M68k::COND_NE: | 
 |   case M68k::COND_CS: | 
 |   case M68k::COND_HI: | 
 |   case M68k::COND_LS: | 
 |   case M68k::COND_CC: | 
 |     return true; | 
 |   case M68k::COND_GT: | 
 |   case M68k::COND_GE: | 
 |   case M68k::COND_LT: | 
 |   case M68k::COND_LE: | 
 |     return false; | 
 |   } | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::EmitCmp(SDValue Op0, SDValue Op1, unsigned M68kCC, | 
 |                                     const SDLoc &DL, SelectionDAG &DAG) const { | 
 |   if (isNullConstant(Op1)) | 
 |     return EmitTest(Op0, M68kCC, DL, DAG); | 
 |  | 
 |   assert(!(isa<ConstantSDNode>(Op1) && Op0.getValueType() == MVT::i1) && | 
 |          "Unexpected comparison operation for MVT::i1 operands"); | 
 |  | 
 |   if ((Op0.getValueType() == MVT::i8 || Op0.getValueType() == MVT::i16 || | 
 |        Op0.getValueType() == MVT::i32 || Op0.getValueType() == MVT::i64)) { | 
 |     // Only promote the compare up to I32 if it is a 16 bit operation | 
 |     // with an immediate.  16 bit immediates are to be avoided. | 
 |     if ((Op0.getValueType() == MVT::i16 && | 
 |          (isa<ConstantSDNode>(Op0) || isa<ConstantSDNode>(Op1))) && | 
 |         !DAG.getMachineFunction().getFunction().hasMinSize()) { | 
 |       unsigned ExtendOp = | 
 |           isM68kCCUnsigned(M68kCC) ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND; | 
 |       Op0 = DAG.getNode(ExtendOp, DL, MVT::i32, Op0); | 
 |       Op1 = DAG.getNode(ExtendOp, DL, MVT::i32, Op1); | 
 |     } | 
 |     // Use SUB instead of CMP to enable CSE between SUB and CMP. | 
 |     SDVTList VTs = DAG.getVTList(Op0.getValueType(), MVT::i8); | 
 |     SDValue Sub = DAG.getNode(M68kISD::SUB, DL, VTs, Op0, Op1); | 
 |     return SDValue(Sub.getNode(), 1); | 
 |   } | 
 |   return DAG.getNode(M68kISD::CMP, DL, MVT::i8, Op0, Op1); | 
 | } | 
 |  | 
 | /// Result of 'and' or 'trunc to i1' is compared against zero. | 
 | /// Change to a BTST node if possible. | 
 | SDValue M68kTargetLowering::LowerToBTST(SDValue Op, ISD::CondCode CC, | 
 |                                         const SDLoc &DL, | 
 |                                         SelectionDAG &DAG) const { | 
 |   if (Op.getOpcode() == ISD::AND) | 
 |     return LowerAndToBTST(Op, CC, DL, DAG); | 
 |   if (Op.getOpcode() == ISD::TRUNCATE && Op.getValueType() == MVT::i1) | 
 |     return LowerTruncateToBTST(Op, CC, DL, DAG); | 
 |   return SDValue(); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { | 
 |   MVT VT = Op.getSimpleValueType(); | 
 |   assert(VT == MVT::i8 && "SetCC type must be 8-bit integer"); | 
 |  | 
 |   SDValue Op0 = Op.getOperand(0); | 
 |   SDValue Op1 = Op.getOperand(1); | 
 |   SDLoc DL(Op); | 
 |   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); | 
 |  | 
 |   // Optimize to BTST if possible. | 
 |   // Lower (X & (1 << N)) == 0 to BTST(X, N). | 
 |   // Lower ((X >>u N) & 1) != 0 to BTST(X, N). | 
 |   // Lower ((X >>s N) & 1) != 0 to BTST(X, N). | 
 |   // Lower (trunc (X >> N) to i1) to BTST(X, N). | 
 |   if (Op0.hasOneUse() && isNullConstant(Op1) && | 
 |       (CC == ISD::SETEQ || CC == ISD::SETNE)) { | 
 |     if (SDValue NewSetCC = LowerToBTST(Op0, CC, DL, DAG)) { | 
 |       if (VT == MVT::i1) | 
 |         return DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, NewSetCC); | 
 |       return NewSetCC; | 
 |     } | 
 |   } | 
 |  | 
 |   // Look for X == 0, X == 1, X != 0, or X != 1.  We can simplify some forms of | 
 |   // these. | 
 |   if ((isOneConstant(Op1) || isNullConstant(Op1)) && | 
 |       (CC == ISD::SETEQ || CC == ISD::SETNE)) { | 
 |  | 
 |     // If the input is a setcc, then reuse the input setcc or use a new one with | 
 |     // the inverted condition. | 
 |     if (Op0.getOpcode() == M68kISD::SETCC) { | 
 |       M68k::CondCode CCode = (M68k::CondCode)Op0.getConstantOperandVal(0); | 
 |       bool Invert = (CC == ISD::SETNE) ^ isNullConstant(Op1); | 
 |       if (!Invert) | 
 |         return Op0; | 
 |  | 
 |       CCode = M68k::GetOppositeBranchCondition(CCode); | 
 |       SDValue SetCC = | 
 |           DAG.getNode(M68kISD::SETCC, DL, MVT::i8, | 
 |                       DAG.getConstant(CCode, DL, MVT::i8), Op0.getOperand(1)); | 
 |       if (VT == MVT::i1) | 
 |         return DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, SetCC); | 
 |       return SetCC; | 
 |     } | 
 |   } | 
 |   if (Op0.getValueType() == MVT::i1 && (CC == ISD::SETEQ || CC == ISD::SETNE)) { | 
 |     if (isOneConstant(Op1)) { | 
 |       ISD::CondCode NewCC = ISD::GlobalISel::getSetCCInverse(CC, true); | 
 |       return DAG.getSetCC(DL, VT, Op0, DAG.getConstant(0, DL, MVT::i1), NewCC); | 
 |     } | 
 |     if (!isNullConstant(Op1)) { | 
 |       SDValue Xor = DAG.getNode(ISD::XOR, DL, MVT::i1, Op0, Op1); | 
 |       return DAG.getSetCC(DL, VT, Xor, DAG.getConstant(0, DL, MVT::i1), CC); | 
 |     } | 
 |   } | 
 |  | 
 |   bool IsFP = Op1.getSimpleValueType().isFloatingPoint(); | 
 |   unsigned M68kCC = TranslateM68kCC(CC, DL, IsFP, Op0, Op1, DAG); | 
 |   if (M68kCC == M68k::COND_INVALID) | 
 |     return SDValue(); | 
 |  | 
 |   SDValue CCR = EmitCmp(Op0, Op1, M68kCC, DL, DAG); | 
 |   return DAG.getNode(M68kISD::SETCC, DL, MVT::i8, | 
 |                      DAG.getConstant(M68kCC, DL, MVT::i8), CCR); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerSETCCCARRY(SDValue Op, | 
 |                                             SelectionDAG &DAG) const { | 
 |   SDValue LHS = Op.getOperand(0); | 
 |   SDValue RHS = Op.getOperand(1); | 
 |   SDValue Carry = Op.getOperand(2); | 
 |   SDValue Cond = Op.getOperand(3); | 
 |   SDLoc DL(Op); | 
 |  | 
 |   assert(LHS.getSimpleValueType().isInteger() && "SETCCCARRY is integer only."); | 
 |   M68k::CondCode CC = TranslateIntegerM68kCC(cast<CondCodeSDNode>(Cond)->get()); | 
 |  | 
 |   EVT CarryVT = Carry.getValueType(); | 
 |   APInt NegOne = APInt::getAllOnes(CarryVT.getScalarSizeInBits()); | 
 |   Carry = DAG.getNode(M68kISD::ADD, DL, DAG.getVTList(CarryVT, MVT::i32), Carry, | 
 |                       DAG.getConstant(NegOne, DL, CarryVT)); | 
 |  | 
 |   SDVTList VTs = DAG.getVTList(LHS.getValueType(), MVT::i32); | 
 |   SDValue Cmp = | 
 |       DAG.getNode(M68kISD::SUBX, DL, VTs, LHS, RHS, Carry.getValue(1)); | 
 |  | 
 |   return DAG.getNode(M68kISD::SETCC, DL, MVT::i8, | 
 |                      DAG.getConstant(CC, DL, MVT::i8), Cmp.getValue(1)); | 
 | } | 
 |  | 
 | /// Return true if opcode is a M68k logical comparison. | 
 | static bool isM68kLogicalCmp(SDValue Op) { | 
 |   unsigned Opc = Op.getNode()->getOpcode(); | 
 |   if (Opc == M68kISD::CMP) | 
 |     return true; | 
 |   if (Op.getResNo() == 1 && | 
 |       (Opc == M68kISD::ADD || Opc == M68kISD::SUB || Opc == M68kISD::ADDX || | 
 |        Opc == M68kISD::SUBX || Opc == M68kISD::SMUL || Opc == M68kISD::UMUL || | 
 |        Opc == M68kISD::OR || Opc == M68kISD::XOR || Opc == M68kISD::AND)) | 
 |     return true; | 
 |  | 
 |   if (Op.getResNo() == 2 && Opc == M68kISD::UMUL) | 
 |     return true; | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | static bool isTruncWithZeroHighBitsInput(SDValue V, SelectionDAG &DAG) { | 
 |   if (V.getOpcode() != ISD::TRUNCATE) | 
 |     return false; | 
 |  | 
 |   SDValue VOp0 = V.getOperand(0); | 
 |   unsigned InBits = VOp0.getValueSizeInBits(); | 
 |   unsigned Bits = V.getValueSizeInBits(); | 
 |   return DAG.MaskedValueIsZero(VOp0, | 
 |                                APInt::getHighBitsSet(InBits, InBits - Bits)); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { | 
 |   bool addTest = true; | 
 |   SDValue Cond = Op.getOperand(0); | 
 |   SDValue Op1 = Op.getOperand(1); | 
 |   SDValue Op2 = Op.getOperand(2); | 
 |   SDLoc DL(Op); | 
 |   SDValue CC; | 
 |  | 
 |   if (Cond.getOpcode() == ISD::SETCC) { | 
 |     if (SDValue NewCond = LowerSETCC(Cond, DAG)) | 
 |       Cond = NewCond; | 
 |   } | 
 |  | 
 |   // (select (x == 0), -1, y) -> (sign_bit (x - 1)) | y | 
 |   // (select (x == 0), y, -1) -> ~(sign_bit (x - 1)) | y | 
 |   // (select (x != 0), y, -1) -> (sign_bit (x - 1)) | y | 
 |   // (select (x != 0), -1, y) -> ~(sign_bit (x - 1)) | y | 
 |   if (Cond.getOpcode() == M68kISD::SETCC && | 
 |       Cond.getOperand(1).getOpcode() == M68kISD::CMP && | 
 |       isNullConstant(Cond.getOperand(1).getOperand(0))) { | 
 |     SDValue Cmp = Cond.getOperand(1); | 
 |  | 
 |     unsigned CondCode = Cond.getConstantOperandVal(0); | 
 |  | 
 |     if ((isAllOnesConstant(Op1) || isAllOnesConstant(Op2)) && | 
 |         (CondCode == M68k::COND_EQ || CondCode == M68k::COND_NE)) { | 
 |       SDValue Y = isAllOnesConstant(Op2) ? Op1 : Op2; | 
 |  | 
 |       SDValue CmpOp0 = Cmp.getOperand(1); | 
 |       // Apply further optimizations for special cases | 
 |       // (select (x != 0), -1, 0) -> neg & sbb | 
 |       // (select (x == 0), 0, -1) -> neg & sbb | 
 |       if (isNullConstant(Y) && | 
 |           (isAllOnesConstant(Op1) == (CondCode == M68k::COND_NE))) { | 
 |  | 
 |         SDVTList VTs = DAG.getVTList(CmpOp0.getValueType(), MVT::i32); | 
 |  | 
 |         SDValue Neg = | 
 |             DAG.getNode(M68kISD::SUB, DL, VTs, | 
 |                         DAG.getConstant(0, DL, CmpOp0.getValueType()), CmpOp0); | 
 |  | 
 |         SDValue Res = DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(), | 
 |                                   DAG.getConstant(M68k::COND_CS, DL, MVT::i8), | 
 |                                   SDValue(Neg.getNode(), 1)); | 
 |         return Res; | 
 |       } | 
 |  | 
 |       Cmp = DAG.getNode(M68kISD::CMP, DL, MVT::i8, | 
 |                         DAG.getConstant(1, DL, CmpOp0.getValueType()), CmpOp0); | 
 |  | 
 |       SDValue Res = // Res = 0 or -1. | 
 |           DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(), | 
 |                       DAG.getConstant(M68k::COND_CS, DL, MVT::i8), Cmp); | 
 |  | 
 |       if (isAllOnesConstant(Op1) != (CondCode == M68k::COND_EQ)) | 
 |         Res = DAG.getNOT(DL, Res, Res.getValueType()); | 
 |  | 
 |       if (!isNullConstant(Op2)) | 
 |         Res = DAG.getNode(ISD::OR, DL, Res.getValueType(), Res, Y); | 
 |       return Res; | 
 |     } | 
 |   } | 
 |  | 
 |   // Look past (and (setcc_carry (cmp ...)), 1). | 
 |   if (Cond.getOpcode() == ISD::AND && | 
 |       Cond.getOperand(0).getOpcode() == M68kISD::SETCC_CARRY && | 
 |       isOneConstant(Cond.getOperand(1))) | 
 |     Cond = Cond.getOperand(0); | 
 |  | 
 |   // If condition flag is set by a M68kISD::CMP, then use it as the condition | 
 |   // setting operand in place of the M68kISD::SETCC. | 
 |   unsigned CondOpcode = Cond.getOpcode(); | 
 |   if (CondOpcode == M68kISD::SETCC || CondOpcode == M68kISD::SETCC_CARRY) { | 
 |     CC = Cond.getOperand(0); | 
 |  | 
 |     SDValue Cmp = Cond.getOperand(1); | 
 |     unsigned Opc = Cmp.getOpcode(); | 
 |  | 
 |     bool IllegalFPCMov = false; | 
 |  | 
 |     if ((isM68kLogicalCmp(Cmp) && !IllegalFPCMov) || Opc == M68kISD::BTST) { | 
 |       Cond = Cmp; | 
 |       addTest = false; | 
 |     } | 
 |   } else if (isOverflowArithmetic(CondOpcode)) { | 
 |     // Result is unused here. | 
 |     SDValue Result; | 
 |     unsigned CCode; | 
 |     lowerOverflowArithmetic(Cond, DAG, Result, Cond, CCode); | 
 |     CC = DAG.getConstant(CCode, DL, MVT::i8); | 
 |     addTest = false; | 
 |   } | 
 |  | 
 |   if (addTest) { | 
 |     // Look past the truncate if the high bits are known zero. | 
 |     if (isTruncWithZeroHighBitsInput(Cond, DAG)) | 
 |       Cond = Cond.getOperand(0); | 
 |  | 
 |     // We know the result of AND is compared against zero. Try to match | 
 |     // it to BT. | 
 |     if (Cond.getOpcode() == ISD::AND && Cond.hasOneUse()) { | 
 |       if (SDValue NewSetCC = LowerToBTST(Cond, ISD::SETNE, DL, DAG)) { | 
 |         CC = NewSetCC.getOperand(0); | 
 |         Cond = NewSetCC.getOperand(1); | 
 |         addTest = false; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   if (addTest) { | 
 |     CC = DAG.getConstant(M68k::COND_NE, DL, MVT::i8); | 
 |     Cond = EmitTest(Cond, M68k::COND_NE, DL, DAG); | 
 |   } | 
 |  | 
 |   // a <  b ? -1 :  0 -> RES = ~setcc_carry | 
 |   // a <  b ?  0 : -1 -> RES = setcc_carry | 
 |   // a >= b ? -1 :  0 -> RES = setcc_carry | 
 |   // a >= b ?  0 : -1 -> RES = ~setcc_carry | 
 |   if (Cond.getOpcode() == M68kISD::SUB) { | 
 |     unsigned CondCode = CC->getAsZExtVal(); | 
 |  | 
 |     if ((CondCode == M68k::COND_CC || CondCode == M68k::COND_CS) && | 
 |         (isAllOnesConstant(Op1) || isAllOnesConstant(Op2)) && | 
 |         (isNullConstant(Op1) || isNullConstant(Op2))) { | 
 |       SDValue Res = | 
 |           DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(), | 
 |                       DAG.getConstant(M68k::COND_CS, DL, MVT::i8), Cond); | 
 |       if (isAllOnesConstant(Op1) != (CondCode == M68k::COND_CS)) | 
 |         return DAG.getNOT(DL, Res, Res.getValueType()); | 
 |       return Res; | 
 |     } | 
 |   } | 
 |  | 
 |   // M68k doesn't have an i8 cmov. If both operands are the result of a | 
 |   // truncate widen the cmov and push the truncate through. This avoids | 
 |   // introducing a new branch during isel and doesn't add any extensions. | 
 |   if (Op.getValueType() == MVT::i8 && Op1.getOpcode() == ISD::TRUNCATE && | 
 |       Op2.getOpcode() == ISD::TRUNCATE) { | 
 |     SDValue T1 = Op1.getOperand(0), T2 = Op2.getOperand(0); | 
 |     if (T1.getValueType() == T2.getValueType() && | 
 |         // Block CopyFromReg so partial register stalls are avoided. | 
 |         T1.getOpcode() != ISD::CopyFromReg && | 
 |         T2.getOpcode() != ISD::CopyFromReg) { | 
 |       SDValue Cmov = | 
 |           DAG.getNode(M68kISD::CMOV, DL, T1.getValueType(), T2, T1, CC, Cond); | 
 |       return DAG.getNode(ISD::TRUNCATE, DL, Op.getValueType(), Cmov); | 
 |     } | 
 |   } | 
 |  | 
 |   // Simple optimization when Cond is a constant to avoid generating | 
 |   // M68kISD::CMOV if possible. | 
 |   // TODO: Generalize this to use SelectionDAG::computeKnownBits. | 
 |   if (auto *Const = dyn_cast<ConstantSDNode>(Cond.getNode())) { | 
 |     const APInt &C = Const->getAPIntValue(); | 
 |     if (C.countr_zero() >= 5) | 
 |       return Op2; | 
 |     else if (C.countr_one() >= 5) | 
 |       return Op1; | 
 |   } | 
 |  | 
 |   // M68kISD::CMOV means set the result (which is operand 1) to the RHS if | 
 |   // condition is true. | 
 |   SDValue Ops[] = {Op2, Op1, CC, Cond}; | 
 |   return DAG.getNode(M68kISD::CMOV, DL, Op.getValueType(), Ops); | 
 | } | 
 |  | 
 | /// Return true if node is an ISD::AND or ISD::OR of two M68k::SETcc nodes | 
 | /// each of which has no other use apart from the AND / OR. | 
 | static bool isAndOrOfSetCCs(SDValue Op, unsigned &Opc) { | 
 |   Opc = Op.getOpcode(); | 
 |   if (Opc != ISD::OR && Opc != ISD::AND) | 
 |     return false; | 
 |   return (M68k::IsSETCC(Op.getOperand(0).getOpcode()) && | 
 |           Op.getOperand(0).hasOneUse() && | 
 |           M68k::IsSETCC(Op.getOperand(1).getOpcode()) && | 
 |           Op.getOperand(1).hasOneUse()); | 
 | } | 
 |  | 
 | /// Return true if node is an ISD::XOR of a M68kISD::SETCC and 1 and that the | 
 | /// SETCC node has a single use. | 
 | static bool isXor1OfSetCC(SDValue Op) { | 
 |   if (Op.getOpcode() != ISD::XOR) | 
 |     return false; | 
 |   if (isOneConstant(Op.getOperand(1))) | 
 |     return Op.getOperand(0).getOpcode() == M68kISD::SETCC && | 
 |            Op.getOperand(0).hasOneUse(); | 
 |   return false; | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { | 
 |   bool AddTest = true; | 
 |   SDValue Chain = Op.getOperand(0); | 
 |   SDValue Cond = Op.getOperand(1); | 
 |   SDValue Dest = Op.getOperand(2); | 
 |   SDLoc DL(Op); | 
 |   SDValue CC; | 
 |   bool Inverted = false; | 
 |  | 
 |   if (Cond.getOpcode() == ISD::SETCC) { | 
 |     // Check for setcc([su]{add,sub}o == 0). | 
 |     if (cast<CondCodeSDNode>(Cond.getOperand(2))->get() == ISD::SETEQ && | 
 |         isNullConstant(Cond.getOperand(1)) && | 
 |         Cond.getOperand(0).getResNo() == 1 && | 
 |         (Cond.getOperand(0).getOpcode() == ISD::SADDO || | 
 |          Cond.getOperand(0).getOpcode() == ISD::UADDO || | 
 |          Cond.getOperand(0).getOpcode() == ISD::SSUBO || | 
 |          Cond.getOperand(0).getOpcode() == ISD::USUBO)) { | 
 |       Inverted = true; | 
 |       Cond = Cond.getOperand(0); | 
 |     } else { | 
 |       if (SDValue NewCond = LowerSETCC(Cond, DAG)) | 
 |         Cond = NewCond; | 
 |     } | 
 |   } | 
 |  | 
 |   // Look pass (and (setcc_carry (cmp ...)), 1). | 
 |   if (Cond.getOpcode() == ISD::AND && | 
 |       Cond.getOperand(0).getOpcode() == M68kISD::SETCC_CARRY && | 
 |       isOneConstant(Cond.getOperand(1))) | 
 |     Cond = Cond.getOperand(0); | 
 |  | 
 |   // If condition flag is set by a M68kISD::CMP, then use it as the condition | 
 |   // setting operand in place of the M68kISD::SETCC. | 
 |   unsigned CondOpcode = Cond.getOpcode(); | 
 |   if (CondOpcode == M68kISD::SETCC || CondOpcode == M68kISD::SETCC_CARRY) { | 
 |     CC = Cond.getOperand(0); | 
 |  | 
 |     SDValue Cmp = Cond.getOperand(1); | 
 |     unsigned Opc = Cmp.getOpcode(); | 
 |  | 
 |     if (isM68kLogicalCmp(Cmp) || Opc == M68kISD::BTST) { | 
 |       Cond = Cmp; | 
 |       AddTest = false; | 
 |     } else { | 
 |       switch (CC->getAsZExtVal()) { | 
 |       default: | 
 |         break; | 
 |       case M68k::COND_VS: | 
 |       case M68k::COND_CS: | 
 |         // These can only come from an arithmetic instruction with overflow, | 
 |         // e.g. SADDO, UADDO. | 
 |         Cond = Cond.getNode()->getOperand(1); | 
 |         AddTest = false; | 
 |         break; | 
 |       } | 
 |     } | 
 |   } | 
 |   CondOpcode = Cond.getOpcode(); | 
 |   if (isOverflowArithmetic(CondOpcode)) { | 
 |     SDValue Result; | 
 |     unsigned CCode; | 
 |     lowerOverflowArithmetic(Cond, DAG, Result, Cond, CCode); | 
 |  | 
 |     if (Inverted) | 
 |       CCode = M68k::GetOppositeBranchCondition((M68k::CondCode)CCode); | 
 |     CC = DAG.getConstant(CCode, DL, MVT::i8); | 
 |  | 
 |     AddTest = false; | 
 |   } else { | 
 |     unsigned CondOpc; | 
 |     if (Cond.hasOneUse() && isAndOrOfSetCCs(Cond, CondOpc)) { | 
 |       SDValue Cmp = Cond.getOperand(0).getOperand(1); | 
 |       if (CondOpc == ISD::OR) { | 
 |         // Also, recognize the pattern generated by an FCMP_UNE. We can emit | 
 |         // two branches instead of an explicit OR instruction with a | 
 |         // separate test. | 
 |         if (Cmp == Cond.getOperand(1).getOperand(1) && isM68kLogicalCmp(Cmp)) { | 
 |           CC = Cond.getOperand(0).getOperand(0); | 
 |           Chain = DAG.getNode(M68kISD::BRCOND, DL, Op.getValueType(), Chain, | 
 |                               Dest, CC, Cmp); | 
 |           CC = Cond.getOperand(1).getOperand(0); | 
 |           Cond = Cmp; | 
 |           AddTest = false; | 
 |         } | 
 |       } else { // ISD::AND | 
 |         // Also, recognize the pattern generated by an FCMP_OEQ. We can emit | 
 |         // two branches instead of an explicit AND instruction with a | 
 |         // separate test. However, we only do this if this block doesn't | 
 |         // have a fall-through edge, because this requires an explicit | 
 |         // jmp when the condition is false. | 
 |         if (Cmp == Cond.getOperand(1).getOperand(1) && isM68kLogicalCmp(Cmp) && | 
 |             Op.getNode()->hasOneUse()) { | 
 |           M68k::CondCode CCode = | 
 |               (M68k::CondCode)Cond.getOperand(0).getConstantOperandVal(0); | 
 |           CCode = M68k::GetOppositeBranchCondition(CCode); | 
 |           CC = DAG.getConstant(CCode, DL, MVT::i8); | 
 |           SDNode *User = *Op.getNode()->user_begin(); | 
 |           // Look for an unconditional branch following this conditional branch. | 
 |           // We need this because we need to reverse the successors in order | 
 |           // to implement FCMP_OEQ. | 
 |           if (User->getOpcode() == ISD::BR) { | 
 |             SDValue FalseBB = User->getOperand(1); | 
 |             SDNode *NewBR = | 
 |                 DAG.UpdateNodeOperands(User, User->getOperand(0), Dest); | 
 |             assert(NewBR == User); | 
 |             (void)NewBR; | 
 |             Dest = FalseBB; | 
 |  | 
 |             Chain = DAG.getNode(M68kISD::BRCOND, DL, Op.getValueType(), Chain, | 
 |                                 Dest, CC, Cmp); | 
 |             M68k::CondCode CCode = | 
 |                 (M68k::CondCode)Cond.getOperand(1).getConstantOperandVal(0); | 
 |             CCode = M68k::GetOppositeBranchCondition(CCode); | 
 |             CC = DAG.getConstant(CCode, DL, MVT::i8); | 
 |             Cond = Cmp; | 
 |             AddTest = false; | 
 |           } | 
 |         } | 
 |       } | 
 |     } else if (Cond.hasOneUse() && isXor1OfSetCC(Cond)) { | 
 |       // Recognize for xorb (setcc), 1 patterns. The xor inverts the condition. | 
 |       // It should be transformed during dag combiner except when the condition | 
 |       // is set by a arithmetics with overflow node. | 
 |       M68k::CondCode CCode = | 
 |           (M68k::CondCode)Cond.getOperand(0).getConstantOperandVal(0); | 
 |       CCode = M68k::GetOppositeBranchCondition(CCode); | 
 |       CC = DAG.getConstant(CCode, DL, MVT::i8); | 
 |       Cond = Cond.getOperand(0).getOperand(1); | 
 |       AddTest = false; | 
 |     } | 
 |   } | 
 |  | 
 |   if (AddTest) { | 
 |     // Look pass the truncate if the high bits are known zero. | 
 |     if (isTruncWithZeroHighBitsInput(Cond, DAG)) | 
 |       Cond = Cond.getOperand(0); | 
 |  | 
 |     // We know the result is compared against zero. Try to match it to BT. | 
 |     if (Cond.hasOneUse()) { | 
 |       if (SDValue NewSetCC = LowerToBTST(Cond, ISD::SETNE, DL, DAG)) { | 
 |         CC = NewSetCC.getOperand(0); | 
 |         Cond = NewSetCC.getOperand(1); | 
 |         AddTest = false; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   if (AddTest) { | 
 |     M68k::CondCode MxCond = Inverted ? M68k::COND_EQ : M68k::COND_NE; | 
 |     CC = DAG.getConstant(MxCond, DL, MVT::i8); | 
 |     Cond = EmitTest(Cond, MxCond, DL, DAG); | 
 |   } | 
 |   return DAG.getNode(M68kISD::BRCOND, DL, Op.getValueType(), Chain, Dest, CC, | 
 |                      Cond); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerADDC_ADDE_SUBC_SUBE(SDValue Op, | 
 |                                                      SelectionDAG &DAG) const { | 
 |   MVT VT = Op.getNode()->getSimpleValueType(0); | 
 |  | 
 |   // Let legalize expand this if it isn't a legal type yet. | 
 |   if (!DAG.getTargetLoweringInfo().isTypeLegal(VT)) | 
 |     return SDValue(); | 
 |  | 
 |   SDVTList VTs = DAG.getVTList(VT, MVT::i8); | 
 |  | 
 |   unsigned Opc; | 
 |   bool ExtraOp = false; | 
 |   switch (Op.getOpcode()) { | 
 |   default: | 
 |     llvm_unreachable("Invalid code"); | 
 |   case ISD::ADDC: | 
 |     Opc = M68kISD::ADD; | 
 |     break; | 
 |   case ISD::ADDE: | 
 |     Opc = M68kISD::ADDX; | 
 |     ExtraOp = true; | 
 |     break; | 
 |   case ISD::SUBC: | 
 |     Opc = M68kISD::SUB; | 
 |     break; | 
 |   case ISD::SUBE: | 
 |     Opc = M68kISD::SUBX; | 
 |     ExtraOp = true; | 
 |     break; | 
 |   } | 
 |  | 
 |   if (!ExtraOp) | 
 |     return DAG.getNode(Opc, SDLoc(Op), VTs, Op.getOperand(0), Op.getOperand(1)); | 
 |   return DAG.getNode(Opc, SDLoc(Op), VTs, Op.getOperand(0), Op.getOperand(1), | 
 |                      Op.getOperand(2)); | 
 | } | 
 |  | 
 | // ConstantPool, JumpTable, GlobalAddress, and ExternalSymbol are lowered as | 
 | // their target countpart wrapped in the M68kISD::Wrapper node. Suppose N is | 
 | // one of the above mentioned nodes. It has to be wrapped because otherwise | 
 | // Select(N) returns N. So the raw TargetGlobalAddress nodes, etc. can only | 
 | // be used to form addressing mode. These wrapped nodes will be selected | 
 | // into MOV32ri. | 
 | SDValue M68kTargetLowering::LowerConstantPool(SDValue Op, | 
 |                                               SelectionDAG &DAG) const { | 
 |   ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); | 
 |  | 
 |   // In PIC mode (unless we're in PCRel PIC mode) we add an offset to the | 
 |   // global base reg. | 
 |   unsigned char OpFlag = Subtarget.classifyLocalReference(nullptr); | 
 |  | 
 |   unsigned WrapperKind = M68kISD::Wrapper; | 
 |   if (M68kII::isPCRelGlobalReference(OpFlag)) { | 
 |     WrapperKind = M68kISD::WrapperPC; | 
 |   } | 
 |  | 
 |   MVT PtrVT = getPointerTy(DAG.getDataLayout()); | 
 |   SDValue Result = DAG.getTargetConstantPool( | 
 |       CP->getConstVal(), PtrVT, CP->getAlign(), CP->getOffset(), OpFlag); | 
 |  | 
 |   SDLoc DL(CP); | 
 |   Result = DAG.getNode(WrapperKind, DL, PtrVT, Result); | 
 |  | 
 |   // With PIC, the address is actually $g + Offset. | 
 |   if (M68kII::isGlobalRelativeToPICBase(OpFlag)) { | 
 |     Result = DAG.getNode(ISD::ADD, DL, PtrVT, | 
 |                          DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(), PtrVT), | 
 |                          Result); | 
 |   } | 
 |  | 
 |   return Result; | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerExternalSymbol(SDValue Op, | 
 |                                                 SelectionDAG &DAG) const { | 
 |   const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol(); | 
 |  | 
 |   // In PIC mode (unless we're in PCRel PIC mode) we add an offset to the | 
 |   // global base reg. | 
 |   const Module *Mod = DAG.getMachineFunction().getFunction().getParent(); | 
 |   unsigned char OpFlag = Subtarget.classifyExternalReference(*Mod); | 
 |  | 
 |   unsigned WrapperKind = M68kISD::Wrapper; | 
 |   if (M68kII::isPCRelGlobalReference(OpFlag)) { | 
 |     WrapperKind = M68kISD::WrapperPC; | 
 |   } | 
 |  | 
 |   auto PtrVT = getPointerTy(DAG.getDataLayout()); | 
 |   SDValue Result = DAG.getTargetExternalSymbol(Sym, PtrVT, OpFlag); | 
 |  | 
 |   SDLoc DL(Op); | 
 |   Result = DAG.getNode(WrapperKind, DL, PtrVT, Result); | 
 |  | 
 |   // With PIC, the address is actually $g + Offset. | 
 |   if (M68kII::isGlobalRelativeToPICBase(OpFlag)) { | 
 |     Result = DAG.getNode(ISD::ADD, DL, PtrVT, | 
 |                          DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(), PtrVT), | 
 |                          Result); | 
 |   } | 
 |  | 
 |   // For symbols that require a load from a stub to get the address, emit the | 
 |   // load. | 
 |   if (M68kII::isGlobalStubReference(OpFlag)) { | 
 |     Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Result, | 
 |                          MachinePointerInfo::getGOT(DAG.getMachineFunction())); | 
 |   } | 
 |  | 
 |   return Result; | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerBlockAddress(SDValue Op, | 
 |                                               SelectionDAG &DAG) const { | 
 |   unsigned char OpFlags = Subtarget.classifyBlockAddressReference(); | 
 |   const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); | 
 |   int64_t Offset = cast<BlockAddressSDNode>(Op)->getOffset(); | 
 |   SDLoc DL(Op); | 
 |   auto PtrVT = getPointerTy(DAG.getDataLayout()); | 
 |  | 
 |   // Create the TargetBlockAddressAddress node. | 
 |   SDValue Result = DAG.getTargetBlockAddress(BA, PtrVT, Offset, OpFlags); | 
 |  | 
 |   if (M68kII::isPCRelBlockReference(OpFlags)) { | 
 |     Result = DAG.getNode(M68kISD::WrapperPC, DL, PtrVT, Result); | 
 |   } else { | 
 |     Result = DAG.getNode(M68kISD::Wrapper, DL, PtrVT, Result); | 
 |   } | 
 |  | 
 |   // With PIC, the address is actually $g + Offset. | 
 |   if (M68kII::isGlobalRelativeToPICBase(OpFlags)) { | 
 |     Result = | 
 |         DAG.getNode(ISD::ADD, DL, PtrVT, | 
 |                     DAG.getNode(M68kISD::GLOBAL_BASE_REG, DL, PtrVT), Result); | 
 |   } | 
 |  | 
 |   return Result; | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerGlobalAddress(const GlobalValue *GV, | 
 |                                                const SDLoc &DL, int64_t Offset, | 
 |                                                SelectionDAG &DAG) const { | 
 |   unsigned char OpFlags = Subtarget.classifyGlobalReference(GV); | 
 |   auto PtrVT = getPointerTy(DAG.getDataLayout()); | 
 |  | 
 |   // Create the TargetGlobalAddress node, folding in the constant | 
 |   // offset if it is legal. | 
 |   SDValue Result; | 
 |   if (M68kII::isDirectGlobalReference(OpFlags)) { | 
 |     Result = DAG.getTargetGlobalAddress(GV, DL, PtrVT, Offset); | 
 |     Offset = 0; | 
 |   } else { | 
 |     Result = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, OpFlags); | 
 |   } | 
 |  | 
 |   if (M68kII::isPCRelGlobalReference(OpFlags)) | 
 |     Result = DAG.getNode(M68kISD::WrapperPC, DL, PtrVT, Result); | 
 |   else | 
 |     Result = DAG.getNode(M68kISD::Wrapper, DL, PtrVT, Result); | 
 |  | 
 |   // With PIC, the address is actually $g + Offset. | 
 |   if (M68kII::isGlobalRelativeToPICBase(OpFlags)) { | 
 |     Result = | 
 |         DAG.getNode(ISD::ADD, DL, PtrVT, | 
 |                     DAG.getNode(M68kISD::GLOBAL_BASE_REG, DL, PtrVT), Result); | 
 |   } | 
 |  | 
 |   // For globals that require a load from a stub to get the address, emit the | 
 |   // load. | 
 |   if (M68kII::isGlobalStubReference(OpFlags)) { | 
 |     Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Result, | 
 |                          MachinePointerInfo::getGOT(DAG.getMachineFunction())); | 
 |   } | 
 |  | 
 |   // If there was a non-zero offset that we didn't fold, create an explicit | 
 |   // addition for it. | 
 |   if (Offset != 0) { | 
 |     Result = DAG.getNode(ISD::ADD, DL, PtrVT, Result, | 
 |                          DAG.getConstant(Offset, DL, PtrVT)); | 
 |   } | 
 |  | 
 |   return Result; | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerGlobalAddress(SDValue Op, | 
 |                                                SelectionDAG &DAG) const { | 
 |   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); | 
 |   int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset(); | 
 |   return LowerGlobalAddress(GV, SDLoc(Op), Offset, DAG); | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // Custom Lower Jump Table | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | SDValue M68kTargetLowering::LowerJumpTable(SDValue Op, | 
 |                                            SelectionDAG &DAG) const { | 
 |   JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); | 
 |  | 
 |   // In PIC mode (unless we're in PCRel PIC mode) we add an offset to the | 
 |   // global base reg. | 
 |   unsigned char OpFlag = Subtarget.classifyLocalReference(nullptr); | 
 |  | 
 |   unsigned WrapperKind = M68kISD::Wrapper; | 
 |   if (M68kII::isPCRelGlobalReference(OpFlag)) { | 
 |     WrapperKind = M68kISD::WrapperPC; | 
 |   } | 
 |  | 
 |   auto PtrVT = getPointerTy(DAG.getDataLayout()); | 
 |   SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OpFlag); | 
 |   SDLoc DL(JT); | 
 |   Result = DAG.getNode(WrapperKind, DL, PtrVT, Result); | 
 |  | 
 |   // With PIC, the address is actually $g + Offset. | 
 |   if (M68kII::isGlobalRelativeToPICBase(OpFlag)) { | 
 |     Result = DAG.getNode(ISD::ADD, DL, PtrVT, | 
 |                          DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(), PtrVT), | 
 |                          Result); | 
 |   } | 
 |  | 
 |   return Result; | 
 | } | 
 |  | 
 | unsigned M68kTargetLowering::getJumpTableEncoding() const { | 
 |   return Subtarget.getJumpTableEncoding(); | 
 | } | 
 |  | 
 | const MCExpr *M68kTargetLowering::LowerCustomJumpTableEntry( | 
 |     const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, | 
 |     unsigned uid, MCContext &Ctx) const { | 
 |   return MCSymbolRefExpr::create(MBB->getSymbol(), M68kMCExpr::VK_GOTOFF, Ctx); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::getPICJumpTableRelocBase(SDValue Table, | 
 |                                                      SelectionDAG &DAG) const { | 
 |   if (getJumpTableEncoding() == MachineJumpTableInfo::EK_Custom32) | 
 |     return DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(), | 
 |                        getPointerTy(DAG.getDataLayout())); | 
 |  | 
 |   // MachineJumpTableInfo::EK_LabelDifference32 entry | 
 |   return Table; | 
 | } | 
 |  | 
 | // NOTE This only used for MachineJumpTableInfo::EK_LabelDifference32 entries | 
 | const MCExpr *M68kTargetLowering::getPICJumpTableRelocBaseExpr( | 
 |     const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const { | 
 |   return MCSymbolRefExpr::create(MF->getJTISymbol(JTI, Ctx), Ctx); | 
 | } | 
 |  | 
 | M68kTargetLowering::ConstraintType | 
 | M68kTargetLowering::getConstraintType(StringRef Constraint) const { | 
 |   if (Constraint.size() > 0) { | 
 |     switch (Constraint[0]) { | 
 |     case 'a': | 
 |     case 'd': | 
 |       return C_RegisterClass; | 
 |     case 'I': | 
 |     case 'J': | 
 |     case 'K': | 
 |     case 'L': | 
 |     case 'M': | 
 |     case 'N': | 
 |     case 'O': | 
 |     case 'P': | 
 |       return C_Immediate; | 
 |     case 'C': | 
 |       if (Constraint.size() == 2) | 
 |         switch (Constraint[1]) { | 
 |         case '0': | 
 |         case 'i': | 
 |         case 'j': | 
 |           return C_Immediate; | 
 |         default: | 
 |           break; | 
 |         } | 
 |       break; | 
 |     case 'Q': | 
 |     case 'U': | 
 |       return C_Memory; | 
 |     default: | 
 |       break; | 
 |     } | 
 |   } | 
 |  | 
 |   return TargetLowering::getConstraintType(Constraint); | 
 | } | 
 |  | 
 | void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op, | 
 |                                                       StringRef Constraint, | 
 |                                                       std::vector<SDValue> &Ops, | 
 |                                                       SelectionDAG &DAG) const { | 
 |   SDValue Result; | 
 |  | 
 |   if (Constraint.size() == 1) { | 
 |     // Constant constraints | 
 |     switch (Constraint[0]) { | 
 |     case 'I': | 
 |     case 'J': | 
 |     case 'K': | 
 |     case 'L': | 
 |     case 'M': | 
 |     case 'N': | 
 |     case 'O': | 
 |     case 'P': { | 
 |       auto *C = dyn_cast<ConstantSDNode>(Op); | 
 |       if (!C) | 
 |         return; | 
 |  | 
 |       int64_t Val = C->getSExtValue(); | 
 |       switch (Constraint[0]) { | 
 |       case 'I': // constant integer in the range [1,8] | 
 |         if (Val > 0 && Val <= 8) | 
 |           break; | 
 |         return; | 
 |       case 'J': // constant signed 16-bit integer | 
 |         if (isInt<16>(Val)) | 
 |           break; | 
 |         return; | 
 |       case 'K': // constant that is NOT in the range of [-0x80, 0x80) | 
 |         if (Val < -0x80 || Val >= 0x80) | 
 |           break; | 
 |         return; | 
 |       case 'L': // constant integer in the range [-8,-1] | 
 |         if (Val < 0 && Val >= -8) | 
 |           break; | 
 |         return; | 
 |       case 'M': // constant that is NOT in the range of [-0x100, 0x100] | 
 |         if (Val < -0x100 || Val >= 0x100) | 
 |           break; | 
 |         return; | 
 |       case 'N': // constant integer in the range [24,31] | 
 |         if (Val >= 24 && Val <= 31) | 
 |           break; | 
 |         return; | 
 |       case 'O': // constant integer 16 | 
 |         if (Val == 16) | 
 |           break; | 
 |         return; | 
 |       case 'P': // constant integer in the range [8,15] | 
 |         if (Val >= 8 && Val <= 15) | 
 |           break; | 
 |         return; | 
 |       default: | 
 |         llvm_unreachable("Unhandled constant constraint"); | 
 |       } | 
 |  | 
 |       Result = DAG.getSignedTargetConstant(Val, SDLoc(Op), Op.getValueType()); | 
 |       break; | 
 |     } | 
 |     default: | 
 |       break; | 
 |     } | 
 |   } | 
 |  | 
 |   if (Constraint.size() == 2) { | 
 |     switch (Constraint[0]) { | 
 |     case 'C': | 
 |       // Constant constraints start with 'C' | 
 |       switch (Constraint[1]) { | 
 |       case '0': | 
 |       case 'i': | 
 |       case 'j': { | 
 |         auto *C = dyn_cast<ConstantSDNode>(Op); | 
 |         if (!C) | 
 |           break; | 
 |  | 
 |         int64_t Val = C->getSExtValue(); | 
 |         switch (Constraint[1]) { | 
 |         case '0': // constant integer 0 | 
 |           if (!Val) | 
 |             break; | 
 |           return; | 
 |         case 'i': // constant integer | 
 |           break; | 
 |         case 'j': // integer constant that doesn't fit in 16 bits | 
 |           if (!isInt<16>(C->getSExtValue())) | 
 |             break; | 
 |           return; | 
 |         default: | 
 |           llvm_unreachable("Unhandled constant constraint"); | 
 |         } | 
 |  | 
 |         Result = DAG.getSignedTargetConstant(Val, SDLoc(Op), Op.getValueType()); | 
 |         break; | 
 |       } | 
 |       default: | 
 |         break; | 
 |       } | 
 |       break; | 
 |     default: | 
 |       break; | 
 |     } | 
 |   } | 
 |  | 
 |   if (Result.getNode()) { | 
 |     Ops.push_back(Result); | 
 |     return; | 
 |   } | 
 |  | 
 |   TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); | 
 | } | 
 |  | 
 | std::pair<unsigned, const TargetRegisterClass *> | 
 | M68kTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, | 
 |                                                  StringRef Constraint, | 
 |                                                  MVT VT) const { | 
 |   if (Constraint.size() == 1) { | 
 |     switch (Constraint[0]) { | 
 |     case 'r': | 
 |     case 'd': | 
 |       switch (VT.SimpleTy) { | 
 |       case MVT::i8: | 
 |         return std::make_pair(0U, &M68k::DR8RegClass); | 
 |       case MVT::i16: | 
 |         return std::make_pair(0U, &M68k::DR16RegClass); | 
 |       case MVT::i32: | 
 |         return std::make_pair(0U, &M68k::DR32RegClass); | 
 |       default: | 
 |         break; | 
 |       } | 
 |       break; | 
 |     case 'a': | 
 |       switch (VT.SimpleTy) { | 
 |       case MVT::i16: | 
 |         return std::make_pair(0U, &M68k::AR16RegClass); | 
 |       case MVT::i32: | 
 |         return std::make_pair(0U, &M68k::AR32RegClass); | 
 |       default: | 
 |         break; | 
 |       } | 
 |       break; | 
 |     default: | 
 |       break; | 
 |     } | 
 |   } | 
 |  | 
 |   return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); | 
 | } | 
 |  | 
 | /// Determines whether the callee is required to pop its own arguments. | 
 | /// Callee pop is necessary to support tail calls. | 
 | bool M68k::isCalleePop(CallingConv::ID CC, bool IsVarArg, bool GuaranteeTCO) { | 
 |   return CC == CallingConv::M68k_RTD && !IsVarArg; | 
 | } | 
 |  | 
 | // Return true if it is OK for this CMOV pseudo-opcode to be cascaded | 
 | // together with other CMOV pseudo-opcodes into a single basic-block with | 
 | // conditional jump around it. | 
 | static bool isCMOVPseudo(MachineInstr &MI) { | 
 |   switch (MI.getOpcode()) { | 
 |   case M68k::CMOV8d: | 
 |   case M68k::CMOV16d: | 
 |   case M68k::CMOV32r: | 
 |     return true; | 
 |  | 
 |   default: | 
 |     return false; | 
 |   } | 
 | } | 
 |  | 
 | // The CCR operand of SelectItr might be missing a kill marker | 
 | // because there were multiple uses of CCR, and ISel didn't know | 
 | // which to mark. Figure out whether SelectItr should have had a | 
 | // kill marker, and set it if it should. Returns the correct kill | 
 | // marker value. | 
 | static bool checkAndUpdateCCRKill(MachineBasicBlock::iterator SelectItr, | 
 |                                   MachineBasicBlock *BB, | 
 |                                   const TargetRegisterInfo *TRI) { | 
 |   // Scan forward through BB for a use/def of CCR. | 
 |   MachineBasicBlock::iterator miI(std::next(SelectItr)); | 
 |   for (MachineBasicBlock::iterator miE = BB->end(); miI != miE; ++miI) { | 
 |     const MachineInstr &mi = *miI; | 
 |     if (mi.readsRegister(M68k::CCR, /*TRI=*/nullptr)) | 
 |       return false; | 
 |     if (mi.definesRegister(M68k::CCR, /*TRI=*/nullptr)) | 
 |       break; // Should have kill-flag - update below. | 
 |   } | 
 |  | 
 |   // If we hit the end of the block, check whether CCR is live into a | 
 |   // successor. | 
 |   if (miI == BB->end()) | 
 |     for (const auto *SBB : BB->successors()) | 
 |       if (SBB->isLiveIn(M68k::CCR)) | 
 |         return false; | 
 |  | 
 |   // We found a def, or hit the end of the basic block and CCR wasn't live | 
 |   // out. SelectMI should have a kill flag on CCR. | 
 |   SelectItr->addRegisterKilled(M68k::CCR, TRI); | 
 |   return true; | 
 | } | 
 |  | 
 | MachineBasicBlock * | 
 | M68kTargetLowering::EmitLoweredSelect(MachineInstr &MI, | 
 |                                       MachineBasicBlock *MBB) const { | 
 |   const TargetInstrInfo *TII = Subtarget.getInstrInfo(); | 
 |   DebugLoc DL = MI.getDebugLoc(); | 
 |  | 
 |   // To "insert" a SELECT_CC instruction, we actually have to insert the | 
 |   // diamond control-flow pattern.  The incoming instruction knows the | 
 |   // destination vreg to set, the condition code register to branch on, the | 
 |   // true/false values to select between, and a branch opcode to use. | 
 |   const BasicBlock *BB = MBB->getBasicBlock(); | 
 |   MachineFunction::iterator It = ++MBB->getIterator(); | 
 |  | 
 |   //  ThisMBB: | 
 |   //  ... | 
 |   //   TrueVal = ... | 
 |   //   cmp ccX, r1, r2 | 
 |   //   bcc Copy1MBB | 
 |   //   fallthrough --> Copy0MBB | 
 |   MachineBasicBlock *ThisMBB = MBB; | 
 |   MachineFunction *F = MBB->getParent(); | 
 |  | 
 |   // This code lowers all pseudo-CMOV instructions. Generally it lowers these | 
 |   // as described above, by inserting a MBB, and then making a PHI at the join | 
 |   // point to select the true and false operands of the CMOV in the PHI. | 
 |   // | 
 |   // The code also handles two different cases of multiple CMOV opcodes | 
 |   // in a row. | 
 |   // | 
 |   // Case 1: | 
 |   // In this case, there are multiple CMOVs in a row, all which are based on | 
 |   // the same condition setting (or the exact opposite condition setting). | 
 |   // In this case we can lower all the CMOVs using a single inserted MBB, and | 
 |   // then make a number of PHIs at the join point to model the CMOVs. The only | 
 |   // trickiness here, is that in a case like: | 
 |   // | 
 |   // t2 = CMOV cond1 t1, f1 | 
 |   // t3 = CMOV cond1 t2, f2 | 
 |   // | 
 |   // when rewriting this into PHIs, we have to perform some renaming on the | 
 |   // temps since you cannot have a PHI operand refer to a PHI result earlier | 
 |   // in the same block.  The "simple" but wrong lowering would be: | 
 |   // | 
 |   // t2 = PHI t1(BB1), f1(BB2) | 
 |   // t3 = PHI t2(BB1), f2(BB2) | 
 |   // | 
 |   // but clearly t2 is not defined in BB1, so that is incorrect. The proper | 
 |   // renaming is to note that on the path through BB1, t2 is really just a | 
 |   // copy of t1, and do that renaming, properly generating: | 
 |   // | 
 |   // t2 = PHI t1(BB1), f1(BB2) | 
 |   // t3 = PHI t1(BB1), f2(BB2) | 
 |   // | 
 |   // Case 2, we lower cascaded CMOVs such as | 
 |   // | 
 |   //   (CMOV (CMOV F, T, cc1), T, cc2) | 
 |   // | 
 |   // to two successives branches. | 
 |   MachineInstr *CascadedCMOV = nullptr; | 
 |   MachineInstr *LastCMOV = &MI; | 
 |   M68k::CondCode CC = M68k::CondCode(MI.getOperand(3).getImm()); | 
 |   M68k::CondCode OppCC = M68k::GetOppositeBranchCondition(CC); | 
 |   MachineBasicBlock::iterator NextMIIt = | 
 |       std::next(MachineBasicBlock::iterator(MI)); | 
 |  | 
 |   // Check for case 1, where there are multiple CMOVs with the same condition | 
 |   // first.  Of the two cases of multiple CMOV lowerings, case 1 reduces the | 
 |   // number of jumps the most. | 
 |  | 
 |   if (isCMOVPseudo(MI)) { | 
 |     // See if we have a string of CMOVS with the same condition. | 
 |     while (NextMIIt != MBB->end() && isCMOVPseudo(*NextMIIt) && | 
 |            (NextMIIt->getOperand(3).getImm() == CC || | 
 |             NextMIIt->getOperand(3).getImm() == OppCC)) { | 
 |       LastCMOV = &*NextMIIt; | 
 |       ++NextMIIt; | 
 |     } | 
 |   } | 
 |  | 
 |   // This checks for case 2, but only do this if we didn't already find | 
 |   // case 1, as indicated by LastCMOV == MI. | 
 |   if (LastCMOV == &MI && NextMIIt != MBB->end() && | 
 |       NextMIIt->getOpcode() == MI.getOpcode() && | 
 |       NextMIIt->getOperand(2).getReg() == MI.getOperand(2).getReg() && | 
 |       NextMIIt->getOperand(1).getReg() == MI.getOperand(0).getReg() && | 
 |       NextMIIt->getOperand(1).isKill()) { | 
 |     CascadedCMOV = &*NextMIIt; | 
 |   } | 
 |  | 
 |   MachineBasicBlock *Jcc1MBB = nullptr; | 
 |  | 
 |   // If we have a cascaded CMOV, we lower it to two successive branches to | 
 |   // the same block.  CCR is used by both, so mark it as live in the second. | 
 |   if (CascadedCMOV) { | 
 |     Jcc1MBB = F->CreateMachineBasicBlock(BB); | 
 |     F->insert(It, Jcc1MBB); | 
 |     Jcc1MBB->addLiveIn(M68k::CCR); | 
 |   } | 
 |  | 
 |   MachineBasicBlock *Copy0MBB = F->CreateMachineBasicBlock(BB); | 
 |   MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(BB); | 
 |   F->insert(It, Copy0MBB); | 
 |   F->insert(It, SinkMBB); | 
 |  | 
 |   // Set the call frame size on entry to the new basic blocks. | 
 |   unsigned CallFrameSize = TII->getCallFrameSizeAt(MI); | 
 |   Copy0MBB->setCallFrameSize(CallFrameSize); | 
 |   SinkMBB->setCallFrameSize(CallFrameSize); | 
 |  | 
 |   // If the CCR register isn't dead in the terminator, then claim that it's | 
 |   // live into the sink and copy blocks. | 
 |   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); | 
 |  | 
 |   MachineInstr *LastCCRSUser = CascadedCMOV ? CascadedCMOV : LastCMOV; | 
 |   if (!LastCCRSUser->killsRegister(M68k::CCR, /*TRI=*/nullptr) && | 
 |       !checkAndUpdateCCRKill(LastCCRSUser, MBB, TRI)) { | 
 |     Copy0MBB->addLiveIn(M68k::CCR); | 
 |     SinkMBB->addLiveIn(M68k::CCR); | 
 |   } | 
 |  | 
 |   // Transfer the remainder of MBB and its successor edges to SinkMBB. | 
 |   SinkMBB->splice(SinkMBB->begin(), MBB, | 
 |                   std::next(MachineBasicBlock::iterator(LastCMOV)), MBB->end()); | 
 |   SinkMBB->transferSuccessorsAndUpdatePHIs(MBB); | 
 |  | 
 |   // Add the true and fallthrough blocks as its successors. | 
 |   if (CascadedCMOV) { | 
 |     // The fallthrough block may be Jcc1MBB, if we have a cascaded CMOV. | 
 |     MBB->addSuccessor(Jcc1MBB); | 
 |  | 
 |     // In that case, Jcc1MBB will itself fallthrough the Copy0MBB, and | 
 |     // jump to the SinkMBB. | 
 |     Jcc1MBB->addSuccessor(Copy0MBB); | 
 |     Jcc1MBB->addSuccessor(SinkMBB); | 
 |   } else { | 
 |     MBB->addSuccessor(Copy0MBB); | 
 |   } | 
 |  | 
 |   // The true block target of the first (or only) branch is always SinkMBB. | 
 |   MBB->addSuccessor(SinkMBB); | 
 |  | 
 |   // Create the conditional branch instruction. | 
 |   unsigned Opc = M68k::GetCondBranchFromCond(CC); | 
 |   BuildMI(MBB, DL, TII->get(Opc)).addMBB(SinkMBB); | 
 |  | 
 |   if (CascadedCMOV) { | 
 |     unsigned Opc2 = M68k::GetCondBranchFromCond( | 
 |         (M68k::CondCode)CascadedCMOV->getOperand(3).getImm()); | 
 |     BuildMI(Jcc1MBB, DL, TII->get(Opc2)).addMBB(SinkMBB); | 
 |   } | 
 |  | 
 |   //  Copy0MBB: | 
 |   //   %FalseValue = ... | 
 |   //   # fallthrough to SinkMBB | 
 |   Copy0MBB->addSuccessor(SinkMBB); | 
 |  | 
 |   //  SinkMBB: | 
 |   //   %Result = phi [ %FalseValue, Copy0MBB ], [ %TrueValue, ThisMBB ] | 
 |   //  ... | 
 |   MachineBasicBlock::iterator MIItBegin = MachineBasicBlock::iterator(MI); | 
 |   MachineBasicBlock::iterator MIItEnd = | 
 |       std::next(MachineBasicBlock::iterator(LastCMOV)); | 
 |   MachineBasicBlock::iterator SinkInsertionPoint = SinkMBB->begin(); | 
 |   DenseMap<unsigned, std::pair<unsigned, unsigned>> RegRewriteTable; | 
 |   MachineInstrBuilder MIB; | 
 |  | 
 |   // As we are creating the PHIs, we have to be careful if there is more than | 
 |   // one.  Later CMOVs may reference the results of earlier CMOVs, but later | 
 |   // PHIs have to reference the individual true/false inputs from earlier PHIs. | 
 |   // That also means that PHI construction must work forward from earlier to | 
 |   // later, and that the code must maintain a mapping from earlier PHI's | 
 |   // destination registers, and the registers that went into the PHI. | 
 |  | 
 |   for (MachineBasicBlock::iterator MIIt = MIItBegin; MIIt != MIItEnd; ++MIIt) { | 
 |     Register DestReg = MIIt->getOperand(0).getReg(); | 
 |     Register Op1Reg = MIIt->getOperand(1).getReg(); | 
 |     Register Op2Reg = MIIt->getOperand(2).getReg(); | 
 |  | 
 |     // If this CMOV we are generating is the opposite condition from | 
 |     // the jump we generated, then we have to swap the operands for the | 
 |     // PHI that is going to be generated. | 
 |     if (MIIt->getOperand(3).getImm() == OppCC) | 
 |       std::swap(Op1Reg, Op2Reg); | 
 |  | 
 |     if (RegRewriteTable.find(Op1Reg) != RegRewriteTable.end()) | 
 |       Op1Reg = RegRewriteTable[Op1Reg].first; | 
 |  | 
 |     if (RegRewriteTable.find(Op2Reg) != RegRewriteTable.end()) | 
 |       Op2Reg = RegRewriteTable[Op2Reg].second; | 
 |  | 
 |     MIB = | 
 |         BuildMI(*SinkMBB, SinkInsertionPoint, DL, TII->get(M68k::PHI), DestReg) | 
 |             .addReg(Op1Reg) | 
 |             .addMBB(Copy0MBB) | 
 |             .addReg(Op2Reg) | 
 |             .addMBB(ThisMBB); | 
 |  | 
 |     // Add this PHI to the rewrite table. | 
 |     RegRewriteTable[DestReg] = std::make_pair(Op1Reg, Op2Reg); | 
 |   } | 
 |  | 
 |   // If we have a cascaded CMOV, the second Jcc provides the same incoming | 
 |   // value as the first Jcc (the True operand of the SELECT_CC/CMOV nodes). | 
 |   if (CascadedCMOV) { | 
 |     MIB.addReg(MI.getOperand(2).getReg()).addMBB(Jcc1MBB); | 
 |     // Copy the PHI result to the register defined by the second CMOV. | 
 |     BuildMI(*SinkMBB, std::next(MachineBasicBlock::iterator(MIB.getInstr())), | 
 |             DL, TII->get(TargetOpcode::COPY), | 
 |             CascadedCMOV->getOperand(0).getReg()) | 
 |         .addReg(MI.getOperand(0).getReg()); | 
 |     CascadedCMOV->eraseFromParent(); | 
 |   } | 
 |  | 
 |   // Now remove the CMOV(s). | 
 |   for (MachineBasicBlock::iterator MIIt = MIItBegin; MIIt != MIItEnd;) | 
 |     (MIIt++)->eraseFromParent(); | 
 |  | 
 |   return SinkMBB; | 
 | } | 
 |  | 
 | MachineBasicBlock * | 
 | M68kTargetLowering::EmitLoweredSegAlloca(MachineInstr &MI, | 
 |                                          MachineBasicBlock *BB) const { | 
 |   llvm_unreachable("Cannot lower Segmented Stack Alloca with stack-split on"); | 
 | } | 
 |  | 
 | MachineBasicBlock * | 
 | M68kTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, | 
 |                                                 MachineBasicBlock *BB) const { | 
 |   switch (MI.getOpcode()) { | 
 |   default: | 
 |     llvm_unreachable("Unexpected instr type to insert"); | 
 |   case M68k::CMOV8d: | 
 |   case M68k::CMOV16d: | 
 |   case M68k::CMOV32r: | 
 |     return EmitLoweredSelect(MI, BB); | 
 |   case M68k::SALLOCA: | 
 |     return EmitLoweredSegAlloca(MI, BB); | 
 |   } | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { | 
 |   MachineFunction &MF = DAG.getMachineFunction(); | 
 |   auto PtrVT = getPointerTy(MF.getDataLayout()); | 
 |   M68kMachineFunctionInfo *FuncInfo = MF.getInfo<M68kMachineFunctionInfo>(); | 
 |  | 
 |   const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); | 
 |   SDLoc DL(Op); | 
 |  | 
 |   // vastart just stores the address of the VarArgsFrameIndex slot into the | 
 |   // memory location argument. | 
 |   SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT); | 
 |   return DAG.getStore(Op.getOperand(0), DL, FR, Op.getOperand(1), | 
 |                       MachinePointerInfo(SV)); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerATOMICFENCE(SDValue Op, | 
 |                                              SelectionDAG &DAG) const { | 
 |   // Lower to a memory barrier created from inline asm. | 
 |   const TargetLowering &TLI = DAG.getTargetLoweringInfo(); | 
 |   LLVMContext &Ctx = *DAG.getContext(); | 
 |  | 
 |   const unsigned Flags = InlineAsm::Extra_MayLoad | InlineAsm::Extra_MayStore | | 
 |                          InlineAsm::Extra_HasSideEffects; | 
 |   const SDValue AsmOperands[4] = { | 
 |       Op.getOperand(0), // Input chain | 
 |       DAG.getTargetExternalSymbol( | 
 |           "", TLI.getProgramPointerTy( | 
 |                   DAG.getDataLayout())),   // Empty inline asm string | 
 |       DAG.getMDNode(MDNode::get(Ctx, {})), // (empty) srcloc | 
 |       DAG.getTargetConstant(Flags, SDLoc(Op), | 
 |                             TLI.getPointerTy(DAG.getDataLayout())), // Flags | 
 |   }; | 
 |  | 
 |   return DAG.getNode(ISD::INLINEASM, SDLoc(Op), | 
 |                      DAG.getVTList(MVT::Other, MVT::Glue), AsmOperands); | 
 | } | 
 |  | 
 | // Lower dynamic stack allocation to _alloca call for Cygwin/Mingw targets. | 
 | // Calls to _alloca are needed to probe the stack when allocating more than 4k | 
 | // bytes in one go. Touching the stack at 4K increments is necessary to ensure | 
 | // that the guard pages used by the OS virtual memory manager are allocated in | 
 | // correct sequence. | 
 | SDValue M68kTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, | 
 |                                                     SelectionDAG &DAG) const { | 
 |   MachineFunction &MF = DAG.getMachineFunction(); | 
 |   bool SplitStack = MF.shouldSplitStack(); | 
 |  | 
 |   SDLoc DL(Op); | 
 |  | 
 |   // Get the inputs. | 
 |   SDNode *Node = Op.getNode(); | 
 |   SDValue Chain = Op.getOperand(0); | 
 |   SDValue Size = Op.getOperand(1); | 
 |   unsigned Align = Op.getConstantOperandVal(2); | 
 |   EVT VT = Node->getValueType(0); | 
 |  | 
 |   // Chain the dynamic stack allocation so that it doesn't modify the stack | 
 |   // pointer when other instructions are using the stack. | 
 |   Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL); | 
 |  | 
 |   SDValue Result; | 
 |   if (SplitStack) { | 
 |     auto &MRI = MF.getRegInfo(); | 
 |     auto SPTy = getPointerTy(DAG.getDataLayout()); | 
 |     auto *ARClass = getRegClassFor(SPTy); | 
 |     Register Vreg = MRI.createVirtualRegister(ARClass); | 
 |     Chain = DAG.getCopyToReg(Chain, DL, Vreg, Size); | 
 |     Result = DAG.getNode(M68kISD::SEG_ALLOCA, DL, SPTy, Chain, | 
 |                          DAG.getRegister(Vreg, SPTy)); | 
 |   } else { | 
 |     auto &TLI = DAG.getTargetLoweringInfo(); | 
 |     Register SPReg = TLI.getStackPointerRegisterToSaveRestore(); | 
 |     assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and" | 
 |                     " not tell us which reg is the stack pointer!"); | 
 |  | 
 |     SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT); | 
 |     Chain = SP.getValue(1); | 
 |     const TargetFrameLowering &TFI = *Subtarget.getFrameLowering(); | 
 |     unsigned StackAlign = TFI.getStackAlignment(); | 
 |     Result = DAG.getNode(ISD::SUB, DL, VT, SP, Size); // Value | 
 |     if (Align > StackAlign) | 
 |       Result = DAG.getNode(ISD::AND, DL, VT, Result, | 
 |                            DAG.getSignedConstant(-(uint64_t)Align, DL, VT)); | 
 |     Chain = DAG.getCopyToReg(Chain, DL, SPReg, Result); // Output chain | 
 |   } | 
 |  | 
 |   Chain = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), DL); | 
 |  | 
 |   SDValue Ops[2] = {Result, Chain}; | 
 |   return DAG.getMergeValues(Ops, DL); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerShiftLeftParts(SDValue Op, | 
 |                                                 SelectionDAG &DAG) const { | 
 |   SDLoc DL(Op); | 
 |   SDValue Lo = Op.getOperand(0); | 
 |   SDValue Hi = Op.getOperand(1); | 
 |   SDValue Shamt = Op.getOperand(2); | 
 |   EVT VT = Lo.getValueType(); | 
 |  | 
 |   // if Shamt - register size < 0: // Shamt < register size | 
 |   //   Lo = Lo << Shamt | 
 |   //   Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (register size - 1 ^ Shamt)) | 
 |   // else: | 
 |   //   Lo = 0 | 
 |   //   Hi = Lo << (Shamt - register size) | 
 |  | 
 |   SDValue Zero = DAG.getConstant(0, DL, VT); | 
 |   SDValue One = DAG.getConstant(1, DL, VT); | 
 |   SDValue MinusRegisterSize = DAG.getSignedConstant(-32, DL, VT); | 
 |   SDValue RegisterSizeMinus1 = DAG.getConstant(32 - 1, DL, VT); | 
 |   SDValue ShamtMinusRegisterSize = | 
 |       DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusRegisterSize); | 
 |   SDValue RegisterSizeMinus1Shamt = | 
 |       DAG.getNode(ISD::XOR, DL, VT, RegisterSizeMinus1, Shamt); | 
 |  | 
 |   SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); | 
 |   SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One); | 
 |   SDValue ShiftRightLo = | 
 |       DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, RegisterSizeMinus1Shamt); | 
 |   SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); | 
 |   SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); | 
 |   SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusRegisterSize); | 
 |  | 
 |   SDValue CC = | 
 |       DAG.getSetCC(DL, MVT::i8, ShamtMinusRegisterSize, Zero, ISD::SETLT); | 
 |  | 
 |   Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero); | 
 |   Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); | 
 |  | 
 |   return DAG.getMergeValues({Lo, Hi}, DL); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::LowerShiftRightParts(SDValue Op, SelectionDAG &DAG, | 
 |                                                  bool IsSRA) const { | 
 |   SDLoc DL(Op); | 
 |   SDValue Lo = Op.getOperand(0); | 
 |   SDValue Hi = Op.getOperand(1); | 
 |   SDValue Shamt = Op.getOperand(2); | 
 |   EVT VT = Lo.getValueType(); | 
 |  | 
 |   // SRA expansion: | 
 |   //   if Shamt - register size < 0: // Shamt < register size | 
 |   //     Lo = (Lo >>u Shamt) | ((Hi << 1) << (register size - 1 ^ Shamt)) | 
 |   //     Hi = Hi >>s Shamt | 
 |   //   else: | 
 |   //     Lo = Hi >>s (Shamt - register size); | 
 |   //     Hi = Hi >>s (register size - 1) | 
 |   // | 
 |   // SRL expansion: | 
 |   //   if Shamt - register size < 0: // Shamt < register size | 
 |   //     Lo = (Lo >>u Shamt) | ((Hi << 1) << (register size - 1 ^ Shamt)) | 
 |   //     Hi = Hi >>u Shamt | 
 |   //   else: | 
 |   //     Lo = Hi >>u (Shamt - register size); | 
 |   //     Hi = 0; | 
 |  | 
 |   unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL; | 
 |  | 
 |   SDValue Zero = DAG.getConstant(0, DL, VT); | 
 |   SDValue One = DAG.getConstant(1, DL, VT); | 
 |   SDValue MinusRegisterSize = DAG.getSignedConstant(-32, DL, VT); | 
 |   SDValue RegisterSizeMinus1 = DAG.getConstant(32 - 1, DL, VT); | 
 |   SDValue ShamtMinusRegisterSize = | 
 |       DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusRegisterSize); | 
 |   SDValue RegisterSizeMinus1Shamt = | 
 |       DAG.getNode(ISD::XOR, DL, VT, RegisterSizeMinus1, Shamt); | 
 |  | 
 |   SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); | 
 |   SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One); | 
 |   SDValue ShiftLeftHi = | 
 |       DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, RegisterSizeMinus1Shamt); | 
 |   SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi); | 
 |   SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt); | 
 |   SDValue LoFalse = | 
 |       DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusRegisterSize); | 
 |   SDValue HiFalse = | 
 |       IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, RegisterSizeMinus1) : Zero; | 
 |  | 
 |   SDValue CC = | 
 |       DAG.getSetCC(DL, MVT::i8, ShamtMinusRegisterSize, Zero, ISD::SETLT); | 
 |  | 
 |   Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse); | 
 |   Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); | 
 |  | 
 |   return DAG.getMergeValues({Lo, Hi}, DL); | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // DAG Combine | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | static SDValue getSETCC(M68k::CondCode Cond, SDValue CCR, const SDLoc &dl, | 
 |                         SelectionDAG &DAG) { | 
 |   return DAG.getNode(M68kISD::SETCC, dl, MVT::i8, | 
 |                      DAG.getConstant(Cond, dl, MVT::i8), CCR); | 
 | } | 
 | // When legalizing carry, we create carries via add X, -1 | 
 | // If that comes from an actual carry, via setcc, we use the | 
 | // carry directly. | 
 | static SDValue combineCarryThroughADD(SDValue CCR) { | 
 |   if (CCR.getOpcode() == M68kISD::ADD) { | 
 |     if (isAllOnesConstant(CCR.getOperand(1))) { | 
 |       SDValue Carry = CCR.getOperand(0); | 
 |       while (Carry.getOpcode() == ISD::TRUNCATE || | 
 |              Carry.getOpcode() == ISD::ZERO_EXTEND || | 
 |              Carry.getOpcode() == ISD::SIGN_EXTEND || | 
 |              Carry.getOpcode() == ISD::ANY_EXTEND || | 
 |              (Carry.getOpcode() == ISD::AND && | 
 |               isOneConstant(Carry.getOperand(1)))) | 
 |         Carry = Carry.getOperand(0); | 
 |       if (Carry.getOpcode() == M68kISD::SETCC || | 
 |           Carry.getOpcode() == M68kISD::SETCC_CARRY) { | 
 |         if (Carry.getConstantOperandVal(0) == M68k::COND_CS) | 
 |           return Carry.getOperand(1); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   return SDValue(); | 
 | } | 
 |  | 
 | /// Optimize a CCR definition used according to the condition code \p CC into | 
 | /// a simpler CCR value, potentially returning a new \p CC and replacing uses | 
 | /// of chain values. | 
 | static SDValue combineSetCCCCR(SDValue CCR, M68k::CondCode &CC, | 
 |                                SelectionDAG &DAG, | 
 |                                const M68kSubtarget &Subtarget) { | 
 |   if (CC == M68k::COND_CS) | 
 |     if (SDValue Flags = combineCarryThroughADD(CCR)) | 
 |       return Flags; | 
 |  | 
 |   return SDValue(); | 
 | } | 
 |  | 
 | // Optimize  RES = M68kISD::SETCC CONDCODE, CCR_INPUT | 
 | static SDValue combineM68kSetCC(SDNode *N, SelectionDAG &DAG, | 
 |                                 const M68kSubtarget &Subtarget) { | 
 |   SDLoc DL(N); | 
 |   M68k::CondCode CC = M68k::CondCode(N->getConstantOperandVal(0)); | 
 |   SDValue CCR = N->getOperand(1); | 
 |  | 
 |   // Try to simplify the CCR and condition code operands. | 
 |   if (SDValue Flags = combineSetCCCCR(CCR, CC, DAG, Subtarget)) | 
 |     return getSETCC(CC, Flags, DL, DAG); | 
 |  | 
 |   return SDValue(); | 
 | } | 
 | static SDValue combineM68kBrCond(SDNode *N, SelectionDAG &DAG, | 
 |                                  const M68kSubtarget &Subtarget) { | 
 |   SDLoc DL(N); | 
 |   M68k::CondCode CC = M68k::CondCode(N->getConstantOperandVal(2)); | 
 |   SDValue CCR = N->getOperand(3); | 
 |  | 
 |   // Try to simplify the CCR and condition code operands. | 
 |   // Make sure to not keep references to operands, as combineSetCCCCR can | 
 |   // RAUW them under us. | 
 |   if (SDValue Flags = combineSetCCCCR(CCR, CC, DAG, Subtarget)) { | 
 |     SDValue Cond = DAG.getConstant(CC, DL, MVT::i8); | 
 |     return DAG.getNode(M68kISD::BRCOND, DL, N->getVTList(), N->getOperand(0), | 
 |                        N->getOperand(1), Cond, Flags); | 
 |   } | 
 |  | 
 |   return SDValue(); | 
 | } | 
 |  | 
 | static SDValue combineSUBX(SDNode *N, SelectionDAG &DAG) { | 
 |   if (SDValue Flags = combineCarryThroughADD(N->getOperand(2))) { | 
 |     MVT VT = N->getSimpleValueType(0); | 
 |     SDVTList VTs = DAG.getVTList(VT, MVT::i32); | 
 |     return DAG.getNode(M68kISD::SUBX, SDLoc(N), VTs, N->getOperand(0), | 
 |                        N->getOperand(1), Flags); | 
 |   } | 
 |  | 
 |   return SDValue(); | 
 | } | 
 |  | 
 | // Optimize RES, CCR = M68kISD::ADDX LHS, RHS, CCR | 
 | static SDValue combineADDX(SDNode *N, SelectionDAG &DAG, | 
 |                            TargetLowering::DAGCombinerInfo &DCI) { | 
 |   if (SDValue Flags = combineCarryThroughADD(N->getOperand(2))) { | 
 |     MVT VT = N->getSimpleValueType(0); | 
 |     SDVTList VTs = DAG.getVTList(VT, MVT::i32); | 
 |     return DAG.getNode(M68kISD::ADDX, SDLoc(N), VTs, N->getOperand(0), | 
 |                        N->getOperand(1), Flags); | 
 |   } | 
 |  | 
 |   return SDValue(); | 
 | } | 
 |  | 
 | SDValue M68kTargetLowering::PerformDAGCombine(SDNode *N, | 
 |                                               DAGCombinerInfo &DCI) const { | 
 |   SelectionDAG &DAG = DCI.DAG; | 
 |   switch (N->getOpcode()) { | 
 |   case M68kISD::SUBX: | 
 |     return combineSUBX(N, DAG); | 
 |   case M68kISD::ADDX: | 
 |     return combineADDX(N, DAG, DCI); | 
 |   case M68kISD::SETCC: | 
 |     return combineM68kSetCC(N, DAG, Subtarget); | 
 |   case M68kISD::BRCOND: | 
 |     return combineM68kBrCond(N, DAG, Subtarget); | 
 |   } | 
 |  | 
 |   return SDValue(); | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // M68kISD Node Names | 
 | //===----------------------------------------------------------------------===// | 
 | const char *M68kTargetLowering::getTargetNodeName(unsigned Opcode) const { | 
 |   switch (Opcode) { | 
 |   case M68kISD::CALL: | 
 |     return "M68kISD::CALL"; | 
 |   case M68kISD::TAIL_CALL: | 
 |     return "M68kISD::TAIL_CALL"; | 
 |   case M68kISD::RET: | 
 |     return "M68kISD::RET"; | 
 |   case M68kISD::TC_RETURN: | 
 |     return "M68kISD::TC_RETURN"; | 
 |   case M68kISD::ADD: | 
 |     return "M68kISD::ADD"; | 
 |   case M68kISD::SUB: | 
 |     return "M68kISD::SUB"; | 
 |   case M68kISD::ADDX: | 
 |     return "M68kISD::ADDX"; | 
 |   case M68kISD::SUBX: | 
 |     return "M68kISD::SUBX"; | 
 |   case M68kISD::SMUL: | 
 |     return "M68kISD::SMUL"; | 
 |   case M68kISD::UMUL: | 
 |     return "M68kISD::UMUL"; | 
 |   case M68kISD::OR: | 
 |     return "M68kISD::OR"; | 
 |   case M68kISD::XOR: | 
 |     return "M68kISD::XOR"; | 
 |   case M68kISD::AND: | 
 |     return "M68kISD::AND"; | 
 |   case M68kISD::CMP: | 
 |     return "M68kISD::CMP"; | 
 |   case M68kISD::BTST: | 
 |     return "M68kISD::BTST"; | 
 |   case M68kISD::SELECT: | 
 |     return "M68kISD::SELECT"; | 
 |   case M68kISD::CMOV: | 
 |     return "M68kISD::CMOV"; | 
 |   case M68kISD::BRCOND: | 
 |     return "M68kISD::BRCOND"; | 
 |   case M68kISD::SETCC: | 
 |     return "M68kISD::SETCC"; | 
 |   case M68kISD::SETCC_CARRY: | 
 |     return "M68kISD::SETCC_CARRY"; | 
 |   case M68kISD::GLOBAL_BASE_REG: | 
 |     return "M68kISD::GLOBAL_BASE_REG"; | 
 |   case M68kISD::Wrapper: | 
 |     return "M68kISD::Wrapper"; | 
 |   case M68kISD::WrapperPC: | 
 |     return "M68kISD::WrapperPC"; | 
 |   case M68kISD::SEG_ALLOCA: | 
 |     return "M68kISD::SEG_ALLOCA"; | 
 |   default: | 
 |     return NULL; | 
 |   } | 
 | } | 
 |  | 
 | CCAssignFn *M68kTargetLowering::getCCAssignFn(CallingConv::ID CC, bool Return, | 
 |                                               bool IsVarArg) const { | 
 |   if (Return) | 
 |     return RetCC_M68k_C; | 
 |   else | 
 |     return CC_M68k_C; | 
 | } |