Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/ARC/ARCISelDAGToDAG.cpp
35267 views
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"
15
#include "llvm/CodeGen/MachineFrameInfo.h"
16
#include "llvm/CodeGen/MachineFunction.h"
17
#include "llvm/CodeGen/MachineInstrBuilder.h"
18
#include "llvm/CodeGen/MachineRegisterInfo.h"
19
#include "llvm/CodeGen/SelectionDAG.h"
20
#include "llvm/CodeGen/SelectionDAGISel.h"
21
#include "llvm/CodeGen/TargetLowering.h"
22
#include "llvm/IR/CallingConv.h"
23
#include "llvm/IR/Constants.h"
24
#include "llvm/IR/DerivedTypes.h"
25
#include "llvm/IR/Function.h"
26
#include "llvm/IR/Intrinsics.h"
27
#include "llvm/IR/LLVMContext.h"
28
#include "llvm/Support/Compiler.h"
29
#include "llvm/Support/Debug.h"
30
#include "llvm/Support/ErrorHandling.h"
31
#include "llvm/Support/raw_ostream.h"
32
33
using 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.
40
namespace {
41
42
class ARCDAGToDAGISel : public SelectionDAGISel {
43
public:
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
61
class ARCDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
62
public:
63
static char ID;
64
explicit ARCDAGToDAGISelLegacy(ARCTargetMachine &TM, CodeGenOptLevel OptLevel)
65
: SelectionDAGISelLegacy(
66
ID, std::make_unique<ARCDAGToDAGISel>(TM, OptLevel)) {}
67
};
68
69
char ARCDAGToDAGISelLegacy::ID;
70
71
} // end anonymous namespace
72
73
INITIALIZE_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.
77
FunctionPass *llvm::createARCISelDag(ARCTargetMachine &TM,
78
CodeGenOptLevel OptLevel) {
79
return new ARCDAGToDAGISelLegacy(TM, OptLevel);
80
}
81
82
bool 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
92
bool 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
134
bool 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.
153
bool 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
176
void 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
}
189
190