-
Notifications
You must be signed in to change notification settings - Fork 1
/
LM32ISelDAGToDAG.cpp
278 lines (243 loc) · 9.67 KB
/
LM32ISelDAGToDAG.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
//===-- LM32ISelDAGToDAG.cpp - A dag to dag inst selector for LM32 --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an instruction selector for the LM32 target.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "lm32-isel"
#include "LM32.h"
#include "LM32MachineFunctionInfo.h"
#include "LM32RegisterInfo.h"
#include "LM32Subtarget.h"
#include "LM32TargetMachine.h"
#include "llvm/GlobalValue.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/CFG.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// Instruction Selector Implementation
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// LM32DAGToDAGISel - LM32 specific code to select LM32 machine
// instructions for SelectionDAG operations.
//===----------------------------------------------------------------------===//
namespace {
class LM32DAGToDAGISel : public SelectionDAGISel {
/// TM - Keep a reference to LM32TargetMachine.
LM32TargetMachine &TM;
/// Subtarget - Keep a pointer to the LM32Subtarget around so that we can
/// make the right decision when generating code for different targets.
const LM32Subtarget &Subtarget;
public:
explicit LM32DAGToDAGISel(LM32TargetMachine &tm) :
SelectionDAGISel(tm),
TM(tm), Subtarget(tm.getSubtarget<LM32Subtarget>()) {}
// Pass Name
virtual const char *getPassName() const {
return "LM32 DAG->DAG Pattern Instruction Selection";
}
private:
// Include the pieces autogenerated from the target description.
#include "LM32GenDAGISel.inc"
/// getTargetMachine - Return a reference to the TargetMachine, casted
/// to the target-specific type.
const LM32TargetMachine &getTargetMachine() {
return static_cast<const LM32TargetMachine &>(TM);
}
/// getInstrInfo - Return a reference to the TargetInstrInfo, casted
/// to the target-specific type.
const LM32InstrInfo *getInstrInfo() {
return getTargetMachine().getInstrInfo();
}
// SDNode *getGlobalBaseReg();
SDNode *Select(SDNode *N);
// Address Selection
bool SelectAddrRegImm(SDValue N, SDValue &Disp, SDValue &Base);
// getI32Imm - Return a target constant with the specified value, of type i32.
inline SDValue getI32Imm(unsigned Imm) {
return CurDAG->getTargetConstant(Imm, MVT::i32);
}
};
}
///
/// This is modeled after SPARC.
/// Note that the initial pattern in MonarchInstrInfo.td only matches
/// frameindex.
/// XCore has a different approach. It also matches add and defines
/// pseudo-instructions that are eliminated in eliminateFrameIndex.
///
bool LM32DAGToDAGISel::
SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset) {
// errs() << "value type: " << Addr.getValueType().getEVTString();
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
Offset = CurDAG->getTargetConstant(0, MVT::i32);
// errs() << "base result value type: " << Base.getValueType().getEVTString();
return true;
}
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
Addr.getOpcode() == ISD::TargetGlobalAddress)
return false; // direct calls.
// Operand is a result from an ADD
if (Addr.getOpcode() == ISD::ADD) {
// If the operand is a constant value that fits in a sign-extended 16bit
// offset (such that we can just do ADDI R1,4).
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
if (isInt<16>(CN->getSExtValue())) {
// if the first operand is a frameindex, get the TargetFI node,
if (FrameIndexSDNode *FIN =
dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
//FIXME: why do we change this to a targetFrameIndex?
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
} else {
Base = Addr.getOperand(0);
}
Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
// errs() << "base result value type: " << Base.getValueType().getEVTString();
return true;
}
}
// These are optimizations. If there's an ADD of a MonarchISD::Lo
// (16bit constant) offset it can be incorporated into the ADDri
// addressing mode. Note the Hi part must be shifted so it don't work.
// E.g. (ld (add lo hi) 0) -> (ld (hi) lo)
// also see LowerGlobalAddress etc. for a similar optimization.
#if 0
// FIXME: add this back in
if (Addr.getOperand(0).getOpcode() == MonarchISD::Lo) {
assert(0 && "FIXME: I don't think this will work since Lo is zero-extended and LD will expected sign-extended\n");
Base = Addr.getOperand(1);
Offset = Addr.getOperand(0).getOperand(0);
return true;
}
if (Addr.getOperand(1).getOpcode() == MonarchISD::Lo) {
assert(0 && "FIXME: I don't think this will work since Lo is zero-extended and LD will expected sign-extended\n");
Base = Addr.getOperand(0);
Offset = Addr.getOperand(1).getOperand(0);
return true;
}
#endif
}
Base = Addr;
Offset = CurDAG->getTargetConstant(0, MVT::i32);
// errs() << "base result value type: " << Base.getValueType().getEVTString();
return true;
}
#if 0
//FIXME: No PIC support.
/// getGlobalBaseReg - Output the instructions required to put the
/// GOT address into a register.
SDNode *LM32DAGToDAGISel::getGlobalBaseReg() {
//FIXME: not ported to LM32
assert(0 && "getGlobalBaseReg() not supported.");
unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode();
}
#endif
/// Select instructions not customized! Used for
/// expanded, promoted and normal instructions
/// from MBlaze:
SDNode* LM32DAGToDAGISel::Select(SDNode *Node) {
//FIXME: not ported to LM32
unsigned Opcode = Node->getOpcode();
DebugLoc dl = Node->getDebugLoc();
// If we have a custom node, we already have selected!
if (Node->isMachineOpcode())
return NULL;
///
// Instruction Selection not handled by the auto-generated
// tablegen selection should be handled here.
///
switch (Opcode) {
default: break;
// Get target GOT address.
case ISD::GLOBAL_OFFSET_TABLE: {
#if 0
//FIXME: No PIC support.
return getGlobalBaseReg();
#endif
assert(0 && "No PIC support.");
return Node; // quiet error message
}
case ISD::FrameIndex: {
SDValue imm = CurDAG->getTargetConstant(0, MVT::i32);
int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex();
EVT VT = Node->getValueType(0);
// errs() << "ISD::FrameIndex value type: " << VT.getEVTString() << "/n";
SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
unsigned Opc = LM32::ADDI;
if (Node->hasOneUse())
return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm);
return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm);
}
#if 0
/// Handle direct and indirect calls when using PIC. On PIC, when
/// GOT is smaller than about 64k (small code) the GA target is
/// loaded with only one instruction. Otherwise GA's target must
/// be loaded with 3 instructions.
case LM32ISD::JmpLink: {
if (TM.getRelocationModel() == Reloc::PIC_) {
SDValue Chain = Node->getOperand(0);
SDValue Callee = Node->getOperand(1);
SDValue R20Reg = CurDAG->getRegister(LM32::R20, MVT::i32);
SDValue InFlag(0, 0);
if ((isa<GlobalAddressSDNode>(Callee)) ||
(isa<ExternalSymbolSDNode>(Callee)))
{
/// Direct call for global addresses and external symbols
SDValue GPReg = CurDAG->getRegister(LM32::R15, MVT::i32);
// Use load to get GOT target
SDValue Ops[] = { Callee, GPReg, Chain };
SDValue Load = SDValue(CurDAG->getMachineNode(LM32::LW, dl,
MVT::i32, MVT::Other, Ops, 3), 0);
Chain = Load.getValue(1);
// Call target must be on T9
Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Load, InFlag);
} else
/// Indirect call
Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Callee, InFlag);
// Emit Jump and Link Register
SDNode *ResNode = CurDAG->getMachineNode(LM32::BRLID, dl, MVT::Other,
MVT::Glue, R20Reg, Chain);
Chain = SDValue(ResNode, 0);
InFlag = SDValue(ResNode, 1);
ReplaceUses(SDValue(Node, 0), Chain);
ReplaceUses(SDValue(Node, 1), InFlag);
return ResNode;
}
}
#endif
}
// Select the default instruction
SDNode *ResNode = SelectCode(Node);
DEBUG(errs() << "=> ");
if (ResNode == NULL || ResNode == Node)
DEBUG(Node->dump(CurDAG));
else
DEBUG(ResNode->dump(CurDAG));
DEBUG(errs() << "\n");
return ResNode;
}
/// createLM32ISelDag - This pass converts a legalized DAG into a
/// LM32-specific DAG, ready for instruction scheduling.
FunctionPass *llvm::createLM32ISelDag(LM32TargetMachine &TM) {
return new LM32DAGToDAGISel(TM);
}