LLVM 22.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 "ARCSelectionDAGInfo.h"
15#include "ARCTargetMachine.h"
23#include "llvm/IR/CallingConv.h"
24#include "llvm/IR/Constants.h"
26#include "llvm/IR/Function.h"
27#include "llvm/IR/Intrinsics.h"
28#include "llvm/IR/LLVMContext.h"
30#include "llvm/Support/Debug.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 machine
40/// 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)
67 ID, std::make_unique<ARCDAGToDAGISel>(TM, OptLevel)) {}
68};
69
70char ARCDAGToDAGISelLegacy::ID;
71
72} // end anonymous namespace
73
74INITIALIZE_PASS(ARCDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
75
76/// This pass converts a legalized DAG into a ARC-specific DAG, ready for
77/// instruction scheduling.
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 index
168 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}
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:56
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:314
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:259
@ FrameIndex
Definition: ISDOpcodes.h:90
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
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:82
#define N