LLVM 20.0.0git
ARCISelDAGToDAG.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines an instruction selector for the ARC target.
10//
11//===----------------------------------------------------------------------===//
12
13#include "ARC.h"
14#include "ARCTargetMachine.h"
22#include "llvm/IR/CallingConv.h"
23#include "llvm/IR/Constants.h"
25#include "llvm/IR/Function.h"
26#include "llvm/IR/Intrinsics.h"
27#include "llvm/IR/LLVMContext.h"
29#include "llvm/Support/Debug.h"
32
33using namespace llvm;
34
35#define DEBUG_TYPE "arc-isel"
36#define PASS_NAME "ARC DAG->DAG Pattern Instruction Selection"
37
38/// ARCDAGToDAGISel - ARC specific code to select ARC machine
39/// instructions for SelectionDAG operations.
40namespace {
41
42class ARCDAGToDAGISel : public SelectionDAGISel {
43public:
44 ARCDAGToDAGISel() = delete;
45
46 ARCDAGToDAGISel(ARCTargetMachine &TM, CodeGenOptLevel OptLevel)
47 : SelectionDAGISel(TM, OptLevel) {}
48
49 void Select(SDNode *N) override;
50
51 // Complex Pattern Selectors.
52 bool SelectFrameADDR_ri(SDValue Addr, SDValue &Base, SDValue &Offset);
53 bool SelectAddrModeS9(SDValue Addr, SDValue &Base, SDValue &Offset);
54 bool SelectAddrModeImm(SDValue Addr, SDValue &Base, SDValue &Offset);
55 bool SelectAddrModeFar(SDValue Addr, SDValue &Base, SDValue &Offset);
56
57// Include the pieces autogenerated from the target description.
58#include "ARCGenDAGISel.inc"
59};
60
61class ARCDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
62public:
63 static char ID;
64 explicit ARCDAGToDAGISelLegacy(ARCTargetMachine &TM, CodeGenOptLevel OptLevel)
66 ID, std::make_unique<ARCDAGToDAGISel>(TM, OptLevel)) {}
67};
68
69char ARCDAGToDAGISelLegacy::ID;
70
71} // end anonymous namespace
72
73INITIALIZE_PASS(ARCDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
74
75/// This pass converts a legalized DAG into a ARC-specific DAG, ready for
76/// instruction scheduling.
78 CodeGenOptLevel OptLevel) {
79 return new ARCDAGToDAGISelLegacy(TM, OptLevel);
80}
81
82bool ARCDAGToDAGISel::SelectAddrModeImm(SDValue Addr, SDValue &Base,
83 SDValue &Offset) {
84 if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
85 Base = Addr.getOperand(0);
86 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
87 return true;
88 }
89 return false;
90}
91
92bool ARCDAGToDAGISel::SelectAddrModeS9(SDValue Addr, SDValue &Base,
93 SDValue &Offset) {
94 if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
95 return false;
96 }
97
98 if (Addr.getOpcode() != ISD::ADD && Addr.getOpcode() != ISD::SUB &&
99 !CurDAG->isBaseWithConstantOffset(Addr)) {
100 if (Addr.getOpcode() == ISD::FrameIndex) {
101 // Match frame index.
102 int FI = cast<FrameIndexSDNode>(Addr)->getIndex();
103 Base = CurDAG->getTargetFrameIndex(
104 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
105 } else {
106 Base = Addr;
107 }
108 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
109 return true;
110 }
111
112 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
113 int32_t RHSC = RHS->getSExtValue();
114 if (Addr.getOpcode() == ISD::SUB)
115 RHSC = -RHSC;
116
117 // Do we need more than 9 bits to encode?
118 if (!isInt<9>(RHSC))
119 return false;
120 Base = Addr.getOperand(0);
121 if (Base.getOpcode() == ISD::FrameIndex) {
122 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
123 Base = CurDAG->getTargetFrameIndex(
124 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
125 }
126 Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);
127 return true;
128 }
129 Base = Addr;
130 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
131 return true;
132}
133
134bool ARCDAGToDAGISel::SelectAddrModeFar(SDValue Addr, SDValue &Base,
135 SDValue &Offset) {
136 if (SelectAddrModeS9(Addr, Base, Offset))
137 return false;
138 if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
139 return false;
140 }
141 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
142 int32_t RHSC = RHS->getSExtValue();
143 if (Addr.getOpcode() == ISD::SUB)
144 RHSC = -RHSC;
145 Base = Addr.getOperand(0);
146 Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);
147 return true;
148 }
149 return false;
150}
151
152// Is this a legal frame index addressing expression.
153bool ARCDAGToDAGISel::SelectFrameADDR_ri(SDValue Addr, SDValue &Base,
154 SDValue &Offset) {
155 FrameIndexSDNode *FIN = nullptr;
156 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
157 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
158 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
159 return true;
160 }
161 if (Addr.getOpcode() == ISD::ADD) {
162 ConstantSDNode *CN = nullptr;
163 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&
164 (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&
165 (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
166 // Constant positive word offset from frame index
167 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
168 Offset =
169 CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), MVT::i32);
170 return true;
171 }
172 }
173 return false;
174}
175
176void ARCDAGToDAGISel::Select(SDNode *N) {
177 switch (N->getOpcode()) {
178 case ISD::Constant: {
179 uint64_t CVal = N->getAsZExtVal();
180 ReplaceNode(N, CurDAG->getMachineNode(
181 isInt<12>(CVal) ? ARC::MOV_rs12 : ARC::MOV_rlimm,
182 SDLoc(N), MVT::i32,
183 CurDAG->getTargetConstant(CVal, SDLoc(N), MVT::i32)));
184 return;
185 }
186 }
187 SelectCode(N);
188}
amdgpu AMDGPU Register Bank Select
#define PASS_NAME
#define DEBUG_TYPE
This file contains the declarations for the subclasses of Constant, which represent the different fla...
uint64_t Addr
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
This file describes how to lower LLVM code to machine code.
Value * RHS
int64_t getSExtValue() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
@ FrameIndex
Definition: ISDOpcodes.h:80
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
FunctionPass * createARCISelDag(ARCTargetMachine &TM, CodeGenOptLevel OptLevel)
This pass converts a legalized DAG into a ARC-specific DAG, ready for instruction scheduling.
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
#define N