blob: f40cdba0ba468280aa82c98559290de2c91a74c7 [file] [log] [blame]
Tom Stellard75aadc22012-12-11 21:25:42 +00001//===-- AMDILISelDAGToDAG.cpp - A dag to dag inst selector for AMDIL ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//==-----------------------------------------------------------------------===//
9//
10/// \file
11/// \brief Defines an instruction selector for the AMDGPU target.
12//
13//===----------------------------------------------------------------------===//
14#include "AMDGPUInstrInfo.h"
15#include "AMDGPUISelLowering.h" // For AMDGPUISD
16#include "AMDGPURegisterInfo.h"
Tom Stellard2e59a452014-06-13 01:32:00 +000017#include "AMDGPUSubtarget.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000018#include "R600InstrInfo.h"
Tom Stellardb02094e2014-07-21 15:45:01 +000019#include "SIDefines.h"
Christian Konigf82901a2013-02-26 17:52:23 +000020#include "SIISelLowering.h"
Tom Stellardb02094e2014-07-21 15:45:01 +000021#include "SIMachineFunctionInfo.h"
Tom Stellard58ac7442014-04-29 23:12:48 +000022#include "llvm/CodeGen/FunctionLoweringInfo.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000023#include "llvm/CodeGen/PseudoSourceValue.h"
Tom Stellardb02094e2014-07-21 15:45:01 +000024#include "llvm/CodeGen/MachineFrameInfo.h"
25#include "llvm/CodeGen/MachineRegisterInfo.h"
Benjamin Kramerd78bb462013-05-23 17:10:37 +000026#include "llvm/CodeGen/SelectionDAG.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000027#include "llvm/CodeGen/SelectionDAGISel.h"
Tom Stellard58ac7442014-04-29 23:12:48 +000028#include "llvm/IR/Function.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000029
30using namespace llvm;
31
32//===----------------------------------------------------------------------===//
33// Instruction Selector Implementation
34//===----------------------------------------------------------------------===//
35
36namespace {
37/// AMDGPU specific code to select AMDGPU machine instructions for
38/// SelectionDAG operations.
39class AMDGPUDAGToDAGISel : public SelectionDAGISel {
40 // Subtarget - Keep a pointer to the AMDGPU Subtarget around so that we can
41 // make the right decision when generating code for different targets.
Eric Christopher7792e322015-01-30 23:24:40 +000042 const AMDGPUSubtarget *Subtarget;
Tom Stellard75aadc22012-12-11 21:25:42 +000043public:
44 AMDGPUDAGToDAGISel(TargetMachine &TM);
45 virtual ~AMDGPUDAGToDAGISel();
Eric Christopher7792e322015-01-30 23:24:40 +000046 bool runOnMachineFunction(MachineFunction &MF) override;
Craig Topper5656db42014-04-29 07:57:24 +000047 SDNode *Select(SDNode *N) override;
48 const char *getPassName() const override;
49 void PostprocessISelDAG() override;
Tom Stellard75aadc22012-12-11 21:25:42 +000050
51private:
Tom Stellard7ed0b522014-04-03 20:19:27 +000052 bool isInlineImmediate(SDNode *N) const;
Vincent Lejeunec6896792013-06-04 23:17:15 +000053 bool FoldOperand(SDValue &Src, SDValue &Sel, SDValue &Neg, SDValue &Abs,
Tom Stellard84021442013-07-23 01:48:24 +000054 const R600InstrInfo *TII);
Tom Stellard365366f2013-01-23 02:09:06 +000055 bool FoldOperands(unsigned, const R600InstrInfo *, std::vector<SDValue> &);
Vincent Lejeunec6896792013-06-04 23:17:15 +000056 bool FoldDotOperands(unsigned, const R600InstrInfo *, std::vector<SDValue> &);
Tom Stellard75aadc22012-12-11 21:25:42 +000057
58 // Complex pattern selectors
59 bool SelectADDRParam(SDValue Addr, SDValue& R1, SDValue& R2);
60 bool SelectADDR(SDValue N, SDValue &R1, SDValue &R2);
61 bool SelectADDR64(SDValue N, SDValue &R1, SDValue &R2);
62
63 static bool checkType(const Value *ptr, unsigned int addrspace);
Nick Lewyckyaad475b2014-04-15 07:22:52 +000064 static bool checkPrivateAddress(const MachineMemOperand *Op);
Tom Stellard75aadc22012-12-11 21:25:42 +000065
66 static bool isGlobalStore(const StoreSDNode *N);
Matt Arsenault3f981402014-09-15 15:41:53 +000067 static bool isFlatStore(const StoreSDNode *N);
Tom Stellard75aadc22012-12-11 21:25:42 +000068 static bool isPrivateStore(const StoreSDNode *N);
69 static bool isLocalStore(const StoreSDNode *N);
70 static bool isRegionStore(const StoreSDNode *N);
71
Matt Arsenault2aabb062013-06-18 23:37:58 +000072 bool isCPLoad(const LoadSDNode *N) const;
73 bool isConstantLoad(const LoadSDNode *N, int cbID) const;
74 bool isGlobalLoad(const LoadSDNode *N) const;
Matt Arsenault3f981402014-09-15 15:41:53 +000075 bool isFlatLoad(const LoadSDNode *N) const;
Matt Arsenault2aabb062013-06-18 23:37:58 +000076 bool isParamLoad(const LoadSDNode *N) const;
77 bool isPrivateLoad(const LoadSDNode *N) const;
78 bool isLocalLoad(const LoadSDNode *N) const;
79 bool isRegionLoad(const LoadSDNode *N) const;
Tom Stellard75aadc22012-12-11 21:25:42 +000080
Tom Stellard381a94a2015-05-12 15:00:49 +000081 SDNode *glueCopyToM0(SDNode *N) const;
82
Tom Stellarddf94dc32013-08-14 23:24:24 +000083 const TargetRegisterClass *getOperandRegClass(SDNode *N, unsigned OpNo) const;
Tom Stellard365366f2013-01-23 02:09:06 +000084 bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue& IntPtr);
Matt Arsenault209a7b92014-04-18 07:40:20 +000085 bool SelectGlobalValueVariableOffset(SDValue Addr, SDValue &BaseReg,
86 SDValue& Offset);
Tom Stellard75aadc22012-12-11 21:25:42 +000087 bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset);
Tom Stellardf3b2a1e2013-02-06 17:32:29 +000088 bool SelectADDRIndirect(SDValue Addr, SDValue &Base, SDValue &Offset);
Tom Stellard85e8b6d2014-08-22 18:49:33 +000089 bool isDSOffsetLegal(const SDValue &Base, unsigned Offset,
90 unsigned OffsetBits) const;
91 bool SelectDS1Addr1Offset(SDValue Ptr, SDValue &Base, SDValue &Offset) const;
Tom Stellardf3fc5552014-08-22 18:49:35 +000092 bool SelectDS64Bit4ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0,
93 SDValue &Offset1) const;
Tom Stellard155bbb72014-08-11 22:18:17 +000094 void SelectMUBUF(SDValue Addr, SDValue &SRsrc, SDValue &VAddr,
95 SDValue &SOffset, SDValue &Offset, SDValue &Offen,
96 SDValue &Idxen, SDValue &Addr64, SDValue &GLC, SDValue &SLC,
97 SDValue &TFE) const;
98 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, SDValue &VAddr,
Tom Stellard1f9939f2015-02-27 14:59:41 +000099 SDValue &SOffset, SDValue &Offset, SDValue &GLC,
100 SDValue &SLC, SDValue &TFE) const;
Tom Stellard7980fc82014-09-25 18:30:26 +0000101 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
Tom Stellardc53861a2015-02-11 00:34:32 +0000102 SDValue &VAddr, SDValue &SOffset, SDValue &Offset,
Tom Stellard7980fc82014-09-25 18:30:26 +0000103 SDValue &SLC) const;
Tom Stellardb02094e2014-07-21 15:45:01 +0000104 bool SelectMUBUFScratch(SDValue Addr, SDValue &RSrc, SDValue &VAddr,
105 SDValue &SOffset, SDValue &ImmOffset) const;
Tom Stellard155bbb72014-08-11 22:18:17 +0000106 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &SOffset,
107 SDValue &Offset, SDValue &GLC, SDValue &SLC,
Tom Stellardb02094e2014-07-21 15:45:01 +0000108 SDValue &TFE) const;
Tom Stellard7980fc82014-09-25 18:30:26 +0000109 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset,
110 SDValue &Offset, SDValue &GLC) const;
Tom Stellarddee26a22015-08-06 19:28:30 +0000111 bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue &Offset,
112 bool &Imm) const;
113 bool SelectSMRD(SDValue Addr, SDValue &SBase, SDValue &Offset,
114 bool &Imm) const;
115 bool SelectSMRDImm(SDValue Addr, SDValue &SBase, SDValue &Offset) const;
116 bool SelectSMRDSgpr(SDValue Addr, SDValue &SBase, SDValue &Offset) const;
117 bool SelectSMRDBufferImm(SDValue Addr, SDValue &Offset) const;
118 bool SelectSMRDBufferSgpr(SDValue Addr, SDValue &Offset) const;
Matt Arsenault3f981402014-09-15 15:41:53 +0000119 SDNode *SelectAddrSpaceCast(SDNode *N);
Tom Stellardb4a313a2014-08-01 00:32:39 +0000120 bool SelectVOP3Mods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
Tom Stellarddb5a11f2015-07-13 15:47:57 +0000121 bool SelectVOP3NoMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
Tom Stellardb4a313a2014-08-01 00:32:39 +0000122 bool SelectVOP3Mods0(SDValue In, SDValue &Src, SDValue &SrcMods,
123 SDValue &Clamp, SDValue &Omod) const;
Tom Stellarddb5a11f2015-07-13 15:47:57 +0000124 bool SelectVOP3NoMods0(SDValue In, SDValue &Src, SDValue &SrcMods,
125 SDValue &Clamp, SDValue &Omod) const;
Tom Stellard75aadc22012-12-11 21:25:42 +0000126
Matt Arsenault1cffa4c2014-11-13 19:49:04 +0000127 bool SelectVOP3Mods0Clamp(SDValue In, SDValue &Src, SDValue &SrcMods,
128 SDValue &Omod) const;
Matt Arsenault4831ce52015-01-06 23:00:37 +0000129 bool SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src, SDValue &SrcMods,
130 SDValue &Clamp,
131 SDValue &Omod) const;
Matt Arsenault1cffa4c2014-11-13 19:49:04 +0000132
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000133 SDNode *SelectADD_SUB_I64(SDNode *N);
Matt Arsenaultf2b0aeb2014-06-23 18:28:28 +0000134 SDNode *SelectDIV_SCALE(SDNode *N);
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000135
Marek Olsak9b728682015-03-24 13:40:27 +0000136 SDNode *getS_BFE(unsigned Opcode, SDLoc DL, SDValue Val,
137 uint32_t Offset, uint32_t Width);
138 SDNode *SelectS_BFEFromShifts(SDNode *N);
139 SDNode *SelectS_BFE(SDNode *N);
140
Tom Stellard75aadc22012-12-11 21:25:42 +0000141 // Include the pieces autogenerated from the target description.
142#include "AMDGPUGenDAGISel.inc"
143};
144} // end anonymous namespace
145
146/// \brief This pass converts a legalized DAG into a AMDGPU-specific
147// DAG, ready for instruction scheduling.
Matt Arsenault209a7b92014-04-18 07:40:20 +0000148FunctionPass *llvm::createAMDGPUISelDag(TargetMachine &TM) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000149 return new AMDGPUDAGToDAGISel(TM);
150}
151
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000152AMDGPUDAGToDAGISel::AMDGPUDAGToDAGISel(TargetMachine &TM)
Eric Christopher7792e322015-01-30 23:24:40 +0000153 : SelectionDAGISel(TM) {}
154
155bool AMDGPUDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
156 Subtarget = &static_cast<const AMDGPUSubtarget &>(MF.getSubtarget());
157 return SelectionDAGISel::runOnMachineFunction(MF);
Tom Stellard75aadc22012-12-11 21:25:42 +0000158}
159
160AMDGPUDAGToDAGISel::~AMDGPUDAGToDAGISel() {
161}
162
Tom Stellard7ed0b522014-04-03 20:19:27 +0000163bool AMDGPUDAGToDAGISel::isInlineImmediate(SDNode *N) const {
164 const SITargetLowering *TL
165 = static_cast<const SITargetLowering *>(getTargetLowering());
166 return TL->analyzeImmediate(N) == 0;
167}
168
Tom Stellarddf94dc32013-08-14 23:24:24 +0000169/// \brief Determine the register class for \p OpNo
170/// \returns The register class of the virtual register that will be used for
171/// the given operand number \OpNo or NULL if the register class cannot be
172/// determined.
173const TargetRegisterClass *AMDGPUDAGToDAGISel::getOperandRegClass(SDNode *N,
174 unsigned OpNo) const {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000175 if (!N->isMachineOpcode())
176 return nullptr;
177
Tom Stellarddf94dc32013-08-14 23:24:24 +0000178 switch (N->getMachineOpcode()) {
179 default: {
Eric Christopherd9134482014-08-04 21:25:23 +0000180 const MCInstrDesc &Desc =
Eric Christopher7792e322015-01-30 23:24:40 +0000181 Subtarget->getInstrInfo()->get(N->getMachineOpcode());
Alexey Samsonov3186eb32013-08-15 07:11:34 +0000182 unsigned OpIdx = Desc.getNumDefs() + OpNo;
183 if (OpIdx >= Desc.getNumOperands())
Matt Arsenault209a7b92014-04-18 07:40:20 +0000184 return nullptr;
Alexey Samsonov3186eb32013-08-15 07:11:34 +0000185 int RegClass = Desc.OpInfo[OpIdx].RegClass;
Matt Arsenault209a7b92014-04-18 07:40:20 +0000186 if (RegClass == -1)
187 return nullptr;
188
Eric Christopher7792e322015-01-30 23:24:40 +0000189 return Subtarget->getRegisterInfo()->getRegClass(RegClass);
Tom Stellarddf94dc32013-08-14 23:24:24 +0000190 }
191 case AMDGPU::REG_SEQUENCE: {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000192 unsigned RCID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
Eric Christopherd9134482014-08-04 21:25:23 +0000193 const TargetRegisterClass *SuperRC =
Eric Christopher7792e322015-01-30 23:24:40 +0000194 Subtarget->getRegisterInfo()->getRegClass(RCID);
Matt Arsenault209a7b92014-04-18 07:40:20 +0000195
196 SDValue SubRegOp = N->getOperand(OpNo + 1);
197 unsigned SubRegIdx = cast<ConstantSDNode>(SubRegOp)->getZExtValue();
Eric Christopher7792e322015-01-30 23:24:40 +0000198 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC,
199 SubRegIdx);
Tom Stellarddf94dc32013-08-14 23:24:24 +0000200 }
201 }
202}
203
Tom Stellard75aadc22012-12-11 21:25:42 +0000204bool AMDGPUDAGToDAGISel::SelectADDRParam(
Matt Arsenault209a7b92014-04-18 07:40:20 +0000205 SDValue Addr, SDValue& R1, SDValue& R2) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000206
207 if (Addr.getOpcode() == ISD::FrameIndex) {
208 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
209 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000210 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000211 } else {
212 R1 = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000213 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000214 }
215 } else if (Addr.getOpcode() == ISD::ADD) {
216 R1 = Addr.getOperand(0);
217 R2 = Addr.getOperand(1);
218 } else {
219 R1 = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000220 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000221 }
222 return true;
223}
224
225bool AMDGPUDAGToDAGISel::SelectADDR(SDValue Addr, SDValue& R1, SDValue& R2) {
226 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
227 Addr.getOpcode() == ISD::TargetGlobalAddress) {
228 return false;
229 }
230 return SelectADDRParam(Addr, R1, R2);
231}
232
233
234bool AMDGPUDAGToDAGISel::SelectADDR64(SDValue Addr, SDValue& R1, SDValue& R2) {
235 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
236 Addr.getOpcode() == ISD::TargetGlobalAddress) {
237 return false;
238 }
239
240 if (Addr.getOpcode() == ISD::FrameIndex) {
241 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
242 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000243 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i64);
Tom Stellard75aadc22012-12-11 21:25:42 +0000244 } else {
245 R1 = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000246 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i64);
Tom Stellard75aadc22012-12-11 21:25:42 +0000247 }
248 } else if (Addr.getOpcode() == ISD::ADD) {
249 R1 = Addr.getOperand(0);
250 R2 = Addr.getOperand(1);
251 } else {
252 R1 = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000253 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i64);
Tom Stellard75aadc22012-12-11 21:25:42 +0000254 }
255 return true;
256}
257
Tom Stellard381a94a2015-05-12 15:00:49 +0000258SDNode *AMDGPUDAGToDAGISel::glueCopyToM0(SDNode *N) const {
259 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS ||
260 !checkType(cast<MemSDNode>(N)->getMemOperand()->getValue(),
261 AMDGPUAS::LOCAL_ADDRESS))
262 return N;
263
264 const SITargetLowering& Lowering =
265 *static_cast<const SITargetLowering*>(getTargetLowering());
266
267 // Write max value to m0 before each load operation
268
269 SDValue M0 = Lowering.copyToM0(*CurDAG, CurDAG->getEntryNode(), SDLoc(N),
270 CurDAG->getTargetConstant(-1, SDLoc(N), MVT::i32));
271
272 SDValue Glue = M0.getValue(1);
273
274 SmallVector <SDValue, 8> Ops;
275 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
276 Ops.push_back(N->getOperand(i));
277 }
278 Ops.push_back(Glue);
279 CurDAG->MorphNodeTo(N, N->getOpcode(), N->getVTList(), Ops);
280
281 return N;
282}
283
Tom Stellard75aadc22012-12-11 21:25:42 +0000284SDNode *AMDGPUDAGToDAGISel::Select(SDNode *N) {
285 unsigned int Opc = N->getOpcode();
286 if (N->isMachineOpcode()) {
Tim Northover31d093c2013-09-22 08:21:56 +0000287 N->setNodeId(-1);
Matt Arsenault209a7b92014-04-18 07:40:20 +0000288 return nullptr; // Already selected.
Tom Stellard75aadc22012-12-11 21:25:42 +0000289 }
Matt Arsenault78b86702014-04-18 05:19:26 +0000290
Tom Stellard381a94a2015-05-12 15:00:49 +0000291 if (isa<AtomicSDNode>(N))
292 N = glueCopyToM0(N);
293
Tom Stellard75aadc22012-12-11 21:25:42 +0000294 switch (Opc) {
295 default: break;
Tom Stellard1f15bff2014-02-25 21:36:18 +0000296 // We are selecting i64 ADD here instead of custom lower it during
297 // DAG legalization, so we can fold some i64 ADDs used for address
298 // calculation into the LOAD and STORE instructions.
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000299 case ISD::ADD:
300 case ISD::SUB: {
Tom Stellard1f15bff2014-02-25 21:36:18 +0000301 if (N->getValueType(0) != MVT::i64 ||
Eric Christopher7792e322015-01-30 23:24:40 +0000302 Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS)
Tom Stellard1f15bff2014-02-25 21:36:18 +0000303 break;
304
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000305 return SelectADD_SUB_I64(N);
Tom Stellard1f15bff2014-02-25 21:36:18 +0000306 }
Matt Arsenault064c2062014-06-11 17:40:32 +0000307 case ISD::SCALAR_TO_VECTOR:
Tom Stellard880a80a2014-06-17 16:53:14 +0000308 case AMDGPUISD::BUILD_VERTICAL_VECTOR:
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000309 case ISD::BUILD_VECTOR: {
Tom Stellard8e5da412013-08-14 23:24:32 +0000310 unsigned RegClassID;
Eric Christopher7792e322015-01-30 23:24:40 +0000311 const AMDGPURegisterInfo *TRI = Subtarget->getRegisterInfo();
Tom Stellard8e5da412013-08-14 23:24:32 +0000312 EVT VT = N->getValueType(0);
313 unsigned NumVectorElts = VT.getVectorNumElements();
Matt Arsenault064c2062014-06-11 17:40:32 +0000314 EVT EltVT = VT.getVectorElementType();
315 assert(EltVT.bitsEq(MVT::i32));
Eric Christopher7792e322015-01-30 23:24:40 +0000316 if (Subtarget->getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) {
Tom Stellard8e5da412013-08-14 23:24:32 +0000317 bool UseVReg = true;
318 for (SDNode::use_iterator U = N->use_begin(), E = SDNode::use_end();
319 U != E; ++U) {
320 if (!U->isMachineOpcode()) {
321 continue;
322 }
323 const TargetRegisterClass *RC = getOperandRegClass(*U, U.getOperandNo());
324 if (!RC) {
325 continue;
326 }
Eric Christopher7792e322015-01-30 23:24:40 +0000327 if (static_cast<const SIRegisterInfo *>(TRI)->isSGPRClass(RC)) {
Tom Stellard8e5da412013-08-14 23:24:32 +0000328 UseVReg = false;
329 }
330 }
331 switch(NumVectorElts) {
Tom Stellard45c0b3a2015-01-07 20:59:25 +0000332 case 1: RegClassID = UseVReg ? AMDGPU::VGPR_32RegClassID :
Tom Stellard8e5da412013-08-14 23:24:32 +0000333 AMDGPU::SReg_32RegClassID;
334 break;
335 case 2: RegClassID = UseVReg ? AMDGPU::VReg_64RegClassID :
336 AMDGPU::SReg_64RegClassID;
337 break;
338 case 4: RegClassID = UseVReg ? AMDGPU::VReg_128RegClassID :
339 AMDGPU::SReg_128RegClassID;
340 break;
341 case 8: RegClassID = UseVReg ? AMDGPU::VReg_256RegClassID :
342 AMDGPU::SReg_256RegClassID;
343 break;
344 case 16: RegClassID = UseVReg ? AMDGPU::VReg_512RegClassID :
345 AMDGPU::SReg_512RegClassID;
346 break;
Benjamin Kramerbda73ff2013-08-31 21:20:04 +0000347 default: llvm_unreachable("Do not know how to lower this BUILD_VECTOR");
Tom Stellard8e5da412013-08-14 23:24:32 +0000348 }
349 } else {
350 // BUILD_VECTOR was lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG
351 // that adds a 128 bits reg copy when going through TwoAddressInstructions
352 // pass. We want to avoid 128 bits copies as much as possible because they
353 // can't be bundled by our scheduler.
354 switch(NumVectorElts) {
355 case 2: RegClassID = AMDGPU::R600_Reg64RegClassID; break;
Tom Stellard880a80a2014-06-17 16:53:14 +0000356 case 4:
357 if (Opc == AMDGPUISD::BUILD_VERTICAL_VECTOR)
358 RegClassID = AMDGPU::R600_Reg128VerticalRegClassID;
359 else
360 RegClassID = AMDGPU::R600_Reg128RegClassID;
361 break;
Tom Stellard8e5da412013-08-14 23:24:32 +0000362 default: llvm_unreachable("Do not know how to lower this BUILD_VECTOR");
363 }
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000364 }
Tom Stellard0344cdf2013-08-01 15:23:42 +0000365
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000366 SDLoc DL(N);
367 SDValue RegClass = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32);
Tom Stellard8e5da412013-08-14 23:24:32 +0000368
369 if (NumVectorElts == 1) {
Matt Arsenault064c2062014-06-11 17:40:32 +0000370 return CurDAG->SelectNodeTo(N, AMDGPU::COPY_TO_REGCLASS, EltVT,
Tom Stellard8e5da412013-08-14 23:24:32 +0000371 N->getOperand(0), RegClass);
Tom Stellard0344cdf2013-08-01 15:23:42 +0000372 }
Tom Stellard8e5da412013-08-14 23:24:32 +0000373
374 assert(NumVectorElts <= 16 && "Vectors with more than 16 elements not "
375 "supported yet");
376 // 16 = Max Num Vector Elements
377 // 2 = 2 REG_SEQUENCE operands per element (value, subreg index)
378 // 1 = Vector Register Class
Matt Arsenault064c2062014-06-11 17:40:32 +0000379 SmallVector<SDValue, 16 * 2 + 1> RegSeqArgs(NumVectorElts * 2 + 1);
Tom Stellard8e5da412013-08-14 23:24:32 +0000380
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000381 RegSeqArgs[0] = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32);
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000382 bool IsRegSeq = true;
Matt Arsenault064c2062014-06-11 17:40:32 +0000383 unsigned NOps = N->getNumOperands();
384 for (unsigned i = 0; i < NOps; i++) {
Tom Stellard8e5da412013-08-14 23:24:32 +0000385 // XXX: Why is this here?
Benjamin Kramer619c4e52015-04-10 11:24:51 +0000386 if (isa<RegisterSDNode>(N->getOperand(i))) {
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000387 IsRegSeq = false;
388 break;
389 }
Tom Stellard8e5da412013-08-14 23:24:32 +0000390 RegSeqArgs[1 + (2 * i)] = N->getOperand(i);
391 RegSeqArgs[1 + (2 * i) + 1] =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000392 CurDAG->getTargetConstant(TRI->getSubRegFromChannel(i), DL,
393 MVT::i32);
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000394 }
Matt Arsenault064c2062014-06-11 17:40:32 +0000395
396 if (NOps != NumVectorElts) {
397 // Fill in the missing undef elements if this was a scalar_to_vector.
398 assert(Opc == ISD::SCALAR_TO_VECTOR && NOps < NumVectorElts);
399
400 MachineSDNode *ImpDef = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000401 DL, EltVT);
Matt Arsenault064c2062014-06-11 17:40:32 +0000402 for (unsigned i = NOps; i < NumVectorElts; ++i) {
403 RegSeqArgs[1 + (2 * i)] = SDValue(ImpDef, 0);
404 RegSeqArgs[1 + (2 * i) + 1] =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000405 CurDAG->getTargetConstant(TRI->getSubRegFromChannel(i), DL, MVT::i32);
Matt Arsenault064c2062014-06-11 17:40:32 +0000406 }
407 }
408
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000409 if (!IsRegSeq)
410 break;
411 return CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, N->getVTList(),
Craig Topper481fb282014-04-27 19:21:11 +0000412 RegSeqArgs);
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000413 }
Tom Stellard754f80f2013-04-05 23:31:51 +0000414 case ISD::BUILD_PAIR: {
415 SDValue RC, SubReg0, SubReg1;
Eric Christopher7792e322015-01-30 23:24:40 +0000416 if (Subtarget->getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
Tom Stellard754f80f2013-04-05 23:31:51 +0000417 break;
418 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000419 SDLoc DL(N);
Tom Stellard754f80f2013-04-05 23:31:51 +0000420 if (N->getValueType(0) == MVT::i128) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000421 RC = CurDAG->getTargetConstant(AMDGPU::SReg_128RegClassID, DL, MVT::i32);
422 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32);
423 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32);
Tom Stellard754f80f2013-04-05 23:31:51 +0000424 } else if (N->getValueType(0) == MVT::i64) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000425 RC = CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32);
426 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32);
427 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32);
Tom Stellard754f80f2013-04-05 23:31:51 +0000428 } else {
429 llvm_unreachable("Unhandled value type for BUILD_PAIR");
430 }
431 const SDValue Ops[] = { RC, N->getOperand(0), SubReg0,
432 N->getOperand(1), SubReg1 };
433 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000434 DL, N->getValueType(0), Ops);
Tom Stellard754f80f2013-04-05 23:31:51 +0000435 }
Tom Stellard7ed0b522014-04-03 20:19:27 +0000436
437 case ISD::Constant:
438 case ISD::ConstantFP: {
Eric Christopher7792e322015-01-30 23:24:40 +0000439 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS ||
Tom Stellard7ed0b522014-04-03 20:19:27 +0000440 N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(N))
441 break;
442
443 uint64_t Imm;
444 if (ConstantFPSDNode *FP = dyn_cast<ConstantFPSDNode>(N))
445 Imm = FP->getValueAPF().bitcastToAPInt().getZExtValue();
446 else {
Tom Stellard3cbe0142014-04-07 19:31:13 +0000447 ConstantSDNode *C = cast<ConstantSDNode>(N);
Tom Stellard7ed0b522014-04-03 20:19:27 +0000448 Imm = C->getZExtValue();
449 }
450
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000451 SDLoc DL(N);
452 SDNode *Lo = CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
453 CurDAG->getConstant(Imm & 0xFFFFFFFF, DL,
454 MVT::i32));
455 SDNode *Hi = CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
456 CurDAG->getConstant(Imm >> 32, DL, MVT::i32));
Tom Stellard7ed0b522014-04-03 20:19:27 +0000457 const SDValue Ops[] = {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000458 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32),
459 SDValue(Lo, 0), CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
460 SDValue(Hi, 0), CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32)
Tom Stellard7ed0b522014-04-03 20:19:27 +0000461 };
462
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000463 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
Tom Stellard7ed0b522014-04-03 20:19:27 +0000464 N->getValueType(0), Ops);
465 }
466
Tom Stellard20f6c072015-01-23 22:05:45 +0000467 case ISD::LOAD: {
Tom Stellard381a94a2015-05-12 15:00:49 +0000468 LoadSDNode *LD = cast<LoadSDNode>(N);
469 SDLoc SL(N);
470 EVT VT = N->getValueType(0);
471
472 if (VT != MVT::i64 || LD->getExtensionType() != ISD::NON_EXTLOAD) {
473 N = glueCopyToM0(N);
474 break;
475 }
476
Tom Stellard20f6c072015-01-23 22:05:45 +0000477 // To simplify the TableGen patters, we replace all i64 loads with
478 // v2i32 loads. Alternatively, we could promote i64 loads to v2i32
479 // during DAG legalization, however, so places (ExpandUnalignedLoad)
480 // in the DAG legalizer assume that if i64 is legal, so doing this
481 // promotion early can cause problems.
Tom Stellard20f6c072015-01-23 22:05:45 +0000482
483 SDValue NewLoad = CurDAG->getLoad(MVT::v2i32, SDLoc(N), LD->getChain(),
Tom Stellard381a94a2015-05-12 15:00:49 +0000484 LD->getBasePtr(), LD->getMemOperand());
485 SDValue BitCast = CurDAG->getNode(ISD::BITCAST, SL,
Tom Stellard20f6c072015-01-23 22:05:45 +0000486 MVT::i64, NewLoad);
487 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 1), NewLoad.getValue(1));
488 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), BitCast);
Tom Stellard381a94a2015-05-12 15:00:49 +0000489 SDNode *Load = glueCopyToM0(NewLoad.getNode());
490 SelectCode(Load);
Tom Stellard20f6c072015-01-23 22:05:45 +0000491 N = BitCast.getNode();
492 break;
493 }
494
Tom Stellard096b8c12015-02-04 20:49:49 +0000495 case ISD::STORE: {
496 // Handle i64 stores here for the same reason mentioned above for loads.
497 StoreSDNode *ST = cast<StoreSDNode>(N);
498 SDValue Value = ST->getValue();
Tom Stellard381a94a2015-05-12 15:00:49 +0000499 if (Value.getValueType() == MVT::i64 && !ST->isTruncatingStore()) {
Tom Stellard096b8c12015-02-04 20:49:49 +0000500
Tom Stellard381a94a2015-05-12 15:00:49 +0000501 SDValue NewValue = CurDAG->getNode(ISD::BITCAST, SDLoc(N),
502 MVT::v2i32, Value);
503 SDValue NewStore = CurDAG->getStore(ST->getChain(), SDLoc(N), NewValue,
504 ST->getBasePtr(), ST->getMemOperand());
Tom Stellard096b8c12015-02-04 20:49:49 +0000505
Tom Stellard381a94a2015-05-12 15:00:49 +0000506 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), NewStore);
Tom Stellard096b8c12015-02-04 20:49:49 +0000507
Tom Stellard381a94a2015-05-12 15:00:49 +0000508 if (NewValue.getOpcode() == ISD::BITCAST) {
509 Select(NewStore.getNode());
510 return SelectCode(NewValue.getNode());
511 }
512
513 // getNode() may fold the bitcast if its input was another bitcast. If that
514 // happens we should only select the new store.
515 N = NewStore.getNode();
Tom Stellard096b8c12015-02-04 20:49:49 +0000516 }
517
Tom Stellard381a94a2015-05-12 15:00:49 +0000518 N = glueCopyToM0(N);
Tom Stellard096b8c12015-02-04 20:49:49 +0000519 break;
520 }
521
Tom Stellard81d871d2013-11-13 23:36:50 +0000522 case AMDGPUISD::REGISTER_LOAD: {
Eric Christopher7792e322015-01-30 23:24:40 +0000523 if (Subtarget->getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
Tom Stellard81d871d2013-11-13 23:36:50 +0000524 break;
525 SDValue Addr, Offset;
526
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000527 SDLoc DL(N);
Tom Stellard81d871d2013-11-13 23:36:50 +0000528 SelectADDRIndirect(N->getOperand(1), Addr, Offset);
529 const SDValue Ops[] = {
530 Addr,
531 Offset,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000532 CurDAG->getTargetConstant(0, DL, MVT::i32),
Tom Stellard81d871d2013-11-13 23:36:50 +0000533 N->getOperand(0),
534 };
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000535 return CurDAG->getMachineNode(AMDGPU::SI_RegisterLoad, DL,
536 CurDAG->getVTList(MVT::i32, MVT::i64,
537 MVT::Other),
Tom Stellard81d871d2013-11-13 23:36:50 +0000538 Ops);
539 }
540 case AMDGPUISD::REGISTER_STORE: {
Eric Christopher7792e322015-01-30 23:24:40 +0000541 if (Subtarget->getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
Tom Stellard81d871d2013-11-13 23:36:50 +0000542 break;
543 SDValue Addr, Offset;
544 SelectADDRIndirect(N->getOperand(2), Addr, Offset);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000545 SDLoc DL(N);
Tom Stellard81d871d2013-11-13 23:36:50 +0000546 const SDValue Ops[] = {
547 N->getOperand(1),
548 Addr,
549 Offset,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000550 CurDAG->getTargetConstant(0, DL, MVT::i32),
Tom Stellard81d871d2013-11-13 23:36:50 +0000551 N->getOperand(0),
552 };
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000553 return CurDAG->getMachineNode(AMDGPU::SI_RegisterStorePseudo, DL,
Tom Stellard81d871d2013-11-13 23:36:50 +0000554 CurDAG->getVTList(MVT::Other),
555 Ops);
556 }
Matt Arsenault78b86702014-04-18 05:19:26 +0000557
558 case AMDGPUISD::BFE_I32:
559 case AMDGPUISD::BFE_U32: {
Eric Christopher7792e322015-01-30 23:24:40 +0000560 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS)
Matt Arsenault78b86702014-04-18 05:19:26 +0000561 break;
562
563 // There is a scalar version available, but unlike the vector version which
564 // has a separate operand for the offset and width, the scalar version packs
565 // the width and offset into a single operand. Try to move to the scalar
566 // version if the offsets are constant, so that we can try to keep extended
567 // loads of kernel arguments in SGPRs.
568
569 // TODO: Technically we could try to pattern match scalar bitshifts of
570 // dynamic values, but it's probably not useful.
571 ConstantSDNode *Offset = dyn_cast<ConstantSDNode>(N->getOperand(1));
572 if (!Offset)
573 break;
574
575 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2));
576 if (!Width)
577 break;
578
579 bool Signed = Opc == AMDGPUISD::BFE_I32;
580
Matt Arsenault78b86702014-04-18 05:19:26 +0000581 uint32_t OffsetVal = Offset->getZExtValue();
582 uint32_t WidthVal = Width->getZExtValue();
583
Marek Olsak9b728682015-03-24 13:40:27 +0000584 return getS_BFE(Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32, SDLoc(N),
585 N->getOperand(0), OffsetVal, WidthVal);
Matt Arsenault78b86702014-04-18 05:19:26 +0000586
587 }
Matt Arsenaultf2b0aeb2014-06-23 18:28:28 +0000588 case AMDGPUISD::DIV_SCALE: {
589 return SelectDIV_SCALE(N);
590 }
Tom Stellard3457a842014-10-09 19:06:00 +0000591 case ISD::CopyToReg: {
592 const SITargetLowering& Lowering =
593 *static_cast<const SITargetLowering*>(getTargetLowering());
594 Lowering.legalizeTargetIndependentNode(N, *CurDAG);
595 break;
596 }
Matt Arsenault3f981402014-09-15 15:41:53 +0000597 case ISD::ADDRSPACECAST:
598 return SelectAddrSpaceCast(N);
Marek Olsak9b728682015-03-24 13:40:27 +0000599 case ISD::AND:
600 case ISD::SRL:
601 case ISD::SRA:
602 if (N->getValueType(0) != MVT::i32 ||
603 Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS)
604 break;
605
606 return SelectS_BFE(N);
Tom Stellard75aadc22012-12-11 21:25:42 +0000607 }
Tom Stellard3457a842014-10-09 19:06:00 +0000608
Vincent Lejeune0167a312013-09-12 23:45:00 +0000609 return SelectCode(N);
Tom Stellard365366f2013-01-23 02:09:06 +0000610}
611
Tom Stellard75aadc22012-12-11 21:25:42 +0000612
Matt Arsenault209a7b92014-04-18 07:40:20 +0000613bool AMDGPUDAGToDAGISel::checkType(const Value *Ptr, unsigned AS) {
614 assert(AS != 0 && "Use checkPrivateAddress instead.");
615 if (!Ptr)
Tom Stellard75aadc22012-12-11 21:25:42 +0000616 return false;
Matt Arsenault209a7b92014-04-18 07:40:20 +0000617
618 return Ptr->getType()->getPointerAddressSpace() == AS;
Tom Stellard75aadc22012-12-11 21:25:42 +0000619}
620
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000621bool AMDGPUDAGToDAGISel::checkPrivateAddress(const MachineMemOperand *Op) {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000622 if (Op->getPseudoValue())
623 return true;
624
625 if (PointerType *PT = dyn_cast<PointerType>(Op->getValue()->getType()))
626 return PT->getAddressSpace() == AMDGPUAS::PRIVATE_ADDRESS;
627
628 return false;
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000629}
630
Tom Stellard75aadc22012-12-11 21:25:42 +0000631bool AMDGPUDAGToDAGISel::isGlobalStore(const StoreSDNode *N) {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000632 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::GLOBAL_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000633}
634
635bool AMDGPUDAGToDAGISel::isPrivateStore(const StoreSDNode *N) {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000636 const Value *MemVal = N->getMemOperand()->getValue();
637 return (!checkType(MemVal, AMDGPUAS::LOCAL_ADDRESS) &&
638 !checkType(MemVal, AMDGPUAS::GLOBAL_ADDRESS) &&
639 !checkType(MemVal, AMDGPUAS::REGION_ADDRESS));
Tom Stellard75aadc22012-12-11 21:25:42 +0000640}
641
642bool AMDGPUDAGToDAGISel::isLocalStore(const StoreSDNode *N) {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000643 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::LOCAL_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000644}
645
Matt Arsenault3f981402014-09-15 15:41:53 +0000646bool AMDGPUDAGToDAGISel::isFlatStore(const StoreSDNode *N) {
647 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::FLAT_ADDRESS);
648}
649
Tom Stellard75aadc22012-12-11 21:25:42 +0000650bool AMDGPUDAGToDAGISel::isRegionStore(const StoreSDNode *N) {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000651 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::REGION_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000652}
653
Tom Stellard1e803092013-07-23 01:48:18 +0000654bool AMDGPUDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int CbId) const {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000655 const Value *MemVal = N->getMemOperand()->getValue();
656 if (CbId == -1)
657 return checkType(MemVal, AMDGPUAS::CONSTANT_ADDRESS);
658
659 return checkType(MemVal, AMDGPUAS::CONSTANT_BUFFER_0 + CbId);
Tom Stellard75aadc22012-12-11 21:25:42 +0000660}
661
Matt Arsenault2aabb062013-06-18 23:37:58 +0000662bool AMDGPUDAGToDAGISel::isGlobalLoad(const LoadSDNode *N) const {
Eric Christopher7792e322015-01-30 23:24:40 +0000663 if (N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS)
664 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS ||
665 N->getMemoryVT().bitsLT(MVT::i32))
Tom Stellard8cb0e472013-07-23 23:54:56 +0000666 return true;
Eric Christopher7792e322015-01-30 23:24:40 +0000667
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000668 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::GLOBAL_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000669}
670
Matt Arsenault2aabb062013-06-18 23:37:58 +0000671bool AMDGPUDAGToDAGISel::isParamLoad(const LoadSDNode *N) const {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000672 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::PARAM_I_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000673}
674
Matt Arsenault2aabb062013-06-18 23:37:58 +0000675bool AMDGPUDAGToDAGISel::isLocalLoad(const LoadSDNode *N) const {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000676 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::LOCAL_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000677}
678
Matt Arsenault3f981402014-09-15 15:41:53 +0000679bool AMDGPUDAGToDAGISel::isFlatLoad(const LoadSDNode *N) const {
680 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::FLAT_ADDRESS);
681}
682
Matt Arsenault2aabb062013-06-18 23:37:58 +0000683bool AMDGPUDAGToDAGISel::isRegionLoad(const LoadSDNode *N) const {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000684 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::REGION_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000685}
686
Matt Arsenault2aabb062013-06-18 23:37:58 +0000687bool AMDGPUDAGToDAGISel::isCPLoad(const LoadSDNode *N) const {
Tom Stellard75aadc22012-12-11 21:25:42 +0000688 MachineMemOperand *MMO = N->getMemOperand();
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000689 if (checkPrivateAddress(N->getMemOperand())) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000690 if (MMO) {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000691 const PseudoSourceValue *PSV = MMO->getPseudoValue();
Tom Stellard75aadc22012-12-11 21:25:42 +0000692 if (PSV && PSV == PseudoSourceValue::getConstantPool()) {
693 return true;
694 }
695 }
696 }
697 return false;
698}
699
Matt Arsenault2aabb062013-06-18 23:37:58 +0000700bool AMDGPUDAGToDAGISel::isPrivateLoad(const LoadSDNode *N) const {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000701 if (checkPrivateAddress(N->getMemOperand())) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000702 // Check to make sure we are not a constant pool load or a constant load
703 // that is marked as a private load
704 if (isCPLoad(N) || isConstantLoad(N, -1)) {
705 return false;
706 }
707 }
Matt Arsenault209a7b92014-04-18 07:40:20 +0000708
709 const Value *MemVal = N->getMemOperand()->getValue();
710 if (!checkType(MemVal, AMDGPUAS::LOCAL_ADDRESS) &&
711 !checkType(MemVal, AMDGPUAS::GLOBAL_ADDRESS) &&
Matt Arsenault3f981402014-09-15 15:41:53 +0000712 !checkType(MemVal, AMDGPUAS::FLAT_ADDRESS) &&
Matt Arsenault209a7b92014-04-18 07:40:20 +0000713 !checkType(MemVal, AMDGPUAS::REGION_ADDRESS) &&
714 !checkType(MemVal, AMDGPUAS::CONSTANT_ADDRESS) &&
715 !checkType(MemVal, AMDGPUAS::PARAM_D_ADDRESS) &&
Matt Arsenault3f981402014-09-15 15:41:53 +0000716 !checkType(MemVal, AMDGPUAS::PARAM_I_ADDRESS)) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000717 return true;
718 }
719 return false;
720}
721
722const char *AMDGPUDAGToDAGISel::getPassName() const {
723 return "AMDGPU DAG->DAG Pattern Instruction Selection";
724}
725
726#ifdef DEBUGTMP
727#undef INT64_C
728#endif
729#undef DEBUGTMP
730
Tom Stellard41fc7852013-07-23 01:48:42 +0000731//===----------------------------------------------------------------------===//
732// Complex Patterns
733//===----------------------------------------------------------------------===//
Tom Stellard75aadc22012-12-11 21:25:42 +0000734
Tom Stellard365366f2013-01-23 02:09:06 +0000735bool AMDGPUDAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr,
Matt Arsenault209a7b92014-04-18 07:40:20 +0000736 SDValue& IntPtr) {
Tom Stellard365366f2013-01-23 02:09:06 +0000737 if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Addr)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000738 IntPtr = CurDAG->getIntPtrConstant(Cst->getZExtValue() / 4, SDLoc(Addr),
739 true);
Tom Stellard365366f2013-01-23 02:09:06 +0000740 return true;
741 }
742 return false;
743}
744
745bool AMDGPUDAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr,
746 SDValue& BaseReg, SDValue &Offset) {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000747 if (!isa<ConstantSDNode>(Addr)) {
Tom Stellard365366f2013-01-23 02:09:06 +0000748 BaseReg = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000749 Offset = CurDAG->getIntPtrConstant(0, SDLoc(Addr), true);
Tom Stellard365366f2013-01-23 02:09:06 +0000750 return true;
751 }
752 return false;
753}
754
Tom Stellard75aadc22012-12-11 21:25:42 +0000755bool AMDGPUDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
756 SDValue &Offset) {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000757 ConstantSDNode *IMMOffset;
Tom Stellard75aadc22012-12-11 21:25:42 +0000758
759 if (Addr.getOpcode() == ISD::ADD
760 && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
761 && isInt<16>(IMMOffset->getZExtValue())) {
762
763 Base = Addr.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000764 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr),
765 MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000766 return true;
767 // If the pointer address is constant, we can move it to the offset field.
768 } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr))
769 && isInt<16>(IMMOffset->getZExtValue())) {
770 Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
Andrew Trickef9de2a2013-05-25 02:42:55 +0000771 SDLoc(CurDAG->getEntryNode()),
Tom Stellard75aadc22012-12-11 21:25:42 +0000772 AMDGPU::ZERO, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000773 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr),
774 MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000775 return true;
776 }
777
778 // Default case, no offset
779 Base = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000780 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000781 return true;
782}
783
Tom Stellardf3b2a1e2013-02-06 17:32:29 +0000784bool AMDGPUDAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base,
785 SDValue &Offset) {
786 ConstantSDNode *C;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000787 SDLoc DL(Addr);
Tom Stellardf3b2a1e2013-02-06 17:32:29 +0000788
789 if ((C = dyn_cast<ConstantSDNode>(Addr))) {
790 Base = CurDAG->getRegister(AMDGPU::INDIRECT_BASE_ADDR, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000791 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
Tom Stellardf3b2a1e2013-02-06 17:32:29 +0000792 } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) &&
793 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) {
794 Base = Addr.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000795 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
Tom Stellardf3b2a1e2013-02-06 17:32:29 +0000796 } else {
797 Base = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000798 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellardf3b2a1e2013-02-06 17:32:29 +0000799 }
800
801 return true;
802}
Christian Konigd910b7d2013-02-26 17:52:16 +0000803
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000804SDNode *AMDGPUDAGToDAGISel::SelectADD_SUB_I64(SDNode *N) {
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000805 SDLoc DL(N);
806 SDValue LHS = N->getOperand(0);
807 SDValue RHS = N->getOperand(1);
808
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000809 bool IsAdd = (N->getOpcode() == ISD::ADD);
810
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000811 SDValue Sub0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32);
812 SDValue Sub1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32);
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000813
814 SDNode *Lo0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
815 DL, MVT::i32, LHS, Sub0);
816 SDNode *Hi0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
817 DL, MVT::i32, LHS, Sub1);
818
819 SDNode *Lo1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
820 DL, MVT::i32, RHS, Sub0);
821 SDNode *Hi1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
822 DL, MVT::i32, RHS, Sub1);
823
824 SDVTList VTList = CurDAG->getVTList(MVT::i32, MVT::Glue);
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000825 SDValue AddLoArgs[] = { SDValue(Lo0, 0), SDValue(Lo1, 0) };
826
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000827
Tom Stellard80942a12014-09-05 14:07:59 +0000828 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000829 unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
830
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000831 SDNode *AddLo = CurDAG->getMachineNode( Opc, DL, VTList, AddLoArgs);
832 SDValue Carry(AddLo, 1);
833 SDNode *AddHi
834 = CurDAG->getMachineNode(CarryOpc, DL, MVT::i32,
835 SDValue(Hi0, 0), SDValue(Hi1, 0), Carry);
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000836
837 SDValue Args[5] = {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000838 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32),
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000839 SDValue(AddLo,0),
840 Sub0,
841 SDValue(AddHi,0),
842 Sub1,
843 };
844 return CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, MVT::i64, Args);
845}
846
Matt Arsenault044f1d12015-02-14 04:24:28 +0000847// We need to handle this here because tablegen doesn't support matching
848// instructions with multiple outputs.
Matt Arsenaultf2b0aeb2014-06-23 18:28:28 +0000849SDNode *AMDGPUDAGToDAGISel::SelectDIV_SCALE(SDNode *N) {
850 SDLoc SL(N);
851 EVT VT = N->getValueType(0);
852
853 assert(VT == MVT::f32 || VT == MVT::f64);
854
855 unsigned Opc
856 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64 : AMDGPU::V_DIV_SCALE_F32;
857
Matt Arsenault044f1d12015-02-14 04:24:28 +0000858 // src0_modifiers, src0, src1_modifiers, src1, src2_modifiers, src2, clamp, omod
859 SDValue Ops[8];
Matt Arsenaultf2b0aeb2014-06-23 18:28:28 +0000860
Matt Arsenault044f1d12015-02-14 04:24:28 +0000861 SelectVOP3Mods0(N->getOperand(0), Ops[1], Ops[0], Ops[6], Ops[7]);
862 SelectVOP3Mods(N->getOperand(1), Ops[3], Ops[2]);
863 SelectVOP3Mods(N->getOperand(2), Ops[5], Ops[4]);
Matt Arsenaultf2b0aeb2014-06-23 18:28:28 +0000864 return CurDAG->SelectNodeTo(N, Opc, VT, MVT::i1, Ops);
865}
866
Tom Stellard85e8b6d2014-08-22 18:49:33 +0000867bool AMDGPUDAGToDAGISel::isDSOffsetLegal(const SDValue &Base, unsigned Offset,
868 unsigned OffsetBits) const {
Tom Stellard85e8b6d2014-08-22 18:49:33 +0000869 if ((OffsetBits == 16 && !isUInt<16>(Offset)) ||
870 (OffsetBits == 8 && !isUInt<8>(Offset)))
871 return false;
872
Matt Arsenault706f9302015-07-06 16:01:58 +0000873 if (Subtarget->getGeneration() >= AMDGPUSubtarget::SEA_ISLANDS ||
874 Subtarget->unsafeDSOffsetFoldingEnabled())
Tom Stellard85e8b6d2014-08-22 18:49:33 +0000875 return true;
876
877 // On Southern Islands instruction with a negative base value and an offset
878 // don't seem to work.
879 return CurDAG->SignBitIsZero(Base);
880}
881
882bool AMDGPUDAGToDAGISel::SelectDS1Addr1Offset(SDValue Addr, SDValue &Base,
883 SDValue &Offset) const {
884 if (CurDAG->isBaseWithConstantOffset(Addr)) {
885 SDValue N0 = Addr.getOperand(0);
886 SDValue N1 = Addr.getOperand(1);
887 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
888 if (isDSOffsetLegal(N0, C1->getSExtValue(), 16)) {
889 // (add n0, c0)
890 Base = N0;
891 Offset = N1;
892 return true;
893 }
894 }
895
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000896 SDLoc DL(Addr);
897
Matt Arsenaulte775f5f2014-10-14 17:21:19 +0000898 // If we have a constant address, prefer to put the constant into the
899 // offset. This can save moves to load the constant address since multiple
900 // operations can share the zero base address register, and enables merging
901 // into read2 / write2 instructions.
902 if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) {
903 if (isUInt<16>(CAddr->getZExtValue())) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000904 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellardc8d79202014-10-15 21:08:59 +0000905 MachineSDNode *MovZero = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000906 DL, MVT::i32, Zero);
Tom Stellardc8d79202014-10-15 21:08:59 +0000907 Base = SDValue(MovZero, 0);
Matt Arsenaulte775f5f2014-10-14 17:21:19 +0000908 Offset = Addr;
909 return true;
910 }
911 }
912
Tom Stellard85e8b6d2014-08-22 18:49:33 +0000913 // default case
914 Base = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000915 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
Tom Stellard85e8b6d2014-08-22 18:49:33 +0000916 return true;
917}
918
Tom Stellardf3fc5552014-08-22 18:49:35 +0000919bool AMDGPUDAGToDAGISel::SelectDS64Bit4ByteAligned(SDValue Addr, SDValue &Base,
920 SDValue &Offset0,
921 SDValue &Offset1) const {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000922 SDLoc DL(Addr);
923
Tom Stellardf3fc5552014-08-22 18:49:35 +0000924 if (CurDAG->isBaseWithConstantOffset(Addr)) {
925 SDValue N0 = Addr.getOperand(0);
926 SDValue N1 = Addr.getOperand(1);
927 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
928 unsigned DWordOffset0 = C1->getZExtValue() / 4;
929 unsigned DWordOffset1 = DWordOffset0 + 1;
930 // (add n0, c0)
931 if (isDSOffsetLegal(N0, DWordOffset1, 8)) {
932 Base = N0;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000933 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8);
934 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8);
Tom Stellardf3fc5552014-08-22 18:49:35 +0000935 return true;
936 }
937 }
938
Matt Arsenault1a74aff2014-10-15 18:06:43 +0000939 if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) {
940 unsigned DWordOffset0 = CAddr->getZExtValue() / 4;
941 unsigned DWordOffset1 = DWordOffset0 + 1;
942 assert(4 * DWordOffset0 == CAddr->getZExtValue());
943
944 if (isUInt<8>(DWordOffset0) && isUInt<8>(DWordOffset1)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000945 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
Matt Arsenault1a74aff2014-10-15 18:06:43 +0000946 MachineSDNode *MovZero
947 = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000948 DL, MVT::i32, Zero);
Matt Arsenault1a74aff2014-10-15 18:06:43 +0000949 Base = SDValue(MovZero, 0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000950 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8);
951 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8);
Matt Arsenault1a74aff2014-10-15 18:06:43 +0000952 return true;
953 }
954 }
955
Tom Stellardf3fc5552014-08-22 18:49:35 +0000956 // default case
957 Base = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000958 Offset0 = CurDAG->getTargetConstant(0, DL, MVT::i8);
959 Offset1 = CurDAG->getTargetConstant(1, DL, MVT::i8);
Tom Stellardf3fc5552014-08-22 18:49:35 +0000960 return true;
961}
962
Tom Stellardb02094e2014-07-21 15:45:01 +0000963static bool isLegalMUBUFImmOffset(const ConstantSDNode *Imm) {
964 return isUInt<12>(Imm->getZExtValue());
965}
966
Tom Stellard155bbb72014-08-11 22:18:17 +0000967void AMDGPUDAGToDAGISel::SelectMUBUF(SDValue Addr, SDValue &Ptr,
968 SDValue &VAddr, SDValue &SOffset,
969 SDValue &Offset, SDValue &Offen,
970 SDValue &Idxen, SDValue &Addr64,
971 SDValue &GLC, SDValue &SLC,
972 SDValue &TFE) const {
Tom Stellardb02c2682014-06-24 23:33:07 +0000973 SDLoc DL(Addr);
974
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000975 GLC = CurDAG->getTargetConstant(0, DL, MVT::i1);
976 SLC = CurDAG->getTargetConstant(0, DL, MVT::i1);
977 TFE = CurDAG->getTargetConstant(0, DL, MVT::i1);
Tom Stellard155bbb72014-08-11 22:18:17 +0000978
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000979 Idxen = CurDAG->getTargetConstant(0, DL, MVT::i1);
980 Offen = CurDAG->getTargetConstant(0, DL, MVT::i1);
981 Addr64 = CurDAG->getTargetConstant(0, DL, MVT::i1);
982 SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellard155bbb72014-08-11 22:18:17 +0000983
Tom Stellardb02c2682014-06-24 23:33:07 +0000984 if (CurDAG->isBaseWithConstantOffset(Addr)) {
985 SDValue N0 = Addr.getOperand(0);
986 SDValue N1 = Addr.getOperand(1);
987 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
988
Tom Stellard94b72312015-02-11 00:34:35 +0000989 if (N0.getOpcode() == ISD::ADD) {
990 // (add (add N2, N3), C1) -> addr64
991 SDValue N2 = N0.getOperand(0);
992 SDValue N3 = N0.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000993 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1);
Tom Stellard94b72312015-02-11 00:34:35 +0000994 Ptr = N2;
995 VAddr = N3;
996 } else {
Tom Stellardb02c2682014-06-24 23:33:07 +0000997
Tom Stellard155bbb72014-08-11 22:18:17 +0000998 // (add N0, C1) -> offset
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000999 VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellard155bbb72014-08-11 22:18:17 +00001000 Ptr = N0;
Tom Stellard94b72312015-02-11 00:34:35 +00001001 }
1002
1003 if (isLegalMUBUFImmOffset(C1)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001004 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16);
Tom Stellard94b72312015-02-11 00:34:35 +00001005 return;
1006 } else if (isUInt<32>(C1->getZExtValue())) {
1007 // Illegal offset, store it in soffset.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001008 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
Tom Stellard94b72312015-02-11 00:34:35 +00001009 SOffset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001010 CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32)),
1011 0);
Tom Stellard155bbb72014-08-11 22:18:17 +00001012 return;
Tom Stellardb02c2682014-06-24 23:33:07 +00001013 }
1014 }
Tom Stellard94b72312015-02-11 00:34:35 +00001015
Tom Stellardb02c2682014-06-24 23:33:07 +00001016 if (Addr.getOpcode() == ISD::ADD) {
Tom Stellard155bbb72014-08-11 22:18:17 +00001017 // (add N0, N1) -> addr64
Tom Stellardb02c2682014-06-24 23:33:07 +00001018 SDValue N0 = Addr.getOperand(0);
1019 SDValue N1 = Addr.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001020 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1);
Tom Stellard155bbb72014-08-11 22:18:17 +00001021 Ptr = N0;
1022 VAddr = N1;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001023 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
Tom Stellard155bbb72014-08-11 22:18:17 +00001024 return;
Tom Stellardb02c2682014-06-24 23:33:07 +00001025 }
1026
Tom Stellard155bbb72014-08-11 22:18:17 +00001027 // default case -> offset
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001028 VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellard155bbb72014-08-11 22:18:17 +00001029 Ptr = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001030 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
Tom Stellard155bbb72014-08-11 22:18:17 +00001031
1032}
1033
1034bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
Tom Stellardc53861a2015-02-11 00:34:32 +00001035 SDValue &VAddr, SDValue &SOffset,
Tom Stellard1f9939f2015-02-27 14:59:41 +00001036 SDValue &Offset, SDValue &GLC,
1037 SDValue &SLC, SDValue &TFE) const {
1038 SDValue Ptr, Offen, Idxen, Addr64;
Tom Stellard155bbb72014-08-11 22:18:17 +00001039
Tom Stellard70580f82015-07-20 14:28:41 +00001040 // addr64 bit was removed for volcanic islands.
1041 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
1042 return false;
1043
Tom Stellard155bbb72014-08-11 22:18:17 +00001044 SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64,
1045 GLC, SLC, TFE);
1046
1047 ConstantSDNode *C = cast<ConstantSDNode>(Addr64);
1048 if (C->getSExtValue()) {
1049 SDLoc DL(Addr);
Matt Arsenault485defe2014-11-05 19:01:17 +00001050
1051 const SITargetLowering& Lowering =
1052 *static_cast<const SITargetLowering*>(getTargetLowering());
1053
1054 SRsrc = SDValue(Lowering.wrapAddr64Rsrc(*CurDAG, DL, Ptr), 0);
Tom Stellard155bbb72014-08-11 22:18:17 +00001055 return true;
1056 }
Matt Arsenault485defe2014-11-05 19:01:17 +00001057
Tom Stellard155bbb72014-08-11 22:18:17 +00001058 return false;
1059}
1060
Tom Stellard7980fc82014-09-25 18:30:26 +00001061bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
Tom Stellardc53861a2015-02-11 00:34:32 +00001062 SDValue &VAddr, SDValue &SOffset,
1063 SDValue &Offset,
1064 SDValue &SLC) const {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001065 SLC = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i1);
Tom Stellard1f9939f2015-02-27 14:59:41 +00001066 SDValue GLC, TFE;
Tom Stellard7980fc82014-09-25 18:30:26 +00001067
Tom Stellard1f9939f2015-02-27 14:59:41 +00001068 return SelectMUBUFAddr64(Addr, SRsrc, VAddr, SOffset, Offset, GLC, SLC, TFE);
Tom Stellard7980fc82014-09-25 18:30:26 +00001069}
1070
Tom Stellardb02094e2014-07-21 15:45:01 +00001071bool AMDGPUDAGToDAGISel::SelectMUBUFScratch(SDValue Addr, SDValue &Rsrc,
1072 SDValue &VAddr, SDValue &SOffset,
1073 SDValue &ImmOffset) const {
1074
1075 SDLoc DL(Addr);
1076 MachineFunction &MF = CurDAG->getMachineFunction();
Eric Christopherfc6de422014-08-05 02:39:49 +00001077 const SIRegisterInfo *TRI =
Eric Christopher7792e322015-01-30 23:24:40 +00001078 static_cast<const SIRegisterInfo *>(Subtarget->getRegisterInfo());
Tom Stellardb02094e2014-07-21 15:45:01 +00001079 MachineRegisterInfo &MRI = MF.getRegInfo();
Tom Stellard162a9472014-08-21 20:40:58 +00001080 const SITargetLowering& Lowering =
1081 *static_cast<const SITargetLowering*>(getTargetLowering());
Tom Stellardb02094e2014-07-21 15:45:01 +00001082
Tom Stellardb02094e2014-07-21 15:45:01 +00001083 unsigned ScratchOffsetReg =
1084 TRI->getPreloadedValue(MF, SIRegisterInfo::SCRATCH_WAVE_OFFSET);
Tom Stellard162a9472014-08-21 20:40:58 +00001085 Lowering.CreateLiveInRegister(*CurDAG, &AMDGPU::SReg_32RegClass,
1086 ScratchOffsetReg, MVT::i32);
Tom Stellard95292bb2015-01-20 17:49:47 +00001087 SDValue Sym0 = CurDAG->getExternalSymbol("SCRATCH_RSRC_DWORD0", MVT::i32);
1088 SDValue ScratchRsrcDword0 =
1089 SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, Sym0), 0);
Tom Stellardb02094e2014-07-21 15:45:01 +00001090
Tom Stellard95292bb2015-01-20 17:49:47 +00001091 SDValue Sym1 = CurDAG->getExternalSymbol("SCRATCH_RSRC_DWORD1", MVT::i32);
1092 SDValue ScratchRsrcDword1 =
1093 SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, Sym1), 0);
1094
1095 const SDValue RsrcOps[] = {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001096 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32),
Tom Stellard95292bb2015-01-20 17:49:47 +00001097 ScratchRsrcDword0,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001098 CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
Tom Stellard95292bb2015-01-20 17:49:47 +00001099 ScratchRsrcDword1,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001100 CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32),
Tom Stellard95292bb2015-01-20 17:49:47 +00001101 };
1102 SDValue ScratchPtr = SDValue(CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, DL,
1103 MVT::v2i32, RsrcOps), 0);
Matt Arsenaultf3cd4512014-11-05 19:01:19 +00001104 Rsrc = SDValue(Lowering.buildScratchRSRC(*CurDAG, DL, ScratchPtr), 0);
Tom Stellardb02094e2014-07-21 15:45:01 +00001105 SOffset = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
1106 MRI.getLiveInVirtReg(ScratchOffsetReg), MVT::i32);
1107
1108 // (add n0, c1)
1109 if (CurDAG->isBaseWithConstantOffset(Addr)) {
Tom Stellard78655fc2015-07-16 19:40:09 +00001110 SDValue N0 = Addr.getOperand(0);
Tom Stellardb02094e2014-07-21 15:45:01 +00001111 SDValue N1 = Addr.getOperand(1);
Tom Stellard78655fc2015-07-16 19:40:09 +00001112 // Offsets in vaddr must be positive.
1113 if (CurDAG->SignBitIsZero(N0)) {
1114 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
1115 if (isLegalMUBUFImmOffset(C1)) {
1116 VAddr = N0;
1117 ImmOffset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16);
1118 return true;
1119 }
Tom Stellardb02094e2014-07-21 15:45:01 +00001120 }
1121 }
1122
Tom Stellardb02094e2014-07-21 15:45:01 +00001123 // (node)
1124 VAddr = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001125 ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i16);
Tom Stellardb02094e2014-07-21 15:45:01 +00001126 return true;
1127}
1128
Tom Stellard155bbb72014-08-11 22:18:17 +00001129bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc,
1130 SDValue &SOffset, SDValue &Offset,
1131 SDValue &GLC, SDValue &SLC,
1132 SDValue &TFE) const {
1133 SDValue Ptr, VAddr, Offen, Idxen, Addr64;
Tom Stellard794c8c02014-12-02 17:05:41 +00001134 const SIInstrInfo *TII =
Eric Christopher7792e322015-01-30 23:24:40 +00001135 static_cast<const SIInstrInfo *>(Subtarget->getInstrInfo());
Tom Stellardb02094e2014-07-21 15:45:01 +00001136
Tom Stellard155bbb72014-08-11 22:18:17 +00001137 SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64,
1138 GLC, SLC, TFE);
Tom Stellardb02094e2014-07-21 15:45:01 +00001139
Tom Stellard155bbb72014-08-11 22:18:17 +00001140 if (!cast<ConstantSDNode>(Offen)->getSExtValue() &&
1141 !cast<ConstantSDNode>(Idxen)->getSExtValue() &&
1142 !cast<ConstantSDNode>(Addr64)->getSExtValue()) {
Tom Stellard794c8c02014-12-02 17:05:41 +00001143 uint64_t Rsrc = TII->getDefaultRsrcDataFormat() |
Tom Stellard155bbb72014-08-11 22:18:17 +00001144 APInt::getAllOnesValue(32).getZExtValue(); // Size
1145 SDLoc DL(Addr);
Matt Arsenaultf3cd4512014-11-05 19:01:19 +00001146
1147 const SITargetLowering& Lowering =
1148 *static_cast<const SITargetLowering*>(getTargetLowering());
1149
1150 SRsrc = SDValue(Lowering.buildRSRC(*CurDAG, DL, Ptr, 0, Rsrc), 0);
Tom Stellard155bbb72014-08-11 22:18:17 +00001151 return true;
1152 }
1153 return false;
Tom Stellardb02094e2014-07-21 15:45:01 +00001154}
1155
Tom Stellard7980fc82014-09-25 18:30:26 +00001156bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc,
1157 SDValue &Soffset, SDValue &Offset,
1158 SDValue &GLC) const {
1159 SDValue SLC, TFE;
1160
1161 return SelectMUBUFOffset(Addr, SRsrc, Soffset, Offset, GLC, SLC, TFE);
1162}
1163
Tom Stellarddee26a22015-08-06 19:28:30 +00001164///
1165/// \param EncodedOffset This is the immediate value that will be encoded
1166/// directly into the instruction. On SI/CI the \p EncodedOffset
1167/// will be in units of dwords and on VI+ it will be units of bytes.
1168static bool isLegalSMRDImmOffset(const AMDGPUSubtarget *ST,
1169 int64_t EncodedOffset) {
1170 return ST->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS ?
1171 isUInt<8>(EncodedOffset) : isUInt<20>(EncodedOffset);
1172}
1173
1174bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDValue ByteOffsetNode,
1175 SDValue &Offset, bool &Imm) const {
1176
1177 // FIXME: Handle non-constant offsets.
1178 ConstantSDNode *C = dyn_cast<ConstantSDNode>(ByteOffsetNode);
1179 if (!C)
1180 return false;
1181
1182 SDLoc SL(ByteOffsetNode);
1183 AMDGPUSubtarget::Generation Gen = Subtarget->getGeneration();
1184 int64_t ByteOffset = C->getSExtValue();
1185 int64_t EncodedOffset = Gen < AMDGPUSubtarget::VOLCANIC_ISLANDS ?
1186 ByteOffset >> 2 : ByteOffset;
1187
1188 if (isLegalSMRDImmOffset(Subtarget, EncodedOffset)) {
1189 Offset = CurDAG->getTargetConstant(EncodedOffset, SL, MVT::i32);
1190 Imm = true;
1191 return true;
1192 }
1193
1194 if (isUInt<32>(ByteOffset)) {
1195 SDValue C32Bit = CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32);
1196 Offset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32,
1197 C32Bit), 0);
1198 Imm = false;
1199 return true;
1200 }
1201 return false;
1202}
1203
1204bool AMDGPUDAGToDAGISel::SelectSMRD(SDValue Addr, SDValue &SBase,
1205 SDValue &Offset, bool &Imm) const {
1206
1207 SDLoc SL(Addr);
1208 if (CurDAG->isBaseWithConstantOffset(Addr)) {
1209 SDValue N0 = Addr.getOperand(0);
1210 SDValue N1 = Addr.getOperand(1);
1211
1212 if (SelectSMRDOffset(N1, Offset, Imm)) {
1213 SBase = N0;
1214 return true;
1215 }
1216 }
1217 SBase = Addr;
1218 Offset = CurDAG->getTargetConstant(0, SL, MVT::i32);
1219 Imm = true;
1220 return true;
1221}
1222
1223bool AMDGPUDAGToDAGISel::SelectSMRDImm(SDValue Addr, SDValue &SBase,
1224 SDValue &Offset) const {
1225 bool Imm;
1226 return SelectSMRD(Addr, SBase, Offset, Imm) && Imm;
1227}
1228
1229bool AMDGPUDAGToDAGISel::SelectSMRDSgpr(SDValue Addr, SDValue &SBase,
1230 SDValue &Offset) const {
1231 bool Imm;
1232 return SelectSMRD(Addr, SBase, Offset, Imm) && !Imm;
1233}
1234
1235bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm(SDValue Addr,
1236 SDValue &Offset) const {
1237 bool Imm;
1238 return SelectSMRDOffset(Addr, Offset, Imm) && Imm;
1239}
1240
1241bool AMDGPUDAGToDAGISel::SelectSMRDBufferSgpr(SDValue Addr,
1242 SDValue &Offset) const {
1243 bool Imm;
1244 return SelectSMRDOffset(Addr, Offset, Imm) && !Imm;
1245}
1246
Matt Arsenault3f981402014-09-15 15:41:53 +00001247// FIXME: This is incorrect and only enough to be able to compile.
1248SDNode *AMDGPUDAGToDAGISel::SelectAddrSpaceCast(SDNode *N) {
1249 AddrSpaceCastSDNode *ASC = cast<AddrSpaceCastSDNode>(N);
1250 SDLoc DL(N);
1251
Eric Christopher7792e322015-01-30 23:24:40 +00001252 assert(Subtarget->hasFlatAddressSpace() &&
Matt Arsenault3f981402014-09-15 15:41:53 +00001253 "addrspacecast only supported with flat address space!");
1254
1255 assert((ASC->getSrcAddressSpace() != AMDGPUAS::CONSTANT_ADDRESS &&
1256 ASC->getDestAddressSpace() != AMDGPUAS::CONSTANT_ADDRESS) &&
1257 "Cannot cast address space to / from constant address!");
1258
1259 assert((ASC->getSrcAddressSpace() == AMDGPUAS::FLAT_ADDRESS ||
1260 ASC->getDestAddressSpace() == AMDGPUAS::FLAT_ADDRESS) &&
1261 "Can only cast to / from flat address space!");
1262
1263 // The flat instructions read the address as the index of the VGPR holding the
1264 // address, so casting should just be reinterpreting the base VGPR, so just
1265 // insert trunc / bitcast / zext.
1266
1267 SDValue Src = ASC->getOperand(0);
1268 EVT DestVT = ASC->getValueType(0);
1269 EVT SrcVT = Src.getValueType();
1270
1271 unsigned SrcSize = SrcVT.getSizeInBits();
1272 unsigned DestSize = DestVT.getSizeInBits();
1273
1274 if (SrcSize > DestSize) {
1275 assert(SrcSize == 64 && DestSize == 32);
1276 return CurDAG->getMachineNode(
1277 TargetOpcode::EXTRACT_SUBREG,
1278 DL,
1279 DestVT,
1280 Src,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001281 CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32));
Matt Arsenault3f981402014-09-15 15:41:53 +00001282 }
1283
1284
1285 if (DestSize > SrcSize) {
1286 assert(SrcSize == 32 && DestSize == 64);
1287
Tom Stellardb6550522015-01-12 19:33:18 +00001288 // FIXME: This is probably wrong, we should never be defining
1289 // a register class with both VGPRs and SGPRs
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001290 SDValue RC = CurDAG->getTargetConstant(AMDGPU::VS_64RegClassID, DL,
1291 MVT::i32);
Matt Arsenault3f981402014-09-15 15:41:53 +00001292
1293 const SDValue Ops[] = {
1294 RC,
1295 Src,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001296 CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
1297 SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
1298 CurDAG->getConstant(0, DL, MVT::i32)), 0),
1299 CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32)
Matt Arsenault3f981402014-09-15 15:41:53 +00001300 };
1301
1302 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001303 DL, N->getValueType(0), Ops);
Matt Arsenault3f981402014-09-15 15:41:53 +00001304 }
1305
1306 assert(SrcSize == 64 && DestSize == 64);
1307 return CurDAG->getNode(ISD::BITCAST, DL, DestVT, Src).getNode();
1308}
1309
Marek Olsak9b728682015-03-24 13:40:27 +00001310SDNode *AMDGPUDAGToDAGISel::getS_BFE(unsigned Opcode, SDLoc DL, SDValue Val,
1311 uint32_t Offset, uint32_t Width) {
1312 // Transformation function, pack the offset and width of a BFE into
1313 // the format expected by the S_BFE_I32 / S_BFE_U32. In the second
1314 // source, bits [5:0] contain the offset and bits [22:16] the width.
1315 uint32_t PackedVal = Offset | (Width << 16);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001316 SDValue PackedConst = CurDAG->getTargetConstant(PackedVal, DL, MVT::i32);
Marek Olsak9b728682015-03-24 13:40:27 +00001317
1318 return CurDAG->getMachineNode(Opcode, DL, MVT::i32, Val, PackedConst);
1319}
1320
1321SDNode *AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(SDNode *N) {
1322 // "(a << b) srl c)" ---> "BFE_U32 a, (c-b), (32-c)
1323 // "(a << b) sra c)" ---> "BFE_I32 a, (c-b), (32-c)
1324 // Predicate: 0 < b <= c < 32
1325
1326 const SDValue &Shl = N->getOperand(0);
1327 ConstantSDNode *B = dyn_cast<ConstantSDNode>(Shl->getOperand(1));
1328 ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1));
1329
1330 if (B && C) {
1331 uint32_t BVal = B->getZExtValue();
1332 uint32_t CVal = C->getZExtValue();
1333
1334 if (0 < BVal && BVal <= CVal && CVal < 32) {
1335 bool Signed = N->getOpcode() == ISD::SRA;
1336 unsigned Opcode = Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
1337
1338 return getS_BFE(Opcode, SDLoc(N), Shl.getOperand(0),
1339 CVal - BVal, 32 - CVal);
1340 }
1341 }
1342 return SelectCode(N);
1343}
1344
1345SDNode *AMDGPUDAGToDAGISel::SelectS_BFE(SDNode *N) {
1346 switch (N->getOpcode()) {
1347 case ISD::AND:
1348 if (N->getOperand(0).getOpcode() == ISD::SRL) {
1349 // "(a srl b) & mask" ---> "BFE_U32 a, b, popcount(mask)"
1350 // Predicate: isMask(mask)
1351 const SDValue &Srl = N->getOperand(0);
1352 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(Srl.getOperand(1));
1353 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(N->getOperand(1));
1354
1355 if (Shift && Mask) {
1356 uint32_t ShiftVal = Shift->getZExtValue();
1357 uint32_t MaskVal = Mask->getZExtValue();
1358
1359 if (isMask_32(MaskVal)) {
1360 uint32_t WidthVal = countPopulation(MaskVal);
1361
1362 return getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N), Srl.getOperand(0),
1363 ShiftVal, WidthVal);
1364 }
1365 }
1366 }
1367 break;
1368 case ISD::SRL:
1369 if (N->getOperand(0).getOpcode() == ISD::AND) {
1370 // "(a & mask) srl b)" ---> "BFE_U32 a, b, popcount(mask >> b)"
1371 // Predicate: isMask(mask >> b)
1372 const SDValue &And = N->getOperand(0);
1373 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N->getOperand(1));
1374 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(And->getOperand(1));
1375
1376 if (Shift && Mask) {
1377 uint32_t ShiftVal = Shift->getZExtValue();
1378 uint32_t MaskVal = Mask->getZExtValue() >> ShiftVal;
1379
1380 if (isMask_32(MaskVal)) {
1381 uint32_t WidthVal = countPopulation(MaskVal);
1382
1383 return getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N), And.getOperand(0),
1384 ShiftVal, WidthVal);
1385 }
1386 }
1387 } else if (N->getOperand(0).getOpcode() == ISD::SHL)
1388 return SelectS_BFEFromShifts(N);
1389 break;
1390 case ISD::SRA:
1391 if (N->getOperand(0).getOpcode() == ISD::SHL)
1392 return SelectS_BFEFromShifts(N);
1393 break;
1394 }
1395
1396 return SelectCode(N);
1397}
1398
Tom Stellardb4a313a2014-08-01 00:32:39 +00001399bool AMDGPUDAGToDAGISel::SelectVOP3Mods(SDValue In, SDValue &Src,
1400 SDValue &SrcMods) const {
1401
1402 unsigned Mods = 0;
1403
1404 Src = In;
1405
1406 if (Src.getOpcode() == ISD::FNEG) {
1407 Mods |= SISrcMods::NEG;
1408 Src = Src.getOperand(0);
1409 }
1410
1411 if (Src.getOpcode() == ISD::FABS) {
1412 Mods |= SISrcMods::ABS;
1413 Src = Src.getOperand(0);
1414 }
1415
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001416 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
Tom Stellardb4a313a2014-08-01 00:32:39 +00001417
1418 return true;
1419}
1420
Tom Stellarddb5a11f2015-07-13 15:47:57 +00001421bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(SDValue In, SDValue &Src,
1422 SDValue &SrcMods) const {
1423 bool Res = SelectVOP3Mods(In, Src, SrcMods);
1424 return Res && cast<ConstantSDNode>(SrcMods)->isNullValue();
1425}
1426
Tom Stellardb4a313a2014-08-01 00:32:39 +00001427bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(SDValue In, SDValue &Src,
1428 SDValue &SrcMods, SDValue &Clamp,
1429 SDValue &Omod) const {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001430 SDLoc DL(In);
Tom Stellardb4a313a2014-08-01 00:32:39 +00001431 // FIXME: Handle Clamp and Omod
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001432 Clamp = CurDAG->getTargetConstant(0, DL, MVT::i32);
1433 Omod = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellardb4a313a2014-08-01 00:32:39 +00001434
1435 return SelectVOP3Mods(In, Src, SrcMods);
1436}
1437
Tom Stellarddb5a11f2015-07-13 15:47:57 +00001438bool AMDGPUDAGToDAGISel::SelectVOP3NoMods0(SDValue In, SDValue &Src,
1439 SDValue &SrcMods, SDValue &Clamp,
1440 SDValue &Omod) const {
1441 bool Res = SelectVOP3Mods0(In, Src, SrcMods, Clamp, Omod);
1442
1443 return Res && cast<ConstantSDNode>(SrcMods)->isNullValue() &&
1444 cast<ConstantSDNode>(Clamp)->isNullValue() &&
1445 cast<ConstantSDNode>(Omod)->isNullValue();
1446}
1447
Matt Arsenault1cffa4c2014-11-13 19:49:04 +00001448bool AMDGPUDAGToDAGISel::SelectVOP3Mods0Clamp(SDValue In, SDValue &Src,
1449 SDValue &SrcMods,
1450 SDValue &Omod) const {
1451 // FIXME: Handle Omod
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001452 Omod = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32);
Matt Arsenault1cffa4c2014-11-13 19:49:04 +00001453
1454 return SelectVOP3Mods(In, Src, SrcMods);
1455}
1456
Matt Arsenault4831ce52015-01-06 23:00:37 +00001457bool AMDGPUDAGToDAGISel::SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src,
1458 SDValue &SrcMods,
1459 SDValue &Clamp,
1460 SDValue &Omod) const {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001461 Clamp = Omod = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32);
Matt Arsenault4831ce52015-01-06 23:00:37 +00001462 return SelectVOP3Mods(In, Src, SrcMods);
1463}
1464
Christian Konigd910b7d2013-02-26 17:52:16 +00001465void AMDGPUDAGToDAGISel::PostprocessISelDAG() {
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001466 const AMDGPUTargetLowering& Lowering =
Matt Arsenault209a7b92014-04-18 07:40:20 +00001467 *static_cast<const AMDGPUTargetLowering*>(getTargetLowering());
Vincent Lejeuneab3baf82013-09-12 23:44:44 +00001468 bool IsModified = false;
1469 do {
1470 IsModified = false;
1471 // Go over all selected nodes and try to fold them a bit more
Pete Cooper65c69402015-07-14 22:10:54 +00001472 for (SDNode &Node : CurDAG->allnodes()) {
1473 MachineSDNode *MachineNode = dyn_cast<MachineSDNode>(&Node);
Vincent Lejeuneab3baf82013-09-12 23:44:44 +00001474 if (!MachineNode)
1475 continue;
Christian Konigd910b7d2013-02-26 17:52:16 +00001476
Vincent Lejeuneab3baf82013-09-12 23:44:44 +00001477 SDNode *ResNode = Lowering.PostISelFolding(MachineNode, *CurDAG);
Pete Cooper65c69402015-07-14 22:10:54 +00001478 if (ResNode != &Node) {
1479 ReplaceUses(&Node, ResNode);
Vincent Lejeuneab3baf82013-09-12 23:44:44 +00001480 IsModified = true;
1481 }
Tom Stellard2183b702013-06-03 17:39:46 +00001482 }
Vincent Lejeuneab3baf82013-09-12 23:44:44 +00001483 CurDAG->RemoveDeadNodes();
1484 } while (IsModified);
Christian Konigd910b7d2013-02-26 17:52:16 +00001485}