1 //===-- VEISelDAGToDAG.cpp - A dag to dag inst selector for VE ------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines an instruction selector for the VE target.
11 //===----------------------------------------------------------------------===//
13 #include "VETargetMachine.h"
14 #include "llvm/CodeGen/MachineRegisterInfo.h"
15 #include "llvm/CodeGen/SelectionDAGISel.h"
16 #include "llvm/IR/Intrinsics.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
22 //===----------------------------------------------------------------------===//
23 // Instruction Selector Implementation
24 //===----------------------------------------------------------------------===//
26 /// Convert a DAG integer condition code to a VE ICC condition.
27 inline static VECC::CondCode
intCondCode2Icc(ISD::CondCode CC
) {
30 llvm_unreachable("Unknown integer condition code!");
54 /// Convert a DAG floating point condition code to a VE FCC condition.
55 inline static VECC::CondCode
fpCondCode2Fcc(ISD::CondCode CC
) {
58 llvm_unreachable("Unknown fp condition code!");
84 return VECC::CC_EQNAN
;
86 return VECC::CC_NENAN
;
92 return VECC::CC_LENAN
;
94 return VECC::CC_GENAN
;
100 /// getImmVal - get immediate representation of integer value
101 inline static uint64_t getImmVal(const ConstantSDNode
*N
) {
102 return N
->getSExtValue();
105 /// getFpImmVal - get immediate representation of floating point value
106 inline static uint64_t getFpImmVal(const ConstantFPSDNode
*N
) {
107 const APInt
&Imm
= N
->getValueAPF().bitcastToAPInt();
108 uint64_t Val
= Imm
.getZExtValue();
109 if (Imm
.getBitWidth() == 32) {
110 // Immediate value of float place places at higher bits on VE.
116 //===--------------------------------------------------------------------===//
117 /// VEDAGToDAGISel - VE specific code to select VE machine
118 /// instructions for SelectionDAG operations.
121 class VEDAGToDAGISel
: public SelectionDAGISel
{
122 /// Subtarget - Keep a pointer to the VE Subtarget around so that we can
123 /// make the right decision when generating code for different targets.
124 const VESubtarget
*Subtarget
;
127 explicit VEDAGToDAGISel(VETargetMachine
&tm
) : SelectionDAGISel(tm
) {}
129 bool runOnMachineFunction(MachineFunction
&MF
) override
{
130 Subtarget
= &MF
.getSubtarget
<VESubtarget
>();
131 return SelectionDAGISel::runOnMachineFunction(MF
);
134 void Select(SDNode
*N
) override
;
136 // Complex Pattern Selectors.
137 bool selectADDRrri(SDValue N
, SDValue
&Base
, SDValue
&Index
, SDValue
&Offset
);
138 bool selectADDRrii(SDValue N
, SDValue
&Base
, SDValue
&Index
, SDValue
&Offset
);
139 bool selectADDRzri(SDValue N
, SDValue
&Base
, SDValue
&Index
, SDValue
&Offset
);
140 bool selectADDRzii(SDValue N
, SDValue
&Base
, SDValue
&Index
, SDValue
&Offset
);
141 bool selectADDRri(SDValue N
, SDValue
&Base
, SDValue
&Offset
);
142 bool selectADDRzi(SDValue N
, SDValue
&Base
, SDValue
&Offset
);
144 StringRef
getPassName() const override
{
145 return "VE DAG->DAG Pattern Instruction Selection";
148 // Include the pieces autogenerated from the target description.
149 #include "VEGenDAGISel.inc"
152 SDNode
*getGlobalBaseReg();
154 bool matchADDRrr(SDValue N
, SDValue
&Base
, SDValue
&Index
);
155 bool matchADDRri(SDValue N
, SDValue
&Base
, SDValue
&Offset
);
157 } // end anonymous namespace
159 bool VEDAGToDAGISel::selectADDRrri(SDValue Addr
, SDValue
&Base
, SDValue
&Index
,
161 if (Addr
.getOpcode() == ISD::FrameIndex
)
163 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
164 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
165 Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
)
166 return false; // direct calls.
169 if (matchADDRri(Addr
, LHS
, RHS
)) {
170 if (matchADDRrr(LHS
, Base
, Index
)) {
174 // Return false to try selectADDRrii.
177 if (matchADDRrr(Addr
, LHS
, RHS
)) {
178 // If the input is a pair of a frame-index and a register, move a
179 // frame-index to LHS. This generates MI with following operands.
180 // %dest, #FI, %reg, offset
181 // In the eliminateFrameIndex, above MI is converted to the following.
182 // %dest, %fp, %reg, fi_offset + offset
183 if (isa
<FrameIndexSDNode
>(RHS
))
186 if (matchADDRri(RHS
, Index
, Offset
)) {
190 if (matchADDRri(LHS
, Base
, Offset
)) {
196 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
199 return false; // Let the reg+imm(=0) pattern catch this!
202 bool VEDAGToDAGISel::selectADDRrii(SDValue Addr
, SDValue
&Base
, SDValue
&Index
,
204 if (matchADDRri(Addr
, Base
, Offset
)) {
205 Index
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
210 Index
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
211 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
215 bool VEDAGToDAGISel::selectADDRzri(SDValue Addr
, SDValue
&Base
, SDValue
&Index
,
221 bool VEDAGToDAGISel::selectADDRzii(SDValue Addr
, SDValue
&Base
, SDValue
&Index
,
223 if (isa
<FrameIndexSDNode
>(Addr
))
225 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
226 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
227 Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
)
228 return false; // direct calls.
230 if (auto *CN
= dyn_cast
<ConstantSDNode
>(Addr
)) {
231 if (isInt
<32>(CN
->getSExtValue())) {
232 Base
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
233 Index
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
235 CurDAG
->getTargetConstant(CN
->getZExtValue(), SDLoc(Addr
), MVT::i32
);
242 bool VEDAGToDAGISel::selectADDRri(SDValue Addr
, SDValue
&Base
,
244 if (matchADDRri(Addr
, Base
, Offset
))
248 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
252 bool VEDAGToDAGISel::selectADDRzi(SDValue Addr
, SDValue
&Base
,
254 if (isa
<FrameIndexSDNode
>(Addr
))
256 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
257 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
258 Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
)
259 return false; // direct calls.
261 if (auto *CN
= dyn_cast
<ConstantSDNode
>(Addr
)) {
262 if (isInt
<32>(CN
->getSExtValue())) {
263 Base
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
265 CurDAG
->getTargetConstant(CN
->getZExtValue(), SDLoc(Addr
), MVT::i32
);
272 bool VEDAGToDAGISel::matchADDRrr(SDValue Addr
, SDValue
&Base
, SDValue
&Index
) {
273 if (isa
<FrameIndexSDNode
>(Addr
))
275 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
276 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
277 Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
)
278 return false; // direct calls.
280 if (Addr
.getOpcode() == ISD::ADD
) {
281 ; // Nothing to do here.
282 } else if (Addr
.getOpcode() == ISD::OR
) {
283 // We want to look through a transform in InstCombine and DAGCombiner that
284 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
285 if (!CurDAG
->haveNoCommonBitsSet(Addr
.getOperand(0), Addr
.getOperand(1)))
291 if (Addr
.getOperand(0).getOpcode() == VEISD::Lo
||
292 Addr
.getOperand(1).getOpcode() == VEISD::Lo
)
293 return false; // Let the LEASL patterns catch this!
295 Base
= Addr
.getOperand(0);
296 Index
= Addr
.getOperand(1);
300 bool VEDAGToDAGISel::matchADDRri(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
) {
301 auto AddrTy
= Addr
->getValueType(0);
302 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
303 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), AddrTy
);
304 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
307 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
308 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
309 Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
)
310 return false; // direct calls.
312 if (CurDAG
->isBaseWithConstantOffset(Addr
)) {
313 ConstantSDNode
*CN
= cast
<ConstantSDNode
>(Addr
.getOperand(1));
314 if (isInt
<32>(CN
->getSExtValue())) {
315 if (FrameIndexSDNode
*FIN
=
316 dyn_cast
<FrameIndexSDNode
>(Addr
.getOperand(0))) {
317 // Constant offset from frame ref.
318 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), AddrTy
);
320 Base
= Addr
.getOperand(0);
323 CurDAG
->getTargetConstant(CN
->getZExtValue(), SDLoc(Addr
), MVT::i32
);
330 void VEDAGToDAGISel::Select(SDNode
*N
) {
332 if (N
->isMachineOpcode()) {
334 return; // Already selected.
337 switch (N
->getOpcode()) {
338 case VEISD::GLOBAL_BASE_REG
:
339 ReplaceNode(N
, getGlobalBaseReg());
346 SDNode
*VEDAGToDAGISel::getGlobalBaseReg() {
347 Register GlobalBaseReg
= Subtarget
->getInstrInfo()->getGlobalBaseReg(MF
);
349 ->getRegister(GlobalBaseReg
, TLI
->getPointerTy(CurDAG
->getDataLayout()))
353 /// createVEISelDag - This pass converts a legalized DAG into a
354 /// VE-specific DAG, ready for instruction scheduling.
356 FunctionPass
*llvm::createVEISelDag(VETargetMachine
&TM
) {
357 return new VEDAGToDAGISel(TM
);