1 //===-- R600ISelDAGToDAG.cpp - A dag to dag inst selector for R600 --------===//
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 //==-----------------------------------------------------------------------===//
10 /// Defines an instruction selector for the R600 subtarget.
12 //===----------------------------------------------------------------------===//
15 #include "AMDGPUISelDAGToDAG.h"
16 #include "MCTargetDesc/R600MCTargetDesc.h"
18 #include "R600Subtarget.h"
19 #include "llvm/Analysis/ValueTracking.h"
22 class R600DAGToDAGISel
: public AMDGPUDAGToDAGISel
{
23 const R600Subtarget
*Subtarget
= nullptr;
25 bool isConstantLoad(const MemSDNode
*N
, int cbID
) const;
26 bool SelectGlobalValueConstantOffset(SDValue Addr
, SDValue
&IntPtr
);
27 bool SelectGlobalValueVariableOffset(SDValue Addr
, SDValue
&BaseReg
,
31 R600DAGToDAGISel() = delete;
33 explicit R600DAGToDAGISel(TargetMachine
&TM
, CodeGenOptLevel OptLevel
)
34 : AMDGPUDAGToDAGISel(TM
, OptLevel
) {}
36 void Select(SDNode
*N
) override
;
38 bool SelectADDRIndirect(SDValue Addr
, SDValue
&Base
,
39 SDValue
&Offset
) override
;
40 bool SelectADDRVTX_READ(SDValue Addr
, SDValue
&Base
,
41 SDValue
&Offset
) override
;
43 bool runOnMachineFunction(MachineFunction
&MF
) override
;
45 void PreprocessISelDAG() override
{}
48 // Include the pieces autogenerated from the target description.
49 #include "R600GenDAGISel.inc"
52 class R600DAGToDAGISelLegacy
: public SelectionDAGISelLegacy
{
55 explicit R600DAGToDAGISelLegacy(TargetMachine
&TM
, CodeGenOptLevel OptLevel
)
56 : SelectionDAGISelLegacy(
57 ID
, std::make_unique
<R600DAGToDAGISel
>(TM
, OptLevel
)) {}
60 char R600DAGToDAGISelLegacy::ID
= 0;
64 bool R600DAGToDAGISel::runOnMachineFunction(MachineFunction
&MF
) {
65 Subtarget
= &MF
.getSubtarget
<R600Subtarget
>();
66 return SelectionDAGISel::runOnMachineFunction(MF
);
69 bool R600DAGToDAGISel::isConstantLoad(const MemSDNode
*N
, int CbId
) const {
73 return N
->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS
||
74 N
->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT
;
76 return N
->getAddressSpace() == AMDGPUAS::CONSTANT_BUFFER_0
+ CbId
;
79 bool R600DAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr
,
81 if (ConstantSDNode
*Cst
= dyn_cast
<ConstantSDNode
>(Addr
)) {
83 CurDAG
->getIntPtrConstant(Cst
->getZExtValue() / 4, SDLoc(Addr
), true);
89 bool R600DAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr
,
92 if (!isa
<ConstantSDNode
>(Addr
)) {
94 Offset
= CurDAG
->getIntPtrConstant(0, SDLoc(Addr
), true);
100 void R600DAGToDAGISel::Select(SDNode
*N
) {
101 unsigned int Opc
= N
->getOpcode();
102 if (N
->isMachineOpcode()) {
104 return; // Already selected.
110 case AMDGPUISD::BUILD_VERTICAL_VECTOR
:
111 case ISD::SCALAR_TO_VECTOR
:
112 case ISD::BUILD_VECTOR
: {
113 EVT VT
= N
->getValueType(0);
114 unsigned NumVectorElts
= VT
.getVectorNumElements();
116 // BUILD_VECTOR was lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG
117 // that adds a 128 bits reg copy when going through TwoAddressInstructions
118 // pass. We want to avoid 128 bits copies as much as possible because they
119 // can't be bundled by our scheduler.
120 switch (NumVectorElts
) {
122 RegClassID
= R600::R600_Reg64RegClassID
;
125 if (Opc
== AMDGPUISD::BUILD_VERTICAL_VECTOR
)
126 RegClassID
= R600::R600_Reg128VerticalRegClassID
;
128 RegClassID
= R600::R600_Reg128RegClassID
;
131 llvm_unreachable("Do not know how to lower this BUILD_VECTOR");
133 SelectBuildVector(N
, RegClassID
);
141 bool R600DAGToDAGISel::SelectADDRIndirect(SDValue Addr
, SDValue
&Base
,
146 if ((C
= dyn_cast
<ConstantSDNode
>(Addr
))) {
147 Base
= CurDAG
->getRegister(R600::INDIRECT_BASE_ADDR
, MVT::i32
);
148 Offset
= CurDAG
->getTargetConstant(C
->getZExtValue(), DL
, MVT::i32
);
149 } else if ((Addr
.getOpcode() == AMDGPUISD::DWORDADDR
) &&
150 (C
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(0)))) {
151 Base
= CurDAG
->getRegister(R600::INDIRECT_BASE_ADDR
, MVT::i32
);
152 Offset
= CurDAG
->getTargetConstant(C
->getZExtValue(), DL
, MVT::i32
);
153 } else if ((Addr
.getOpcode() == ISD::ADD
|| Addr
.getOpcode() == ISD::OR
) &&
154 (C
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1)))) {
155 Base
= Addr
.getOperand(0);
156 Offset
= CurDAG
->getTargetConstant(C
->getZExtValue(), DL
, MVT::i32
);
159 Offset
= CurDAG
->getTargetConstant(0, DL
, MVT::i32
);
165 bool R600DAGToDAGISel::SelectADDRVTX_READ(SDValue Addr
, SDValue
&Base
,
167 ConstantSDNode
*IMMOffset
;
169 if (Addr
.getOpcode() == ISD::ADD
&&
170 (IMMOffset
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1))) &&
171 isInt
<16>(IMMOffset
->getZExtValue())) {
173 Base
= Addr
.getOperand(0);
174 Offset
= CurDAG
->getTargetConstant(IMMOffset
->getZExtValue(), SDLoc(Addr
),
177 // If the pointer address is constant, we can move it to the offset field.
179 if ((IMMOffset
= dyn_cast
<ConstantSDNode
>(Addr
)) &&
180 isInt
<16>(IMMOffset
->getZExtValue())) {
181 Base
= CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(),
182 SDLoc(CurDAG
->getEntryNode()), R600::ZERO
,
184 Offset
= CurDAG
->getTargetConstant(IMMOffset
->getZExtValue(), SDLoc(Addr
),
189 // Default case, no offset
191 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
195 /// This pass converts a legalized DAG into a R600-specific
196 // DAG, ready for instruction scheduling.
197 FunctionPass
*llvm::createR600ISelDag(TargetMachine
&TM
,
198 CodeGenOptLevel OptLevel
) {
199 return new R600DAGToDAGISelLegacy(TM
, OptLevel
);