Path: blob/main/contrib/llvm-project/llvm/lib/Target/ARC/ARCISelDAGToDAG.cpp
35267 views
//===- ARCISelDAGToDAG.cpp - ARC dag to dag inst selector -------*- 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// This file defines an instruction selector for the ARC target.9//10//===----------------------------------------------------------------------===//1112#include "ARC.h"13#include "ARCTargetMachine.h"14#include "llvm/CodeGen/MachineFrameInfo.h"15#include "llvm/CodeGen/MachineFunction.h"16#include "llvm/CodeGen/MachineInstrBuilder.h"17#include "llvm/CodeGen/MachineRegisterInfo.h"18#include "llvm/CodeGen/SelectionDAG.h"19#include "llvm/CodeGen/SelectionDAGISel.h"20#include "llvm/CodeGen/TargetLowering.h"21#include "llvm/IR/CallingConv.h"22#include "llvm/IR/Constants.h"23#include "llvm/IR/DerivedTypes.h"24#include "llvm/IR/Function.h"25#include "llvm/IR/Intrinsics.h"26#include "llvm/IR/LLVMContext.h"27#include "llvm/Support/Compiler.h"28#include "llvm/Support/Debug.h"29#include "llvm/Support/ErrorHandling.h"30#include "llvm/Support/raw_ostream.h"3132using namespace llvm;3334#define DEBUG_TYPE "arc-isel"35#define PASS_NAME "ARC DAG->DAG Pattern Instruction Selection"3637/// ARCDAGToDAGISel - ARC specific code to select ARC machine38/// instructions for SelectionDAG operations.39namespace {4041class ARCDAGToDAGISel : public SelectionDAGISel {42public:43ARCDAGToDAGISel() = delete;4445ARCDAGToDAGISel(ARCTargetMachine &TM, CodeGenOptLevel OptLevel)46: SelectionDAGISel(TM, OptLevel) {}4748void Select(SDNode *N) override;4950// Complex Pattern Selectors.51bool SelectFrameADDR_ri(SDValue Addr, SDValue &Base, SDValue &Offset);52bool SelectAddrModeS9(SDValue Addr, SDValue &Base, SDValue &Offset);53bool SelectAddrModeImm(SDValue Addr, SDValue &Base, SDValue &Offset);54bool SelectAddrModeFar(SDValue Addr, SDValue &Base, SDValue &Offset);5556// Include the pieces autogenerated from the target description.57#include "ARCGenDAGISel.inc"58};5960class ARCDAGToDAGISelLegacy : public SelectionDAGISelLegacy {61public:62static char ID;63explicit ARCDAGToDAGISelLegacy(ARCTargetMachine &TM, CodeGenOptLevel OptLevel)64: SelectionDAGISelLegacy(65ID, std::make_unique<ARCDAGToDAGISel>(TM, OptLevel)) {}66};6768char ARCDAGToDAGISelLegacy::ID;6970} // end anonymous namespace7172INITIALIZE_PASS(ARCDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)7374/// This pass converts a legalized DAG into a ARC-specific DAG, ready for75/// instruction scheduling.76FunctionPass *llvm::createARCISelDag(ARCTargetMachine &TM,77CodeGenOptLevel OptLevel) {78return new ARCDAGToDAGISelLegacy(TM, OptLevel);79}8081bool ARCDAGToDAGISel::SelectAddrModeImm(SDValue Addr, SDValue &Base,82SDValue &Offset) {83if (Addr.getOpcode() == ARCISD::GAWRAPPER) {84Base = Addr.getOperand(0);85Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);86return true;87}88return false;89}9091bool ARCDAGToDAGISel::SelectAddrModeS9(SDValue Addr, SDValue &Base,92SDValue &Offset) {93if (Addr.getOpcode() == ARCISD::GAWRAPPER) {94return false;95}9697if (Addr.getOpcode() != ISD::ADD && Addr.getOpcode() != ISD::SUB &&98!CurDAG->isBaseWithConstantOffset(Addr)) {99if (Addr.getOpcode() == ISD::FrameIndex) {100// Match frame index.101int FI = cast<FrameIndexSDNode>(Addr)->getIndex();102Base = CurDAG->getTargetFrameIndex(103FI, TLI->getPointerTy(CurDAG->getDataLayout()));104} else {105Base = Addr;106}107Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);108return true;109}110111if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {112int32_t RHSC = RHS->getSExtValue();113if (Addr.getOpcode() == ISD::SUB)114RHSC = -RHSC;115116// Do we need more than 9 bits to encode?117if (!isInt<9>(RHSC))118return false;119Base = Addr.getOperand(0);120if (Base.getOpcode() == ISD::FrameIndex) {121int FI = cast<FrameIndexSDNode>(Base)->getIndex();122Base = CurDAG->getTargetFrameIndex(123FI, TLI->getPointerTy(CurDAG->getDataLayout()));124}125Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);126return true;127}128Base = Addr;129Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);130return true;131}132133bool ARCDAGToDAGISel::SelectAddrModeFar(SDValue Addr, SDValue &Base,134SDValue &Offset) {135if (SelectAddrModeS9(Addr, Base, Offset))136return false;137if (Addr.getOpcode() == ARCISD::GAWRAPPER) {138return false;139}140if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {141int32_t RHSC = RHS->getSExtValue();142if (Addr.getOpcode() == ISD::SUB)143RHSC = -RHSC;144Base = Addr.getOperand(0);145Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);146return true;147}148return false;149}150151// Is this a legal frame index addressing expression.152bool ARCDAGToDAGISel::SelectFrameADDR_ri(SDValue Addr, SDValue &Base,153SDValue &Offset) {154FrameIndexSDNode *FIN = nullptr;155if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {156Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);157Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);158return true;159}160if (Addr.getOpcode() == ISD::ADD) {161ConstantSDNode *CN = nullptr;162if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&163(CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&164(CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {165// Constant positive word offset from frame index166Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);167Offset =168CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), MVT::i32);169return true;170}171}172return false;173}174175void ARCDAGToDAGISel::Select(SDNode *N) {176switch (N->getOpcode()) {177case ISD::Constant: {178uint64_t CVal = N->getAsZExtVal();179ReplaceNode(N, CurDAG->getMachineNode(180isInt<12>(CVal) ? ARC::MOV_rs12 : ARC::MOV_rlimm,181SDLoc(N), MVT::i32,182CurDAG->getTargetConstant(CVal, SDLoc(N), MVT::i32)));183return;184}185}186SelectCode(N);187}188189190