brintos

brintos / llvm-project-archived public Read only

0
0
Text · 50.9 KiB · e118169 Raw
1411 lines · cpp
1//===-- MSP430ISelLowering.cpp - MSP430 DAG Lowering Implementation  ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the MSP430TargetLowering class.10//11//===----------------------------------------------------------------------===//12 13#include "MSP430ISelLowering.h"14#include "MSP430.h"15#include "MSP430MachineFunctionInfo.h"16#include "MSP430SelectionDAGInfo.h"17#include "MSP430Subtarget.h"18#include "MSP430TargetMachine.h"19#include "llvm/CodeGen/CallingConvLower.h"20#include "llvm/CodeGen/MachineFrameInfo.h"21#include "llvm/CodeGen/MachineFunction.h"22#include "llvm/CodeGen/MachineInstrBuilder.h"23#include "llvm/CodeGen/MachineRegisterInfo.h"24#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"25#include "llvm/CodeGen/ValueTypes.h"26#include "llvm/IR/CallingConv.h"27#include "llvm/IR/DerivedTypes.h"28#include "llvm/IR/Function.h"29#include "llvm/IR/Intrinsics.h"30#include "llvm/Support/CommandLine.h"31#include "llvm/Support/Debug.h"32#include "llvm/Support/ErrorHandling.h"33#include "llvm/Support/raw_ostream.h"34using namespace llvm;35 36#define DEBUG_TYPE "msp430-lower"37 38static cl::opt<bool>MSP430NoLegalImmediate(39  "msp430-no-legal-immediate", cl::Hidden,40  cl::desc("Enable non legal immediates (for testing purposes only)"),41  cl::init(false));42 43MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM,44                                           const MSP430Subtarget &STI)45    : TargetLowering(TM, STI) {46 47  // Set up the register classes.48  addRegisterClass(MVT::i8,  &MSP430::GR8RegClass);49  addRegisterClass(MVT::i16, &MSP430::GR16RegClass);50 51  // Compute derived properties from the register classes52  computeRegisterProperties(STI.getRegisterInfo());53 54  // Provide all sorts of operation actions55  setStackPointerRegisterToSaveRestore(MSP430::SP);56  setBooleanContents(ZeroOrOneBooleanContent);57  setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?58 59  // We have post-incremented loads / stores.60  setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal);61  setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal);62 63  for (MVT VT : MVT::integer_valuetypes()) {64    setLoadExtAction(ISD::EXTLOAD,  VT, MVT::i1,  Promote);65    setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1,  Promote);66    setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1,  Promote);67    setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8,  Expand);68    setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i16, Expand);69  }70 71  // We don't have any truncstores72  setTruncStoreAction(MVT::i16, MVT::i8, Expand);73 74  setOperationAction(ISD::SRA,              MVT::i8,    Custom);75  setOperationAction(ISD::SHL,              MVT::i8,    Custom);76  setOperationAction(ISD::SRL,              MVT::i8,    Custom);77  setOperationAction(ISD::SRA,              MVT::i16,   Custom);78  setOperationAction(ISD::SHL,              MVT::i16,   Custom);79  setOperationAction(ISD::SRL,              MVT::i16,   Custom);80  setOperationAction(ISD::ROTL,             MVT::i8,    Expand);81  setOperationAction(ISD::ROTR,             MVT::i8,    Expand);82  setOperationAction(ISD::ROTL,             MVT::i16,   Expand);83  setOperationAction(ISD::ROTR,             MVT::i16,   Expand);84  setOperationAction(ISD::GlobalAddress,    MVT::i16,   Custom);85  setOperationAction(ISD::ExternalSymbol,   MVT::i16,   Custom);86  setOperationAction(ISD::BlockAddress,     MVT::i16,   Custom);87  setOperationAction(ISD::BR_JT,            MVT::Other, Expand);88  setOperationAction(ISD::BR_CC,            MVT::i8,    Custom);89  setOperationAction(ISD::BR_CC,            MVT::i16,   Custom);90  setOperationAction(ISD::BRCOND,           MVT::Other, Expand);91  setOperationAction(ISD::SETCC,            MVT::i8,    Custom);92  setOperationAction(ISD::SETCC,            MVT::i16,   Custom);93  setOperationAction(ISD::SELECT,           MVT::i8,    Expand);94  setOperationAction(ISD::SELECT,           MVT::i16,   Expand);95  setOperationAction(ISD::SELECT_CC,        MVT::i8,    Custom);96  setOperationAction(ISD::SELECT_CC,        MVT::i16,   Custom);97  setOperationAction(ISD::SIGN_EXTEND,      MVT::i16,   Custom);98  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i8, Expand);99  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i16, Expand);100  setOperationAction(ISD::STACKSAVE,        MVT::Other, Expand);101  setOperationAction(ISD::STACKRESTORE,     MVT::Other, Expand);102 103  setOperationAction(ISD::CTTZ,             MVT::i8,    Expand);104  setOperationAction(ISD::CTTZ,             MVT::i16,   Expand);105  setOperationAction(ISD::CTLZ,             MVT::i8,    Expand);106  setOperationAction(ISD::CTLZ,             MVT::i16,   Expand);107  setOperationAction(ISD::CTPOP,            MVT::i8,    Expand);108  setOperationAction(ISD::CTPOP,            MVT::i16,   Expand);109 110  setOperationAction(ISD::SHL_PARTS,        MVT::i8,    Expand);111  setOperationAction(ISD::SHL_PARTS,        MVT::i16,   Expand);112  setOperationAction(ISD::SRL_PARTS,        MVT::i8,    Expand);113  setOperationAction(ISD::SRL_PARTS,        MVT::i16,   Expand);114  setOperationAction(ISD::SRA_PARTS,        MVT::i8,    Expand);115  setOperationAction(ISD::SRA_PARTS,        MVT::i16,   Expand);116 117  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1,   Expand);118 119  // FIXME: Implement efficiently multiplication by a constant120  setOperationAction(ISD::MUL,              MVT::i8,    Promote);121  setOperationAction(ISD::MULHS,            MVT::i8,    Promote);122  setOperationAction(ISD::MULHU,            MVT::i8,    Promote);123  setOperationAction(ISD::SMUL_LOHI,        MVT::i8,    Promote);124  setOperationAction(ISD::UMUL_LOHI,        MVT::i8,    Promote);125  setOperationAction(ISD::MUL,              MVT::i16,   LibCall);126  setOperationAction(ISD::MULHS,            MVT::i16,   Expand);127  setOperationAction(ISD::MULHU,            MVT::i16,   Expand);128  setOperationAction(ISD::SMUL_LOHI,        MVT::i16,   Expand);129  setOperationAction(ISD::UMUL_LOHI,        MVT::i16,   Expand);130 131  setOperationAction(ISD::UDIV,             MVT::i8,    Promote);132  setOperationAction(ISD::UDIVREM,          MVT::i8,    Promote);133  setOperationAction(ISD::UREM,             MVT::i8,    Promote);134  setOperationAction(ISD::SDIV,             MVT::i8,    Promote);135  setOperationAction(ISD::SDIVREM,          MVT::i8,    Promote);136  setOperationAction(ISD::SREM,             MVT::i8,    Promote);137  setOperationAction(ISD::UDIV,             MVT::i16,   LibCall);138  setOperationAction(ISD::UDIVREM,          MVT::i16,   Expand);139  setOperationAction(ISD::UREM,             MVT::i16,   LibCall);140  setOperationAction(ISD::SDIV,             MVT::i16,   LibCall);141  setOperationAction(ISD::SDIVREM,          MVT::i16,   Expand);142  setOperationAction(ISD::SREM,             MVT::i16,   LibCall);143 144  // varargs support145  setOperationAction(ISD::VASTART,          MVT::Other, Custom);146  setOperationAction(ISD::VAARG,            MVT::Other, Expand);147  setOperationAction(ISD::VAEND,            MVT::Other, Expand);148  setOperationAction(ISD::VACOPY,           MVT::Other, Expand);149  setOperationAction(ISD::JumpTable,        MVT::i16,   Custom);150 151  setMinFunctionAlignment(Align(2));152  setPrefFunctionAlignment(Align(2));153  setMaxAtomicSizeInBitsSupported(0);154}155 156SDValue MSP430TargetLowering::LowerOperation(SDValue Op,157                                             SelectionDAG &DAG) const {158  switch (Op.getOpcode()) {159  case ISD::SHL: // FALLTHROUGH160  case ISD::SRL:161  case ISD::SRA:              return LowerShifts(Op, DAG);162  case ISD::GlobalAddress:    return LowerGlobalAddress(Op, DAG);163  case ISD::BlockAddress:     return LowerBlockAddress(Op, DAG);164  case ISD::ExternalSymbol:   return LowerExternalSymbol(Op, DAG);165  case ISD::SETCC:            return LowerSETCC(Op, DAG);166  case ISD::BR_CC:            return LowerBR_CC(Op, DAG);167  case ISD::SELECT_CC:        return LowerSELECT_CC(Op, DAG);168  case ISD::SIGN_EXTEND:      return LowerSIGN_EXTEND(Op, DAG);169  case ISD::RETURNADDR:       return LowerRETURNADDR(Op, DAG);170  case ISD::FRAMEADDR:        return LowerFRAMEADDR(Op, DAG);171  case ISD::VASTART:          return LowerVASTART(Op, DAG);172  case ISD::JumpTable:        return LowerJumpTable(Op, DAG);173  default:174    llvm_unreachable("unimplemented operand");175  }176}177 178// Define non profitable transforms into shifts179bool MSP430TargetLowering::shouldAvoidTransformToShift(EVT VT,180                                                       unsigned Amount) const {181  return !(Amount == 8 || Amount == 9 || Amount<=2);182}183 184// Implemented to verify test case assertions in185// tests/codegen/msp430/shift-amount-threshold-b.ll186bool MSP430TargetLowering::isLegalICmpImmediate(int64_t Immed) const {187  if (MSP430NoLegalImmediate)188    return Immed >= -32 && Immed < 32;189  return TargetLowering::isLegalICmpImmediate(Immed);190}191 192//===----------------------------------------------------------------------===//193//                       MSP430 Inline Assembly Support194//===----------------------------------------------------------------------===//195 196/// getConstraintType - Given a constraint letter, return the type of197/// constraint it is for this target.198TargetLowering::ConstraintType199MSP430TargetLowering::getConstraintType(StringRef Constraint) const {200  if (Constraint.size() == 1) {201    switch (Constraint[0]) {202    case 'r':203      return C_RegisterClass;204    default:205      break;206    }207  }208  return TargetLowering::getConstraintType(Constraint);209}210 211std::pair<unsigned, const TargetRegisterClass *>212MSP430TargetLowering::getRegForInlineAsmConstraint(213    const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {214  if (Constraint.size() == 1) {215    // GCC Constraint Letters216    switch (Constraint[0]) {217    default: break;218    case 'r':   // GENERAL_REGS219      if (VT == MVT::i8)220        return std::make_pair(0U, &MSP430::GR8RegClass);221 222      return std::make_pair(0U, &MSP430::GR16RegClass);223    }224  }225 226  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);227}228 229//===----------------------------------------------------------------------===//230//                      Calling Convention Implementation231//===----------------------------------------------------------------------===//232 233#include "MSP430GenCallingConv.inc"234 235/// For each argument in a function store the number of pieces it is composed236/// of.237template<typename ArgT>238static void ParseFunctionArgs(const SmallVectorImpl<ArgT> &Args,239                              SmallVectorImpl<unsigned> &Out) {240  unsigned CurrentArgIndex;241 242  if (Args.empty())243    return;244 245  CurrentArgIndex = Args[0].OrigArgIndex;246  Out.push_back(0);247 248  for (auto &Arg : Args) {249    if (CurrentArgIndex == Arg.OrigArgIndex) {250      Out.back() += 1;251    } else {252      Out.push_back(1);253      CurrentArgIndex = Arg.OrigArgIndex;254    }255  }256}257 258static void AnalyzeVarArgs(CCState &State,259                           const SmallVectorImpl<ISD::OutputArg> &Outs) {260  State.AnalyzeCallOperands(Outs, CC_MSP430_AssignStack);261}262 263static void AnalyzeVarArgs(CCState &State,264                           const SmallVectorImpl<ISD::InputArg> &Ins) {265  State.AnalyzeFormalArguments(Ins, CC_MSP430_AssignStack);266}267 268/// Analyze incoming and outgoing function arguments. We need custom C++ code269/// to handle special constraints in the ABI like reversing the order of the270/// pieces of splitted arguments. In addition, all pieces of a certain argument271/// have to be passed either using registers or the stack but never mixing both.272template<typename ArgT>273static void AnalyzeArguments(CCState &State,274                             SmallVectorImpl<CCValAssign> &ArgLocs,275                             const SmallVectorImpl<ArgT> &Args) {276  static const MCPhysReg CRegList[] = {277    MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15278  };279  static const unsigned CNbRegs = std::size(CRegList);280  static const MCPhysReg BuiltinRegList[] = {281    MSP430::R8, MSP430::R9, MSP430::R10, MSP430::R11,282    MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15283  };284  static const unsigned BuiltinNbRegs = std::size(BuiltinRegList);285 286  ArrayRef<MCPhysReg> RegList;287  unsigned NbRegs;288 289  bool Builtin = (State.getCallingConv() == CallingConv::MSP430_BUILTIN);290  if (Builtin) {291    RegList = BuiltinRegList;292    NbRegs = BuiltinNbRegs;293  } else {294    RegList = CRegList;295    NbRegs = CNbRegs;296  }297 298  if (State.isVarArg()) {299    AnalyzeVarArgs(State, Args);300    return;301  }302 303  SmallVector<unsigned, 4> ArgsParts;304  ParseFunctionArgs(Args, ArgsParts);305 306  if (Builtin) {307    assert(ArgsParts.size() == 2 &&308        "Builtin calling convention requires two arguments");309  }310 311  unsigned RegsLeft = NbRegs;312  bool UsedStack = false;313  unsigned ValNo = 0;314 315  for (unsigned i = 0, e = ArgsParts.size(); i != e; i++) {316    MVT ArgVT = Args[ValNo].VT;317    ISD::ArgFlagsTy ArgFlags = Args[ValNo].Flags;318    Type *OrigTy = Args[ValNo].OrigTy;319    MVT LocVT = ArgVT;320    CCValAssign::LocInfo LocInfo = CCValAssign::Full;321 322    // Promote i8 to i16323    if (LocVT == MVT::i8) {324      LocVT = MVT::i16;325      if (ArgFlags.isSExt())326          LocInfo = CCValAssign::SExt;327      else if (ArgFlags.isZExt())328          LocInfo = CCValAssign::ZExt;329      else330          LocInfo = CCValAssign::AExt;331    }332 333    // Handle byval arguments334    if (ArgFlags.isByVal()) {335      State.HandleByVal(ValNo++, ArgVT, LocVT, LocInfo, 2, Align(2), ArgFlags);336      continue;337    }338 339    unsigned Parts = ArgsParts[i];340 341    if (Builtin) {342      assert(Parts == 4 &&343          "Builtin calling convention requires 64-bit arguments");344    }345 346    if (!UsedStack && Parts == 2 && RegsLeft == 1) {347      // Special case for 32-bit register split, see EABI section 3.3.3348      MCRegister Reg = State.AllocateReg(RegList);349      State.addLoc(CCValAssign::getReg(ValNo++, ArgVT, Reg, LocVT, LocInfo));350      RegsLeft -= 1;351 352      UsedStack = true;353      CC_MSP430_AssignStack(ValNo++, ArgVT, LocVT, LocInfo, ArgFlags, OrigTy,354                            State);355    } else if (Parts <= RegsLeft) {356      for (unsigned j = 0; j < Parts; j++) {357        MCRegister Reg = State.AllocateReg(RegList);358        State.addLoc(CCValAssign::getReg(ValNo++, ArgVT, Reg, LocVT, LocInfo));359        RegsLeft--;360      }361    } else {362      UsedStack = true;363      for (unsigned j = 0; j < Parts; j++)364        CC_MSP430_AssignStack(ValNo++, ArgVT, LocVT, LocInfo, ArgFlags, OrigTy,365                              State);366    }367  }368}369 370static void AnalyzeRetResult(CCState &State,371                             const SmallVectorImpl<ISD::InputArg> &Ins) {372  State.AnalyzeCallResult(Ins, RetCC_MSP430);373}374 375static void AnalyzeRetResult(CCState &State,376                             const SmallVectorImpl<ISD::OutputArg> &Outs) {377  State.AnalyzeReturn(Outs, RetCC_MSP430);378}379 380template<typename ArgT>381static void AnalyzeReturnValues(CCState &State,382                                SmallVectorImpl<CCValAssign> &RVLocs,383                                const SmallVectorImpl<ArgT> &Args) {384  AnalyzeRetResult(State, Args);385}386 387SDValue MSP430TargetLowering::LowerFormalArguments(388    SDValue Chain, CallingConv::ID CallConv, bool isVarArg,389    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,390    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {391 392  switch (CallConv) {393  default:394    report_fatal_error("Unsupported calling convention");395  case CallingConv::C:396  case CallingConv::Fast:397    return LowerCCCArguments(Chain, CallConv, isVarArg, Ins, dl, DAG, InVals);398  case CallingConv::MSP430_INTR:399    if (Ins.empty())400      return Chain;401    report_fatal_error("ISRs cannot have arguments");402  }403}404 405SDValue406MSP430TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,407                                SmallVectorImpl<SDValue> &InVals) const {408  SelectionDAG &DAG                     = CLI.DAG;409  SDLoc &dl                             = CLI.DL;410  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;411  SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;412  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;413  SDValue Chain                         = CLI.Chain;414  SDValue Callee                        = CLI.Callee;415  bool &isTailCall                      = CLI.IsTailCall;416  CallingConv::ID CallConv              = CLI.CallConv;417  bool isVarArg                         = CLI.IsVarArg;418 419  // MSP430 target does not yet support tail call optimization.420  isTailCall = false;421 422  switch (CallConv) {423  default:424    report_fatal_error("Unsupported calling convention");425  case CallingConv::MSP430_BUILTIN:426  case CallingConv::Fast:427  case CallingConv::C:428    return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,429                          Outs, OutVals, Ins, dl, DAG, InVals);430  case CallingConv::MSP430_INTR:431    report_fatal_error("ISRs cannot be called directly");432  }433}434 435/// LowerCCCArguments - transform physical registers into virtual registers and436/// generate load operations for arguments places on the stack.437// FIXME: struct return stuff438SDValue MSP430TargetLowering::LowerCCCArguments(439    SDValue Chain, CallingConv::ID CallConv, bool isVarArg,440    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,441    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {442  MachineFunction &MF = DAG.getMachineFunction();443  MachineFrameInfo &MFI = MF.getFrameInfo();444  MachineRegisterInfo &RegInfo = MF.getRegInfo();445  MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();446 447  // Assign locations to all of the incoming arguments.448  SmallVector<CCValAssign, 16> ArgLocs;449  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,450                 *DAG.getContext());451  AnalyzeArguments(CCInfo, ArgLocs, Ins);452 453  // Create frame index for the start of the first vararg value454  if (isVarArg) {455    unsigned Offset = CCInfo.getStackSize();456    FuncInfo->setVarArgsFrameIndex(MFI.CreateFixedObject(1, Offset, true));457  }458 459  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {460    CCValAssign &VA = ArgLocs[i];461    if (VA.isRegLoc()) {462      // Arguments passed in registers463      EVT RegVT = VA.getLocVT();464      switch (RegVT.getSimpleVT().SimpleTy) {465      default:466        {467#ifndef NDEBUG468          errs() << "LowerFormalArguments Unhandled argument type: "469                 << RegVT << "\n";470#endif471          llvm_unreachable(nullptr);472        }473      case MVT::i16:474        Register VReg = RegInfo.createVirtualRegister(&MSP430::GR16RegClass);475        RegInfo.addLiveIn(VA.getLocReg(), VReg);476        SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);477 478        // If this is an 8-bit value, it is really passed promoted to 16479        // bits. Insert an assert[sz]ext to capture this, then truncate to the480        // right size.481        if (VA.getLocInfo() == CCValAssign::SExt)482          ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue,483                                 DAG.getValueType(VA.getValVT()));484        else if (VA.getLocInfo() == CCValAssign::ZExt)485          ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue,486                                 DAG.getValueType(VA.getValVT()));487 488        if (VA.getLocInfo() != CCValAssign::Full)489          ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);490 491        InVals.push_back(ArgValue);492      }493    } else {494      // Only arguments passed on the stack should make it here.495      assert(VA.isMemLoc());496 497      SDValue InVal;498      ISD::ArgFlagsTy Flags = Ins[i].Flags;499 500      if (Flags.isByVal()) {501        MVT PtrVT = VA.getLocVT();502        int FI = MFI.CreateFixedObject(Flags.getByValSize(),503                                       VA.getLocMemOffset(), true);504        InVal = DAG.getFrameIndex(FI, PtrVT);505      } else {506        // Load the argument to a virtual register507        unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;508        if (ObjSize > 2) {509            errs() << "LowerFormalArguments Unhandled argument type: "510                << VA.getLocVT() << "\n";511        }512        // Create the frame index object for this incoming parameter...513        int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);514 515        // Create the SelectionDAG nodes corresponding to a load516        //from this parameter517        SDValue FIN = DAG.getFrameIndex(FI, MVT::i16);518        InVal = DAG.getLoad(519            VA.getLocVT(), dl, Chain, FIN,520            MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI));521      }522 523      InVals.push_back(InVal);524    }525  }526 527  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {528    if (Ins[i].Flags.isSRet()) {529      Register Reg = FuncInfo->getSRetReturnReg();530      if (!Reg) {531        Reg = MF.getRegInfo().createVirtualRegister(532            getRegClassFor(MVT::i16));533        FuncInfo->setSRetReturnReg(Reg);534      }535      SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[i]);536      Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);537    }538  }539 540  return Chain;541}542 543bool544MSP430TargetLowering::CanLowerReturn(CallingConv::ID CallConv,545                                     MachineFunction &MF,546                                     bool IsVarArg,547                                     const SmallVectorImpl<ISD::OutputArg> &Outs,548                                     LLVMContext &Context,549                                     const Type *RetTy) const {550  SmallVector<CCValAssign, 16> RVLocs;551  CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);552  return CCInfo.CheckReturn(Outs, RetCC_MSP430);553}554 555SDValue556MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,557                                  bool isVarArg,558                                  const SmallVectorImpl<ISD::OutputArg> &Outs,559                                  const SmallVectorImpl<SDValue> &OutVals,560                                  const SDLoc &dl, SelectionDAG &DAG) const {561 562  MachineFunction &MF = DAG.getMachineFunction();563 564  // CCValAssign - represent the assignment of the return value to a location565  SmallVector<CCValAssign, 16> RVLocs;566 567  // ISRs cannot return any value.568  if (CallConv == CallingConv::MSP430_INTR && !Outs.empty())569    report_fatal_error("ISRs cannot return any value");570 571  // CCState - Info about the registers and stack slot.572  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,573                 *DAG.getContext());574 575  // Analize return values.576  AnalyzeReturnValues(CCInfo, RVLocs, Outs);577 578  SDValue Glue;579  SmallVector<SDValue, 4> RetOps(1, Chain);580 581  // Copy the result values into the output registers.582  for (unsigned i = 0; i != RVLocs.size(); ++i) {583    CCValAssign &VA = RVLocs[i];584    assert(VA.isRegLoc() && "Can only return in registers!");585 586    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),587                             OutVals[i], Glue);588 589    // Guarantee that all emitted copies are stuck together,590    // avoiding something bad.591    Glue = Chain.getValue(1);592    RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));593  }594 595  if (MF.getFunction().hasStructRetAttr()) {596    MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();597    Register Reg = FuncInfo->getSRetReturnReg();598 599    if (!Reg)600      llvm_unreachable("sret virtual register not created in entry block");601 602    MVT PtrVT = getFrameIndexTy(DAG.getDataLayout());603    SDValue Val =604      DAG.getCopyFromReg(Chain, dl, Reg, PtrVT);605    unsigned R12 = MSP430::R12;606 607    Chain = DAG.getCopyToReg(Chain, dl, R12, Val, Glue);608    Glue = Chain.getValue(1);609    RetOps.push_back(DAG.getRegister(R12, PtrVT));610  }611 612  unsigned Opc = (CallConv == CallingConv::MSP430_INTR ?613                  MSP430ISD::RETI_GLUE : MSP430ISD::RET_GLUE);614 615  RetOps[0] = Chain;  // Update chain.616 617  // Add the glue if we have it.618  if (Glue.getNode())619    RetOps.push_back(Glue);620 621  return DAG.getNode(Opc, dl, MVT::Other, RetOps);622}623 624/// LowerCCCCallTo - functions arguments are copied from virtual regs to625/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.626SDValue MSP430TargetLowering::LowerCCCCallTo(627    SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg,628    bool isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs,629    const SmallVectorImpl<SDValue> &OutVals,630    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,631    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {632  // Analyze operands of the call, assigning locations to each operand.633  SmallVector<CCValAssign, 16> ArgLocs;634  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,635                 *DAG.getContext());636  AnalyzeArguments(CCInfo, ArgLocs, Outs);637 638  // Get a count of how many bytes are to be pushed on the stack.639  unsigned NumBytes = CCInfo.getStackSize();640  MVT PtrVT = getFrameIndexTy(DAG.getDataLayout());641 642  Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);643 644  SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;645  SmallVector<SDValue, 12> MemOpChains;646  SDValue StackPtr;647 648  // Walk the register/memloc assignments, inserting copies/loads.649  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {650    CCValAssign &VA = ArgLocs[i];651 652    SDValue Arg = OutVals[i];653 654    // Promote the value if needed.655    switch (VA.getLocInfo()) {656      default: llvm_unreachable("Unknown loc info!");657      case CCValAssign::Full: break;658      case CCValAssign::SExt:659        Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);660        break;661      case CCValAssign::ZExt:662        Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);663        break;664      case CCValAssign::AExt:665        Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);666        break;667    }668 669    // Arguments that can be passed on register must be kept at RegsToPass670    // vector671    if (VA.isRegLoc()) {672      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));673    } else {674      assert(VA.isMemLoc());675 676      if (!StackPtr.getNode())677        StackPtr = DAG.getCopyFromReg(Chain, dl, MSP430::SP, PtrVT);678 679      SDValue PtrOff =680          DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr,681                      DAG.getIntPtrConstant(VA.getLocMemOffset(), dl));682 683      SDValue MemOp;684      ISD::ArgFlagsTy Flags = Outs[i].Flags;685 686      if (Flags.isByVal()) {687        SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), dl, MVT::i16);688        MemOp = DAG.getMemcpy(Chain, dl, PtrOff, Arg, SizeNode,689                              Flags.getNonZeroByValAlign(),690                              /*isVolatile*/ false,691                              /*AlwaysInline=*/true,692                              /*CI=*/nullptr, std::nullopt,693                              MachinePointerInfo(), MachinePointerInfo());694      } else {695        MemOp = DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());696      }697 698      MemOpChains.push_back(MemOp);699    }700  }701 702  // Transform all store nodes into one single node because all store nodes are703  // independent of each other.704  if (!MemOpChains.empty())705    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);706 707  // Build a sequence of copy-to-reg nodes chained together with token chain and708  // flag operands which copy the outgoing args into registers.  The InGlue in709  // necessary since all emitted instructions must be stuck together.710  SDValue InGlue;711  for (const auto &[Reg, N] : RegsToPass) {712    Chain = DAG.getCopyToReg(Chain, dl, Reg, N, InGlue);713    InGlue = Chain.getValue(1);714  }715 716  // If the callee is a GlobalAddress node (quite common, every direct call is)717  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.718  // Likewise ExternalSymbol -> TargetExternalSymbol.719  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))720    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i16);721  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))722    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i16);723 724  // Returns a chain & a flag for retval copy to use.725  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);726  SmallVector<SDValue, 8> Ops;727  Ops.push_back(Chain);728  Ops.push_back(Callee);729 730  // Add argument registers to the end of the list so that they are731  // known live into the call.732  for (const auto &[Reg, N] : RegsToPass)733    Ops.push_back(DAG.getRegister(Reg, N.getValueType()));734 735  if (InGlue.getNode())736    Ops.push_back(InGlue);737 738  Chain = DAG.getNode(MSP430ISD::CALL, dl, NodeTys, Ops);739  InGlue = Chain.getValue(1);740 741  // Create the CALLSEQ_END node.742  Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, dl);743  InGlue = Chain.getValue(1);744 745  // Handle result values, copying them out of physregs into vregs that we746  // return.747  return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl,748                         DAG, InVals);749}750 751/// LowerCallResult - Lower the result values of a call into the752/// appropriate copies out of appropriate physical registers.753///754SDValue MSP430TargetLowering::LowerCallResult(755    SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,756    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,757    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {758 759  // Assign locations to each value returned by this call.760  SmallVector<CCValAssign, 16> RVLocs;761  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,762                 *DAG.getContext());763 764  AnalyzeReturnValues(CCInfo, RVLocs, Ins);765 766  // Copy all of the result registers out of their specified physreg.767  for (unsigned i = 0; i != RVLocs.size(); ++i) {768    Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),769                               RVLocs[i].getValVT(), InGlue).getValue(1);770    InGlue = Chain.getValue(2);771    InVals.push_back(Chain.getValue(0));772  }773 774  return Chain;775}776 777SDValue MSP430TargetLowering::LowerShifts(SDValue Op,778                                          SelectionDAG &DAG) const {779  unsigned Opc = Op.getOpcode();780  SDNode* N = Op.getNode();781  EVT VT = Op.getValueType();782  SDLoc dl(N);783 784  // Expand non-constant shifts to loops:785  if (!isa<ConstantSDNode>(N->getOperand(1)))786    return Op;787 788  uint64_t ShiftAmount = N->getConstantOperandVal(1);789 790  // Expand the stuff into sequence of shifts.791  SDValue Victim = N->getOperand(0);792 793  if (ShiftAmount >= 8) {794    assert(VT == MVT::i16 && "Can not shift i8 by 8 and more");795    switch(Opc) {796    default:797      llvm_unreachable("Unknown shift");798    case ISD::SHL:799      // foo << (8 + N) => swpb(zext(foo)) << N800      Victim = DAG.getZeroExtendInReg(Victim, dl, MVT::i8);801      Victim = DAG.getNode(ISD::BSWAP, dl, VT, Victim);802      break;803    case ISD::SRA:804    case ISD::SRL:805      // foo >> (8 + N) => sxt(swpb(foo)) >> N806      Victim = DAG.getNode(ISD::BSWAP, dl, VT, Victim);807      Victim = (Opc == ISD::SRA)808                   ? DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, VT, Victim,809                                 DAG.getValueType(MVT::i8))810                   : DAG.getZeroExtendInReg(Victim, dl, MVT::i8);811      break;812    }813    ShiftAmount -= 8;814  }815 816  if (Opc == ISD::SRL && ShiftAmount) {817    // Emit a special goodness here:818    // srl A, 1 => clrc; rrc A819    Victim = DAG.getNode(MSP430ISD::RRCL, dl, VT, Victim);820    ShiftAmount -= 1;821  }822 823  while (ShiftAmount--)824    Victim = DAG.getNode((Opc == ISD::SHL ? MSP430ISD::RLA : MSP430ISD::RRA),825                         dl, VT, Victim);826 827  return Victim;828}829 830SDValue MSP430TargetLowering::LowerGlobalAddress(SDValue Op,831                                                 SelectionDAG &DAG) const {832  const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();833  int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();834  EVT PtrVT = Op.getValueType();835 836  // Create the TargetGlobalAddress node, folding in the constant offset.837  SDValue Result = DAG.getTargetGlobalAddress(GV, SDLoc(Op), PtrVT, Offset);838  return DAG.getNode(MSP430ISD::Wrapper, SDLoc(Op), PtrVT, Result);839}840 841SDValue MSP430TargetLowering::LowerExternalSymbol(SDValue Op,842                                                  SelectionDAG &DAG) const {843  SDLoc dl(Op);844  const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();845  EVT PtrVT = Op.getValueType();846  SDValue Result = DAG.getTargetExternalSymbol(Sym, PtrVT);847 848  return DAG.getNode(MSP430ISD::Wrapper, dl, PtrVT, Result);849}850 851SDValue MSP430TargetLowering::LowerBlockAddress(SDValue Op,852                                                SelectionDAG &DAG) const {853  SDLoc dl(Op);854  const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();855  EVT PtrVT = Op.getValueType();856  SDValue Result = DAG.getTargetBlockAddress(BA, PtrVT);857 858  return DAG.getNode(MSP430ISD::Wrapper, dl, PtrVT, Result);859}860 861static SDValue EmitCMP(SDValue &LHS, SDValue &RHS, SDValue &TargetCC,862                       ISD::CondCode CC, const SDLoc &dl, SelectionDAG &DAG) {863  // FIXME: Handle bittests someday864  assert(!LHS.getValueType().isFloatingPoint() && "We don't handle FP yet");865 866  // FIXME: Handle jump negative someday867  MSP430CC::CondCodes TCC = MSP430CC::COND_INVALID;868  switch (CC) {869  default: llvm_unreachable("Invalid integer condition!");870  case ISD::SETEQ:871    TCC = MSP430CC::COND_E;     // aka COND_Z872    // Minor optimization: if LHS is a constant, swap operands, then the873    // constant can be folded into comparison.874    if (LHS.getOpcode() == ISD::Constant)875      std::swap(LHS, RHS);876    break;877  case ISD::SETNE:878    TCC = MSP430CC::COND_NE;    // aka COND_NZ879    // Minor optimization: if LHS is a constant, swap operands, then the880    // constant can be folded into comparison.881    if (LHS.getOpcode() == ISD::Constant)882      std::swap(LHS, RHS);883    break;884  case ISD::SETULE:885    std::swap(LHS, RHS);886    [[fallthrough]];887  case ISD::SETUGE:888    // Turn lhs u>= rhs with lhs constant into rhs u< lhs+1, this allows us to889    // fold constant into instruction.890    if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {891      LHS = RHS;892      RHS = DAG.getConstant(C->getSExtValue() + 1, dl, C->getValueType(0));893      TCC = MSP430CC::COND_LO;894      break;895    }896    TCC = MSP430CC::COND_HS;    // aka COND_C897    break;898  case ISD::SETUGT:899    std::swap(LHS, RHS);900    [[fallthrough]];901  case ISD::SETULT:902    // Turn lhs u< rhs with lhs constant into rhs u>= lhs+1, this allows us to903    // fold constant into instruction.904    if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {905      LHS = RHS;906      RHS = DAG.getConstant(C->getSExtValue() + 1, dl, C->getValueType(0));907      TCC = MSP430CC::COND_HS;908      break;909    }910    TCC = MSP430CC::COND_LO;    // aka COND_NC911    break;912  case ISD::SETLE:913    std::swap(LHS, RHS);914    [[fallthrough]];915  case ISD::SETGE:916    // Turn lhs >= rhs with lhs constant into rhs < lhs+1, this allows us to917    // fold constant into instruction.918    if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {919      LHS = RHS;920      RHS = DAG.getConstant(C->getSExtValue() + 1, dl, C->getValueType(0));921      TCC = MSP430CC::COND_L;922      break;923    }924    TCC = MSP430CC::COND_GE;925    break;926  case ISD::SETGT:927    std::swap(LHS, RHS);928    [[fallthrough]];929  case ISD::SETLT:930    // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to931    // fold constant into instruction.932    if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {933      LHS = RHS;934      RHS = DAG.getConstant(C->getSExtValue() + 1, dl, C->getValueType(0));935      TCC = MSP430CC::COND_GE;936      break;937    }938    TCC = MSP430CC::COND_L;939    break;940  }941 942  TargetCC = DAG.getConstant(TCC, dl, MVT::i8);943  return DAG.getNode(MSP430ISD::CMP, dl, MVT::Glue, LHS, RHS);944}945 946 947SDValue MSP430TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {948  SDValue Chain = Op.getOperand(0);949  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();950  SDValue LHS   = Op.getOperand(2);951  SDValue RHS   = Op.getOperand(3);952  SDValue Dest  = Op.getOperand(4);953  SDLoc dl  (Op);954 955  SDValue TargetCC;956  SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);957 958  return DAG.getNode(MSP430ISD::BR_CC, dl, Op.getValueType(),959                     Chain, Dest, TargetCC, Flag);960}961 962SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {963  SDValue LHS   = Op.getOperand(0);964  SDValue RHS   = Op.getOperand(1);965  SDLoc dl  (Op);966 967  // If we are doing an AND and testing against zero, then the CMP968  // will not be generated.  The AND (or BIT) will generate the condition codes,969  // but they are different from CMP.970  // FIXME: since we're doing a post-processing, use a pseudoinstr here, so971  // lowering & isel wouldn't diverge.972  bool andCC = isNullConstant(RHS) && LHS.hasOneUse() &&973               (LHS.getOpcode() == ISD::AND ||974                (LHS.getOpcode() == ISD::TRUNCATE &&975                 LHS.getOperand(0).getOpcode() == ISD::AND));976  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();977  SDValue TargetCC;978  SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);979 980  // Get the condition codes directly from the status register, if its easy.981  // Otherwise a branch will be generated.  Note that the AND and BIT982  // instructions generate different flags than CMP, the carry bit can be used983  // for NE/EQ.984  bool Invert = false;985  bool Shift = false;986  bool Convert = true;987  switch (TargetCC->getAsZExtVal()) {988  default:989    Convert = false;990    break;991   case MSP430CC::COND_HS:992     // Res = SR & 1, no processing is required993     break;994   case MSP430CC::COND_LO:995     // Res = ~(SR & 1)996     Invert = true;997     break;998   case MSP430CC::COND_NE:999     if (andCC) {1000       // C = ~Z, thus Res = SR & 1, no processing is required1001     } else {1002       // Res = ~((SR >> 1) & 1)1003       Shift = true;1004       Invert = true;1005     }1006     break;1007   case MSP430CC::COND_E:1008     Shift = true;1009     // C = ~Z for AND instruction, thus we can put Res = ~(SR & 1), however,1010     // Res = (SR >> 1) & 1 is 1 word shorter.1011     break;1012   }1013  EVT VT = Op.getValueType();1014  SDValue One  = DAG.getConstant(1, dl, VT);1015  if (Convert) {1016    SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SR,1017                                    MVT::i16, Flag);1018    if (Shift)1019      // FIXME: somewhere this is turned into a SRL, lower it MSP specific?1020      SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One);1021    SR = DAG.getNode(ISD::AND, dl, MVT::i16, SR, One);1022    if (Invert)1023      SR = DAG.getNode(ISD::XOR, dl, MVT::i16, SR, One);1024    return SR;1025  } else {1026    SDValue Zero = DAG.getConstant(0, dl, VT);1027    SDValue Ops[] = {One, Zero, TargetCC, Flag};1028    return DAG.getNode(MSP430ISD::SELECT_CC, dl, Op.getValueType(), Ops);1029  }1030}1031 1032SDValue MSP430TargetLowering::LowerSELECT_CC(SDValue Op,1033                                             SelectionDAG &DAG) const {1034  SDValue LHS    = Op.getOperand(0);1035  SDValue RHS    = Op.getOperand(1);1036  SDValue TrueV  = Op.getOperand(2);1037  SDValue FalseV = Op.getOperand(3);1038  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();1039  SDLoc dl   (Op);1040 1041  SDValue TargetCC;1042  SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);1043 1044  SDValue Ops[] = {TrueV, FalseV, TargetCC, Flag};1045 1046  return DAG.getNode(MSP430ISD::SELECT_CC, dl, Op.getValueType(), Ops);1047}1048 1049SDValue MSP430TargetLowering::LowerSIGN_EXTEND(SDValue Op,1050                                               SelectionDAG &DAG) const {1051  SDValue Val = Op.getOperand(0);1052  EVT VT      = Op.getValueType();1053  SDLoc dl(Op);1054 1055  assert(VT == MVT::i16 && "Only support i16 for now!");1056 1057  return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, VT,1058                     DAG.getNode(ISD::ANY_EXTEND, dl, VT, Val),1059                     DAG.getValueType(Val.getValueType()));1060}1061 1062SDValue1063MSP430TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const {1064  MachineFunction &MF = DAG.getMachineFunction();1065  MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();1066  int ReturnAddrIndex = FuncInfo->getRAIndex();1067  MVT PtrVT = getFrameIndexTy(MF.getDataLayout());1068 1069  if (ReturnAddrIndex == 0) {1070    // Set up a frame object for the return address.1071    uint64_t SlotSize = PtrVT.getStoreSize();1072    ReturnAddrIndex = MF.getFrameInfo().CreateFixedObject(SlotSize, -SlotSize,1073                                                           true);1074    FuncInfo->setRAIndex(ReturnAddrIndex);1075  }1076 1077  return DAG.getFrameIndex(ReturnAddrIndex, PtrVT);1078}1079 1080SDValue MSP430TargetLowering::LowerRETURNADDR(SDValue Op,1081                                              SelectionDAG &DAG) const {1082  MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();1083  MFI.setReturnAddressIsTaken(true);1084 1085  unsigned Depth = Op.getConstantOperandVal(0);1086  SDLoc dl(Op);1087  EVT PtrVT = Op.getValueType();1088 1089  if (Depth > 0) {1090    SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);1091    SDValue Offset =1092      DAG.getConstant(PtrVT.getStoreSize(), dl, MVT::i16);1093    return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(),1094                       DAG.getNode(ISD::ADD, dl, PtrVT, FrameAddr, Offset),1095                       MachinePointerInfo());1096  }1097 1098  // Just load the return address.1099  SDValue RetAddrFI = getReturnAddressFrameIndex(DAG);1100  return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), RetAddrFI,1101                     MachinePointerInfo());1102}1103 1104SDValue MSP430TargetLowering::LowerFRAMEADDR(SDValue Op,1105                                             SelectionDAG &DAG) const {1106  MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();1107  MFI.setFrameAddressIsTaken(true);1108 1109  EVT VT = Op.getValueType();1110  SDLoc dl(Op);  // FIXME probably not meaningful1111  unsigned Depth = Op.getConstantOperandVal(0);1112  SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl,1113                                         MSP430::R4, VT);1114  while (Depth--)1115    FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,1116                            MachinePointerInfo());1117  return FrameAddr;1118}1119 1120SDValue MSP430TargetLowering::LowerVASTART(SDValue Op,1121                                           SelectionDAG &DAG) const {1122  MachineFunction &MF = DAG.getMachineFunction();1123  MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();1124 1125  SDValue Ptr = Op.getOperand(1);1126  EVT PtrVT = Ptr.getValueType();1127 1128  // Frame index of first vararg argument1129  SDValue FrameIndex =1130      DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);1131  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();1132 1133  // Create a store of the frame index to the location operand1134  return DAG.getStore(Op.getOperand(0), SDLoc(Op), FrameIndex, Ptr,1135                      MachinePointerInfo(SV));1136}1137 1138SDValue MSP430TargetLowering::LowerJumpTable(SDValue Op,1139                                             SelectionDAG &DAG) const {1140    JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);1141    EVT PtrVT = Op.getValueType();1142    SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);1143    return DAG.getNode(MSP430ISD::Wrapper, SDLoc(JT), PtrVT, Result);1144}1145 1146/// getPostIndexedAddressParts - returns true by value, base pointer and1147/// offset pointer and addressing mode by reference if this node can be1148/// combined with a load / store to form a post-indexed load / store.1149bool MSP430TargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,1150                                                      SDValue &Base,1151                                                      SDValue &Offset,1152                                                      ISD::MemIndexedMode &AM,1153                                                      SelectionDAG &DAG) const {1154 1155  LoadSDNode *LD = cast<LoadSDNode>(N);1156  if (LD->getExtensionType() != ISD::NON_EXTLOAD)1157    return false;1158 1159  EVT VT = LD->getMemoryVT();1160  if (VT != MVT::i8 && VT != MVT::i16)1161    return false;1162 1163  if (Op->getOpcode() != ISD::ADD)1164    return false;1165 1166  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Op->getOperand(1))) {1167    uint64_t RHSC = RHS->getZExtValue();1168    if ((VT == MVT::i16 && RHSC != 2) ||1169        (VT == MVT::i8 && RHSC != 1))1170      return false;1171 1172    Base = Op->getOperand(0);1173    Offset = DAG.getConstant(RHSC, SDLoc(N), VT);1174    AM = ISD::POST_INC;1175    return true;1176  }1177 1178  return false;1179}1180 1181bool MSP430TargetLowering::isTruncateFree(Type *Ty1,1182                                          Type *Ty2) const {1183  if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())1184    return false;1185 1186  return (Ty1->getPrimitiveSizeInBits().getFixedValue() >1187          Ty2->getPrimitiveSizeInBits().getFixedValue());1188}1189 1190bool MSP430TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {1191  if (!VT1.isInteger() || !VT2.isInteger())1192    return false;1193 1194  return (VT1.getFixedSizeInBits() > VT2.getFixedSizeInBits());1195}1196 1197bool MSP430TargetLowering::isZExtFree(Type *Ty1, Type *Ty2) const {1198  // MSP430 implicitly zero-extends 8-bit results in 16-bit registers.1199  return false && Ty1->isIntegerTy(8) && Ty2->isIntegerTy(16);1200}1201 1202bool MSP430TargetLowering::isZExtFree(EVT VT1, EVT VT2) const {1203  // MSP430 implicitly zero-extends 8-bit results in 16-bit registers.1204  return false && VT1 == MVT::i8 && VT2 == MVT::i16;1205}1206 1207//===----------------------------------------------------------------------===//1208//  Other Lowering Code1209//===----------------------------------------------------------------------===//1210 1211MachineBasicBlock *1212MSP430TargetLowering::EmitShiftInstr(MachineInstr &MI,1213                                     MachineBasicBlock *BB) const {1214  MachineFunction *F = BB->getParent();1215  MachineRegisterInfo &RI = F->getRegInfo();1216  DebugLoc dl = MI.getDebugLoc();1217  const TargetInstrInfo &TII = *F->getSubtarget().getInstrInfo();1218 1219  unsigned Opc;1220  bool ClearCarry = false;1221  const TargetRegisterClass * RC;1222  switch (MI.getOpcode()) {1223  default: llvm_unreachable("Invalid shift opcode!");1224  case MSP430::Shl8:1225    Opc = MSP430::ADD8rr;1226    RC = &MSP430::GR8RegClass;1227    break;1228  case MSP430::Shl16:1229    Opc = MSP430::ADD16rr;1230    RC = &MSP430::GR16RegClass;1231    break;1232  case MSP430::Sra8:1233    Opc = MSP430::RRA8r;1234    RC = &MSP430::GR8RegClass;1235    break;1236  case MSP430::Sra16:1237    Opc = MSP430::RRA16r;1238    RC = &MSP430::GR16RegClass;1239    break;1240  case MSP430::Srl8:1241    ClearCarry = true;1242    Opc = MSP430::RRC8r;1243    RC = &MSP430::GR8RegClass;1244    break;1245  case MSP430::Srl16:1246    ClearCarry = true;1247    Opc = MSP430::RRC16r;1248    RC = &MSP430::GR16RegClass;1249    break;1250  case MSP430::Rrcl8:1251  case MSP430::Rrcl16: {1252    BuildMI(*BB, MI, dl, TII.get(MSP430::BIC16rc), MSP430::SR)1253      .addReg(MSP430::SR).addImm(1);1254    Register SrcReg = MI.getOperand(1).getReg();1255    Register DstReg = MI.getOperand(0).getReg();1256    unsigned RrcOpc = MI.getOpcode() == MSP430::Rrcl161257                    ? MSP430::RRC16r : MSP430::RRC8r;1258    BuildMI(*BB, MI, dl, TII.get(RrcOpc), DstReg)1259      .addReg(SrcReg);1260    MI.eraseFromParent(); // The pseudo instruction is gone now.1261    return BB;1262  }1263  }1264 1265  const BasicBlock *LLVM_BB = BB->getBasicBlock();1266  MachineFunction::iterator I = ++BB->getIterator();1267 1268  // Create loop block1269  MachineBasicBlock *LoopBB = F->CreateMachineBasicBlock(LLVM_BB);1270  MachineBasicBlock *RemBB  = F->CreateMachineBasicBlock(LLVM_BB);1271 1272  F->insert(I, LoopBB);1273  F->insert(I, RemBB);1274 1275  // Update machine-CFG edges by transferring all successors of the current1276  // block to the block containing instructions after shift.1277  RemBB->splice(RemBB->begin(), BB, std::next(MachineBasicBlock::iterator(MI)),1278                BB->end());1279  RemBB->transferSuccessorsAndUpdatePHIs(BB);1280 1281  // Add edges BB => LoopBB => RemBB, BB => RemBB, LoopBB => LoopBB1282  BB->addSuccessor(LoopBB);1283  BB->addSuccessor(RemBB);1284  LoopBB->addSuccessor(RemBB);1285  LoopBB->addSuccessor(LoopBB);1286 1287  Register ShiftAmtReg = RI.createVirtualRegister(&MSP430::GR8RegClass);1288  Register ShiftAmtReg2 = RI.createVirtualRegister(&MSP430::GR8RegClass);1289  Register ShiftReg = RI.createVirtualRegister(RC);1290  Register ShiftReg2 = RI.createVirtualRegister(RC);1291  Register ShiftAmtSrcReg = MI.getOperand(2).getReg();1292  Register SrcReg = MI.getOperand(1).getReg();1293  Register DstReg = MI.getOperand(0).getReg();1294 1295  // BB:1296  // cmp 0, N1297  // je RemBB1298  BuildMI(BB, dl, TII.get(MSP430::CMP8ri))1299    .addReg(ShiftAmtSrcReg).addImm(0);1300  BuildMI(BB, dl, TII.get(MSP430::JCC))1301    .addMBB(RemBB)1302    .addImm(MSP430CC::COND_E);1303 1304  // LoopBB:1305  // ShiftReg = phi [%SrcReg, BB], [%ShiftReg2, LoopBB]1306  // ShiftAmt = phi [%N, BB],      [%ShiftAmt2, LoopBB]1307  // ShiftReg2 = shift ShiftReg1308  // ShiftAmt2 = ShiftAmt - 1;1309  BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftReg)1310    .addReg(SrcReg).addMBB(BB)1311    .addReg(ShiftReg2).addMBB(LoopBB);1312  BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftAmtReg)1313    .addReg(ShiftAmtSrcReg).addMBB(BB)1314    .addReg(ShiftAmtReg2).addMBB(LoopBB);1315  if (ClearCarry)1316    BuildMI(LoopBB, dl, TII.get(MSP430::BIC16rc), MSP430::SR)1317      .addReg(MSP430::SR).addImm(1);1318  if (Opc == MSP430::ADD8rr || Opc == MSP430::ADD16rr)1319    BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2)1320      .addReg(ShiftReg)1321      .addReg(ShiftReg);1322  else1323    BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2)1324      .addReg(ShiftReg);1325  BuildMI(LoopBB, dl, TII.get(MSP430::SUB8ri), ShiftAmtReg2)1326    .addReg(ShiftAmtReg).addImm(1);1327  BuildMI(LoopBB, dl, TII.get(MSP430::JCC))1328    .addMBB(LoopBB)1329    .addImm(MSP430CC::COND_NE);1330 1331  // RemBB:1332  // DestReg = phi [%SrcReg, BB], [%ShiftReg, LoopBB]1333  BuildMI(*RemBB, RemBB->begin(), dl, TII.get(MSP430::PHI), DstReg)1334    .addReg(SrcReg).addMBB(BB)1335    .addReg(ShiftReg2).addMBB(LoopBB);1336 1337  MI.eraseFromParent(); // The pseudo instruction is gone now.1338  return RemBB;1339}1340 1341MachineBasicBlock *1342MSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,1343                                                  MachineBasicBlock *BB) const {1344  unsigned Opc = MI.getOpcode();1345 1346  if (Opc == MSP430::Shl8  || Opc == MSP430::Shl16 ||1347      Opc == MSP430::Sra8  || Opc == MSP430::Sra16 ||1348      Opc == MSP430::Srl8  || Opc == MSP430::Srl16 ||1349      Opc == MSP430::Rrcl8 || Opc == MSP430::Rrcl16)1350    return EmitShiftInstr(MI, BB);1351 1352  const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo();1353  DebugLoc dl = MI.getDebugLoc();1354 1355  assert((Opc == MSP430::Select16 || Opc == MSP430::Select8) &&1356         "Unexpected instr type to insert");1357 1358  // To "insert" a SELECT instruction, we actually have to insert the diamond1359  // control-flow pattern.  The incoming instruction knows the destination vreg1360  // to set, the condition code register to branch on, the true/false values to1361  // select between, and a branch opcode to use.1362  const BasicBlock *LLVM_BB = BB->getBasicBlock();1363  MachineFunction::iterator I = ++BB->getIterator();1364 1365  //  thisMBB:1366  //  ...1367  //   TrueVal = ...1368  //   cmpTY ccX, r1, r21369  //   jCC copy1MBB1370  //   fallthrough --> copy0MBB1371  MachineBasicBlock *thisMBB = BB;1372  MachineFunction *F = BB->getParent();1373  MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);1374  MachineBasicBlock *copy1MBB = F->CreateMachineBasicBlock(LLVM_BB);1375  F->insert(I, copy0MBB);1376  F->insert(I, copy1MBB);1377  // Update machine-CFG edges by transferring all successors of the current1378  // block to the new block which will contain the Phi node for the select.1379  copy1MBB->splice(copy1MBB->begin(), BB,1380                   std::next(MachineBasicBlock::iterator(MI)), BB->end());1381  copy1MBB->transferSuccessorsAndUpdatePHIs(BB);1382  // Next, add the true and fallthrough blocks as its successors.1383  BB->addSuccessor(copy0MBB);1384  BB->addSuccessor(copy1MBB);1385 1386  BuildMI(BB, dl, TII.get(MSP430::JCC))1387      .addMBB(copy1MBB)1388      .addImm(MI.getOperand(3).getImm());1389 1390  //  copy0MBB:1391  //   %FalseValue = ...1392  //   # fallthrough to copy1MBB1393  BB = copy0MBB;1394 1395  // Update machine-CFG edges1396  BB->addSuccessor(copy1MBB);1397 1398  //  copy1MBB:1399  //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]1400  //  ...1401  BB = copy1MBB;1402  BuildMI(*BB, BB->begin(), dl, TII.get(MSP430::PHI), MI.getOperand(0).getReg())1403      .addReg(MI.getOperand(2).getReg())1404      .addMBB(copy0MBB)1405      .addReg(MI.getOperand(1).getReg())1406      .addMBB(thisMBB);1407 1408  MI.eraseFromParent(); // The pseudo instruction is gone now.1409  return BB;1410}1411