LLVM 19.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 static char ID;
45
46 ARCDAGToDAGISel() = delete;
47
48 ARCDAGToDAGISel(ARCTargetMachine &TM, CodeGenOptLevel OptLevel)
49 : SelectionDAGISel(ID, TM, OptLevel) {}
50
51 void Select(SDNode *N) override;
52
53 // Complex Pattern Selectors.
54 bool SelectFrameADDR_ri(SDValue Addr, SDValue &Base, SDValue &Offset);
55 bool SelectAddrModeS9(SDValue Addr, SDValue &Base, SDValue &Offset);
56 bool SelectAddrModeImm(SDValue Addr, SDValue &Base, SDValue &Offset);
57 bool SelectAddrModeFar(SDValue Addr, SDValue &Base, SDValue &Offset);
58
59// Include the pieces autogenerated from the target description.
60#include "ARCGenDAGISel.inc"
61};
62
63char ARCDAGToDAGISel::ID;
64
65} // end anonymous namespace
66
67INITIALIZE_PASS(ARCDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
68
69/// This pass converts a legalized DAG into a ARC-specific DAG, ready for
70/// instruction scheduling.
72 CodeGenOptLevel OptLevel) {
73 return new ARCDAGToDAGISel(TM, OptLevel);
74}
75
76bool ARCDAGToDAGISel::SelectAddrModeImm(SDValue Addr, SDValue &Base,
77 SDValue &Offset) {
78 if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
79 Base = Addr.getOperand(0);
80 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
81 return true;
82 }
83 return false;
84}
85
86bool ARCDAGToDAGISel::SelectAddrModeS9(SDValue Addr, SDValue &Base,
87 SDValue &Offset) {
88 if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
89 return false;
90 }
91
92 if (Addr.getOpcode() != ISD::ADD && Addr.getOpcode() != ISD::SUB &&
93 !CurDAG->isBaseWithConstantOffset(Addr)) {
94 if (Addr.getOpcode() == ISD::FrameIndex) {
95 // Match frame index.
96 int FI = cast<FrameIndexSDNode>(Addr)->getIndex();
97 Base = CurDAG->getTargetFrameIndex(
98 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
99 } else {
100 Base = Addr;
101 }
102 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
103 return true;
104 }
105
106 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
107 int32_t RHSC = RHS->getSExtValue();
108 if (Addr.getOpcode() == ISD::SUB)
109 RHSC = -RHSC;
110
111 // Do we need more than 9 bits to encode?
112 if (!isInt<9>(RHSC))
113 return false;
114 Base = Addr.getOperand(0);
115 if (Base.getOpcode() == ISD::FrameIndex) {
116 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
117 Base = CurDAG->getTargetFrameIndex(
118 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
119 }
120 Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);
121 return true;
122 }
123 Base = Addr;
124 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
125 return true;
126}
127
128bool ARCDAGToDAGISel::SelectAddrModeFar(SDValue Addr, SDValue &Base,
129 SDValue &Offset) {
130 if (SelectAddrModeS9(Addr, Base, Offset))
131 return false;
132 if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
133 return false;
134 }
135 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
136 int32_t RHSC = RHS->getSExtValue();
137 if (Addr.getOpcode() == ISD::SUB)
138 RHSC = -RHSC;
139 Base = Addr.getOperand(0);
140 Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);
141 return true;
142 }
143 return false;
144}
145
146// Is this a legal frame index addressing expression.
147bool ARCDAGToDAGISel::SelectFrameADDR_ri(SDValue Addr, SDValue &Base,
148 SDValue &Offset) {
149 FrameIndexSDNode *FIN = nullptr;
150 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
151 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
152 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
153 return true;
154 }
155 if (Addr.getOpcode() == ISD::ADD) {
156 ConstantSDNode *CN = nullptr;
157 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&
158 (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&
159 (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
160 // Constant positive word offset from frame index
161 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
162 Offset =
163 CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), MVT::i32);
164 return true;
165 }
166 }
167 return false;
168}
169
170void ARCDAGToDAGISel::Select(SDNode *N) {
171 switch (N->getOpcode()) {
172 case ISD::Constant: {
173 uint64_t CVal = N->getAsZExtVal();
174 ReplaceNode(N, CurDAG->getMachineNode(
175 isInt<12>(CVal) ? ARC::MOV_rs12 : ARC::MOV_rlimm,
176 SDLoc(N), MVT::i32,
177 CurDAG->getTargetConstant(CVal, SDLoc(N), MVT::i32)));
178 return;
179 }
180 }
181 SelectCode(N);
182}
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
const char LLVMTargetMachineRef TM
#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:311
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:239
@ FrameIndex
Definition: ISDOpcodes.h:80
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
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