LLVM 20.0.0git
R600ISelDAGToDAG.cpp
Go to the documentation of this file.
1//===-- R600ISelDAGToDAG.cpp - A dag to dag inst selector for R600 --------===//
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/// \file
10/// Defines an instruction selector for the R600 subtarget.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AMDGPU.h"
15#include "AMDGPUISelDAGToDAG.h"
17#include "R600.h"
18#include "R600Subtarget.h"
20
21using namespace llvm;
22
23namespace {
24class R600DAGToDAGISel : public AMDGPUDAGToDAGISel {
25 const R600Subtarget *Subtarget = nullptr;
26
27 bool isConstantLoad(const MemSDNode *N, int cbID) const;
28 bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue &IntPtr);
29 bool SelectGlobalValueVariableOffset(SDValue Addr, SDValue &BaseReg,
31
32public:
33 R600DAGToDAGISel() = delete;
34
35 explicit R600DAGToDAGISel(TargetMachine &TM, CodeGenOptLevel OptLevel)
36 : AMDGPUDAGToDAGISel(TM, OptLevel) {}
37
38 void Select(SDNode *N) override;
39
40 bool SelectADDRIndirect(SDValue Addr, SDValue &Base,
41 SDValue &Offset) override;
42 bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
43 SDValue &Offset) override;
44
45 bool runOnMachineFunction(MachineFunction &MF) override;
46
47 void PreprocessISelDAG() override {}
48
49protected:
50 // Include the pieces autogenerated from the target description.
51#include "R600GenDAGISel.inc"
52};
53
54class R600DAGToDAGISelLegacy : public SelectionDAGISelLegacy {
55public:
56 static char ID;
57 explicit R600DAGToDAGISelLegacy(TargetMachine &TM, CodeGenOptLevel OptLevel)
59 ID, std::make_unique<R600DAGToDAGISel>(TM, OptLevel)) {}
60};
61
62char R600DAGToDAGISelLegacy::ID = 0;
63
64} // namespace
65
66bool R600DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
67 Subtarget = &MF.getSubtarget<R600Subtarget>();
69}
70
71bool R600DAGToDAGISel::isConstantLoad(const MemSDNode *N, int CbId) const {
72 if (!N->readMem())
73 return false;
74 if (CbId == -1)
75 return N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS ||
76 N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT;
77
78 return N->getAddressSpace() == AMDGPUAS::CONSTANT_BUFFER_0 + CbId;
79}
80
81bool R600DAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr,
82 SDValue &IntPtr) {
83 if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Addr)) {
84 IntPtr =
85 CurDAG->getIntPtrConstant(Cst->getZExtValue() / 4, SDLoc(Addr), true);
86 return true;
87 }
88 return false;
89}
90
91bool R600DAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr,
92 SDValue &BaseReg,
93 SDValue &Offset) {
94 if (!isa<ConstantSDNode>(Addr)) {
95 BaseReg = Addr;
96 Offset = CurDAG->getIntPtrConstant(0, SDLoc(Addr), true);
97 return true;
98 }
99 return false;
100}
101
102void R600DAGToDAGISel::Select(SDNode *N) {
103 unsigned int Opc = N->getOpcode();
104 if (N->isMachineOpcode()) {
105 N->setNodeId(-1);
106 return; // Already selected.
107 }
108
109 switch (Opc) {
110 default:
111 break;
114 case ISD::BUILD_VECTOR: {
115 EVT VT = N->getValueType(0);
116 unsigned NumVectorElts = VT.getVectorNumElements();
117 unsigned RegClassID;
118 // BUILD_VECTOR was lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG
119 // that adds a 128 bits reg copy when going through TwoAddressInstructions
120 // pass. We want to avoid 128 bits copies as much as possible because they
121 // can't be bundled by our scheduler.
122 switch (NumVectorElts) {
123 case 2:
124 RegClassID = R600::R600_Reg64RegClassID;
125 break;
126 case 4:
128 RegClassID = R600::R600_Reg128VerticalRegClassID;
129 else
130 RegClassID = R600::R600_Reg128RegClassID;
131 break;
132 default:
133 llvm_unreachable("Do not know how to lower this BUILD_VECTOR");
134 }
135 SelectBuildVector(N, RegClassID);
136 return;
137 }
138 }
139
140 SelectCode(N);
141}
142
143bool R600DAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base,
144 SDValue &Offset) {
146 SDLoc DL(Addr);
147
148 if ((C = dyn_cast<ConstantSDNode>(Addr))) {
149 Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);
150 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
151 } else if ((Addr.getOpcode() == AMDGPUISD::DWORDADDR) &&
152 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(0)))) {
153 Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);
154 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
155 } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) &&
156 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) {
157 Base = Addr.getOperand(0);
158 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
159 } else {
160 Base = Addr;
161 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
162 }
163
164 return true;
165}
166
167bool R600DAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
168 SDValue &Offset) {
169 ConstantSDNode *IMMOffset;
170
171 if (Addr.getOpcode() == ISD::ADD &&
172 (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&
173 isInt<16>(IMMOffset->getZExtValue())) {
174
175 Base = Addr.getOperand(0);
176 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr),
177 MVT::i32);
178 return true;
179 // If the pointer address is constant, we can move it to the offset field.
180 }
181 if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr)) &&
182 isInt<16>(IMMOffset->getZExtValue())) {
183 Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
184 SDLoc(CurDAG->getEntryNode()), R600::ZERO,
185 MVT::i32);
186 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr),
187 MVT::i32);
188 return true;
189 }
190
191 // Default case, no offset
192 Base = Addr;
193 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
194 return true;
195}
196
197/// This pass converts a legalized DAG into a R600-specific
198// DAG, ready for instruction scheduling.
200 CodeGenOptLevel OptLevel) {
201 return new R600DAGToDAGISelLegacy(TM, OptLevel);
202}
Defines an instruction selector for the AMDGPU target.
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
uint64_t Addr
Provides R600 specific target descriptions.
AMDGPU R600 specific subclass of TargetSubtarget.
AMDGPU specific code to select AMDGPU machine instructions for SelectionDAG operations.
bool runOnMachineFunction(MachineFunction &MF) override
void PreprocessISelDAG() override
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
uint64_t getZExtValue() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
This is an abstract virtual class for memory operations.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
virtual bool runOnMachineFunction(MachineFunction &mf)
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:77
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ BUILD_VERTICAL_VECTOR
This node is for VLIW targets and it is used to represent a vector that is stored in consecutive regi...
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition: ISDOpcodes.h:635
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition: ISDOpcodes.h:530
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
FunctionPass * createR600ISelDag(TargetMachine &TM, CodeGenOptLevel OptLevel)
This pass converts a legalized DAG into a R600-specific.
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
#define N
Extended Value Type.
Definition: ValueTypes.h:35
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition: ValueTypes.h:331