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