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 //===----------------------------------------------------------------------===//
14 #include "VETargetMachine.h"
15 #include "llvm/CodeGen/MachineRegisterInfo.h"
16 #include "llvm/CodeGen/SelectionDAGISel.h"
17 #include "llvm/IR/Intrinsics.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/raw_ostream.h"
23 #define DEBUG_TYPE "ve-isel"
24 #define PASS_NAME "VE DAG->DAG Pattern Instruction Selection"
26 //===--------------------------------------------------------------------===//
27 /// VEDAGToDAGISel - VE specific code to select VE machine
28 /// instructions for SelectionDAG operations.
31 class VEDAGToDAGISel
: public SelectionDAGISel
{
32 /// Subtarget - Keep a pointer to the VE Subtarget around so that we can
33 /// make the right decision when generating code for different targets.
34 const VESubtarget
*Subtarget
;
39 VEDAGToDAGISel() = delete;
41 explicit VEDAGToDAGISel(VETargetMachine
&tm
) : SelectionDAGISel(ID
, tm
) {}
43 bool runOnMachineFunction(MachineFunction
&MF
) override
{
44 Subtarget
= &MF
.getSubtarget
<VESubtarget
>();
45 return SelectionDAGISel::runOnMachineFunction(MF
);
48 void Select(SDNode
*N
) override
;
50 // Complex Pattern Selectors.
51 bool selectADDRrri(SDValue N
, SDValue
&Base
, SDValue
&Index
, SDValue
&Offset
);
52 bool selectADDRrii(SDValue N
, SDValue
&Base
, SDValue
&Index
, SDValue
&Offset
);
53 bool selectADDRzri(SDValue N
, SDValue
&Base
, SDValue
&Index
, SDValue
&Offset
);
54 bool selectADDRzii(SDValue N
, SDValue
&Base
, SDValue
&Index
, SDValue
&Offset
);
55 bool selectADDRri(SDValue N
, SDValue
&Base
, SDValue
&Offset
);
56 bool selectADDRzi(SDValue N
, SDValue
&Base
, SDValue
&Offset
);
58 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
59 /// inline asm expressions.
60 bool SelectInlineAsmMemoryOperand(const SDValue
&Op
,
61 InlineAsm::ConstraintCode ConstraintID
,
62 std::vector
<SDValue
> &OutOps
) override
;
64 // Include the pieces autogenerated from the target description.
65 #include "VEGenDAGISel.inc"
68 SDNode
*getGlobalBaseReg();
70 bool matchADDRrr(SDValue N
, SDValue
&Base
, SDValue
&Index
);
71 bool matchADDRri(SDValue N
, SDValue
&Base
, SDValue
&Offset
);
73 } // end anonymous namespace
75 char VEDAGToDAGISel::ID
= 0;
77 INITIALIZE_PASS(VEDAGToDAGISel
, DEBUG_TYPE
, PASS_NAME
, false, false)
79 bool VEDAGToDAGISel::selectADDRrri(SDValue Addr
, SDValue
&Base
, SDValue
&Index
,
81 if (Addr
.getOpcode() == ISD::FrameIndex
)
83 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
84 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
85 Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
)
86 return false; // direct calls.
89 if (matchADDRri(Addr
, LHS
, RHS
)) {
90 if (matchADDRrr(LHS
, Base
, Index
)) {
94 // Return false to try selectADDRrii.
97 if (matchADDRrr(Addr
, LHS
, RHS
)) {
98 // If the input is a pair of a frame-index and a register, move a
99 // frame-index to LHS. This generates MI with following operands.
100 // %dest, #FI, %reg, offset
101 // In the eliminateFrameIndex, above MI is converted to the following.
102 // %dest, %fp, %reg, fi_offset + offset
103 if (isa
<FrameIndexSDNode
>(RHS
))
106 if (matchADDRri(RHS
, Index
, Offset
)) {
110 if (matchADDRri(LHS
, Base
, Offset
)) {
116 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
119 return false; // Let the reg+imm(=0) pattern catch this!
122 bool VEDAGToDAGISel::selectADDRrii(SDValue Addr
, SDValue
&Base
, SDValue
&Index
,
124 if (matchADDRri(Addr
, Base
, Offset
)) {
125 Index
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
130 Index
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
131 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
135 bool VEDAGToDAGISel::selectADDRzri(SDValue Addr
, SDValue
&Base
, SDValue
&Index
,
141 bool VEDAGToDAGISel::selectADDRzii(SDValue Addr
, SDValue
&Base
, SDValue
&Index
,
143 if (isa
<FrameIndexSDNode
>(Addr
))
145 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
146 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
147 Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
)
148 return false; // direct calls.
150 if (auto *CN
= dyn_cast
<ConstantSDNode
>(Addr
)) {
151 if (isInt
<32>(CN
->getSExtValue())) {
152 Base
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
153 Index
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
155 CurDAG
->getTargetConstant(CN
->getZExtValue(), SDLoc(Addr
), MVT::i32
);
162 bool VEDAGToDAGISel::selectADDRri(SDValue Addr
, SDValue
&Base
,
164 if (matchADDRri(Addr
, Base
, Offset
))
168 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
172 bool VEDAGToDAGISel::selectADDRzi(SDValue Addr
, SDValue
&Base
,
174 if (isa
<FrameIndexSDNode
>(Addr
))
176 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
177 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
178 Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
)
179 return false; // direct calls.
181 if (auto *CN
= dyn_cast
<ConstantSDNode
>(Addr
)) {
182 if (isInt
<32>(CN
->getSExtValue())) {
183 Base
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
185 CurDAG
->getTargetConstant(CN
->getZExtValue(), SDLoc(Addr
), MVT::i32
);
192 bool VEDAGToDAGISel::matchADDRrr(SDValue Addr
, SDValue
&Base
, SDValue
&Index
) {
193 if (isa
<FrameIndexSDNode
>(Addr
))
195 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
196 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
197 Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
)
198 return false; // direct calls.
200 if (Addr
.getOpcode() == ISD::ADD
) {
201 ; // Nothing to do here.
202 } else if (Addr
.getOpcode() == ISD::OR
) {
203 // We want to look through a transform in InstCombine and DAGCombiner that
204 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
205 if (!CurDAG
->haveNoCommonBitsSet(Addr
.getOperand(0), Addr
.getOperand(1)))
211 if (Addr
.getOperand(0).getOpcode() == VEISD::Lo
||
212 Addr
.getOperand(1).getOpcode() == VEISD::Lo
)
213 return false; // Let the LEASL patterns catch this!
215 Base
= Addr
.getOperand(0);
216 Index
= Addr
.getOperand(1);
220 bool VEDAGToDAGISel::matchADDRri(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
) {
221 auto AddrTy
= Addr
->getValueType(0);
222 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
223 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), AddrTy
);
224 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
227 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
228 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
229 Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
)
230 return false; // direct calls.
232 if (CurDAG
->isBaseWithConstantOffset(Addr
)) {
233 ConstantSDNode
*CN
= cast
<ConstantSDNode
>(Addr
.getOperand(1));
234 if (isInt
<32>(CN
->getSExtValue())) {
235 if (FrameIndexSDNode
*FIN
=
236 dyn_cast
<FrameIndexSDNode
>(Addr
.getOperand(0))) {
237 // Constant offset from frame ref.
238 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), AddrTy
);
240 Base
= Addr
.getOperand(0);
243 CurDAG
->getTargetConstant(CN
->getZExtValue(), SDLoc(Addr
), MVT::i32
);
250 void VEDAGToDAGISel::Select(SDNode
*N
) {
252 if (N
->isMachineOpcode()) {
254 return; // Already selected.
257 switch (N
->getOpcode()) {
259 // Late eliminate the LEGALAVL wrapper
260 case VEISD::LEGALAVL
:
261 ReplaceNode(N
, N
->getOperand(0).getNode());
264 // Lower (broadcast 1) and (broadcast 0) to VM[P]0
265 case VEISD::VEC_BROADCAST
: {
266 MVT SplatResTy
= N
->getSimpleValueType(0);
267 if (SplatResTy
.getVectorElementType() != MVT::i1
)
270 // Constant non-zero broadcast.
271 auto BConst
= dyn_cast
<ConstantSDNode
>(N
->getOperand(0));
274 bool BCTrueMask
= (BConst
->getSExtValue() != 0);
278 // Packed or non-packed.
280 if (SplatResTy
.getVectorNumElements() == StandardVectorWidth
) {
281 New
= CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(), SDLoc(N
), VE::VM0
,
283 } else if (SplatResTy
.getVectorNumElements() == PackedVectorWidth
) {
284 New
= CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(), SDLoc(N
), VE::VMP0
,
290 ReplaceNode(N
, New
.getNode());
294 case VEISD::GLOBAL_BASE_REG
:
295 ReplaceNode(N
, getGlobalBaseReg());
302 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
303 /// inline asm expressions.
304 bool VEDAGToDAGISel::SelectInlineAsmMemoryOperand(
305 const SDValue
&Op
, InlineAsm::ConstraintCode ConstraintID
,
306 std::vector
<SDValue
> &OutOps
) {
308 switch (ConstraintID
) {
310 llvm_unreachable("Unexpected asm memory constraint");
311 case InlineAsm::ConstraintCode::o
:
312 case InlineAsm::ConstraintCode::m
: // memory
313 // Try to match ADDRri since reg+imm style is safe for all VE instructions
314 // with a memory operand.
315 if (selectADDRri(Op
, Op0
, Op1
)) {
316 OutOps
.push_back(Op0
);
317 OutOps
.push_back(Op1
);
320 // Otherwise, require the address to be in a register and immediate 0.
321 OutOps
.push_back(Op
);
322 OutOps
.push_back(CurDAG
->getTargetConstant(0, SDLoc(Op
), MVT::i32
));
328 SDNode
*VEDAGToDAGISel::getGlobalBaseReg() {
329 Register GlobalBaseReg
= Subtarget
->getInstrInfo()->getGlobalBaseReg(MF
);
331 ->getRegister(GlobalBaseReg
, TLI
->getPointerTy(CurDAG
->getDataLayout()))
335 /// createVEISelDag - This pass converts a legalized DAG into a
336 /// VE-specific DAG, ready for instruction scheduling.
338 FunctionPass
*llvm::createVEISelDag(VETargetMachine
&TM
) {
339 return new VEDAGToDAGISel(TM
);