Path: blob/main/contrib/llvm-project/llvm/lib/Target/M68k/M68kISelLowering.cpp
35294 views
//===-- M68kISelLowering.cpp - M68k DAG Lowering Impl -----------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file defines the interfaces that M68k uses to lower LLVM code into a10/// selection DAG.11///12//===----------------------------------------------------------------------===//1314#include "M68kISelLowering.h"15#include "M68kCallingConv.h"16#include "M68kMachineFunction.h"17#include "M68kSubtarget.h"18#include "M68kTargetMachine.h"19#include "M68kTargetObjectFile.h"2021#include "llvm/ADT/Statistic.h"22#include "llvm/CodeGen/CallingConvLower.h"23#include "llvm/CodeGen/MachineFrameInfo.h"24#include "llvm/CodeGen/MachineFunction.h"25#include "llvm/CodeGen/MachineInstrBuilder.h"26#include "llvm/CodeGen/MachineJumpTableInfo.h"27#include "llvm/CodeGen/MachineRegisterInfo.h"28#include "llvm/CodeGen/SelectionDAG.h"29#include "llvm/CodeGen/ValueTypes.h"30#include "llvm/IR/CallingConv.h"31#include "llvm/IR/DerivedTypes.h"32#include "llvm/IR/GlobalVariable.h"33#include "llvm/Support/CommandLine.h"34#include "llvm/Support/Debug.h"35#include "llvm/Support/ErrorHandling.h"36#include "llvm/Support/KnownBits.h"37#include "llvm/Support/raw_ostream.h"3839using namespace llvm;4041#define DEBUG_TYPE "M68k-isel"4243STATISTIC(NumTailCalls, "Number of tail calls");4445M68kTargetLowering::M68kTargetLowering(const M68kTargetMachine &TM,46const M68kSubtarget &STI)47: TargetLowering(TM), Subtarget(STI), TM(TM) {4849MVT PtrVT = MVT::i32;5051setBooleanContents(ZeroOrOneBooleanContent);5253auto *RegInfo = Subtarget.getRegisterInfo();54setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());5556// Set up the register classes.57addRegisterClass(MVT::i8, &M68k::DR8RegClass);58addRegisterClass(MVT::i16, &M68k::XR16RegClass);59addRegisterClass(MVT::i32, &M68k::XR32RegClass);6061for (auto VT : MVT::integer_valuetypes()) {62setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);63setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);64setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);65}6667// We don't accept any truncstore of integer registers.68setTruncStoreAction(MVT::i64, MVT::i32, Expand);69setTruncStoreAction(MVT::i64, MVT::i16, Expand);70setTruncStoreAction(MVT::i64, MVT::i8, Expand);71setTruncStoreAction(MVT::i32, MVT::i16, Expand);72setTruncStoreAction(MVT::i32, MVT::i8, Expand);73setTruncStoreAction(MVT::i16, MVT::i8, Expand);7475setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i8, Promote);76setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i16, Legal);77if (Subtarget.atLeastM68020())78setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i32, Legal);79else80setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i32, LibCall);81setOperationAction(ISD::MUL, MVT::i64, LibCall);8283for (auto OP :84{ISD::SREM, ISD::UREM, ISD::UDIVREM, ISD::SDIVREM,85ISD::MULHS, ISD::MULHU, ISD::UMUL_LOHI, ISD::SMUL_LOHI}) {86setOperationAction(OP, MVT::i8, Promote);87setOperationAction(OP, MVT::i16, Legal);88setOperationAction(OP, MVT::i32, LibCall);89}9091for (auto OP : {ISD::UMUL_LOHI, ISD::SMUL_LOHI}) {92setOperationAction(OP, MVT::i8, Expand);93setOperationAction(OP, MVT::i16, Expand);94}9596for (auto OP : {ISD::SMULO, ISD::UMULO}) {97setOperationAction(OP, MVT::i8, Custom);98setOperationAction(OP, MVT::i16, Custom);99setOperationAction(OP, MVT::i32, Custom);100}101102for (auto OP : {ISD::SHL_PARTS, ISD::SRA_PARTS, ISD::SRL_PARTS})103setOperationAction(OP, MVT::i32, Custom);104105// Add/Sub overflow ops with MVT::Glues are lowered to CCR dependences.106for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {107setOperationAction(ISD::ADDC, VT, Custom);108setOperationAction(ISD::ADDE, VT, Custom);109setOperationAction(ISD::SUBC, VT, Custom);110setOperationAction(ISD::SUBE, VT, Custom);111}112113// SADDO and friends are legal with this setup, i hope114for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {115setOperationAction(ISD::SADDO, VT, Custom);116setOperationAction(ISD::UADDO, VT, Custom);117setOperationAction(ISD::SSUBO, VT, Custom);118setOperationAction(ISD::USUBO, VT, Custom);119}120121setOperationAction(ISD::BR_JT, MVT::Other, Expand);122setOperationAction(ISD::BRCOND, MVT::Other, Custom);123124for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {125setOperationAction(ISD::BR_CC, VT, Expand);126setOperationAction(ISD::SELECT, VT, Custom);127setOperationAction(ISD::SELECT_CC, VT, Expand);128setOperationAction(ISD::SETCC, VT, Custom);129setOperationAction(ISD::SETCCCARRY, VT, Custom);130}131132for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {133setOperationAction(ISD::BSWAP, VT, Expand);134setOperationAction(ISD::CTTZ, VT, Expand);135setOperationAction(ISD::CTLZ, VT, Expand);136setOperationAction(ISD::CTPOP, VT, Expand);137}138139setOperationAction(ISD::ConstantPool, MVT::i32, Custom);140setOperationAction(ISD::JumpTable, MVT::i32, Custom);141setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);142setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);143setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);144setOperationAction(ISD::BlockAddress, MVT::i32, Custom);145146setOperationAction(ISD::VASTART, MVT::Other, Custom);147setOperationAction(ISD::VAEND, MVT::Other, Expand);148setOperationAction(ISD::VAARG, MVT::Other, Expand);149setOperationAction(ISD::VACOPY, MVT::Other, Expand);150151setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);152setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);153154setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom);155156computeRegisterProperties(STI.getRegisterInfo());157158// We lower the `atomic-compare-and-swap` to `__sync_val_compare_and_swap`159// for subtarget < M68020160setMaxAtomicSizeInBitsSupported(32);161setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i8, MVT::i16, MVT::i32},162Subtarget.atLeastM68020() ? Legal : LibCall);163164setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);165166// M68k does not have native read-modify-write support, so expand all of them167// to `__sync_fetch_*` for target < M68020, otherwise expand to CmpxChg.168// See `shouldExpandAtomicRMWInIR` below.169setOperationAction(170{171ISD::ATOMIC_LOAD_ADD,172ISD::ATOMIC_LOAD_SUB,173ISD::ATOMIC_LOAD_AND,174ISD::ATOMIC_LOAD_OR,175ISD::ATOMIC_LOAD_XOR,176ISD::ATOMIC_LOAD_NAND,177ISD::ATOMIC_LOAD_MIN,178ISD::ATOMIC_LOAD_MAX,179ISD::ATOMIC_LOAD_UMIN,180ISD::ATOMIC_LOAD_UMAX,181ISD::ATOMIC_SWAP,182},183{MVT::i8, MVT::i16, MVT::i32}, LibCall);184185setMinFunctionAlignment(Align(2));186}187188TargetLoweringBase::AtomicExpansionKind189M68kTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const {190return Subtarget.atLeastM68020()191? TargetLoweringBase::AtomicExpansionKind::CmpXChg192: TargetLoweringBase::AtomicExpansionKind::None;193}194195Register196M68kTargetLowering::getExceptionPointerRegister(const Constant *) const {197return M68k::D0;198}199200Register201M68kTargetLowering::getExceptionSelectorRegister(const Constant *) const {202return M68k::D1;203}204205InlineAsm::ConstraintCode206M68kTargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const {207return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)208.Case("Q", InlineAsm::ConstraintCode::Q)209// We borrow ConstraintCode::Um for 'U'.210.Case("U", InlineAsm::ConstraintCode::Um)211.Default(TargetLowering::getInlineAsmMemConstraint(ConstraintCode));212}213214EVT M68kTargetLowering::getSetCCResultType(const DataLayout &DL,215LLVMContext &Context, EVT VT) const {216// M68k SETcc producess either 0x00 or 0xFF217return MVT::i8;218}219220MVT M68kTargetLowering::getScalarShiftAmountTy(const DataLayout &DL,221EVT Ty) const {222if (Ty.isSimple()) {223return Ty.getSimpleVT();224}225return MVT::getIntegerVT(DL.getPointerSizeInBits(0));226}227228#include "M68kGenCallingConv.inc"229230enum StructReturnType { NotStructReturn, RegStructReturn, StackStructReturn };231232static StructReturnType233callIsStructReturn(const SmallVectorImpl<ISD::OutputArg> &Outs) {234if (Outs.empty())235return NotStructReturn;236237const ISD::ArgFlagsTy &Flags = Outs[0].Flags;238if (!Flags.isSRet())239return NotStructReturn;240if (Flags.isInReg())241return RegStructReturn;242return StackStructReturn;243}244245/// Determines whether a function uses struct return semantics.246static StructReturnType247argsAreStructReturn(const SmallVectorImpl<ISD::InputArg> &Ins) {248if (Ins.empty())249return NotStructReturn;250251const ISD::ArgFlagsTy &Flags = Ins[0].Flags;252if (!Flags.isSRet())253return NotStructReturn;254if (Flags.isInReg())255return RegStructReturn;256return StackStructReturn;257}258259/// Make a copy of an aggregate at address specified by "Src" to address260/// "Dst" with size and alignment information specified by the specific261/// parameter attribute. The copy will be passed as a byval function parameter.262static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst,263SDValue Chain, ISD::ArgFlagsTy Flags,264SelectionDAG &DAG, const SDLoc &DL) {265SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), DL, MVT::i32);266267return DAG.getMemcpy(268Chain, DL, Dst, Src, SizeNode, Flags.getNonZeroByValAlign(),269/*isVolatile=*/false, /*AlwaysInline=*/true,270/*CI=*/nullptr, std::nullopt, MachinePointerInfo(), MachinePointerInfo());271}272273/// Return true if the calling convention is one that we can guarantee TCO for.274static bool canGuaranteeTCO(CallingConv::ID CC) { return false; }275276/// Return true if we might ever do TCO for calls with this calling convention.277static bool mayTailCallThisCC(CallingConv::ID CC) {278switch (CC) {279// C calling conventions:280case CallingConv::C:281return true;282default:283return canGuaranteeTCO(CC);284}285}286287/// Return true if the function is being made into a tailcall target by288/// changing its ABI.289static bool shouldGuaranteeTCO(CallingConv::ID CC, bool GuaranteedTailCallOpt) {290return GuaranteedTailCallOpt && canGuaranteeTCO(CC);291}292293/// Return true if the given stack call argument is already available in the294/// same position (relatively) of the caller's incoming argument stack.295static bool MatchingStackOffset(SDValue Arg, unsigned Offset,296ISD::ArgFlagsTy Flags, MachineFrameInfo &MFI,297const MachineRegisterInfo *MRI,298const M68kInstrInfo *TII,299const CCValAssign &VA) {300unsigned Bytes = Arg.getValueType().getSizeInBits() / 8;301302for (;;) {303// Look through nodes that don't alter the bits of the incoming value.304unsigned Op = Arg.getOpcode();305if (Op == ISD::ZERO_EXTEND || Op == ISD::ANY_EXTEND || Op == ISD::BITCAST) {306Arg = Arg.getOperand(0);307continue;308}309if (Op == ISD::TRUNCATE) {310const SDValue &TruncInput = Arg.getOperand(0);311if (TruncInput.getOpcode() == ISD::AssertZext &&312cast<VTSDNode>(TruncInput.getOperand(1))->getVT() ==313Arg.getValueType()) {314Arg = TruncInput.getOperand(0);315continue;316}317}318break;319}320321int FI = INT_MAX;322if (Arg.getOpcode() == ISD::CopyFromReg) {323Register VR = cast<RegisterSDNode>(Arg.getOperand(1))->getReg();324if (!Register::isVirtualRegister(VR))325return false;326MachineInstr *Def = MRI->getVRegDef(VR);327if (!Def)328return false;329if (!Flags.isByVal()) {330if (!TII->isLoadFromStackSlot(*Def, FI))331return false;332} else {333unsigned Opcode = Def->getOpcode();334if ((Opcode == M68k::LEA32p || Opcode == M68k::LEA32f) &&335Def->getOperand(1).isFI()) {336FI = Def->getOperand(1).getIndex();337Bytes = Flags.getByValSize();338} else339return false;340}341} else if (auto *Ld = dyn_cast<LoadSDNode>(Arg)) {342if (Flags.isByVal())343// ByVal argument is passed in as a pointer but it's now being344// dereferenced. e.g.345// define @foo(%struct.X* %A) {346// tail call @bar(%struct.X* byval %A)347// }348return false;349SDValue Ptr = Ld->getBasePtr();350FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(Ptr);351if (!FINode)352return false;353FI = FINode->getIndex();354} else if (Arg.getOpcode() == ISD::FrameIndex && Flags.isByVal()) {355FrameIndexSDNode *FINode = cast<FrameIndexSDNode>(Arg);356FI = FINode->getIndex();357Bytes = Flags.getByValSize();358} else359return false;360361assert(FI != INT_MAX);362if (!MFI.isFixedObjectIndex(FI))363return false;364365if (Offset != MFI.getObjectOffset(FI))366return false;367368if (VA.getLocVT().getSizeInBits() > Arg.getValueType().getSizeInBits()) {369// If the argument location is wider than the argument type, check that any370// extension flags match.371if (Flags.isZExt() != MFI.isObjectZExt(FI) ||372Flags.isSExt() != MFI.isObjectSExt(FI)) {373return false;374}375}376377return Bytes == MFI.getObjectSize(FI);378}379380SDValue381M68kTargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const {382MachineFunction &MF = DAG.getMachineFunction();383M68kMachineFunctionInfo *FuncInfo = MF.getInfo<M68kMachineFunctionInfo>();384int ReturnAddrIndex = FuncInfo->getRAIndex();385386if (ReturnAddrIndex == 0) {387// Set up a frame object for the return address.388unsigned SlotSize = Subtarget.getSlotSize();389ReturnAddrIndex = MF.getFrameInfo().CreateFixedObject(390SlotSize, -(int64_t)SlotSize, false);391FuncInfo->setRAIndex(ReturnAddrIndex);392}393394return DAG.getFrameIndex(ReturnAddrIndex, getPointerTy(DAG.getDataLayout()));395}396397SDValue M68kTargetLowering::EmitTailCallLoadRetAddr(SelectionDAG &DAG,398SDValue &OutRetAddr,399SDValue Chain,400bool IsTailCall, int FPDiff,401const SDLoc &DL) const {402EVT VT = getPointerTy(DAG.getDataLayout());403OutRetAddr = getReturnAddressFrameIndex(DAG);404405// Load the "old" Return address.406OutRetAddr = DAG.getLoad(VT, DL, Chain, OutRetAddr, MachinePointerInfo());407return SDValue(OutRetAddr.getNode(), 1);408}409410SDValue M68kTargetLowering::EmitTailCallStoreRetAddr(411SelectionDAG &DAG, MachineFunction &MF, SDValue Chain, SDValue RetFI,412EVT PtrVT, unsigned SlotSize, int FPDiff, const SDLoc &DL) const {413if (!FPDiff)414return Chain;415416// Calculate the new stack slot for the return address.417int NewFO = MF.getFrameInfo().CreateFixedObject(418SlotSize, (int64_t)FPDiff - SlotSize, false);419420SDValue NewFI = DAG.getFrameIndex(NewFO, PtrVT);421// Store the return address to the appropriate stack slot.422Chain = DAG.getStore(423Chain, DL, RetFI, NewFI,424MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), NewFO));425return Chain;426}427428SDValue429M68kTargetLowering::LowerMemArgument(SDValue Chain, CallingConv::ID CallConv,430const SmallVectorImpl<ISD::InputArg> &Ins,431const SDLoc &DL, SelectionDAG &DAG,432const CCValAssign &VA,433MachineFrameInfo &MFI,434unsigned ArgIdx) const {435// Create the nodes corresponding to a load from this parameter slot.436ISD::ArgFlagsTy Flags = Ins[ArgIdx].Flags;437EVT ValVT;438439// If value is passed by pointer we have address passed instead of the value440// itself.441if (VA.getLocInfo() == CCValAssign::Indirect)442ValVT = VA.getLocVT();443else444ValVT = VA.getValVT();445446// Because we are dealing with BE architecture we need to offset loading of447// partial types448int Offset = VA.getLocMemOffset();449if (VA.getValVT() == MVT::i8) {450Offset += 3;451} else if (VA.getValVT() == MVT::i16) {452Offset += 2;453}454455// TODO Interrupt handlers456// Calculate SP offset of interrupt parameter, re-arrange the slot normally457// taken by a return address.458459// FIXME For now, all byval parameter objects are marked mutable. This can460// be changed with more analysis. In case of tail call optimization mark all461// arguments mutable. Since they could be overwritten by lowering of arguments462// in case of a tail call.463bool AlwaysUseMutable = shouldGuaranteeTCO(464CallConv, DAG.getTarget().Options.GuaranteedTailCallOpt);465bool IsImmutable = !AlwaysUseMutable && !Flags.isByVal();466467if (Flags.isByVal()) {468unsigned Bytes = Flags.getByValSize();469if (Bytes == 0)470Bytes = 1; // Don't create zero-sized stack objects.471int FI = MFI.CreateFixedObject(Bytes, Offset, IsImmutable);472// TODO Interrupt handlers473// Adjust SP offset of interrupt parameter.474return DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));475} else {476int FI =477MFI.CreateFixedObject(ValVT.getSizeInBits() / 8, Offset, IsImmutable);478479// Set SExt or ZExt flag.480if (VA.getLocInfo() == CCValAssign::ZExt) {481MFI.setObjectZExt(FI, true);482} else if (VA.getLocInfo() == CCValAssign::SExt) {483MFI.setObjectSExt(FI, true);484}485486// TODO Interrupt handlers487// Adjust SP offset of interrupt parameter.488489SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));490SDValue Val = DAG.getLoad(491ValVT, DL, Chain, FIN,492MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI));493return VA.isExtInLoc() ? DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val)494: Val;495}496}497498SDValue M68kTargetLowering::LowerMemOpCallTo(SDValue Chain, SDValue StackPtr,499SDValue Arg, const SDLoc &DL,500SelectionDAG &DAG,501const CCValAssign &VA,502ISD::ArgFlagsTy Flags) const {503unsigned LocMemOffset = VA.getLocMemOffset();504SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset, DL);505PtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()),506StackPtr, PtrOff);507if (Flags.isByVal())508return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG, DL);509510return DAG.getStore(511Chain, DL, Arg, PtrOff,512MachinePointerInfo::getStack(DAG.getMachineFunction(), LocMemOffset));513}514515//===----------------------------------------------------------------------===//516// Call517//===----------------------------------------------------------------------===//518519SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,520SmallVectorImpl<SDValue> &InVals) const {521SelectionDAG &DAG = CLI.DAG;522SDLoc &DL = CLI.DL;523SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;524SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;525SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;526SDValue Chain = CLI.Chain;527SDValue Callee = CLI.Callee;528CallingConv::ID CallConv = CLI.CallConv;529bool &IsTailCall = CLI.IsTailCall;530bool IsVarArg = CLI.IsVarArg;531532MachineFunction &MF = DAG.getMachineFunction();533StructReturnType SR = callIsStructReturn(Outs);534bool IsSibcall = false;535M68kMachineFunctionInfo *MFI = MF.getInfo<M68kMachineFunctionInfo>();536// const M68kRegisterInfo *TRI = Subtarget.getRegisterInfo();537538if (CallConv == CallingConv::M68k_INTR)539report_fatal_error("M68k interrupts may not be called directly");540541auto Attr = MF.getFunction().getFnAttribute("disable-tail-calls");542if (Attr.getValueAsBool())543IsTailCall = false;544545// FIXME Add tailcalls support546547bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();548if (IsMustTail) {549// Force this to be a tail call. The verifier rules are enough to ensure550// that we can lower this successfully without moving the return address551// around.552IsTailCall = true;553} else if (IsTailCall) {554// Check if it's really possible to do a tail call.555IsTailCall = IsEligibleForTailCallOptimization(556Callee, CallConv, IsVarArg, SR != NotStructReturn,557MF.getFunction().hasStructRetAttr(), CLI.RetTy, Outs, OutVals, Ins,558DAG);559560// Sibcalls are automatically detected tailcalls which do not require561// ABI changes.562if (!MF.getTarget().Options.GuaranteedTailCallOpt && IsTailCall)563IsSibcall = true;564565if (IsTailCall)566++NumTailCalls;567}568569assert(!(IsVarArg && canGuaranteeTCO(CallConv)) &&570"Var args not supported with calling convention fastcc");571572// Analyze operands of the call, assigning locations to each operand.573SmallVector<CCValAssign, 16> ArgLocs;574SmallVector<Type *, 4> ArgTypes;575for (const auto &Arg : CLI.getArgs())576ArgTypes.emplace_back(Arg.Ty);577M68kCCState CCInfo(ArgTypes, CallConv, IsVarArg, MF, ArgLocs,578*DAG.getContext());579CCInfo.AnalyzeCallOperands(Outs, CC_M68k);580581// Get a count of how many bytes are to be pushed on the stack.582unsigned NumBytes = CCInfo.getAlignedCallFrameSize();583if (IsSibcall) {584// This is a sibcall. The memory operands are available in caller's585// own caller's stack.586NumBytes = 0;587} else if (MF.getTarget().Options.GuaranteedTailCallOpt &&588canGuaranteeTCO(CallConv)) {589NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG);590}591592int FPDiff = 0;593if (IsTailCall && !IsSibcall && !IsMustTail) {594// Lower arguments at fp - stackoffset + fpdiff.595unsigned NumBytesCallerPushed = MFI->getBytesToPopOnReturn();596597FPDiff = NumBytesCallerPushed - NumBytes;598599// Set the delta of movement of the returnaddr stackslot.600// But only set if delta is greater than previous delta.601if (FPDiff < MFI->getTCReturnAddrDelta())602MFI->setTCReturnAddrDelta(FPDiff);603}604605unsigned NumBytesToPush = NumBytes;606unsigned NumBytesToPop = NumBytes;607608// If we have an inalloca argument, all stack space has already been allocated609// for us and be right at the top of the stack. We don't support multiple610// arguments passed in memory when using inalloca.611if (!Outs.empty() && Outs.back().Flags.isInAlloca()) {612NumBytesToPush = 0;613if (!ArgLocs.back().isMemLoc())614report_fatal_error("cannot use inalloca attribute on a register "615"parameter");616if (ArgLocs.back().getLocMemOffset() != 0)617report_fatal_error("any parameter with the inalloca attribute must be "618"the only memory argument");619}620621if (!IsSibcall)622Chain = DAG.getCALLSEQ_START(Chain, NumBytesToPush,623NumBytes - NumBytesToPush, DL);624625SDValue RetFI;626// Load return address for tail calls.627if (IsTailCall && FPDiff)628Chain = EmitTailCallLoadRetAddr(DAG, RetFI, Chain, IsTailCall, FPDiff, DL);629630SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;631SmallVector<SDValue, 8> MemOpChains;632SDValue StackPtr;633634// Walk the register/memloc assignments, inserting copies/loads. In the case635// of tail call optimization arguments are handle later.636const M68kRegisterInfo *RegInfo = Subtarget.getRegisterInfo();637for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {638ISD::ArgFlagsTy Flags = Outs[i].Flags;639640// Skip inalloca arguments, they have already been written.641if (Flags.isInAlloca())642continue;643644CCValAssign &VA = ArgLocs[i];645EVT RegVT = VA.getLocVT();646SDValue Arg = OutVals[i];647bool IsByVal = Flags.isByVal();648649// Promote the value if needed.650switch (VA.getLocInfo()) {651default:652llvm_unreachable("Unknown loc info!");653case CCValAssign::Full:654break;655case CCValAssign::SExt:656Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, RegVT, Arg);657break;658case CCValAssign::ZExt:659Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, RegVT, Arg);660break;661case CCValAssign::AExt:662Arg = DAG.getNode(ISD::ANY_EXTEND, DL, RegVT, Arg);663break;664case CCValAssign::BCvt:665Arg = DAG.getBitcast(RegVT, Arg);666break;667case CCValAssign::Indirect: {668// Store the argument.669SDValue SpillSlot = DAG.CreateStackTemporary(VA.getValVT());670int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();671Chain = DAG.getStore(672Chain, DL, Arg, SpillSlot,673MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI));674Arg = SpillSlot;675break;676}677}678679if (VA.isRegLoc()) {680RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));681} else if (!IsSibcall && (!IsTailCall || IsByVal)) {682assert(VA.isMemLoc());683if (!StackPtr.getNode()) {684StackPtr = DAG.getCopyFromReg(Chain, DL, RegInfo->getStackRegister(),685getPointerTy(DAG.getDataLayout()));686}687MemOpChains.push_back(688LowerMemOpCallTo(Chain, StackPtr, Arg, DL, DAG, VA, Flags));689}690}691692if (!MemOpChains.empty())693Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);694695// FIXME Make sure PIC style GOT works as expected696// The only time GOT is really needed is for Medium-PIC static data697// otherwise we are happy with pc-rel or static references698699if (IsVarArg && IsMustTail) {700const auto &Forwards = MFI->getForwardedMustTailRegParms();701for (const auto &F : Forwards) {702SDValue Val = DAG.getCopyFromReg(Chain, DL, F.VReg, F.VT);703RegsToPass.push_back(std::make_pair(unsigned(F.PReg), Val));704}705}706707// For tail calls lower the arguments to the 'real' stack slots. Sibcalls708// don't need this because the eligibility check rejects calls that require709// shuffling arguments passed in memory.710if (!IsSibcall && IsTailCall) {711// Force all the incoming stack arguments to be loaded from the stack712// before any new outgoing arguments are stored to the stack, because the713// outgoing stack slots may alias the incoming argument stack slots, and714// the alias isn't otherwise explicit. This is slightly more conservative715// than necessary, because it means that each store effectively depends716// on every argument instead of just those arguments it would clobber.717SDValue ArgChain = DAG.getStackArgumentTokenFactor(Chain);718719SmallVector<SDValue, 8> MemOpChains2;720SDValue FIN;721int FI = 0;722for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {723CCValAssign &VA = ArgLocs[i];724if (VA.isRegLoc())725continue;726assert(VA.isMemLoc());727SDValue Arg = OutVals[i];728ISD::ArgFlagsTy Flags = Outs[i].Flags;729// Skip inalloca arguments. They don't require any work.730if (Flags.isInAlloca())731continue;732// Create frame index.733int32_t Offset = VA.getLocMemOffset() + FPDiff;734uint32_t OpSize = (VA.getLocVT().getSizeInBits() + 7) / 8;735FI = MF.getFrameInfo().CreateFixedObject(OpSize, Offset, true);736FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));737738if (Flags.isByVal()) {739// Copy relative to framepointer.740SDValue Source = DAG.getIntPtrConstant(VA.getLocMemOffset(), DL);741if (!StackPtr.getNode()) {742StackPtr = DAG.getCopyFromReg(Chain, DL, RegInfo->getStackRegister(),743getPointerTy(DAG.getDataLayout()));744}745Source = DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()),746StackPtr, Source);747748MemOpChains2.push_back(749CreateCopyOfByValArgument(Source, FIN, ArgChain, Flags, DAG, DL));750} else {751// Store relative to framepointer.752MemOpChains2.push_back(DAG.getStore(753ArgChain, DL, Arg, FIN,754MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)));755}756}757758if (!MemOpChains2.empty())759Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains2);760761// Store the return address to the appropriate stack slot.762Chain = EmitTailCallStoreRetAddr(DAG, MF, Chain, RetFI,763getPointerTy(DAG.getDataLayout()),764Subtarget.getSlotSize(), FPDiff, DL);765}766767// Build a sequence of copy-to-reg nodes chained together with token chain768// and flag operands which copy the outgoing args into registers.769SDValue InGlue;770for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {771Chain = DAG.getCopyToReg(Chain, DL, RegsToPass[i].first,772RegsToPass[i].second, InGlue);773InGlue = Chain.getValue(1);774}775776if (Callee->getOpcode() == ISD::GlobalAddress) {777// If the callee is a GlobalAddress node (quite common, every direct call778// is) turn it into a TargetGlobalAddress node so that legalize doesn't hack779// it.780GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Callee);781782// We should use extra load for direct calls to dllimported functions in783// non-JIT mode.784const GlobalValue *GV = G->getGlobal();785if (!GV->hasDLLImportStorageClass()) {786unsigned char OpFlags = Subtarget.classifyGlobalFunctionReference(GV);787788Callee = DAG.getTargetGlobalAddress(789GV, DL, getPointerTy(DAG.getDataLayout()), G->getOffset(), OpFlags);790791if (OpFlags == M68kII::MO_GOTPCREL) {792793// Add a wrapper.794Callee = DAG.getNode(M68kISD::WrapperPC, DL,795getPointerTy(DAG.getDataLayout()), Callee);796797// Add extra indirection798Callee = DAG.getLoad(799getPointerTy(DAG.getDataLayout()), DL, DAG.getEntryNode(), Callee,800MachinePointerInfo::getGOT(DAG.getMachineFunction()));801}802}803} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {804const Module *Mod = DAG.getMachineFunction().getFunction().getParent();805unsigned char OpFlags =806Subtarget.classifyGlobalFunctionReference(nullptr, *Mod);807808Callee = DAG.getTargetExternalSymbol(809S->getSymbol(), getPointerTy(DAG.getDataLayout()), OpFlags);810}811812// Returns a chain & a flag for retval copy to use.813SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);814SmallVector<SDValue, 8> Ops;815816if (!IsSibcall && IsTailCall) {817Chain = DAG.getCALLSEQ_END(Chain, NumBytesToPop, 0, InGlue, DL);818InGlue = Chain.getValue(1);819}820821Ops.push_back(Chain);822Ops.push_back(Callee);823824if (IsTailCall)825Ops.push_back(DAG.getConstant(FPDiff, DL, MVT::i32));826827// Add argument registers to the end of the list so that they are known live828// into the call.829for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)830Ops.push_back(DAG.getRegister(RegsToPass[i].first,831RegsToPass[i].second.getValueType()));832833// Add a register mask operand representing the call-preserved registers.834const uint32_t *Mask = RegInfo->getCallPreservedMask(MF, CallConv);835assert(Mask && "Missing call preserved mask for calling convention");836837Ops.push_back(DAG.getRegisterMask(Mask));838839if (InGlue.getNode())840Ops.push_back(InGlue);841842if (IsTailCall) {843MF.getFrameInfo().setHasTailCall();844return DAG.getNode(M68kISD::TC_RETURN, DL, NodeTys, Ops);845}846847Chain = DAG.getNode(M68kISD::CALL, DL, NodeTys, Ops);848InGlue = Chain.getValue(1);849850// Create the CALLSEQ_END node.851unsigned NumBytesForCalleeToPop;852if (M68k::isCalleePop(CallConv, IsVarArg,853DAG.getTarget().Options.GuaranteedTailCallOpt)) {854NumBytesForCalleeToPop = NumBytes; // Callee pops everything855} else if (!canGuaranteeTCO(CallConv) && SR == StackStructReturn) {856// If this is a call to a struct-return function, the callee857// pops the hidden struct pointer, so we have to push it back.858NumBytesForCalleeToPop = 4;859} else {860NumBytesForCalleeToPop = 0; // Callee pops nothing.861}862863if (CLI.DoesNotReturn && !getTargetMachine().Options.TrapUnreachable) {864// No need to reset the stack after the call if the call doesn't return. To865// make the MI verify, we'll pretend the callee does it for us.866NumBytesForCalleeToPop = NumBytes;867}868869// Returns a flag for retval copy to use.870if (!IsSibcall) {871Chain = DAG.getCALLSEQ_END(Chain, NumBytesToPop, NumBytesForCalleeToPop,872InGlue, DL);873InGlue = Chain.getValue(1);874}875876// Handle result values, copying them out of physregs into vregs that we877// return.878return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,879InVals);880}881882SDValue M68kTargetLowering::LowerCallResult(883SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,884const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,885SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {886887// Assign locations to each value returned by this call.888SmallVector<CCValAssign, 16> RVLocs;889CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,890*DAG.getContext());891CCInfo.AnalyzeCallResult(Ins, RetCC_M68k);892893// Copy all of the result registers out of their specified physreg.894for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {895CCValAssign &VA = RVLocs[i];896EVT CopyVT = VA.getLocVT();897898/// ??? is this correct?899Chain = DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), CopyVT, InGlue)900.getValue(1);901SDValue Val = Chain.getValue(0);902903if (VA.isExtInLoc() && VA.getValVT().getScalarType() == MVT::i1)904Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);905906InGlue = Chain.getValue(2);907InVals.push_back(Val);908}909910return Chain;911}912913//===----------------------------------------------------------------------===//914// Formal Arguments Calling Convention Implementation915//===----------------------------------------------------------------------===//916917SDValue M68kTargetLowering::LowerFormalArguments(918SDValue Chain, CallingConv::ID CCID, bool IsVarArg,919const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,920SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {921MachineFunction &MF = DAG.getMachineFunction();922M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>();923// const TargetFrameLowering &TFL = *Subtarget.getFrameLowering();924925MachineFrameInfo &MFI = MF.getFrameInfo();926927// Assign locations to all of the incoming arguments.928SmallVector<CCValAssign, 16> ArgLocs;929SmallVector<Type *, 4> ArgTypes;930for (const Argument &Arg : MF.getFunction().args())931ArgTypes.emplace_back(Arg.getType());932M68kCCState CCInfo(ArgTypes, CCID, IsVarArg, MF, ArgLocs, *DAG.getContext());933934CCInfo.AnalyzeFormalArguments(Ins, CC_M68k);935936unsigned LastVal = ~0U;937SDValue ArgValue;938for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {939CCValAssign &VA = ArgLocs[i];940assert(VA.getValNo() != LastVal && "Same value in different locations");941(void)LastVal;942943LastVal = VA.getValNo();944945if (VA.isRegLoc()) {946EVT RegVT = VA.getLocVT();947const TargetRegisterClass *RC;948if (RegVT == MVT::i32)949RC = &M68k::XR32RegClass;950else951llvm_unreachable("Unknown argument type!");952953Register Reg = MF.addLiveIn(VA.getLocReg(), RC);954ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT);955956// If this is an 8 or 16-bit value, it is really passed promoted to 32957// bits. Insert an assert[sz]ext to capture this, then truncate to the958// right size.959if (VA.getLocInfo() == CCValAssign::SExt) {960ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue,961DAG.getValueType(VA.getValVT()));962} else if (VA.getLocInfo() == CCValAssign::ZExt) {963ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue,964DAG.getValueType(VA.getValVT()));965} else if (VA.getLocInfo() == CCValAssign::BCvt) {966ArgValue = DAG.getBitcast(VA.getValVT(), ArgValue);967}968969if (VA.isExtInLoc()) {970ArgValue = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), ArgValue);971}972} else {973assert(VA.isMemLoc());974ArgValue = LowerMemArgument(Chain, CCID, Ins, DL, DAG, VA, MFI, i);975}976977// If value is passed via pointer - do a load.978// TODO Make sure this handling on indirect arguments is correct979if (VA.getLocInfo() == CCValAssign::Indirect)980ArgValue =981DAG.getLoad(VA.getValVT(), DL, Chain, ArgValue, MachinePointerInfo());982983InVals.push_back(ArgValue);984}985986for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {987// Swift calling convention does not require we copy the sret argument988// into %D0 for the return. We don't set SRetReturnReg for Swift.989if (CCID == CallingConv::Swift)990continue;991992// ABI require that for returning structs by value we copy the sret argument993// into %D0 for the return. Save the argument into a virtual register so994// that we can access it from the return points.995if (Ins[i].Flags.isSRet()) {996unsigned Reg = MMFI->getSRetReturnReg();997if (!Reg) {998MVT PtrTy = getPointerTy(DAG.getDataLayout());999Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(PtrTy));1000MMFI->setSRetReturnReg(Reg);1001}1002SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]);1003Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain);1004break;1005}1006}10071008unsigned StackSize = CCInfo.getStackSize();1009// Align stack specially for tail calls.1010if (shouldGuaranteeTCO(CCID, MF.getTarget().Options.GuaranteedTailCallOpt))1011StackSize = GetAlignedArgumentStackSize(StackSize, DAG);10121013// If the function takes variable number of arguments, make a frame index for1014// the start of the first vararg value... for expansion of llvm.va_start. We1015// can skip this if there are no va_start calls.1016if (MFI.hasVAStart()) {1017MMFI->setVarArgsFrameIndex(MFI.CreateFixedObject(1, StackSize, true));1018}10191020if (IsVarArg && MFI.hasMustTailInVarArgFunc()) {1021// We forward some GPRs and some vector types.1022SmallVector<MVT, 2> RegParmTypes;1023MVT IntVT = MVT::i32;1024RegParmTypes.push_back(IntVT);10251026// Compute the set of forwarded registers. The rest are scratch.1027// ??? what is this for?1028SmallVectorImpl<ForwardedRegister> &Forwards =1029MMFI->getForwardedMustTailRegParms();1030CCInfo.analyzeMustTailForwardedRegisters(Forwards, RegParmTypes, CC_M68k);10311032// Copy all forwards from physical to virtual registers.1033for (ForwardedRegister &F : Forwards) {1034// FIXME Can we use a less constrained schedule?1035SDValue RegVal = DAG.getCopyFromReg(Chain, DL, F.VReg, F.VT);1036F.VReg = MF.getRegInfo().createVirtualRegister(getRegClassFor(F.VT));1037Chain = DAG.getCopyToReg(Chain, DL, F.VReg, RegVal);1038}1039}10401041// Some CCs need callee pop.1042if (M68k::isCalleePop(CCID, IsVarArg,1043MF.getTarget().Options.GuaranteedTailCallOpt)) {1044MMFI->setBytesToPopOnReturn(StackSize); // Callee pops everything.1045} else {1046MMFI->setBytesToPopOnReturn(0); // Callee pops nothing.1047// If this is an sret function, the return should pop the hidden pointer.1048if (!canGuaranteeTCO(CCID) && argsAreStructReturn(Ins) == StackStructReturn)1049MMFI->setBytesToPopOnReturn(4);1050}10511052MMFI->setArgumentStackSize(StackSize);10531054return Chain;1055}10561057//===----------------------------------------------------------------------===//1058// Return Value Calling Convention Implementation1059//===----------------------------------------------------------------------===//10601061bool M68kTargetLowering::CanLowerReturn(1062CallingConv::ID CCID, MachineFunction &MF, bool IsVarArg,1063const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {1064SmallVector<CCValAssign, 16> RVLocs;1065CCState CCInfo(CCID, IsVarArg, MF, RVLocs, Context);1066return CCInfo.CheckReturn(Outs, RetCC_M68k);1067}10681069SDValue1070M68kTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CCID,1071bool IsVarArg,1072const SmallVectorImpl<ISD::OutputArg> &Outs,1073const SmallVectorImpl<SDValue> &OutVals,1074const SDLoc &DL, SelectionDAG &DAG) const {1075MachineFunction &MF = DAG.getMachineFunction();1076M68kMachineFunctionInfo *MFI = MF.getInfo<M68kMachineFunctionInfo>();10771078SmallVector<CCValAssign, 16> RVLocs;1079CCState CCInfo(CCID, IsVarArg, MF, RVLocs, *DAG.getContext());1080CCInfo.AnalyzeReturn(Outs, RetCC_M68k);10811082SDValue Glue;1083SmallVector<SDValue, 6> RetOps;1084// Operand #0 = Chain (updated below)1085RetOps.push_back(Chain);1086// Operand #1 = Bytes To Pop1087RetOps.push_back(1088DAG.getTargetConstant(MFI->getBytesToPopOnReturn(), DL, MVT::i32));10891090// Copy the result values into the output registers.1091for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {1092CCValAssign &VA = RVLocs[i];1093assert(VA.isRegLoc() && "Can only return in registers!");1094SDValue ValToCopy = OutVals[i];1095EVT ValVT = ValToCopy.getValueType();10961097// Promote values to the appropriate types.1098if (VA.getLocInfo() == CCValAssign::SExt)1099ValToCopy = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), ValToCopy);1100else if (VA.getLocInfo() == CCValAssign::ZExt)1101ValToCopy = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), ValToCopy);1102else if (VA.getLocInfo() == CCValAssign::AExt) {1103if (ValVT.isVector() && ValVT.getVectorElementType() == MVT::i1)1104ValToCopy = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), ValToCopy);1105else1106ValToCopy = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), ValToCopy);1107} else if (VA.getLocInfo() == CCValAssign::BCvt)1108ValToCopy = DAG.getBitcast(VA.getLocVT(), ValToCopy);11091110Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), ValToCopy, Glue);1111Glue = Chain.getValue(1);1112RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));1113}11141115// Swift calling convention does not require we copy the sret argument1116// into %d0 for the return, and SRetReturnReg is not set for Swift.11171118// ABI require that for returning structs by value we copy the sret argument1119// into %D0 for the return. Save the argument into a virtual register so that1120// we can access it from the return points.1121//1122// Checking Function.hasStructRetAttr() here is insufficient because the IR1123// may not have an explicit sret argument. If MFI.CanLowerReturn is1124// false, then an sret argument may be implicitly inserted in the SelDAG. In1125// either case MFI->setSRetReturnReg() will have been called.1126if (unsigned SRetReg = MFI->getSRetReturnReg()) {1127// ??? Can i just move this to the top and escape this explanation?1128// When we have both sret and another return value, we should use the1129// original Chain stored in RetOps[0], instead of the current Chain updated1130// in the above loop. If we only have sret, RetOps[0] equals to Chain.11311132// For the case of sret and another return value, we have1133// Chain_0 at the function entry1134// Chain_1 = getCopyToReg(Chain_0) in the above loop1135// If we use Chain_1 in getCopyFromReg, we will have1136// Val = getCopyFromReg(Chain_1)1137// Chain_2 = getCopyToReg(Chain_1, Val) from below11381139// getCopyToReg(Chain_0) will be glued together with1140// getCopyToReg(Chain_1, Val) into Unit A, getCopyFromReg(Chain_1) will be1141// in Unit B, and we will have cyclic dependency between Unit A and Unit B:1142// Data dependency from Unit B to Unit A due to usage of Val in1143// getCopyToReg(Chain_1, Val)1144// Chain dependency from Unit A to Unit B11451146// So here, we use RetOps[0] (i.e Chain_0) for getCopyFromReg.1147SDValue Val = DAG.getCopyFromReg(RetOps[0], DL, SRetReg,1148getPointerTy(MF.getDataLayout()));11491150// ??? How will this work if CC does not use registers for args passing?1151// ??? What if I return multiple structs?1152unsigned RetValReg = M68k::D0;1153Chain = DAG.getCopyToReg(Chain, DL, RetValReg, Val, Glue);1154Glue = Chain.getValue(1);11551156RetOps.push_back(1157DAG.getRegister(RetValReg, getPointerTy(DAG.getDataLayout())));1158}11591160RetOps[0] = Chain; // Update chain.11611162// Add the glue if we have it.1163if (Glue.getNode())1164RetOps.push_back(Glue);11651166return DAG.getNode(M68kISD::RET, DL, MVT::Other, RetOps);1167}11681169//===----------------------------------------------------------------------===//1170// Fast Calling Convention (tail call) implementation1171//===----------------------------------------------------------------------===//11721173// Like std call, callee cleans arguments, convention except that ECX is1174// reserved for storing the tail called function address. Only 2 registers are1175// free for argument passing (inreg). Tail call optimization is performed1176// provided:1177// * tailcallopt is enabled1178// * caller/callee are fastcc1179// On M68k_64 architecture with GOT-style position independent code only1180// local (within module) calls are supported at the moment. To keep the stack1181// aligned according to platform abi the function GetAlignedArgumentStackSize1182// ensures that argument delta is always multiples of stack alignment. (Dynamic1183// linkers need this - darwin's dyld for example) If a tail called function1184// callee has more arguments than the caller the caller needs to make sure that1185// there is room to move the RETADDR to. This is achieved by reserving an area1186// the size of the argument delta right after the original RETADDR, but before1187// the saved framepointer or the spilled registers e.g. caller(arg1, arg2)1188// calls callee(arg1, arg2,arg3,arg4) stack layout:1189// arg11190// arg21191// RETADDR1192// [ new RETADDR1193// move area ]1194// (possible EBP)1195// ESI1196// EDI1197// local1 ..11981199/// Make the stack size align e.g 16n + 12 aligned for a 16-byte align1200/// requirement.1201unsigned1202M68kTargetLowering::GetAlignedArgumentStackSize(unsigned StackSize,1203SelectionDAG &DAG) const {1204const TargetFrameLowering &TFI = *Subtarget.getFrameLowering();1205unsigned StackAlignment = TFI.getStackAlignment();1206uint64_t AlignMask = StackAlignment - 1;1207int64_t Offset = StackSize;1208unsigned SlotSize = Subtarget.getSlotSize();1209if ((Offset & AlignMask) <= (StackAlignment - SlotSize)) {1210// Number smaller than 12 so just add the difference.1211Offset += ((StackAlignment - SlotSize) - (Offset & AlignMask));1212} else {1213// Mask out lower bits, add stackalignment once plus the 12 bytes.1214Offset =1215((~AlignMask) & Offset) + StackAlignment + (StackAlignment - SlotSize);1216}1217return Offset;1218}12191220/// Check whether the call is eligible for tail call optimization. Targets1221/// that want to do tail call optimization should implement this function.1222bool M68kTargetLowering::IsEligibleForTailCallOptimization(1223SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,1224bool IsCalleeStructRet, bool IsCallerStructRet, Type *RetTy,1225const SmallVectorImpl<ISD::OutputArg> &Outs,1226const SmallVectorImpl<SDValue> &OutVals,1227const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const {1228if (!mayTailCallThisCC(CalleeCC))1229return false;12301231// If -tailcallopt is specified, make fastcc functions tail-callable.1232MachineFunction &MF = DAG.getMachineFunction();1233const auto &CallerF = MF.getFunction();12341235CallingConv::ID CallerCC = CallerF.getCallingConv();1236bool CCMatch = CallerCC == CalleeCC;12371238if (DAG.getTarget().Options.GuaranteedTailCallOpt) {1239if (canGuaranteeTCO(CalleeCC) && CCMatch)1240return true;1241return false;1242}12431244// Look for obvious safe cases to perform tail call optimization that do not1245// require ABI changes. This is what gcc calls sibcall.12461247// Can't do sibcall if stack needs to be dynamically re-aligned. PEI needs to1248// emit a special epilogue.1249const M68kRegisterInfo *RegInfo = Subtarget.getRegisterInfo();1250if (RegInfo->hasStackRealignment(MF))1251return false;12521253// Also avoid sibcall optimization if either caller or callee uses struct1254// return semantics.1255if (IsCalleeStructRet || IsCallerStructRet)1256return false;12571258// Do not sibcall optimize vararg calls unless all arguments are passed via1259// registers.1260LLVMContext &C = *DAG.getContext();1261if (IsVarArg && !Outs.empty()) {12621263SmallVector<CCValAssign, 16> ArgLocs;1264CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, C);12651266CCInfo.AnalyzeCallOperands(Outs, CC_M68k);1267for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i)1268if (!ArgLocs[i].isRegLoc())1269return false;1270}12711272// Check that the call results are passed in the same way.1273if (!CCState::resultsCompatible(CalleeCC, CallerCC, MF, C, Ins, RetCC_M68k,1274RetCC_M68k))1275return false;12761277// The callee has to preserve all registers the caller needs to preserve.1278const M68kRegisterInfo *TRI = Subtarget.getRegisterInfo();1279const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);1280if (!CCMatch) {1281const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC);1282if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))1283return false;1284}12851286unsigned StackArgsSize = 0;12871288// If the callee takes no arguments then go on to check the results of the1289// call.1290if (!Outs.empty()) {1291// Check if stack adjustment is needed. For now, do not do this if any1292// argument is passed on the stack.1293SmallVector<CCValAssign, 16> ArgLocs;1294CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, C);12951296CCInfo.AnalyzeCallOperands(Outs, CC_M68k);1297StackArgsSize = CCInfo.getStackSize();12981299if (StackArgsSize) {1300// Check if the arguments are already laid out in the right way as1301// the caller's fixed stack objects.1302MachineFrameInfo &MFI = MF.getFrameInfo();1303const MachineRegisterInfo *MRI = &MF.getRegInfo();1304const M68kInstrInfo *TII = Subtarget.getInstrInfo();1305for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {1306CCValAssign &VA = ArgLocs[i];1307SDValue Arg = OutVals[i];1308ISD::ArgFlagsTy Flags = Outs[i].Flags;1309if (VA.getLocInfo() == CCValAssign::Indirect)1310return false;1311if (!VA.isRegLoc()) {1312if (!MatchingStackOffset(Arg, VA.getLocMemOffset(), Flags, MFI, MRI,1313TII, VA))1314return false;1315}1316}1317}13181319bool PositionIndependent = isPositionIndependent();1320// If the tailcall address may be in a register, then make sure it's1321// possible to register allocate for it. The call address can1322// only target %A0 or %A1 since the tail call must be scheduled after1323// callee-saved registers are restored. These happen to be the same1324// registers used to pass 'inreg' arguments so watch out for those.1325if ((!isa<GlobalAddressSDNode>(Callee) &&1326!isa<ExternalSymbolSDNode>(Callee)) ||1327PositionIndependent) {1328unsigned NumInRegs = 0;1329// In PIC we need an extra register to formulate the address computation1330// for the callee.1331unsigned MaxInRegs = PositionIndependent ? 1 : 2;13321333for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {1334CCValAssign &VA = ArgLocs[i];1335if (!VA.isRegLoc())1336continue;1337Register Reg = VA.getLocReg();1338switch (Reg) {1339default:1340break;1341case M68k::A0:1342case M68k::A1:1343if (++NumInRegs == MaxInRegs)1344return false;1345break;1346}1347}1348}13491350const MachineRegisterInfo &MRI = MF.getRegInfo();1351if (!parametersInCSRMatch(MRI, CallerPreserved, ArgLocs, OutVals))1352return false;1353}13541355bool CalleeWillPop = M68k::isCalleePop(1356CalleeCC, IsVarArg, MF.getTarget().Options.GuaranteedTailCallOpt);13571358if (unsigned BytesToPop =1359MF.getInfo<M68kMachineFunctionInfo>()->getBytesToPopOnReturn()) {1360// If we have bytes to pop, the callee must pop them.1361bool CalleePopMatches = CalleeWillPop && BytesToPop == StackArgsSize;1362if (!CalleePopMatches)1363return false;1364} else if (CalleeWillPop && StackArgsSize > 0) {1365// If we don't have bytes to pop, make sure the callee doesn't pop any.1366return false;1367}13681369return true;1370}13711372//===----------------------------------------------------------------------===//1373// Custom Lower1374//===----------------------------------------------------------------------===//13751376SDValue M68kTargetLowering::LowerOperation(SDValue Op,1377SelectionDAG &DAG) const {1378switch (Op.getOpcode()) {1379default:1380llvm_unreachable("Should not custom lower this!");1381case ISD::SADDO:1382case ISD::UADDO:1383case ISD::SSUBO:1384case ISD::USUBO:1385case ISD::SMULO:1386case ISD::UMULO:1387return LowerXALUO(Op, DAG);1388case ISD::SETCC:1389return LowerSETCC(Op, DAG);1390case ISD::SETCCCARRY:1391return LowerSETCCCARRY(Op, DAG);1392case ISD::SELECT:1393return LowerSELECT(Op, DAG);1394case ISD::BRCOND:1395return LowerBRCOND(Op, DAG);1396case ISD::ADDC:1397case ISD::ADDE:1398case ISD::SUBC:1399case ISD::SUBE:1400return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);1401case ISD::ConstantPool:1402return LowerConstantPool(Op, DAG);1403case ISD::GlobalAddress:1404return LowerGlobalAddress(Op, DAG);1405case ISD::ExternalSymbol:1406return LowerExternalSymbol(Op, DAG);1407case ISD::BlockAddress:1408return LowerBlockAddress(Op, DAG);1409case ISD::JumpTable:1410return LowerJumpTable(Op, DAG);1411case ISD::VASTART:1412return LowerVASTART(Op, DAG);1413case ISD::DYNAMIC_STACKALLOC:1414return LowerDYNAMIC_STACKALLOC(Op, DAG);1415case ISD::SHL_PARTS:1416return LowerShiftLeftParts(Op, DAG);1417case ISD::SRA_PARTS:1418return LowerShiftRightParts(Op, DAG, true);1419case ISD::SRL_PARTS:1420return LowerShiftRightParts(Op, DAG, false);1421case ISD::ATOMIC_FENCE:1422return LowerATOMICFENCE(Op, DAG);1423case ISD::GlobalTLSAddress:1424return LowerGlobalTLSAddress(Op, DAG);1425}1426}14271428SDValue M68kTargetLowering::LowerExternalSymbolCall(SelectionDAG &DAG,1429SDLoc Loc,1430llvm::StringRef SymbolName,1431ArgListTy &&ArgList) const {1432PointerType *PtrTy = PointerType::get(*DAG.getContext(), 0);1433CallLoweringInfo CLI(DAG);1434CLI.setDebugLoc(Loc)1435.setChain(DAG.getEntryNode())1436.setLibCallee(CallingConv::C, PtrTy,1437DAG.getExternalSymbol(SymbolName.data(),1438getPointerMemTy(DAG.getDataLayout())),1439std::move(ArgList));1440return LowerCallTo(CLI).first;1441}14421443SDValue M68kTargetLowering::getTLSGetAddr(GlobalAddressSDNode *GA,1444SelectionDAG &DAG,1445unsigned TargetFlags) const {1446SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32);1447SDValue TGA = DAG.getTargetGlobalAddress(1448GA->getGlobal(), GA, GA->getValueType(0), GA->getOffset(), TargetFlags);1449SDValue Arg = DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, GOT, TGA);14501451PointerType *PtrTy = PointerType::get(*DAG.getContext(), 0);14521453ArgListTy Args;1454ArgListEntry Entry;1455Entry.Node = Arg;1456Entry.Ty = PtrTy;1457Args.push_back(Entry);1458return LowerExternalSymbolCall(DAG, SDLoc(GA), "__tls_get_addr",1459std::move(Args));1460}14611462SDValue M68kTargetLowering::getM68kReadTp(SDLoc Loc, SelectionDAG &DAG) const {1463return LowerExternalSymbolCall(DAG, Loc, "__m68k_read_tp", ArgListTy());1464}14651466SDValue M68kTargetLowering::LowerTLSGeneralDynamic(GlobalAddressSDNode *GA,1467SelectionDAG &DAG) const {1468return getTLSGetAddr(GA, DAG, M68kII::MO_TLSGD);1469}14701471SDValue M68kTargetLowering::LowerTLSLocalDynamic(GlobalAddressSDNode *GA,1472SelectionDAG &DAG) const {1473SDValue Addr = getTLSGetAddr(GA, DAG, M68kII::MO_TLSLDM);1474SDValue TGA =1475DAG.getTargetGlobalAddress(GA->getGlobal(), GA, GA->getValueType(0),1476GA->getOffset(), M68kII::MO_TLSLD);1477return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, Addr);1478}14791480SDValue M68kTargetLowering::LowerTLSInitialExec(GlobalAddressSDNode *GA,1481SelectionDAG &DAG) const {1482SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32);1483SDValue Tp = getM68kReadTp(SDLoc(GA), DAG);1484SDValue TGA =1485DAG.getTargetGlobalAddress(GA->getGlobal(), GA, GA->getValueType(0),1486GA->getOffset(), M68kII::MO_TLSIE);1487SDValue Addr = DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, GOT);1488SDValue Offset =1489DAG.getLoad(MVT::i32, SDLoc(GA), DAG.getEntryNode(), Addr,1490MachinePointerInfo::getGOT(DAG.getMachineFunction()));14911492return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, Offset, Tp);1493}14941495SDValue M68kTargetLowering::LowerTLSLocalExec(GlobalAddressSDNode *GA,1496SelectionDAG &DAG) const {1497SDValue Tp = getM68kReadTp(SDLoc(GA), DAG);1498SDValue TGA =1499DAG.getTargetGlobalAddress(GA->getGlobal(), GA, GA->getValueType(0),1500GA->getOffset(), M68kII::MO_TLSLE);1501return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, Tp);1502}15031504SDValue M68kTargetLowering::LowerGlobalTLSAddress(SDValue Op,1505SelectionDAG &DAG) const {1506assert(Subtarget.isTargetELF());15071508auto *GA = cast<GlobalAddressSDNode>(Op);1509TLSModel::Model AccessModel = DAG.getTarget().getTLSModel(GA->getGlobal());15101511switch (AccessModel) {1512case TLSModel::GeneralDynamic:1513return LowerTLSGeneralDynamic(GA, DAG);1514case TLSModel::LocalDynamic:1515return LowerTLSLocalDynamic(GA, DAG);1516case TLSModel::InitialExec:1517return LowerTLSInitialExec(GA, DAG);1518case TLSModel::LocalExec:1519return LowerTLSLocalExec(GA, DAG);1520}15211522llvm_unreachable("Unexpected TLS access model type");1523}15241525bool M68kTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,1526SDValue C) const {1527// Shifts and add instructions in M68000 and M68010 support1528// up to 32 bits, but mul only has 16-bit variant. So it's almost1529// certainly beneficial to lower 8/16/32-bit mul to their1530// add / shifts counterparts. But for 64-bits mul, it might be1531// safer to just leave it to compiler runtime implementations.1532return VT.bitsLE(MVT::i32) || Subtarget.atLeastM68020();1533}15341535static bool isOverflowArithmetic(unsigned Opcode) {1536switch (Opcode) {1537case ISD::UADDO:1538case ISD::SADDO:1539case ISD::USUBO:1540case ISD::SSUBO:1541case ISD::UMULO:1542case ISD::SMULO:1543return true;1544default:1545return false;1546}1547}15481549static void lowerOverflowArithmetic(SDValue Op, SelectionDAG &DAG,1550SDValue &Result, SDValue &CCR,1551unsigned &CC) {1552SDNode *N = Op.getNode();1553EVT VT = N->getValueType(0);1554SDValue LHS = N->getOperand(0);1555SDValue RHS = N->getOperand(1);1556SDLoc DL(Op);15571558unsigned TruncOp = 0;1559auto PromoteMULO = [&](unsigned ExtOp) {1560// We don't have 8-bit multiplications, so promote i8 version of U/SMULO1561// to i16.1562// Ideally this should be done by legalizer but sadly there is no promotion1563// rule for U/SMULO at this moment.1564if (VT == MVT::i8) {1565LHS = DAG.getNode(ExtOp, DL, MVT::i16, LHS);1566RHS = DAG.getNode(ExtOp, DL, MVT::i16, RHS);1567VT = MVT::i16;1568TruncOp = ISD::TRUNCATE;1569}1570};15711572bool NoOverflow = false;1573unsigned BaseOp = 0;1574switch (Op.getOpcode()) {1575default:1576llvm_unreachable("Unknown ovf instruction!");1577case ISD::SADDO:1578BaseOp = M68kISD::ADD;1579CC = M68k::COND_VS;1580break;1581case ISD::UADDO:1582BaseOp = M68kISD::ADD;1583CC = M68k::COND_CS;1584break;1585case ISD::SSUBO:1586BaseOp = M68kISD::SUB;1587CC = M68k::COND_VS;1588break;1589case ISD::USUBO:1590BaseOp = M68kISD::SUB;1591CC = M68k::COND_CS;1592break;1593case ISD::UMULO:1594PromoteMULO(ISD::ZERO_EXTEND);1595NoOverflow = VT != MVT::i32;1596BaseOp = NoOverflow ? ISD::MUL : M68kISD::UMUL;1597CC = M68k::COND_VS;1598break;1599case ISD::SMULO:1600PromoteMULO(ISD::SIGN_EXTEND);1601NoOverflow = VT != MVT::i32;1602BaseOp = NoOverflow ? ISD::MUL : M68kISD::SMUL;1603CC = M68k::COND_VS;1604break;1605}16061607SDVTList VTs;1608if (NoOverflow)1609VTs = DAG.getVTList(VT);1610else1611// Also sets CCR.1612VTs = DAG.getVTList(VT, MVT::i8);16131614SDValue Arith = DAG.getNode(BaseOp, DL, VTs, LHS, RHS);1615Result = Arith.getValue(0);1616if (TruncOp)1617// Right now the only place to truncate is from i16 to i8.1618Result = DAG.getNode(TruncOp, DL, MVT::i8, Arith);16191620if (NoOverflow)1621CCR = DAG.getConstant(0, DL, N->getValueType(1));1622else1623CCR = Arith.getValue(1);1624}16251626SDValue M68kTargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const {1627SDNode *N = Op.getNode();1628SDLoc DL(Op);16291630// Lower the "add/sub/mul with overflow" instruction into a regular ins plus1631// a "setcc" instruction that checks the overflow flag.1632SDValue Result, CCR;1633unsigned CC;1634lowerOverflowArithmetic(Op, DAG, Result, CCR, CC);16351636SDValue Overflow;1637if (isa<ConstantSDNode>(CCR)) {1638// It's likely a result of operations that will not overflow1639// hence no setcc is needed.1640Overflow = CCR;1641} else {1642// Generate a M68kISD::SETCC.1643Overflow = DAG.getNode(M68kISD::SETCC, DL, N->getValueType(1),1644DAG.getConstant(CC, DL, MVT::i8), CCR);1645}16461647return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Result, Overflow);1648}16491650/// Create a BTST (Bit Test) node - Test bit \p BitNo in \p Src and set1651/// condition according to equal/not-equal condition code \p CC.1652static SDValue getBitTestCondition(SDValue Src, SDValue BitNo, ISD::CondCode CC,1653const SDLoc &DL, SelectionDAG &DAG) {1654// If Src is i8, promote it to i32 with any_extend. There is no i8 BTST1655// instruction. Since the shift amount is in-range-or-undefined, we know1656// that doing a bittest on the i32 value is ok.1657if (Src.getValueType() == MVT::i8 || Src.getValueType() == MVT::i16)1658Src = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Src);16591660// If the operand types disagree, extend the shift amount to match. Since1661// BTST ignores high bits (like shifts) we can use anyextend.1662if (Src.getValueType() != BitNo.getValueType())1663BitNo = DAG.getNode(ISD::ANY_EXTEND, DL, Src.getValueType(), BitNo);16641665SDValue BTST = DAG.getNode(M68kISD::BTST, DL, MVT::i32, Src, BitNo);16661667// NOTE BTST sets CCR.Z flag1668M68k::CondCode Cond = CC == ISD::SETEQ ? M68k::COND_NE : M68k::COND_EQ;1669return DAG.getNode(M68kISD::SETCC, DL, MVT::i8,1670DAG.getConstant(Cond, DL, MVT::i8), BTST);1671}16721673/// Result of 'and' is compared against zero. Change to a BTST node if possible.1674static SDValue LowerAndToBTST(SDValue And, ISD::CondCode CC, const SDLoc &DL,1675SelectionDAG &DAG) {1676SDValue Op0 = And.getOperand(0);1677SDValue Op1 = And.getOperand(1);1678if (Op0.getOpcode() == ISD::TRUNCATE)1679Op0 = Op0.getOperand(0);1680if (Op1.getOpcode() == ISD::TRUNCATE)1681Op1 = Op1.getOperand(0);16821683SDValue LHS, RHS;1684if (Op1.getOpcode() == ISD::SHL)1685std::swap(Op0, Op1);1686if (Op0.getOpcode() == ISD::SHL) {1687if (isOneConstant(Op0.getOperand(0))) {1688// If we looked past a truncate, check that it's only truncating away1689// known zeros.1690unsigned BitWidth = Op0.getValueSizeInBits();1691unsigned AndBitWidth = And.getValueSizeInBits();1692if (BitWidth > AndBitWidth) {1693auto Known = DAG.computeKnownBits(Op0);1694if (Known.countMinLeadingZeros() < BitWidth - AndBitWidth)1695return SDValue();1696}1697LHS = Op1;1698RHS = Op0.getOperand(1);1699}1700} else if (auto *AndRHS = dyn_cast<ConstantSDNode>(Op1)) {1701uint64_t AndRHSVal = AndRHS->getZExtValue();1702SDValue AndLHS = Op0;17031704if (AndRHSVal == 1 && AndLHS.getOpcode() == ISD::SRL) {1705LHS = AndLHS.getOperand(0);1706RHS = AndLHS.getOperand(1);1707}17081709// Use BTST if the immediate can't be encoded in a TEST instruction.1710if (!isUInt<32>(AndRHSVal) && isPowerOf2_64(AndRHSVal)) {1711LHS = AndLHS;1712RHS = DAG.getConstant(Log2_64_Ceil(AndRHSVal), DL, LHS.getValueType());1713}1714}17151716if (LHS.getNode())1717return getBitTestCondition(LHS, RHS, CC, DL, DAG);17181719return SDValue();1720}17211722static M68k::CondCode TranslateIntegerM68kCC(ISD::CondCode SetCCOpcode) {1723switch (SetCCOpcode) {1724default:1725llvm_unreachable("Invalid integer condition!");1726case ISD::SETEQ:1727return M68k::COND_EQ;1728case ISD::SETGT:1729return M68k::COND_GT;1730case ISD::SETGE:1731return M68k::COND_GE;1732case ISD::SETLT:1733return M68k::COND_LT;1734case ISD::SETLE:1735return M68k::COND_LE;1736case ISD::SETNE:1737return M68k::COND_NE;1738case ISD::SETULT:1739return M68k::COND_CS;1740case ISD::SETUGE:1741return M68k::COND_CC;1742case ISD::SETUGT:1743return M68k::COND_HI;1744case ISD::SETULE:1745return M68k::COND_LS;1746}1747}17481749/// Do a one-to-one translation of a ISD::CondCode to the M68k-specific1750/// condition code, returning the condition code and the LHS/RHS of the1751/// comparison to make.1752static unsigned TranslateM68kCC(ISD::CondCode SetCCOpcode, const SDLoc &DL,1753bool IsFP, SDValue &LHS, SDValue &RHS,1754SelectionDAG &DAG) {1755if (!IsFP) {1756if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) {1757if (SetCCOpcode == ISD::SETGT && RHSC->isAllOnes()) {1758// X > -1 -> X == 0, jump !sign.1759RHS = DAG.getConstant(0, DL, RHS.getValueType());1760return M68k::COND_PL;1761}1762if (SetCCOpcode == ISD::SETLT && RHSC->isZero()) {1763// X < 0 -> X == 0, jump on sign.1764return M68k::COND_MI;1765}1766if (SetCCOpcode == ISD::SETLT && RHSC->getZExtValue() == 1) {1767// X < 1 -> X <= 01768RHS = DAG.getConstant(0, DL, RHS.getValueType());1769return M68k::COND_LE;1770}1771}17721773return TranslateIntegerM68kCC(SetCCOpcode);1774}17751776// First determine if it is required or is profitable to flip the operands.17771778// If LHS is a foldable load, but RHS is not, flip the condition.1779if (ISD::isNON_EXTLoad(LHS.getNode()) && !ISD::isNON_EXTLoad(RHS.getNode())) {1780SetCCOpcode = getSetCCSwappedOperands(SetCCOpcode);1781std::swap(LHS, RHS);1782}17831784switch (SetCCOpcode) {1785default:1786break;1787case ISD::SETOLT:1788case ISD::SETOLE:1789case ISD::SETUGT:1790case ISD::SETUGE:1791std::swap(LHS, RHS);1792break;1793}17941795// On a floating point condition, the flags are set as follows:1796// ZF PF CF op1797// 0 | 0 | 0 | X > Y1798// 0 | 0 | 1 | X < Y1799// 1 | 0 | 0 | X == Y1800// 1 | 1 | 1 | unordered1801switch (SetCCOpcode) {1802default:1803llvm_unreachable("Condcode should be pre-legalized away");1804case ISD::SETUEQ:1805case ISD::SETEQ:1806return M68k::COND_EQ;1807case ISD::SETOLT: // flipped1808case ISD::SETOGT:1809case ISD::SETGT:1810return M68k::COND_HI;1811case ISD::SETOLE: // flipped1812case ISD::SETOGE:1813case ISD::SETGE:1814return M68k::COND_CC;1815case ISD::SETUGT: // flipped1816case ISD::SETULT:1817case ISD::SETLT:1818return M68k::COND_CS;1819case ISD::SETUGE: // flipped1820case ISD::SETULE:1821case ISD::SETLE:1822return M68k::COND_LS;1823case ISD::SETONE:1824case ISD::SETNE:1825return M68k::COND_NE;1826case ISD::SETOEQ:1827case ISD::SETUNE:1828return M68k::COND_INVALID;1829}1830}18311832// Convert (truncate (srl X, N) to i1) to (bt X, N)1833static SDValue LowerTruncateToBTST(SDValue Op, ISD::CondCode CC,1834const SDLoc &DL, SelectionDAG &DAG) {18351836assert(Op.getOpcode() == ISD::TRUNCATE && Op.getValueType() == MVT::i1 &&1837"Expected TRUNCATE to i1 node");18381839if (Op.getOperand(0).getOpcode() != ISD::SRL)1840return SDValue();18411842SDValue ShiftRight = Op.getOperand(0);1843return getBitTestCondition(ShiftRight.getOperand(0), ShiftRight.getOperand(1),1844CC, DL, DAG);1845}18461847/// \brief return true if \c Op has a use that doesn't just read flags.1848static bool hasNonFlagsUse(SDValue Op) {1849for (SDNode::use_iterator UI = Op->use_begin(), UE = Op->use_end(); UI != UE;1850++UI) {1851SDNode *User = *UI;1852unsigned UOpNo = UI.getOperandNo();1853if (User->getOpcode() == ISD::TRUNCATE && User->hasOneUse()) {1854// Look pass truncate.1855UOpNo = User->use_begin().getOperandNo();1856User = *User->use_begin();1857}18581859if (User->getOpcode() != ISD::BRCOND && User->getOpcode() != ISD::SETCC &&1860!(User->getOpcode() == ISD::SELECT && UOpNo == 0))1861return true;1862}1863return false;1864}18651866SDValue M68kTargetLowering::EmitTest(SDValue Op, unsigned M68kCC,1867const SDLoc &DL, SelectionDAG &DAG) const {18681869// CF and OF aren't always set the way we want. Determine which1870// of these we need.1871bool NeedCF = false;1872bool NeedOF = false;1873switch (M68kCC) {1874default:1875break;1876case M68k::COND_HI:1877case M68k::COND_CC:1878case M68k::COND_CS:1879case M68k::COND_LS:1880NeedCF = true;1881break;1882case M68k::COND_GT:1883case M68k::COND_GE:1884case M68k::COND_LT:1885case M68k::COND_LE:1886case M68k::COND_VS:1887case M68k::COND_VC: {1888// Check if we really need to set the1889// Overflow flag. If NoSignedWrap is present1890// that is not actually needed.1891switch (Op->getOpcode()) {1892case ISD::ADD:1893case ISD::SUB:1894case ISD::MUL:1895case ISD::SHL: {1896if (Op.getNode()->getFlags().hasNoSignedWrap())1897break;1898[[fallthrough]];1899}1900default:1901NeedOF = true;1902break;1903}1904break;1905}1906}1907// See if we can use the CCR value from the operand instead of1908// doing a separate TEST. TEST always sets OF and CF to 0, so unless1909// we prove that the arithmetic won't overflow, we can't use OF or CF.1910if (Op.getResNo() != 0 || NeedOF || NeedCF) {1911// Emit a CMP with 0, which is the TEST pattern.1912return DAG.getNode(M68kISD::CMP, DL, MVT::i8,1913DAG.getConstant(0, DL, Op.getValueType()), Op);1914}1915unsigned Opcode = 0;1916unsigned NumOperands = 0;19171918// Truncate operations may prevent the merge of the SETCC instruction1919// and the arithmetic instruction before it. Attempt to truncate the operands1920// of the arithmetic instruction and use a reduced bit-width instruction.1921bool NeedTruncation = false;1922SDValue ArithOp = Op;1923if (Op->getOpcode() == ISD::TRUNCATE && Op->hasOneUse()) {1924SDValue Arith = Op->getOperand(0);1925// Both the trunc and the arithmetic op need to have one user each.1926if (Arith->hasOneUse())1927switch (Arith.getOpcode()) {1928default:1929break;1930case ISD::ADD:1931case ISD::SUB:1932case ISD::AND:1933case ISD::OR:1934case ISD::XOR: {1935NeedTruncation = true;1936ArithOp = Arith;1937}1938}1939}19401941// NOTICE: In the code below we use ArithOp to hold the arithmetic operation1942// which may be the result of a CAST. We use the variable 'Op', which is the1943// non-casted variable when we check for possible users.1944switch (ArithOp.getOpcode()) {1945case ISD::ADD:1946Opcode = M68kISD::ADD;1947NumOperands = 2;1948break;1949case ISD::SHL:1950case ISD::SRL:1951// If we have a constant logical shift that's only used in a comparison1952// against zero turn it into an equivalent AND. This allows turning it into1953// a TEST instruction later.1954if ((M68kCC == M68k::COND_EQ || M68kCC == M68k::COND_NE) &&1955Op->hasOneUse() && isa<ConstantSDNode>(Op->getOperand(1)) &&1956!hasNonFlagsUse(Op)) {1957EVT VT = Op.getValueType();1958unsigned BitWidth = VT.getSizeInBits();1959unsigned ShAmt = Op->getConstantOperandVal(1);1960if (ShAmt >= BitWidth) // Avoid undefined shifts.1961break;1962APInt Mask = ArithOp.getOpcode() == ISD::SRL1963? APInt::getHighBitsSet(BitWidth, BitWidth - ShAmt)1964: APInt::getLowBitsSet(BitWidth, BitWidth - ShAmt);1965if (!Mask.isSignedIntN(32)) // Avoid large immediates.1966break;1967Op = DAG.getNode(ISD::AND, DL, VT, Op->getOperand(0),1968DAG.getConstant(Mask, DL, VT));1969}1970break;19711972case ISD::AND:1973// If the primary 'and' result isn't used, don't bother using1974// M68kISD::AND, because a TEST instruction will be better.1975if (!hasNonFlagsUse(Op)) {1976SDValue Op0 = ArithOp->getOperand(0);1977SDValue Op1 = ArithOp->getOperand(1);1978EVT VT = ArithOp.getValueType();1979bool IsAndn = isBitwiseNot(Op0) || isBitwiseNot(Op1);1980bool IsLegalAndnType = VT == MVT::i32 || VT == MVT::i64;19811982// But if we can combine this into an ANDN operation, then create an AND1983// now and allow it to be pattern matched into an ANDN.1984if (/*!Subtarget.hasBMI() ||*/ !IsAndn || !IsLegalAndnType)1985break;1986}1987[[fallthrough]];1988case ISD::SUB:1989case ISD::OR:1990case ISD::XOR:1991// Due to the ISEL shortcoming noted above, be conservative if this op is1992// likely to be selected as part of a load-modify-store instruction.1993for (const auto *U : Op.getNode()->uses())1994if (U->getOpcode() == ISD::STORE)1995goto default_case;19961997// Otherwise use a regular CCR-setting instruction.1998switch (ArithOp.getOpcode()) {1999default:2000llvm_unreachable("unexpected operator!");2001case ISD::SUB:2002Opcode = M68kISD::SUB;2003break;2004case ISD::XOR:2005Opcode = M68kISD::XOR;2006break;2007case ISD::AND:2008Opcode = M68kISD::AND;2009break;2010case ISD::OR:2011Opcode = M68kISD::OR;2012break;2013}20142015NumOperands = 2;2016break;2017case M68kISD::ADD:2018case M68kISD::SUB:2019case M68kISD::OR:2020case M68kISD::XOR:2021case M68kISD::AND:2022return SDValue(Op.getNode(), 1);2023default:2024default_case:2025break;2026}20272028// If we found that truncation is beneficial, perform the truncation and2029// update 'Op'.2030if (NeedTruncation) {2031EVT VT = Op.getValueType();2032SDValue WideVal = Op->getOperand(0);2033EVT WideVT = WideVal.getValueType();2034unsigned ConvertedOp = 0;2035// Use a target machine opcode to prevent further DAGCombine2036// optimizations that may separate the arithmetic operations2037// from the setcc node.2038switch (WideVal.getOpcode()) {2039default:2040break;2041case ISD::ADD:2042ConvertedOp = M68kISD::ADD;2043break;2044case ISD::SUB:2045ConvertedOp = M68kISD::SUB;2046break;2047case ISD::AND:2048ConvertedOp = M68kISD::AND;2049break;2050case ISD::OR:2051ConvertedOp = M68kISD::OR;2052break;2053case ISD::XOR:2054ConvertedOp = M68kISD::XOR;2055break;2056}20572058if (ConvertedOp) {2059const TargetLowering &TLI = DAG.getTargetLoweringInfo();2060if (TLI.isOperationLegal(WideVal.getOpcode(), WideVT)) {2061SDValue V0 = DAG.getNode(ISD::TRUNCATE, DL, VT, WideVal.getOperand(0));2062SDValue V1 = DAG.getNode(ISD::TRUNCATE, DL, VT, WideVal.getOperand(1));2063Op = DAG.getNode(ConvertedOp, DL, VT, V0, V1);2064}2065}2066}20672068if (Opcode == 0) {2069// Emit a CMP with 0, which is the TEST pattern.2070return DAG.getNode(M68kISD::CMP, DL, MVT::i8,2071DAG.getConstant(0, DL, Op.getValueType()), Op);2072}2073SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::i8);2074SmallVector<SDValue, 4> Ops(Op->op_begin(), Op->op_begin() + NumOperands);20752076SDValue New = DAG.getNode(Opcode, DL, VTs, Ops);2077DAG.ReplaceAllUsesWith(Op, New);2078return SDValue(New.getNode(), 1);2079}20802081/// \brief Return true if the condition is an unsigned comparison operation.2082static bool isM68kCCUnsigned(unsigned M68kCC) {2083switch (M68kCC) {2084default:2085llvm_unreachable("Invalid integer condition!");2086case M68k::COND_EQ:2087case M68k::COND_NE:2088case M68k::COND_CS:2089case M68k::COND_HI:2090case M68k::COND_LS:2091case M68k::COND_CC:2092return true;2093case M68k::COND_GT:2094case M68k::COND_GE:2095case M68k::COND_LT:2096case M68k::COND_LE:2097return false;2098}2099}21002101SDValue M68kTargetLowering::EmitCmp(SDValue Op0, SDValue Op1, unsigned M68kCC,2102const SDLoc &DL, SelectionDAG &DAG) const {2103if (isNullConstant(Op1))2104return EmitTest(Op0, M68kCC, DL, DAG);21052106assert(!(isa<ConstantSDNode>(Op1) && Op0.getValueType() == MVT::i1) &&2107"Unexpected comparison operation for MVT::i1 operands");21082109if ((Op0.getValueType() == MVT::i8 || Op0.getValueType() == MVT::i16 ||2110Op0.getValueType() == MVT::i32 || Op0.getValueType() == MVT::i64)) {2111// Only promote the compare up to I32 if it is a 16 bit operation2112// with an immediate. 16 bit immediates are to be avoided.2113if ((Op0.getValueType() == MVT::i16 &&2114(isa<ConstantSDNode>(Op0) || isa<ConstantSDNode>(Op1))) &&2115!DAG.getMachineFunction().getFunction().hasMinSize()) {2116unsigned ExtendOp =2117isM68kCCUnsigned(M68kCC) ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND;2118Op0 = DAG.getNode(ExtendOp, DL, MVT::i32, Op0);2119Op1 = DAG.getNode(ExtendOp, DL, MVT::i32, Op1);2120}2121// Use SUB instead of CMP to enable CSE between SUB and CMP.2122SDVTList VTs = DAG.getVTList(Op0.getValueType(), MVT::i8);2123SDValue Sub = DAG.getNode(M68kISD::SUB, DL, VTs, Op0, Op1);2124return SDValue(Sub.getNode(), 1);2125}2126return DAG.getNode(M68kISD::CMP, DL, MVT::i8, Op0, Op1);2127}21282129/// Result of 'and' or 'trunc to i1' is compared against zero.2130/// Change to a BTST node if possible.2131SDValue M68kTargetLowering::LowerToBTST(SDValue Op, ISD::CondCode CC,2132const SDLoc &DL,2133SelectionDAG &DAG) const {2134if (Op.getOpcode() == ISD::AND)2135return LowerAndToBTST(Op, CC, DL, DAG);2136if (Op.getOpcode() == ISD::TRUNCATE && Op.getValueType() == MVT::i1)2137return LowerTruncateToBTST(Op, CC, DL, DAG);2138return SDValue();2139}21402141SDValue M68kTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {2142MVT VT = Op.getSimpleValueType();2143assert(VT == MVT::i8 && "SetCC type must be 8-bit integer");21442145SDValue Op0 = Op.getOperand(0);2146SDValue Op1 = Op.getOperand(1);2147SDLoc DL(Op);2148ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();21492150// Optimize to BTST if possible.2151// Lower (X & (1 << N)) == 0 to BTST(X, N).2152// Lower ((X >>u N) & 1) != 0 to BTST(X, N).2153// Lower ((X >>s N) & 1) != 0 to BTST(X, N).2154// Lower (trunc (X >> N) to i1) to BTST(X, N).2155if (Op0.hasOneUse() && isNullConstant(Op1) &&2156(CC == ISD::SETEQ || CC == ISD::SETNE)) {2157if (SDValue NewSetCC = LowerToBTST(Op0, CC, DL, DAG)) {2158if (VT == MVT::i1)2159return DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, NewSetCC);2160return NewSetCC;2161}2162}21632164// Look for X == 0, X == 1, X != 0, or X != 1. We can simplify some forms of2165// these.2166if ((isOneConstant(Op1) || isNullConstant(Op1)) &&2167(CC == ISD::SETEQ || CC == ISD::SETNE)) {21682169// If the input is a setcc, then reuse the input setcc or use a new one with2170// the inverted condition.2171if (Op0.getOpcode() == M68kISD::SETCC) {2172M68k::CondCode CCode = (M68k::CondCode)Op0.getConstantOperandVal(0);2173bool Invert = (CC == ISD::SETNE) ^ isNullConstant(Op1);2174if (!Invert)2175return Op0;21762177CCode = M68k::GetOppositeBranchCondition(CCode);2178SDValue SetCC =2179DAG.getNode(M68kISD::SETCC, DL, MVT::i8,2180DAG.getConstant(CCode, DL, MVT::i8), Op0.getOperand(1));2181if (VT == MVT::i1)2182return DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, SetCC);2183return SetCC;2184}2185}2186if (Op0.getValueType() == MVT::i1 && (CC == ISD::SETEQ || CC == ISD::SETNE)) {2187if (isOneConstant(Op1)) {2188ISD::CondCode NewCC = ISD::GlobalISel::getSetCCInverse(CC, true);2189return DAG.getSetCC(DL, VT, Op0, DAG.getConstant(0, DL, MVT::i1), NewCC);2190}2191if (!isNullConstant(Op1)) {2192SDValue Xor = DAG.getNode(ISD::XOR, DL, MVT::i1, Op0, Op1);2193return DAG.getSetCC(DL, VT, Xor, DAG.getConstant(0, DL, MVT::i1), CC);2194}2195}21962197bool IsFP = Op1.getSimpleValueType().isFloatingPoint();2198unsigned M68kCC = TranslateM68kCC(CC, DL, IsFP, Op0, Op1, DAG);2199if (M68kCC == M68k::COND_INVALID)2200return SDValue();22012202SDValue CCR = EmitCmp(Op0, Op1, M68kCC, DL, DAG);2203return DAG.getNode(M68kISD::SETCC, DL, MVT::i8,2204DAG.getConstant(M68kCC, DL, MVT::i8), CCR);2205}22062207SDValue M68kTargetLowering::LowerSETCCCARRY(SDValue Op,2208SelectionDAG &DAG) const {2209SDValue LHS = Op.getOperand(0);2210SDValue RHS = Op.getOperand(1);2211SDValue Carry = Op.getOperand(2);2212SDValue Cond = Op.getOperand(3);2213SDLoc DL(Op);22142215assert(LHS.getSimpleValueType().isInteger() && "SETCCCARRY is integer only.");2216M68k::CondCode CC = TranslateIntegerM68kCC(cast<CondCodeSDNode>(Cond)->get());22172218EVT CarryVT = Carry.getValueType();2219APInt NegOne = APInt::getAllOnes(CarryVT.getScalarSizeInBits());2220Carry = DAG.getNode(M68kISD::ADD, DL, DAG.getVTList(CarryVT, MVT::i32), Carry,2221DAG.getConstant(NegOne, DL, CarryVT));22222223SDVTList VTs = DAG.getVTList(LHS.getValueType(), MVT::i32);2224SDValue Cmp =2225DAG.getNode(M68kISD::SUBX, DL, VTs, LHS, RHS, Carry.getValue(1));22262227return DAG.getNode(M68kISD::SETCC, DL, MVT::i8,2228DAG.getConstant(CC, DL, MVT::i8), Cmp.getValue(1));2229}22302231/// Return true if opcode is a M68k logical comparison.2232static bool isM68kLogicalCmp(SDValue Op) {2233unsigned Opc = Op.getNode()->getOpcode();2234if (Opc == M68kISD::CMP)2235return true;2236if (Op.getResNo() == 1 &&2237(Opc == M68kISD::ADD || Opc == M68kISD::SUB || Opc == M68kISD::ADDX ||2238Opc == M68kISD::SUBX || Opc == M68kISD::SMUL || Opc == M68kISD::UMUL ||2239Opc == M68kISD::OR || Opc == M68kISD::XOR || Opc == M68kISD::AND))2240return true;22412242if (Op.getResNo() == 2 && Opc == M68kISD::UMUL)2243return true;22442245return false;2246}22472248static bool isTruncWithZeroHighBitsInput(SDValue V, SelectionDAG &DAG) {2249if (V.getOpcode() != ISD::TRUNCATE)2250return false;22512252SDValue VOp0 = V.getOperand(0);2253unsigned InBits = VOp0.getValueSizeInBits();2254unsigned Bits = V.getValueSizeInBits();2255return DAG.MaskedValueIsZero(VOp0,2256APInt::getHighBitsSet(InBits, InBits - Bits));2257}22582259SDValue M68kTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {2260bool addTest = true;2261SDValue Cond = Op.getOperand(0);2262SDValue Op1 = Op.getOperand(1);2263SDValue Op2 = Op.getOperand(2);2264SDLoc DL(Op);2265SDValue CC;22662267if (Cond.getOpcode() == ISD::SETCC) {2268if (SDValue NewCond = LowerSETCC(Cond, DAG))2269Cond = NewCond;2270}22712272// (select (x == 0), -1, y) -> (sign_bit (x - 1)) | y2273// (select (x == 0), y, -1) -> ~(sign_bit (x - 1)) | y2274// (select (x != 0), y, -1) -> (sign_bit (x - 1)) | y2275// (select (x != 0), -1, y) -> ~(sign_bit (x - 1)) | y2276if (Cond.getOpcode() == M68kISD::SETCC &&2277Cond.getOperand(1).getOpcode() == M68kISD::CMP &&2278isNullConstant(Cond.getOperand(1).getOperand(0))) {2279SDValue Cmp = Cond.getOperand(1);22802281unsigned CondCode = Cond.getConstantOperandVal(0);22822283if ((isAllOnesConstant(Op1) || isAllOnesConstant(Op2)) &&2284(CondCode == M68k::COND_EQ || CondCode == M68k::COND_NE)) {2285SDValue Y = isAllOnesConstant(Op2) ? Op1 : Op2;22862287SDValue CmpOp0 = Cmp.getOperand(1);2288// Apply further optimizations for special cases2289// (select (x != 0), -1, 0) -> neg & sbb2290// (select (x == 0), 0, -1) -> neg & sbb2291if (isNullConstant(Y) &&2292(isAllOnesConstant(Op1) == (CondCode == M68k::COND_NE))) {22932294SDVTList VTs = DAG.getVTList(CmpOp0.getValueType(), MVT::i32);22952296SDValue Neg =2297DAG.getNode(M68kISD::SUB, DL, VTs,2298DAG.getConstant(0, DL, CmpOp0.getValueType()), CmpOp0);22992300SDValue Res = DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(),2301DAG.getConstant(M68k::COND_CS, DL, MVT::i8),2302SDValue(Neg.getNode(), 1));2303return Res;2304}23052306Cmp = DAG.getNode(M68kISD::CMP, DL, MVT::i8,2307DAG.getConstant(1, DL, CmpOp0.getValueType()), CmpOp0);23082309SDValue Res = // Res = 0 or -1.2310DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(),2311DAG.getConstant(M68k::COND_CS, DL, MVT::i8), Cmp);23122313if (isAllOnesConstant(Op1) != (CondCode == M68k::COND_EQ))2314Res = DAG.getNOT(DL, Res, Res.getValueType());23152316if (!isNullConstant(Op2))2317Res = DAG.getNode(ISD::OR, DL, Res.getValueType(), Res, Y);2318return Res;2319}2320}23212322// Look past (and (setcc_carry (cmp ...)), 1).2323if (Cond.getOpcode() == ISD::AND &&2324Cond.getOperand(0).getOpcode() == M68kISD::SETCC_CARRY &&2325isOneConstant(Cond.getOperand(1)))2326Cond = Cond.getOperand(0);23272328// If condition flag is set by a M68kISD::CMP, then use it as the condition2329// setting operand in place of the M68kISD::SETCC.2330unsigned CondOpcode = Cond.getOpcode();2331if (CondOpcode == M68kISD::SETCC || CondOpcode == M68kISD::SETCC_CARRY) {2332CC = Cond.getOperand(0);23332334SDValue Cmp = Cond.getOperand(1);2335unsigned Opc = Cmp.getOpcode();23362337bool IllegalFPCMov = false;23382339if ((isM68kLogicalCmp(Cmp) && !IllegalFPCMov) || Opc == M68kISD::BTST) {2340Cond = Cmp;2341addTest = false;2342}2343} else if (isOverflowArithmetic(CondOpcode)) {2344// Result is unused here.2345SDValue Result;2346unsigned CCode;2347lowerOverflowArithmetic(Cond, DAG, Result, Cond, CCode);2348CC = DAG.getConstant(CCode, DL, MVT::i8);2349addTest = false;2350}23512352if (addTest) {2353// Look past the truncate if the high bits are known zero.2354if (isTruncWithZeroHighBitsInput(Cond, DAG))2355Cond = Cond.getOperand(0);23562357// We know the result of AND is compared against zero. Try to match2358// it to BT.2359if (Cond.getOpcode() == ISD::AND && Cond.hasOneUse()) {2360if (SDValue NewSetCC = LowerToBTST(Cond, ISD::SETNE, DL, DAG)) {2361CC = NewSetCC.getOperand(0);2362Cond = NewSetCC.getOperand(1);2363addTest = false;2364}2365}2366}23672368if (addTest) {2369CC = DAG.getConstant(M68k::COND_NE, DL, MVT::i8);2370Cond = EmitTest(Cond, M68k::COND_NE, DL, DAG);2371}23722373// a < b ? -1 : 0 -> RES = ~setcc_carry2374// a < b ? 0 : -1 -> RES = setcc_carry2375// a >= b ? -1 : 0 -> RES = setcc_carry2376// a >= b ? 0 : -1 -> RES = ~setcc_carry2377if (Cond.getOpcode() == M68kISD::SUB) {2378unsigned CondCode = CC->getAsZExtVal();23792380if ((CondCode == M68k::COND_CC || CondCode == M68k::COND_CS) &&2381(isAllOnesConstant(Op1) || isAllOnesConstant(Op2)) &&2382(isNullConstant(Op1) || isNullConstant(Op2))) {2383SDValue Res =2384DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(),2385DAG.getConstant(M68k::COND_CS, DL, MVT::i8), Cond);2386if (isAllOnesConstant(Op1) != (CondCode == M68k::COND_CS))2387return DAG.getNOT(DL, Res, Res.getValueType());2388return Res;2389}2390}23912392// M68k doesn't have an i8 cmov. If both operands are the result of a2393// truncate widen the cmov and push the truncate through. This avoids2394// introducing a new branch during isel and doesn't add any extensions.2395if (Op.getValueType() == MVT::i8 && Op1.getOpcode() == ISD::TRUNCATE &&2396Op2.getOpcode() == ISD::TRUNCATE) {2397SDValue T1 = Op1.getOperand(0), T2 = Op2.getOperand(0);2398if (T1.getValueType() == T2.getValueType() &&2399// Block CopyFromReg so partial register stalls are avoided.2400T1.getOpcode() != ISD::CopyFromReg &&2401T2.getOpcode() != ISD::CopyFromReg) {2402SDVTList VTs = DAG.getVTList(T1.getValueType(), MVT::Glue);2403SDValue Cmov = DAG.getNode(M68kISD::CMOV, DL, VTs, T2, T1, CC, Cond);2404return DAG.getNode(ISD::TRUNCATE, DL, Op.getValueType(), Cmov);2405}2406}24072408// Simple optimization when Cond is a constant to avoid generating2409// M68kISD::CMOV if possible.2410// TODO: Generalize this to use SelectionDAG::computeKnownBits.2411if (auto *Const = dyn_cast<ConstantSDNode>(Cond.getNode())) {2412const APInt &C = Const->getAPIntValue();2413if (C.countr_zero() >= 5)2414return Op2;2415else if (C.countr_one() >= 5)2416return Op1;2417}24182419// M68kISD::CMOV means set the result (which is operand 1) to the RHS if2420// condition is true.2421SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);2422SDValue Ops[] = {Op2, Op1, CC, Cond};2423return DAG.getNode(M68kISD::CMOV, DL, VTs, Ops);2424}24252426/// Return true if node is an ISD::AND or ISD::OR of two M68k::SETcc nodes2427/// each of which has no other use apart from the AND / OR.2428static bool isAndOrOfSetCCs(SDValue Op, unsigned &Opc) {2429Opc = Op.getOpcode();2430if (Opc != ISD::OR && Opc != ISD::AND)2431return false;2432return (M68k::IsSETCC(Op.getOperand(0).getOpcode()) &&2433Op.getOperand(0).hasOneUse() &&2434M68k::IsSETCC(Op.getOperand(1).getOpcode()) &&2435Op.getOperand(1).hasOneUse());2436}24372438/// Return true if node is an ISD::XOR of a M68kISD::SETCC and 1 and that the2439/// SETCC node has a single use.2440static bool isXor1OfSetCC(SDValue Op) {2441if (Op.getOpcode() != ISD::XOR)2442return false;2443if (isOneConstant(Op.getOperand(1)))2444return Op.getOperand(0).getOpcode() == M68kISD::SETCC &&2445Op.getOperand(0).hasOneUse();2446return false;2447}24482449SDValue M68kTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {2450bool AddTest = true;2451SDValue Chain = Op.getOperand(0);2452SDValue Cond = Op.getOperand(1);2453SDValue Dest = Op.getOperand(2);2454SDLoc DL(Op);2455SDValue CC;2456bool Inverted = false;24572458if (Cond.getOpcode() == ISD::SETCC) {2459// Check for setcc([su]{add,sub}o == 0).2460if (cast<CondCodeSDNode>(Cond.getOperand(2))->get() == ISD::SETEQ &&2461isNullConstant(Cond.getOperand(1)) &&2462Cond.getOperand(0).getResNo() == 1 &&2463(Cond.getOperand(0).getOpcode() == ISD::SADDO ||2464Cond.getOperand(0).getOpcode() == ISD::UADDO ||2465Cond.getOperand(0).getOpcode() == ISD::SSUBO ||2466Cond.getOperand(0).getOpcode() == ISD::USUBO)) {2467Inverted = true;2468Cond = Cond.getOperand(0);2469} else {2470if (SDValue NewCond = LowerSETCC(Cond, DAG))2471Cond = NewCond;2472}2473}24742475// Look pass (and (setcc_carry (cmp ...)), 1).2476if (Cond.getOpcode() == ISD::AND &&2477Cond.getOperand(0).getOpcode() == M68kISD::SETCC_CARRY &&2478isOneConstant(Cond.getOperand(1)))2479Cond = Cond.getOperand(0);24802481// If condition flag is set by a M68kISD::CMP, then use it as the condition2482// setting operand in place of the M68kISD::SETCC.2483unsigned CondOpcode = Cond.getOpcode();2484if (CondOpcode == M68kISD::SETCC || CondOpcode == M68kISD::SETCC_CARRY) {2485CC = Cond.getOperand(0);24862487SDValue Cmp = Cond.getOperand(1);2488unsigned Opc = Cmp.getOpcode();24892490if (isM68kLogicalCmp(Cmp) || Opc == M68kISD::BTST) {2491Cond = Cmp;2492AddTest = false;2493} else {2494switch (CC->getAsZExtVal()) {2495default:2496break;2497case M68k::COND_VS:2498case M68k::COND_CS:2499// These can only come from an arithmetic instruction with overflow,2500// e.g. SADDO, UADDO.2501Cond = Cond.getNode()->getOperand(1);2502AddTest = false;2503break;2504}2505}2506}2507CondOpcode = Cond.getOpcode();2508if (isOverflowArithmetic(CondOpcode)) {2509SDValue Result;2510unsigned CCode;2511lowerOverflowArithmetic(Cond, DAG, Result, Cond, CCode);25122513if (Inverted)2514CCode = M68k::GetOppositeBranchCondition((M68k::CondCode)CCode);2515CC = DAG.getConstant(CCode, DL, MVT::i8);25162517AddTest = false;2518} else {2519unsigned CondOpc;2520if (Cond.hasOneUse() && isAndOrOfSetCCs(Cond, CondOpc)) {2521SDValue Cmp = Cond.getOperand(0).getOperand(1);2522if (CondOpc == ISD::OR) {2523// Also, recognize the pattern generated by an FCMP_UNE. We can emit2524// two branches instead of an explicit OR instruction with a2525// separate test.2526if (Cmp == Cond.getOperand(1).getOperand(1) && isM68kLogicalCmp(Cmp)) {2527CC = Cond.getOperand(0).getOperand(0);2528Chain = DAG.getNode(M68kISD::BRCOND, DL, Op.getValueType(), Chain,2529Dest, CC, Cmp);2530CC = Cond.getOperand(1).getOperand(0);2531Cond = Cmp;2532AddTest = false;2533}2534} else { // ISD::AND2535// Also, recognize the pattern generated by an FCMP_OEQ. We can emit2536// two branches instead of an explicit AND instruction with a2537// separate test. However, we only do this if this block doesn't2538// have a fall-through edge, because this requires an explicit2539// jmp when the condition is false.2540if (Cmp == Cond.getOperand(1).getOperand(1) && isM68kLogicalCmp(Cmp) &&2541Op.getNode()->hasOneUse()) {2542M68k::CondCode CCode =2543(M68k::CondCode)Cond.getOperand(0).getConstantOperandVal(0);2544CCode = M68k::GetOppositeBranchCondition(CCode);2545CC = DAG.getConstant(CCode, DL, MVT::i8);2546SDNode *User = *Op.getNode()->use_begin();2547// Look for an unconditional branch following this conditional branch.2548// We need this because we need to reverse the successors in order2549// to implement FCMP_OEQ.2550if (User->getOpcode() == ISD::BR) {2551SDValue FalseBB = User->getOperand(1);2552SDNode *NewBR =2553DAG.UpdateNodeOperands(User, User->getOperand(0), Dest);2554assert(NewBR == User);2555(void)NewBR;2556Dest = FalseBB;25572558Chain = DAG.getNode(M68kISD::BRCOND, DL, Op.getValueType(), Chain,2559Dest, CC, Cmp);2560M68k::CondCode CCode =2561(M68k::CondCode)Cond.getOperand(1).getConstantOperandVal(0);2562CCode = M68k::GetOppositeBranchCondition(CCode);2563CC = DAG.getConstant(CCode, DL, MVT::i8);2564Cond = Cmp;2565AddTest = false;2566}2567}2568}2569} else if (Cond.hasOneUse() && isXor1OfSetCC(Cond)) {2570// Recognize for xorb (setcc), 1 patterns. The xor inverts the condition.2571// It should be transformed during dag combiner except when the condition2572// is set by a arithmetics with overflow node.2573M68k::CondCode CCode =2574(M68k::CondCode)Cond.getOperand(0).getConstantOperandVal(0);2575CCode = M68k::GetOppositeBranchCondition(CCode);2576CC = DAG.getConstant(CCode, DL, MVT::i8);2577Cond = Cond.getOperand(0).getOperand(1);2578AddTest = false;2579}2580}25812582if (AddTest) {2583// Look pass the truncate if the high bits are known zero.2584if (isTruncWithZeroHighBitsInput(Cond, DAG))2585Cond = Cond.getOperand(0);25862587// We know the result is compared against zero. Try to match it to BT.2588if (Cond.hasOneUse()) {2589if (SDValue NewSetCC = LowerToBTST(Cond, ISD::SETNE, DL, DAG)) {2590CC = NewSetCC.getOperand(0);2591Cond = NewSetCC.getOperand(1);2592AddTest = false;2593}2594}2595}25962597if (AddTest) {2598M68k::CondCode MxCond = Inverted ? M68k::COND_EQ : M68k::COND_NE;2599CC = DAG.getConstant(MxCond, DL, MVT::i8);2600Cond = EmitTest(Cond, MxCond, DL, DAG);2601}2602return DAG.getNode(M68kISD::BRCOND, DL, Op.getValueType(), Chain, Dest, CC,2603Cond);2604}26052606SDValue M68kTargetLowering::LowerADDC_ADDE_SUBC_SUBE(SDValue Op,2607SelectionDAG &DAG) const {2608MVT VT = Op.getNode()->getSimpleValueType(0);26092610// Let legalize expand this if it isn't a legal type yet.2611if (!DAG.getTargetLoweringInfo().isTypeLegal(VT))2612return SDValue();26132614SDVTList VTs = DAG.getVTList(VT, MVT::i8);26152616unsigned Opc;2617bool ExtraOp = false;2618switch (Op.getOpcode()) {2619default:2620llvm_unreachable("Invalid code");2621case ISD::ADDC:2622Opc = M68kISD::ADD;2623break;2624case ISD::ADDE:2625Opc = M68kISD::ADDX;2626ExtraOp = true;2627break;2628case ISD::SUBC:2629Opc = M68kISD::SUB;2630break;2631case ISD::SUBE:2632Opc = M68kISD::SUBX;2633ExtraOp = true;2634break;2635}26362637if (!ExtraOp)2638return DAG.getNode(Opc, SDLoc(Op), VTs, Op.getOperand(0), Op.getOperand(1));2639return DAG.getNode(Opc, SDLoc(Op), VTs, Op.getOperand(0), Op.getOperand(1),2640Op.getOperand(2));2641}26422643// ConstantPool, JumpTable, GlobalAddress, and ExternalSymbol are lowered as2644// their target countpart wrapped in the M68kISD::Wrapper node. Suppose N is2645// one of the above mentioned nodes. It has to be wrapped because otherwise2646// Select(N) returns N. So the raw TargetGlobalAddress nodes, etc. can only2647// be used to form addressing mode. These wrapped nodes will be selected2648// into MOV32ri.2649SDValue M68kTargetLowering::LowerConstantPool(SDValue Op,2650SelectionDAG &DAG) const {2651ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);26522653// In PIC mode (unless we're in PCRel PIC mode) we add an offset to the2654// global base reg.2655unsigned char OpFlag = Subtarget.classifyLocalReference(nullptr);26562657unsigned WrapperKind = M68kISD::Wrapper;2658if (M68kII::isPCRelGlobalReference(OpFlag)) {2659WrapperKind = M68kISD::WrapperPC;2660}26612662MVT PtrVT = getPointerTy(DAG.getDataLayout());2663SDValue Result = DAG.getTargetConstantPool(2664CP->getConstVal(), PtrVT, CP->getAlign(), CP->getOffset(), OpFlag);26652666SDLoc DL(CP);2667Result = DAG.getNode(WrapperKind, DL, PtrVT, Result);26682669// With PIC, the address is actually $g + Offset.2670if (M68kII::isGlobalRelativeToPICBase(OpFlag)) {2671Result = DAG.getNode(ISD::ADD, DL, PtrVT,2672DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(), PtrVT),2673Result);2674}26752676return Result;2677}26782679SDValue M68kTargetLowering::LowerExternalSymbol(SDValue Op,2680SelectionDAG &DAG) const {2681const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();26822683// In PIC mode (unless we're in PCRel PIC mode) we add an offset to the2684// global base reg.2685const Module *Mod = DAG.getMachineFunction().getFunction().getParent();2686unsigned char OpFlag = Subtarget.classifyExternalReference(*Mod);26872688unsigned WrapperKind = M68kISD::Wrapper;2689if (M68kII::isPCRelGlobalReference(OpFlag)) {2690WrapperKind = M68kISD::WrapperPC;2691}26922693auto PtrVT = getPointerTy(DAG.getDataLayout());2694SDValue Result = DAG.getTargetExternalSymbol(Sym, PtrVT, OpFlag);26952696SDLoc DL(Op);2697Result = DAG.getNode(WrapperKind, DL, PtrVT, Result);26982699// With PIC, the address is actually $g + Offset.2700if (M68kII::isGlobalRelativeToPICBase(OpFlag)) {2701Result = DAG.getNode(ISD::ADD, DL, PtrVT,2702DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(), PtrVT),2703Result);2704}27052706// For symbols that require a load from a stub to get the address, emit the2707// load.2708if (M68kII::isGlobalStubReference(OpFlag)) {2709Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Result,2710MachinePointerInfo::getGOT(DAG.getMachineFunction()));2711}27122713return Result;2714}27152716SDValue M68kTargetLowering::LowerBlockAddress(SDValue Op,2717SelectionDAG &DAG) const {2718unsigned char OpFlags = Subtarget.classifyBlockAddressReference();2719const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();2720int64_t Offset = cast<BlockAddressSDNode>(Op)->getOffset();2721SDLoc DL(Op);2722auto PtrVT = getPointerTy(DAG.getDataLayout());27232724// Create the TargetBlockAddressAddress node.2725SDValue Result = DAG.getTargetBlockAddress(BA, PtrVT, Offset, OpFlags);27262727if (M68kII::isPCRelBlockReference(OpFlags)) {2728Result = DAG.getNode(M68kISD::WrapperPC, DL, PtrVT, Result);2729} else {2730Result = DAG.getNode(M68kISD::Wrapper, DL, PtrVT, Result);2731}27322733// With PIC, the address is actually $g + Offset.2734if (M68kII::isGlobalRelativeToPICBase(OpFlags)) {2735Result =2736DAG.getNode(ISD::ADD, DL, PtrVT,2737DAG.getNode(M68kISD::GLOBAL_BASE_REG, DL, PtrVT), Result);2738}27392740return Result;2741}27422743SDValue M68kTargetLowering::LowerGlobalAddress(const GlobalValue *GV,2744const SDLoc &DL, int64_t Offset,2745SelectionDAG &DAG) const {2746unsigned char OpFlags = Subtarget.classifyGlobalReference(GV);2747auto PtrVT = getPointerTy(DAG.getDataLayout());27482749// Create the TargetGlobalAddress node, folding in the constant2750// offset if it is legal.2751SDValue Result;2752if (M68kII::isDirectGlobalReference(OpFlags)) {2753Result = DAG.getTargetGlobalAddress(GV, DL, PtrVT, Offset);2754Offset = 0;2755} else {2756Result = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, OpFlags);2757}27582759if (M68kII::isPCRelGlobalReference(OpFlags))2760Result = DAG.getNode(M68kISD::WrapperPC, DL, PtrVT, Result);2761else2762Result = DAG.getNode(M68kISD::Wrapper, DL, PtrVT, Result);27632764// With PIC, the address is actually $g + Offset.2765if (M68kII::isGlobalRelativeToPICBase(OpFlags)) {2766Result =2767DAG.getNode(ISD::ADD, DL, PtrVT,2768DAG.getNode(M68kISD::GLOBAL_BASE_REG, DL, PtrVT), Result);2769}27702771// For globals that require a load from a stub to get the address, emit the2772// load.2773if (M68kII::isGlobalStubReference(OpFlags)) {2774Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Result,2775MachinePointerInfo::getGOT(DAG.getMachineFunction()));2776}27772778// If there was a non-zero offset that we didn't fold, create an explicit2779// addition for it.2780if (Offset != 0) {2781Result = DAG.getNode(ISD::ADD, DL, PtrVT, Result,2782DAG.getConstant(Offset, DL, PtrVT));2783}27842785return Result;2786}27872788SDValue M68kTargetLowering::LowerGlobalAddress(SDValue Op,2789SelectionDAG &DAG) const {2790const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();2791int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();2792return LowerGlobalAddress(GV, SDLoc(Op), Offset, DAG);2793}27942795//===----------------------------------------------------------------------===//2796// Custom Lower Jump Table2797//===----------------------------------------------------------------------===//27982799SDValue M68kTargetLowering::LowerJumpTable(SDValue Op,2800SelectionDAG &DAG) const {2801JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);28022803// In PIC mode (unless we're in PCRel PIC mode) we add an offset to the2804// global base reg.2805unsigned char OpFlag = Subtarget.classifyLocalReference(nullptr);28062807unsigned WrapperKind = M68kISD::Wrapper;2808if (M68kII::isPCRelGlobalReference(OpFlag)) {2809WrapperKind = M68kISD::WrapperPC;2810}28112812auto PtrVT = getPointerTy(DAG.getDataLayout());2813SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OpFlag);2814SDLoc DL(JT);2815Result = DAG.getNode(WrapperKind, DL, PtrVT, Result);28162817// With PIC, the address is actually $g + Offset.2818if (M68kII::isGlobalRelativeToPICBase(OpFlag)) {2819Result = DAG.getNode(ISD::ADD, DL, PtrVT,2820DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(), PtrVT),2821Result);2822}28232824return Result;2825}28262827unsigned M68kTargetLowering::getJumpTableEncoding() const {2828return Subtarget.getJumpTableEncoding();2829}28302831const MCExpr *M68kTargetLowering::LowerCustomJumpTableEntry(2832const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB,2833unsigned uid, MCContext &Ctx) const {2834return MCSymbolRefExpr::create(MBB->getSymbol(), MCSymbolRefExpr::VK_GOTOFF,2835Ctx);2836}28372838SDValue M68kTargetLowering::getPICJumpTableRelocBase(SDValue Table,2839SelectionDAG &DAG) const {2840if (getJumpTableEncoding() == MachineJumpTableInfo::EK_Custom32)2841return DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(),2842getPointerTy(DAG.getDataLayout()));28432844// MachineJumpTableInfo::EK_LabelDifference32 entry2845return Table;2846}28472848// NOTE This only used for MachineJumpTableInfo::EK_LabelDifference32 entries2849const MCExpr *M68kTargetLowering::getPICJumpTableRelocBaseExpr(2850const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const {2851return MCSymbolRefExpr::create(MF->getJTISymbol(JTI, Ctx), Ctx);2852}28532854M68kTargetLowering::ConstraintType2855M68kTargetLowering::getConstraintType(StringRef Constraint) const {2856if (Constraint.size() > 0) {2857switch (Constraint[0]) {2858case 'a':2859case 'd':2860return C_RegisterClass;2861case 'I':2862case 'J':2863case 'K':2864case 'L':2865case 'M':2866case 'N':2867case 'O':2868case 'P':2869return C_Immediate;2870case 'C':2871if (Constraint.size() == 2)2872switch (Constraint[1]) {2873case '0':2874case 'i':2875case 'j':2876return C_Immediate;2877default:2878break;2879}2880break;2881case 'Q':2882case 'U':2883return C_Memory;2884default:2885break;2886}2887}28882889return TargetLowering::getConstraintType(Constraint);2890}28912892void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op,2893StringRef Constraint,2894std::vector<SDValue> &Ops,2895SelectionDAG &DAG) const {2896SDValue Result;28972898if (Constraint.size() == 1) {2899// Constant constraints2900switch (Constraint[0]) {2901case 'I':2902case 'J':2903case 'K':2904case 'L':2905case 'M':2906case 'N':2907case 'O':2908case 'P': {2909auto *C = dyn_cast<ConstantSDNode>(Op);2910if (!C)2911return;29122913int64_t Val = C->getSExtValue();2914switch (Constraint[0]) {2915case 'I': // constant integer in the range [1,8]2916if (Val > 0 && Val <= 8)2917break;2918return;2919case 'J': // constant signed 16-bit integer2920if (isInt<16>(Val))2921break;2922return;2923case 'K': // constant that is NOT in the range of [-0x80, 0x80)2924if (Val < -0x80 || Val >= 0x80)2925break;2926return;2927case 'L': // constant integer in the range [-8,-1]2928if (Val < 0 && Val >= -8)2929break;2930return;2931case 'M': // constant that is NOT in the range of [-0x100, 0x100]2932if (Val < -0x100 || Val >= 0x100)2933break;2934return;2935case 'N': // constant integer in the range [24,31]2936if (Val >= 24 && Val <= 31)2937break;2938return;2939case 'O': // constant integer 162940if (Val == 16)2941break;2942return;2943case 'P': // constant integer in the range [8,15]2944if (Val >= 8 && Val <= 15)2945break;2946return;2947default:2948llvm_unreachable("Unhandled constant constraint");2949}29502951Result = DAG.getTargetConstant(Val, SDLoc(Op), Op.getValueType());2952break;2953}2954default:2955break;2956}2957}29582959if (Constraint.size() == 2) {2960switch (Constraint[0]) {2961case 'C':2962// Constant constraints start with 'C'2963switch (Constraint[1]) {2964case '0':2965case 'i':2966case 'j': {2967auto *C = dyn_cast<ConstantSDNode>(Op);2968if (!C)2969break;29702971int64_t Val = C->getSExtValue();2972switch (Constraint[1]) {2973case '0': // constant integer 02974if (!Val)2975break;2976return;2977case 'i': // constant integer2978break;2979case 'j': // integer constant that doesn't fit in 16 bits2980if (!isInt<16>(C->getSExtValue()))2981break;2982return;2983default:2984llvm_unreachable("Unhandled constant constraint");2985}29862987Result = DAG.getTargetConstant(Val, SDLoc(Op), Op.getValueType());2988break;2989}2990default:2991break;2992}2993break;2994default:2995break;2996}2997}29982999if (Result.getNode()) {3000Ops.push_back(Result);3001return;3002}30033004TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);3005}30063007std::pair<unsigned, const TargetRegisterClass *>3008M68kTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,3009StringRef Constraint,3010MVT VT) const {3011if (Constraint.size() == 1) {3012switch (Constraint[0]) {3013case 'r':3014case 'd':3015switch (VT.SimpleTy) {3016case MVT::i8:3017return std::make_pair(0U, &M68k::DR8RegClass);3018case MVT::i16:3019return std::make_pair(0U, &M68k::DR16RegClass);3020case MVT::i32:3021return std::make_pair(0U, &M68k::DR32RegClass);3022default:3023break;3024}3025break;3026case 'a':3027switch (VT.SimpleTy) {3028case MVT::i16:3029return std::make_pair(0U, &M68k::AR16RegClass);3030case MVT::i32:3031return std::make_pair(0U, &M68k::AR32RegClass);3032default:3033break;3034}3035break;3036default:3037break;3038}3039}30403041return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);3042}30433044/// Determines whether the callee is required to pop its own arguments.3045/// Callee pop is necessary to support tail calls.3046bool M68k::isCalleePop(CallingConv::ID CC, bool IsVarArg, bool GuaranteeTCO) {3047return CC == CallingConv::M68k_RTD && !IsVarArg;3048}30493050// Return true if it is OK for this CMOV pseudo-opcode to be cascaded3051// together with other CMOV pseudo-opcodes into a single basic-block with3052// conditional jump around it.3053static bool isCMOVPseudo(MachineInstr &MI) {3054switch (MI.getOpcode()) {3055case M68k::CMOV8d:3056case M68k::CMOV16d:3057case M68k::CMOV32r:3058return true;30593060default:3061return false;3062}3063}30643065// The CCR operand of SelectItr might be missing a kill marker3066// because there were multiple uses of CCR, and ISel didn't know3067// which to mark. Figure out whether SelectItr should have had a3068// kill marker, and set it if it should. Returns the correct kill3069// marker value.3070static bool checkAndUpdateCCRKill(MachineBasicBlock::iterator SelectItr,3071MachineBasicBlock *BB,3072const TargetRegisterInfo *TRI) {3073// Scan forward through BB for a use/def of CCR.3074MachineBasicBlock::iterator miI(std::next(SelectItr));3075for (MachineBasicBlock::iterator miE = BB->end(); miI != miE; ++miI) {3076const MachineInstr &mi = *miI;3077if (mi.readsRegister(M68k::CCR, /*TRI=*/nullptr))3078return false;3079if (mi.definesRegister(M68k::CCR, /*TRI=*/nullptr))3080break; // Should have kill-flag - update below.3081}30823083// If we hit the end of the block, check whether CCR is live into a3084// successor.3085if (miI == BB->end())3086for (const auto *SBB : BB->successors())3087if (SBB->isLiveIn(M68k::CCR))3088return false;30893090// We found a def, or hit the end of the basic block and CCR wasn't live3091// out. SelectMI should have a kill flag on CCR.3092SelectItr->addRegisterKilled(M68k::CCR, TRI);3093return true;3094}30953096MachineBasicBlock *3097M68kTargetLowering::EmitLoweredSelect(MachineInstr &MI,3098MachineBasicBlock *MBB) const {3099const TargetInstrInfo *TII = Subtarget.getInstrInfo();3100DebugLoc DL = MI.getDebugLoc();31013102// To "insert" a SELECT_CC instruction, we actually have to insert the3103// diamond control-flow pattern. The incoming instruction knows the3104// destination vreg to set, the condition code register to branch on, the3105// true/false values to select between, and a branch opcode to use.3106const BasicBlock *BB = MBB->getBasicBlock();3107MachineFunction::iterator It = ++MBB->getIterator();31083109// ThisMBB:3110// ...3111// TrueVal = ...3112// cmp ccX, r1, r23113// bcc Copy1MBB3114// fallthrough --> Copy0MBB3115MachineBasicBlock *ThisMBB = MBB;3116MachineFunction *F = MBB->getParent();31173118// This code lowers all pseudo-CMOV instructions. Generally it lowers these3119// as described above, by inserting a MBB, and then making a PHI at the join3120// point to select the true and false operands of the CMOV in the PHI.3121//3122// The code also handles two different cases of multiple CMOV opcodes3123// in a row.3124//3125// Case 1:3126// In this case, there are multiple CMOVs in a row, all which are based on3127// the same condition setting (or the exact opposite condition setting).3128// In this case we can lower all the CMOVs using a single inserted MBB, and3129// then make a number of PHIs at the join point to model the CMOVs. The only3130// trickiness here, is that in a case like:3131//3132// t2 = CMOV cond1 t1, f13133// t3 = CMOV cond1 t2, f23134//3135// when rewriting this into PHIs, we have to perform some renaming on the3136// temps since you cannot have a PHI operand refer to a PHI result earlier3137// in the same block. The "simple" but wrong lowering would be:3138//3139// t2 = PHI t1(BB1), f1(BB2)3140// t3 = PHI t2(BB1), f2(BB2)3141//3142// but clearly t2 is not defined in BB1, so that is incorrect. The proper3143// renaming is to note that on the path through BB1, t2 is really just a3144// copy of t1, and do that renaming, properly generating:3145//3146// t2 = PHI t1(BB1), f1(BB2)3147// t3 = PHI t1(BB1), f2(BB2)3148//3149// Case 2, we lower cascaded CMOVs such as3150//3151// (CMOV (CMOV F, T, cc1), T, cc2)3152//3153// to two successives branches.3154MachineInstr *CascadedCMOV = nullptr;3155MachineInstr *LastCMOV = &MI;3156M68k::CondCode CC = M68k::CondCode(MI.getOperand(3).getImm());3157M68k::CondCode OppCC = M68k::GetOppositeBranchCondition(CC);3158MachineBasicBlock::iterator NextMIIt =3159std::next(MachineBasicBlock::iterator(MI));31603161// Check for case 1, where there are multiple CMOVs with the same condition3162// first. Of the two cases of multiple CMOV lowerings, case 1 reduces the3163// number of jumps the most.31643165if (isCMOVPseudo(MI)) {3166// See if we have a string of CMOVS with the same condition.3167while (NextMIIt != MBB->end() && isCMOVPseudo(*NextMIIt) &&3168(NextMIIt->getOperand(3).getImm() == CC ||3169NextMIIt->getOperand(3).getImm() == OppCC)) {3170LastCMOV = &*NextMIIt;3171++NextMIIt;3172}3173}31743175// This checks for case 2, but only do this if we didn't already find3176// case 1, as indicated by LastCMOV == MI.3177if (LastCMOV == &MI && NextMIIt != MBB->end() &&3178NextMIIt->getOpcode() == MI.getOpcode() &&3179NextMIIt->getOperand(2).getReg() == MI.getOperand(2).getReg() &&3180NextMIIt->getOperand(1).getReg() == MI.getOperand(0).getReg() &&3181NextMIIt->getOperand(1).isKill()) {3182CascadedCMOV = &*NextMIIt;3183}31843185MachineBasicBlock *Jcc1MBB = nullptr;31863187// If we have a cascaded CMOV, we lower it to two successive branches to3188// the same block. CCR is used by both, so mark it as live in the second.3189if (CascadedCMOV) {3190Jcc1MBB = F->CreateMachineBasicBlock(BB);3191F->insert(It, Jcc1MBB);3192Jcc1MBB->addLiveIn(M68k::CCR);3193}31943195MachineBasicBlock *Copy0MBB = F->CreateMachineBasicBlock(BB);3196MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(BB);3197F->insert(It, Copy0MBB);3198F->insert(It, SinkMBB);31993200// Set the call frame size on entry to the new basic blocks.3201unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);3202Copy0MBB->setCallFrameSize(CallFrameSize);3203SinkMBB->setCallFrameSize(CallFrameSize);32043205// If the CCR register isn't dead in the terminator, then claim that it's3206// live into the sink and copy blocks.3207const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();32083209MachineInstr *LastCCRSUser = CascadedCMOV ? CascadedCMOV : LastCMOV;3210if (!LastCCRSUser->killsRegister(M68k::CCR, /*TRI=*/nullptr) &&3211!checkAndUpdateCCRKill(LastCCRSUser, MBB, TRI)) {3212Copy0MBB->addLiveIn(M68k::CCR);3213SinkMBB->addLiveIn(M68k::CCR);3214}32153216// Transfer the remainder of MBB and its successor edges to SinkMBB.3217SinkMBB->splice(SinkMBB->begin(), MBB,3218std::next(MachineBasicBlock::iterator(LastCMOV)), MBB->end());3219SinkMBB->transferSuccessorsAndUpdatePHIs(MBB);32203221// Add the true and fallthrough blocks as its successors.3222if (CascadedCMOV) {3223// The fallthrough block may be Jcc1MBB, if we have a cascaded CMOV.3224MBB->addSuccessor(Jcc1MBB);32253226// In that case, Jcc1MBB will itself fallthrough the Copy0MBB, and3227// jump to the SinkMBB.3228Jcc1MBB->addSuccessor(Copy0MBB);3229Jcc1MBB->addSuccessor(SinkMBB);3230} else {3231MBB->addSuccessor(Copy0MBB);3232}32333234// The true block target of the first (or only) branch is always SinkMBB.3235MBB->addSuccessor(SinkMBB);32363237// Create the conditional branch instruction.3238unsigned Opc = M68k::GetCondBranchFromCond(CC);3239BuildMI(MBB, DL, TII->get(Opc)).addMBB(SinkMBB);32403241if (CascadedCMOV) {3242unsigned Opc2 = M68k::GetCondBranchFromCond(3243(M68k::CondCode)CascadedCMOV->getOperand(3).getImm());3244BuildMI(Jcc1MBB, DL, TII->get(Opc2)).addMBB(SinkMBB);3245}32463247// Copy0MBB:3248// %FalseValue = ...3249// # fallthrough to SinkMBB3250Copy0MBB->addSuccessor(SinkMBB);32513252// SinkMBB:3253// %Result = phi [ %FalseValue, Copy0MBB ], [ %TrueValue, ThisMBB ]3254// ...3255MachineBasicBlock::iterator MIItBegin = MachineBasicBlock::iterator(MI);3256MachineBasicBlock::iterator MIItEnd =3257std::next(MachineBasicBlock::iterator(LastCMOV));3258MachineBasicBlock::iterator SinkInsertionPoint = SinkMBB->begin();3259DenseMap<unsigned, std::pair<unsigned, unsigned>> RegRewriteTable;3260MachineInstrBuilder MIB;32613262// As we are creating the PHIs, we have to be careful if there is more than3263// one. Later CMOVs may reference the results of earlier CMOVs, but later3264// PHIs have to reference the individual true/false inputs from earlier PHIs.3265// That also means that PHI construction must work forward from earlier to3266// later, and that the code must maintain a mapping from earlier PHI's3267// destination registers, and the registers that went into the PHI.32683269for (MachineBasicBlock::iterator MIIt = MIItBegin; MIIt != MIItEnd; ++MIIt) {3270Register DestReg = MIIt->getOperand(0).getReg();3271Register Op1Reg = MIIt->getOperand(1).getReg();3272Register Op2Reg = MIIt->getOperand(2).getReg();32733274// If this CMOV we are generating is the opposite condition from3275// the jump we generated, then we have to swap the operands for the3276// PHI that is going to be generated.3277if (MIIt->getOperand(3).getImm() == OppCC)3278std::swap(Op1Reg, Op2Reg);32793280if (RegRewriteTable.find(Op1Reg) != RegRewriteTable.end())3281Op1Reg = RegRewriteTable[Op1Reg].first;32823283if (RegRewriteTable.find(Op2Reg) != RegRewriteTable.end())3284Op2Reg = RegRewriteTable[Op2Reg].second;32853286MIB =3287BuildMI(*SinkMBB, SinkInsertionPoint, DL, TII->get(M68k::PHI), DestReg)3288.addReg(Op1Reg)3289.addMBB(Copy0MBB)3290.addReg(Op2Reg)3291.addMBB(ThisMBB);32923293// Add this PHI to the rewrite table.3294RegRewriteTable[DestReg] = std::make_pair(Op1Reg, Op2Reg);3295}32963297// If we have a cascaded CMOV, the second Jcc provides the same incoming3298// value as the first Jcc (the True operand of the SELECT_CC/CMOV nodes).3299if (CascadedCMOV) {3300MIB.addReg(MI.getOperand(2).getReg()).addMBB(Jcc1MBB);3301// Copy the PHI result to the register defined by the second CMOV.3302BuildMI(*SinkMBB, std::next(MachineBasicBlock::iterator(MIB.getInstr())),3303DL, TII->get(TargetOpcode::COPY),3304CascadedCMOV->getOperand(0).getReg())3305.addReg(MI.getOperand(0).getReg());3306CascadedCMOV->eraseFromParent();3307}33083309// Now remove the CMOV(s).3310for (MachineBasicBlock::iterator MIIt = MIItBegin; MIIt != MIItEnd;)3311(MIIt++)->eraseFromParent();33123313return SinkMBB;3314}33153316MachineBasicBlock *3317M68kTargetLowering::EmitLoweredSegAlloca(MachineInstr &MI,3318MachineBasicBlock *BB) const {3319llvm_unreachable("Cannot lower Segmented Stack Alloca with stack-split on");3320}33213322MachineBasicBlock *3323M68kTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,3324MachineBasicBlock *BB) const {3325switch (MI.getOpcode()) {3326default:3327llvm_unreachable("Unexpected instr type to insert");3328case M68k::CMOV8d:3329case M68k::CMOV16d:3330case M68k::CMOV32r:3331return EmitLoweredSelect(MI, BB);3332case M68k::SALLOCA:3333return EmitLoweredSegAlloca(MI, BB);3334}3335}33363337SDValue M68kTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {3338MachineFunction &MF = DAG.getMachineFunction();3339auto PtrVT = getPointerTy(MF.getDataLayout());3340M68kMachineFunctionInfo *FuncInfo = MF.getInfo<M68kMachineFunctionInfo>();33413342const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();3343SDLoc DL(Op);33443345// vastart just stores the address of the VarArgsFrameIndex slot into the3346// memory location argument.3347SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);3348return DAG.getStore(Op.getOperand(0), DL, FR, Op.getOperand(1),3349MachinePointerInfo(SV));3350}33513352SDValue M68kTargetLowering::LowerATOMICFENCE(SDValue Op,3353SelectionDAG &DAG) const {3354// Lower to a memory barrier created from inline asm.3355const TargetLowering &TLI = DAG.getTargetLoweringInfo();3356LLVMContext &Ctx = *DAG.getContext();33573358const unsigned Flags = InlineAsm::Extra_MayLoad | InlineAsm::Extra_MayStore |3359InlineAsm::Extra_HasSideEffects;3360const SDValue AsmOperands[4] = {3361Op.getOperand(0), // Input chain3362DAG.getTargetExternalSymbol(3363"", TLI.getProgramPointerTy(3364DAG.getDataLayout())), // Empty inline asm string3365DAG.getMDNode(MDNode::get(Ctx, {})), // (empty) srcloc3366DAG.getTargetConstant(Flags, SDLoc(Op),3367TLI.getPointerTy(DAG.getDataLayout())), // Flags3368};33693370return DAG.getNode(ISD::INLINEASM, SDLoc(Op),3371DAG.getVTList(MVT::Other, MVT::Glue), AsmOperands);3372}33733374// Lower dynamic stack allocation to _alloca call for Cygwin/Mingw targets.3375// Calls to _alloca are needed to probe the stack when allocating more than 4k3376// bytes in one go. Touching the stack at 4K increments is necessary to ensure3377// that the guard pages used by the OS virtual memory manager are allocated in3378// correct sequence.3379SDValue M68kTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,3380SelectionDAG &DAG) const {3381MachineFunction &MF = DAG.getMachineFunction();3382bool SplitStack = MF.shouldSplitStack();33833384SDLoc DL(Op);33853386// Get the inputs.3387SDNode *Node = Op.getNode();3388SDValue Chain = Op.getOperand(0);3389SDValue Size = Op.getOperand(1);3390unsigned Align = Op.getConstantOperandVal(2);3391EVT VT = Node->getValueType(0);33923393// Chain the dynamic stack allocation so that it doesn't modify the stack3394// pointer when other instructions are using the stack.3395Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL);33963397SDValue Result;3398if (SplitStack) {3399auto &MRI = MF.getRegInfo();3400auto SPTy = getPointerTy(DAG.getDataLayout());3401auto *ARClass = getRegClassFor(SPTy);3402Register Vreg = MRI.createVirtualRegister(ARClass);3403Chain = DAG.getCopyToReg(Chain, DL, Vreg, Size);3404Result = DAG.getNode(M68kISD::SEG_ALLOCA, DL, SPTy, Chain,3405DAG.getRegister(Vreg, SPTy));3406} else {3407auto &TLI = DAG.getTargetLoweringInfo();3408Register SPReg = TLI.getStackPointerRegisterToSaveRestore();3409assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and"3410" not tell us which reg is the stack pointer!");34113412SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT);3413Chain = SP.getValue(1);3414const TargetFrameLowering &TFI = *Subtarget.getFrameLowering();3415unsigned StackAlign = TFI.getStackAlignment();3416Result = DAG.getNode(ISD::SUB, DL, VT, SP, Size); // Value3417if (Align > StackAlign)3418Result = DAG.getNode(ISD::AND, DL, VT, Result,3419DAG.getConstant(-(uint64_t)Align, DL, VT));3420Chain = DAG.getCopyToReg(Chain, DL, SPReg, Result); // Output chain3421}34223423Chain = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), DL);34243425SDValue Ops[2] = {Result, Chain};3426return DAG.getMergeValues(Ops, DL);3427}34283429SDValue M68kTargetLowering::LowerShiftLeftParts(SDValue Op,3430SelectionDAG &DAG) const {3431SDLoc DL(Op);3432SDValue Lo = Op.getOperand(0);3433SDValue Hi = Op.getOperand(1);3434SDValue Shamt = Op.getOperand(2);3435EVT VT = Lo.getValueType();34363437// if Shamt - register size < 0: // Shamt < register size3438// Lo = Lo << Shamt3439// Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (register size - 1 ^ Shamt))3440// else:3441// Lo = 03442// Hi = Lo << (Shamt - register size)34433444SDValue Zero = DAG.getConstant(0, DL, VT);3445SDValue One = DAG.getConstant(1, DL, VT);3446SDValue MinusRegisterSize = DAG.getConstant(-32, DL, VT);3447SDValue RegisterSizeMinus1 = DAG.getConstant(32 - 1, DL, VT);3448SDValue ShamtMinusRegisterSize =3449DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusRegisterSize);3450SDValue RegisterSizeMinus1Shamt =3451DAG.getNode(ISD::XOR, DL, VT, RegisterSizeMinus1, Shamt);34523453SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt);3454SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One);3455SDValue ShiftRightLo =3456DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, RegisterSizeMinus1Shamt);3457SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt);3458SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo);3459SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusRegisterSize);34603461SDValue CC =3462DAG.getSetCC(DL, MVT::i8, ShamtMinusRegisterSize, Zero, ISD::SETLT);34633464Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero);3465Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);34663467return DAG.getMergeValues({Lo, Hi}, DL);3468}34693470SDValue M68kTargetLowering::LowerShiftRightParts(SDValue Op, SelectionDAG &DAG,3471bool IsSRA) const {3472SDLoc DL(Op);3473SDValue Lo = Op.getOperand(0);3474SDValue Hi = Op.getOperand(1);3475SDValue Shamt = Op.getOperand(2);3476EVT VT = Lo.getValueType();34773478// SRA expansion:3479// if Shamt - register size < 0: // Shamt < register size3480// Lo = (Lo >>u Shamt) | ((Hi << 1) << (register size - 1 ^ Shamt))3481// Hi = Hi >>s Shamt3482// else:3483// Lo = Hi >>s (Shamt - register size);3484// Hi = Hi >>s (register size - 1)3485//3486// SRL expansion:3487// if Shamt - register size < 0: // Shamt < register size3488// Lo = (Lo >>u Shamt) | ((Hi << 1) << (register size - 1 ^ Shamt))3489// Hi = Hi >>u Shamt3490// else:3491// Lo = Hi >>u (Shamt - register size);3492// Hi = 0;34933494unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL;34953496SDValue Zero = DAG.getConstant(0, DL, VT);3497SDValue One = DAG.getConstant(1, DL, VT);3498SDValue MinusRegisterSize = DAG.getConstant(-32, DL, VT);3499SDValue RegisterSizeMinus1 = DAG.getConstant(32 - 1, DL, VT);3500SDValue ShamtMinusRegisterSize =3501DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusRegisterSize);3502SDValue RegisterSizeMinus1Shamt =3503DAG.getNode(ISD::XOR, DL, VT, RegisterSizeMinus1, Shamt);35043505SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt);3506SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One);3507SDValue ShiftLeftHi =3508DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, RegisterSizeMinus1Shamt);3509SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi);3510SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt);3511SDValue LoFalse =3512DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusRegisterSize);3513SDValue HiFalse =3514IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, RegisterSizeMinus1) : Zero;35153516SDValue CC =3517DAG.getSetCC(DL, MVT::i8, ShamtMinusRegisterSize, Zero, ISD::SETLT);35183519Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse);3520Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);35213522return DAG.getMergeValues({Lo, Hi}, DL);3523}35243525//===----------------------------------------------------------------------===//3526// DAG Combine3527//===----------------------------------------------------------------------===//35283529static SDValue getSETCC(M68k::CondCode Cond, SDValue CCR, const SDLoc &dl,3530SelectionDAG &DAG) {3531return DAG.getNode(M68kISD::SETCC, dl, MVT::i8,3532DAG.getConstant(Cond, dl, MVT::i8), CCR);3533}3534// When legalizing carry, we create carries via add X, -13535// If that comes from an actual carry, via setcc, we use the3536// carry directly.3537static SDValue combineCarryThroughADD(SDValue CCR) {3538if (CCR.getOpcode() == M68kISD::ADD) {3539if (isAllOnesConstant(CCR.getOperand(1))) {3540SDValue Carry = CCR.getOperand(0);3541while (Carry.getOpcode() == ISD::TRUNCATE ||3542Carry.getOpcode() == ISD::ZERO_EXTEND ||3543Carry.getOpcode() == ISD::SIGN_EXTEND ||3544Carry.getOpcode() == ISD::ANY_EXTEND ||3545(Carry.getOpcode() == ISD::AND &&3546isOneConstant(Carry.getOperand(1))))3547Carry = Carry.getOperand(0);3548if (Carry.getOpcode() == M68kISD::SETCC ||3549Carry.getOpcode() == M68kISD::SETCC_CARRY) {3550if (Carry.getConstantOperandVal(0) == M68k::COND_CS)3551return Carry.getOperand(1);3552}3553}3554}35553556return SDValue();3557}35583559/// Optimize a CCR definition used according to the condition code \p CC into3560/// a simpler CCR value, potentially returning a new \p CC and replacing uses3561/// of chain values.3562static SDValue combineSetCCCCR(SDValue CCR, M68k::CondCode &CC,3563SelectionDAG &DAG,3564const M68kSubtarget &Subtarget) {3565if (CC == M68k::COND_CS)3566if (SDValue Flags = combineCarryThroughADD(CCR))3567return Flags;35683569return SDValue();3570}35713572// Optimize RES = M68kISD::SETCC CONDCODE, CCR_INPUT3573static SDValue combineM68kSetCC(SDNode *N, SelectionDAG &DAG,3574const M68kSubtarget &Subtarget) {3575SDLoc DL(N);3576M68k::CondCode CC = M68k::CondCode(N->getConstantOperandVal(0));3577SDValue CCR = N->getOperand(1);35783579// Try to simplify the CCR and condition code operands.3580if (SDValue Flags = combineSetCCCCR(CCR, CC, DAG, Subtarget))3581return getSETCC(CC, Flags, DL, DAG);35823583return SDValue();3584}3585static SDValue combineM68kBrCond(SDNode *N, SelectionDAG &DAG,3586const M68kSubtarget &Subtarget) {3587SDLoc DL(N);3588M68k::CondCode CC = M68k::CondCode(N->getConstantOperandVal(2));3589SDValue CCR = N->getOperand(3);35903591// Try to simplify the CCR and condition code operands.3592// Make sure to not keep references to operands, as combineSetCCCCR can3593// RAUW them under us.3594if (SDValue Flags = combineSetCCCCR(CCR, CC, DAG, Subtarget)) {3595SDValue Cond = DAG.getConstant(CC, DL, MVT::i8);3596return DAG.getNode(M68kISD::BRCOND, DL, N->getVTList(), N->getOperand(0),3597N->getOperand(1), Cond, Flags);3598}35993600return SDValue();3601}36023603static SDValue combineSUBX(SDNode *N, SelectionDAG &DAG) {3604if (SDValue Flags = combineCarryThroughADD(N->getOperand(2))) {3605MVT VT = N->getSimpleValueType(0);3606SDVTList VTs = DAG.getVTList(VT, MVT::i32);3607return DAG.getNode(M68kISD::SUBX, SDLoc(N), VTs, N->getOperand(0),3608N->getOperand(1), Flags);3609}36103611return SDValue();3612}36133614// Optimize RES, CCR = M68kISD::ADDX LHS, RHS, CCR3615static SDValue combineADDX(SDNode *N, SelectionDAG &DAG,3616TargetLowering::DAGCombinerInfo &DCI) {3617if (SDValue Flags = combineCarryThroughADD(N->getOperand(2))) {3618MVT VT = N->getSimpleValueType(0);3619SDVTList VTs = DAG.getVTList(VT, MVT::i32);3620return DAG.getNode(M68kISD::ADDX, SDLoc(N), VTs, N->getOperand(0),3621N->getOperand(1), Flags);3622}36233624return SDValue();3625}36263627SDValue M68kTargetLowering::PerformDAGCombine(SDNode *N,3628DAGCombinerInfo &DCI) const {3629SelectionDAG &DAG = DCI.DAG;3630switch (N->getOpcode()) {3631case M68kISD::SUBX:3632return combineSUBX(N, DAG);3633case M68kISD::ADDX:3634return combineADDX(N, DAG, DCI);3635case M68kISD::SETCC:3636return combineM68kSetCC(N, DAG, Subtarget);3637case M68kISD::BRCOND:3638return combineM68kBrCond(N, DAG, Subtarget);3639}36403641return SDValue();3642}36433644//===----------------------------------------------------------------------===//3645// M68kISD Node Names3646//===----------------------------------------------------------------------===//3647const char *M68kTargetLowering::getTargetNodeName(unsigned Opcode) const {3648switch (Opcode) {3649case M68kISD::CALL:3650return "M68kISD::CALL";3651case M68kISD::TAIL_CALL:3652return "M68kISD::TAIL_CALL";3653case M68kISD::RET:3654return "M68kISD::RET";3655case M68kISD::TC_RETURN:3656return "M68kISD::TC_RETURN";3657case M68kISD::ADD:3658return "M68kISD::ADD";3659case M68kISD::SUB:3660return "M68kISD::SUB";3661case M68kISD::ADDX:3662return "M68kISD::ADDX";3663case M68kISD::SUBX:3664return "M68kISD::SUBX";3665case M68kISD::SMUL:3666return "M68kISD::SMUL";3667case M68kISD::UMUL:3668return "M68kISD::UMUL";3669case M68kISD::OR:3670return "M68kISD::OR";3671case M68kISD::XOR:3672return "M68kISD::XOR";3673case M68kISD::AND:3674return "M68kISD::AND";3675case M68kISD::CMP:3676return "M68kISD::CMP";3677case M68kISD::BTST:3678return "M68kISD::BTST";3679case M68kISD::SELECT:3680return "M68kISD::SELECT";3681case M68kISD::CMOV:3682return "M68kISD::CMOV";3683case M68kISD::BRCOND:3684return "M68kISD::BRCOND";3685case M68kISD::SETCC:3686return "M68kISD::SETCC";3687case M68kISD::SETCC_CARRY:3688return "M68kISD::SETCC_CARRY";3689case M68kISD::GLOBAL_BASE_REG:3690return "M68kISD::GLOBAL_BASE_REG";3691case M68kISD::Wrapper:3692return "M68kISD::Wrapper";3693case M68kISD::WrapperPC:3694return "M68kISD::WrapperPC";3695case M68kISD::SEG_ALLOCA:3696return "M68kISD::SEG_ALLOCA";3697default:3698return NULL;3699}3700}37013702CCAssignFn *M68kTargetLowering::getCCAssignFn(CallingConv::ID CC, bool Return,3703bool IsVarArg) const {3704if (Return)3705return RetCC_M68k_C;3706else3707return CC_M68k_C;3708}370937103711