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