brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · 02a5721 Raw
190 lines · cpp
1//===- ARCISelDAGToDAG.cpp - ARC dag to dag inst selector -------*- C++ -*-===//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 defines an instruction selector for the ARC target.10//11//===----------------------------------------------------------------------===//12 13#include "ARC.h"14#include "ARCSelectionDAGInfo.h"15#include "ARCTargetMachine.h"16#include "llvm/CodeGen/MachineFrameInfo.h"17#include "llvm/CodeGen/MachineFunction.h"18#include "llvm/CodeGen/MachineInstrBuilder.h"19#include "llvm/CodeGen/MachineRegisterInfo.h"20#include "llvm/CodeGen/SelectionDAG.h"21#include "llvm/CodeGen/SelectionDAGISel.h"22#include "llvm/CodeGen/TargetLowering.h"23#include "llvm/IR/CallingConv.h"24#include "llvm/IR/Constants.h"25#include "llvm/IR/DerivedTypes.h"26#include "llvm/IR/Function.h"27#include "llvm/IR/Intrinsics.h"28#include "llvm/IR/LLVMContext.h"29#include "llvm/Support/Compiler.h"30#include "llvm/Support/Debug.h"31#include "llvm/Support/ErrorHandling.h"32#include "llvm/Support/raw_ostream.h"33 34using namespace llvm;35 36#define DEBUG_TYPE "arc-isel"37#define PASS_NAME "ARC DAG->DAG Pattern Instruction Selection"38 39/// ARCDAGToDAGISel - ARC specific code to select ARC machine40/// instructions for SelectionDAG operations.41namespace {42 43class ARCDAGToDAGISel : public SelectionDAGISel {44public:45  ARCDAGToDAGISel() = delete;46 47  ARCDAGToDAGISel(ARCTargetMachine &TM, CodeGenOptLevel OptLevel)48      : SelectionDAGISel(TM, OptLevel) {}49 50  void Select(SDNode *N) override;51 52  // Complex Pattern Selectors.53  bool SelectFrameADDR_ri(SDValue Addr, SDValue &Base, SDValue &Offset);54  bool SelectAddrModeS9(SDValue Addr, SDValue &Base, SDValue &Offset);55  bool SelectAddrModeImm(SDValue Addr, SDValue &Base, SDValue &Offset);56  bool SelectAddrModeFar(SDValue Addr, SDValue &Base, SDValue &Offset);57 58// Include the pieces autogenerated from the target description.59#include "ARCGenDAGISel.inc"60};61 62class ARCDAGToDAGISelLegacy : public SelectionDAGISelLegacy {63public:64  static char ID;65  explicit ARCDAGToDAGISelLegacy(ARCTargetMachine &TM, CodeGenOptLevel OptLevel)66      : SelectionDAGISelLegacy(67            ID, std::make_unique<ARCDAGToDAGISel>(TM, OptLevel)) {}68};69 70char ARCDAGToDAGISelLegacy::ID;71 72} // end anonymous namespace73 74INITIALIZE_PASS(ARCDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)75 76/// This pass converts a legalized DAG into a ARC-specific DAG, ready for77/// instruction scheduling.78FunctionPass *llvm::createARCISelDag(ARCTargetMachine &TM,79                                     CodeGenOptLevel OptLevel) {80  return new ARCDAGToDAGISelLegacy(TM, OptLevel);81}82 83bool ARCDAGToDAGISel::SelectAddrModeImm(SDValue Addr, SDValue &Base,84                                        SDValue &Offset) {85  if (Addr.getOpcode() == ARCISD::GAWRAPPER) {86    Base = Addr.getOperand(0);87    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);88    return true;89  }90  return false;91}92 93bool ARCDAGToDAGISel::SelectAddrModeS9(SDValue Addr, SDValue &Base,94                                       SDValue &Offset) {95  if (Addr.getOpcode() == ARCISD::GAWRAPPER) {96    return false;97  }98 99  if (Addr.getOpcode() != ISD::ADD && Addr.getOpcode() != ISD::SUB &&100      !CurDAG->isBaseWithConstantOffset(Addr)) {101    if (Addr.getOpcode() == ISD::FrameIndex) {102      // Match frame index.103      int FI = cast<FrameIndexSDNode>(Addr)->getIndex();104      Base = CurDAG->getTargetFrameIndex(105          FI, TLI->getPointerTy(CurDAG->getDataLayout()));106    } else {107      Base = Addr;108    }109    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);110    return true;111  }112 113  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {114    int32_t RHSC = RHS->getSExtValue();115    if (Addr.getOpcode() == ISD::SUB)116      RHSC = -RHSC;117 118    // Do we need more than 9 bits to encode?119    if (!isInt<9>(RHSC))120      return false;121    Base = Addr.getOperand(0);122    if (Base.getOpcode() == ISD::FrameIndex) {123      int FI = cast<FrameIndexSDNode>(Base)->getIndex();124      Base = CurDAG->getTargetFrameIndex(125          FI, TLI->getPointerTy(CurDAG->getDataLayout()));126    }127    Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);128    return true;129  }130  Base = Addr;131  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);132  return true;133}134 135bool ARCDAGToDAGISel::SelectAddrModeFar(SDValue Addr, SDValue &Base,136                                        SDValue &Offset) {137  if (SelectAddrModeS9(Addr, Base, Offset))138    return false;139  if (Addr.getOpcode() == ARCISD::GAWRAPPER) {140    return false;141  }142  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {143    int32_t RHSC = RHS->getSExtValue();144    if (Addr.getOpcode() == ISD::SUB)145      RHSC = -RHSC;146    Base = Addr.getOperand(0);147    Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);148    return true;149  }150  return false;151}152 153// Is this a legal frame index addressing expression.154bool ARCDAGToDAGISel::SelectFrameADDR_ri(SDValue Addr, SDValue &Base,155                                         SDValue &Offset) {156  FrameIndexSDNode *FIN = nullptr;157  if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {158    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);159    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);160    return true;161  }162  if (Addr.getOpcode() == ISD::ADD) {163    ConstantSDNode *CN = nullptr;164    if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&165        (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&166        (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {167      // Constant positive word offset from frame index168      Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);169      Offset =170          CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), MVT::i32);171      return true;172    }173  }174  return false;175}176 177void ARCDAGToDAGISel::Select(SDNode *N) {178  switch (N->getOpcode()) {179  case ISD::Constant: {180    uint64_t CVal = N->getAsZExtVal();181    ReplaceNode(N, CurDAG->getMachineNode(182                       isInt<12>(CVal) ? ARC::MOV_rs12 : ARC::MOV_rlimm,183                       SDLoc(N), MVT::i32,184                       CurDAG->getTargetConstant(CVal, SDLoc(N), MVT::i32)));185    return;186  }187  }188  SelectCode(N);189}190