blob: 37b77d778d9f8de86ab6165afa8b41d336ee1dff [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;
Matt Arsenault3f981402014-09-15 15:41:53 +0000111 SDNode *SelectAddrSpaceCast(SDNode *N);
Tom Stellardb4a313a2014-08-01 00:32:39 +0000112 bool SelectVOP3Mods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
Tom Stellarddb5a11f2015-07-13 15:47:57 +0000113 bool SelectVOP3NoMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
Tom Stellardb4a313a2014-08-01 00:32:39 +0000114 bool SelectVOP3Mods0(SDValue In, SDValue &Src, SDValue &SrcMods,
115 SDValue &Clamp, SDValue &Omod) const;
Tom Stellarddb5a11f2015-07-13 15:47:57 +0000116 bool SelectVOP3NoMods0(SDValue In, SDValue &Src, SDValue &SrcMods,
117 SDValue &Clamp, SDValue &Omod) const;
Tom Stellard75aadc22012-12-11 21:25:42 +0000118
Matt Arsenault1cffa4c2014-11-13 19:49:04 +0000119 bool SelectVOP3Mods0Clamp(SDValue In, SDValue &Src, SDValue &SrcMods,
120 SDValue &Omod) const;
Matt Arsenault4831ce52015-01-06 23:00:37 +0000121 bool SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src, SDValue &SrcMods,
122 SDValue &Clamp,
123 SDValue &Omod) const;
Matt Arsenault1cffa4c2014-11-13 19:49:04 +0000124
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000125 SDNode *SelectADD_SUB_I64(SDNode *N);
Matt Arsenaultf2b0aeb2014-06-23 18:28:28 +0000126 SDNode *SelectDIV_SCALE(SDNode *N);
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000127
Marek Olsak9b728682015-03-24 13:40:27 +0000128 SDNode *getS_BFE(unsigned Opcode, SDLoc DL, SDValue Val,
129 uint32_t Offset, uint32_t Width);
130 SDNode *SelectS_BFEFromShifts(SDNode *N);
131 SDNode *SelectS_BFE(SDNode *N);
132
Tom Stellard75aadc22012-12-11 21:25:42 +0000133 // Include the pieces autogenerated from the target description.
134#include "AMDGPUGenDAGISel.inc"
135};
136} // end anonymous namespace
137
138/// \brief This pass converts a legalized DAG into a AMDGPU-specific
139// DAG, ready for instruction scheduling.
Matt Arsenault209a7b92014-04-18 07:40:20 +0000140FunctionPass *llvm::createAMDGPUISelDag(TargetMachine &TM) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000141 return new AMDGPUDAGToDAGISel(TM);
142}
143
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000144AMDGPUDAGToDAGISel::AMDGPUDAGToDAGISel(TargetMachine &TM)
Eric Christopher7792e322015-01-30 23:24:40 +0000145 : SelectionDAGISel(TM) {}
146
147bool AMDGPUDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
148 Subtarget = &static_cast<const AMDGPUSubtarget &>(MF.getSubtarget());
149 return SelectionDAGISel::runOnMachineFunction(MF);
Tom Stellard75aadc22012-12-11 21:25:42 +0000150}
151
152AMDGPUDAGToDAGISel::~AMDGPUDAGToDAGISel() {
153}
154
Tom Stellard7ed0b522014-04-03 20:19:27 +0000155bool AMDGPUDAGToDAGISel::isInlineImmediate(SDNode *N) const {
156 const SITargetLowering *TL
157 = static_cast<const SITargetLowering *>(getTargetLowering());
158 return TL->analyzeImmediate(N) == 0;
159}
160
Tom Stellarddf94dc32013-08-14 23:24:24 +0000161/// \brief Determine the register class for \p OpNo
162/// \returns The register class of the virtual register that will be used for
163/// the given operand number \OpNo or NULL if the register class cannot be
164/// determined.
165const TargetRegisterClass *AMDGPUDAGToDAGISel::getOperandRegClass(SDNode *N,
166 unsigned OpNo) const {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000167 if (!N->isMachineOpcode())
168 return nullptr;
169
Tom Stellarddf94dc32013-08-14 23:24:24 +0000170 switch (N->getMachineOpcode()) {
171 default: {
Eric Christopherd9134482014-08-04 21:25:23 +0000172 const MCInstrDesc &Desc =
Eric Christopher7792e322015-01-30 23:24:40 +0000173 Subtarget->getInstrInfo()->get(N->getMachineOpcode());
Alexey Samsonov3186eb32013-08-15 07:11:34 +0000174 unsigned OpIdx = Desc.getNumDefs() + OpNo;
175 if (OpIdx >= Desc.getNumOperands())
Matt Arsenault209a7b92014-04-18 07:40:20 +0000176 return nullptr;
Alexey Samsonov3186eb32013-08-15 07:11:34 +0000177 int RegClass = Desc.OpInfo[OpIdx].RegClass;
Matt Arsenault209a7b92014-04-18 07:40:20 +0000178 if (RegClass == -1)
179 return nullptr;
180
Eric Christopher7792e322015-01-30 23:24:40 +0000181 return Subtarget->getRegisterInfo()->getRegClass(RegClass);
Tom Stellarddf94dc32013-08-14 23:24:24 +0000182 }
183 case AMDGPU::REG_SEQUENCE: {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000184 unsigned RCID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
Eric Christopherd9134482014-08-04 21:25:23 +0000185 const TargetRegisterClass *SuperRC =
Eric Christopher7792e322015-01-30 23:24:40 +0000186 Subtarget->getRegisterInfo()->getRegClass(RCID);
Matt Arsenault209a7b92014-04-18 07:40:20 +0000187
188 SDValue SubRegOp = N->getOperand(OpNo + 1);
189 unsigned SubRegIdx = cast<ConstantSDNode>(SubRegOp)->getZExtValue();
Eric Christopher7792e322015-01-30 23:24:40 +0000190 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC,
191 SubRegIdx);
Tom Stellarddf94dc32013-08-14 23:24:24 +0000192 }
193 }
194}
195
Tom Stellard75aadc22012-12-11 21:25:42 +0000196bool AMDGPUDAGToDAGISel::SelectADDRParam(
Matt Arsenault209a7b92014-04-18 07:40:20 +0000197 SDValue Addr, SDValue& R1, SDValue& R2) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000198
199 if (Addr.getOpcode() == ISD::FrameIndex) {
200 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
201 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000202 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000203 } else {
204 R1 = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000205 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000206 }
207 } else if (Addr.getOpcode() == ISD::ADD) {
208 R1 = Addr.getOperand(0);
209 R2 = Addr.getOperand(1);
210 } else {
211 R1 = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000212 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000213 }
214 return true;
215}
216
217bool AMDGPUDAGToDAGISel::SelectADDR(SDValue Addr, SDValue& R1, SDValue& R2) {
218 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
219 Addr.getOpcode() == ISD::TargetGlobalAddress) {
220 return false;
221 }
222 return SelectADDRParam(Addr, R1, R2);
223}
224
225
226bool AMDGPUDAGToDAGISel::SelectADDR64(SDValue Addr, SDValue& R1, SDValue& R2) {
227 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
228 Addr.getOpcode() == ISD::TargetGlobalAddress) {
229 return false;
230 }
231
232 if (Addr.getOpcode() == ISD::FrameIndex) {
233 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
234 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000235 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i64);
Tom Stellard75aadc22012-12-11 21:25:42 +0000236 } else {
237 R1 = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000238 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i64);
Tom Stellard75aadc22012-12-11 21:25:42 +0000239 }
240 } else if (Addr.getOpcode() == ISD::ADD) {
241 R1 = Addr.getOperand(0);
242 R2 = Addr.getOperand(1);
243 } else {
244 R1 = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000245 R2 = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i64);
Tom Stellard75aadc22012-12-11 21:25:42 +0000246 }
247 return true;
248}
249
Tom Stellard381a94a2015-05-12 15:00:49 +0000250SDNode *AMDGPUDAGToDAGISel::glueCopyToM0(SDNode *N) const {
251 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS ||
252 !checkType(cast<MemSDNode>(N)->getMemOperand()->getValue(),
253 AMDGPUAS::LOCAL_ADDRESS))
254 return N;
255
256 const SITargetLowering& Lowering =
257 *static_cast<const SITargetLowering*>(getTargetLowering());
258
259 // Write max value to m0 before each load operation
260
261 SDValue M0 = Lowering.copyToM0(*CurDAG, CurDAG->getEntryNode(), SDLoc(N),
262 CurDAG->getTargetConstant(-1, SDLoc(N), MVT::i32));
263
264 SDValue Glue = M0.getValue(1);
265
266 SmallVector <SDValue, 8> Ops;
267 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
268 Ops.push_back(N->getOperand(i));
269 }
270 Ops.push_back(Glue);
271 CurDAG->MorphNodeTo(N, N->getOpcode(), N->getVTList(), Ops);
272
273 return N;
274}
275
Tom Stellard75aadc22012-12-11 21:25:42 +0000276SDNode *AMDGPUDAGToDAGISel::Select(SDNode *N) {
277 unsigned int Opc = N->getOpcode();
278 if (N->isMachineOpcode()) {
Tim Northover31d093c2013-09-22 08:21:56 +0000279 N->setNodeId(-1);
Matt Arsenault209a7b92014-04-18 07:40:20 +0000280 return nullptr; // Already selected.
Tom Stellard75aadc22012-12-11 21:25:42 +0000281 }
Matt Arsenault78b86702014-04-18 05:19:26 +0000282
Tom Stellard381a94a2015-05-12 15:00:49 +0000283 if (isa<AtomicSDNode>(N))
284 N = glueCopyToM0(N);
285
Tom Stellard75aadc22012-12-11 21:25:42 +0000286 switch (Opc) {
287 default: break;
Tom Stellard1f15bff2014-02-25 21:36:18 +0000288 // We are selecting i64 ADD here instead of custom lower it during
289 // DAG legalization, so we can fold some i64 ADDs used for address
290 // calculation into the LOAD and STORE instructions.
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000291 case ISD::ADD:
292 case ISD::SUB: {
Tom Stellard1f15bff2014-02-25 21:36:18 +0000293 if (N->getValueType(0) != MVT::i64 ||
Eric Christopher7792e322015-01-30 23:24:40 +0000294 Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS)
Tom Stellard1f15bff2014-02-25 21:36:18 +0000295 break;
296
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000297 return SelectADD_SUB_I64(N);
Tom Stellard1f15bff2014-02-25 21:36:18 +0000298 }
Matt Arsenault064c2062014-06-11 17:40:32 +0000299 case ISD::SCALAR_TO_VECTOR:
Tom Stellard880a80a2014-06-17 16:53:14 +0000300 case AMDGPUISD::BUILD_VERTICAL_VECTOR:
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000301 case ISD::BUILD_VECTOR: {
Tom Stellard8e5da412013-08-14 23:24:32 +0000302 unsigned RegClassID;
Eric Christopher7792e322015-01-30 23:24:40 +0000303 const AMDGPURegisterInfo *TRI = Subtarget->getRegisterInfo();
Tom Stellard8e5da412013-08-14 23:24:32 +0000304 EVT VT = N->getValueType(0);
305 unsigned NumVectorElts = VT.getVectorNumElements();
Matt Arsenault064c2062014-06-11 17:40:32 +0000306 EVT EltVT = VT.getVectorElementType();
307 assert(EltVT.bitsEq(MVT::i32));
Eric Christopher7792e322015-01-30 23:24:40 +0000308 if (Subtarget->getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) {
Tom Stellard8e5da412013-08-14 23:24:32 +0000309 bool UseVReg = true;
310 for (SDNode::use_iterator U = N->use_begin(), E = SDNode::use_end();
311 U != E; ++U) {
312 if (!U->isMachineOpcode()) {
313 continue;
314 }
315 const TargetRegisterClass *RC = getOperandRegClass(*U, U.getOperandNo());
316 if (!RC) {
317 continue;
318 }
Eric Christopher7792e322015-01-30 23:24:40 +0000319 if (static_cast<const SIRegisterInfo *>(TRI)->isSGPRClass(RC)) {
Tom Stellard8e5da412013-08-14 23:24:32 +0000320 UseVReg = false;
321 }
322 }
323 switch(NumVectorElts) {
Tom Stellard45c0b3a2015-01-07 20:59:25 +0000324 case 1: RegClassID = UseVReg ? AMDGPU::VGPR_32RegClassID :
Tom Stellard8e5da412013-08-14 23:24:32 +0000325 AMDGPU::SReg_32RegClassID;
326 break;
327 case 2: RegClassID = UseVReg ? AMDGPU::VReg_64RegClassID :
328 AMDGPU::SReg_64RegClassID;
329 break;
330 case 4: RegClassID = UseVReg ? AMDGPU::VReg_128RegClassID :
331 AMDGPU::SReg_128RegClassID;
332 break;
333 case 8: RegClassID = UseVReg ? AMDGPU::VReg_256RegClassID :
334 AMDGPU::SReg_256RegClassID;
335 break;
336 case 16: RegClassID = UseVReg ? AMDGPU::VReg_512RegClassID :
337 AMDGPU::SReg_512RegClassID;
338 break;
Benjamin Kramerbda73ff2013-08-31 21:20:04 +0000339 default: llvm_unreachable("Do not know how to lower this BUILD_VECTOR");
Tom Stellard8e5da412013-08-14 23:24:32 +0000340 }
341 } else {
342 // BUILD_VECTOR was lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG
343 // that adds a 128 bits reg copy when going through TwoAddressInstructions
344 // pass. We want to avoid 128 bits copies as much as possible because they
345 // can't be bundled by our scheduler.
346 switch(NumVectorElts) {
347 case 2: RegClassID = AMDGPU::R600_Reg64RegClassID; break;
Tom Stellard880a80a2014-06-17 16:53:14 +0000348 case 4:
349 if (Opc == AMDGPUISD::BUILD_VERTICAL_VECTOR)
350 RegClassID = AMDGPU::R600_Reg128VerticalRegClassID;
351 else
352 RegClassID = AMDGPU::R600_Reg128RegClassID;
353 break;
Tom Stellard8e5da412013-08-14 23:24:32 +0000354 default: llvm_unreachable("Do not know how to lower this BUILD_VECTOR");
355 }
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000356 }
Tom Stellard0344cdf2013-08-01 15:23:42 +0000357
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000358 SDLoc DL(N);
359 SDValue RegClass = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32);
Tom Stellard8e5da412013-08-14 23:24:32 +0000360
361 if (NumVectorElts == 1) {
Matt Arsenault064c2062014-06-11 17:40:32 +0000362 return CurDAG->SelectNodeTo(N, AMDGPU::COPY_TO_REGCLASS, EltVT,
Tom Stellard8e5da412013-08-14 23:24:32 +0000363 N->getOperand(0), RegClass);
Tom Stellard0344cdf2013-08-01 15:23:42 +0000364 }
Tom Stellard8e5da412013-08-14 23:24:32 +0000365
366 assert(NumVectorElts <= 16 && "Vectors with more than 16 elements not "
367 "supported yet");
368 // 16 = Max Num Vector Elements
369 // 2 = 2 REG_SEQUENCE operands per element (value, subreg index)
370 // 1 = Vector Register Class
Matt Arsenault064c2062014-06-11 17:40:32 +0000371 SmallVector<SDValue, 16 * 2 + 1> RegSeqArgs(NumVectorElts * 2 + 1);
Tom Stellard8e5da412013-08-14 23:24:32 +0000372
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000373 RegSeqArgs[0] = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32);
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000374 bool IsRegSeq = true;
Matt Arsenault064c2062014-06-11 17:40:32 +0000375 unsigned NOps = N->getNumOperands();
376 for (unsigned i = 0; i < NOps; i++) {
Tom Stellard8e5da412013-08-14 23:24:32 +0000377 // XXX: Why is this here?
Benjamin Kramer619c4e52015-04-10 11:24:51 +0000378 if (isa<RegisterSDNode>(N->getOperand(i))) {
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000379 IsRegSeq = false;
380 break;
381 }
Tom Stellard8e5da412013-08-14 23:24:32 +0000382 RegSeqArgs[1 + (2 * i)] = N->getOperand(i);
383 RegSeqArgs[1 + (2 * i) + 1] =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000384 CurDAG->getTargetConstant(TRI->getSubRegFromChannel(i), DL,
385 MVT::i32);
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000386 }
Matt Arsenault064c2062014-06-11 17:40:32 +0000387
388 if (NOps != NumVectorElts) {
389 // Fill in the missing undef elements if this was a scalar_to_vector.
390 assert(Opc == ISD::SCALAR_TO_VECTOR && NOps < NumVectorElts);
391
392 MachineSDNode *ImpDef = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000393 DL, EltVT);
Matt Arsenault064c2062014-06-11 17:40:32 +0000394 for (unsigned i = NOps; i < NumVectorElts; ++i) {
395 RegSeqArgs[1 + (2 * i)] = SDValue(ImpDef, 0);
396 RegSeqArgs[1 + (2 * i) + 1] =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000397 CurDAG->getTargetConstant(TRI->getSubRegFromChannel(i), DL, MVT::i32);
Matt Arsenault064c2062014-06-11 17:40:32 +0000398 }
399 }
400
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000401 if (!IsRegSeq)
402 break;
403 return CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, N->getVTList(),
Craig Topper481fb282014-04-27 19:21:11 +0000404 RegSeqArgs);
Vincent Lejeune3b6f20e2013-03-05 15:04:49 +0000405 }
Tom Stellard754f80f2013-04-05 23:31:51 +0000406 case ISD::BUILD_PAIR: {
407 SDValue RC, SubReg0, SubReg1;
Eric Christopher7792e322015-01-30 23:24:40 +0000408 if (Subtarget->getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
Tom Stellard754f80f2013-04-05 23:31:51 +0000409 break;
410 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000411 SDLoc DL(N);
Tom Stellard754f80f2013-04-05 23:31:51 +0000412 if (N->getValueType(0) == MVT::i128) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000413 RC = CurDAG->getTargetConstant(AMDGPU::SReg_128RegClassID, DL, MVT::i32);
414 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32);
415 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32);
Tom Stellard754f80f2013-04-05 23:31:51 +0000416 } else if (N->getValueType(0) == MVT::i64) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000417 RC = CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32);
418 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32);
419 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32);
Tom Stellard754f80f2013-04-05 23:31:51 +0000420 } else {
421 llvm_unreachable("Unhandled value type for BUILD_PAIR");
422 }
423 const SDValue Ops[] = { RC, N->getOperand(0), SubReg0,
424 N->getOperand(1), SubReg1 };
425 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000426 DL, N->getValueType(0), Ops);
Tom Stellard754f80f2013-04-05 23:31:51 +0000427 }
Tom Stellard7ed0b522014-04-03 20:19:27 +0000428
429 case ISD::Constant:
430 case ISD::ConstantFP: {
Eric Christopher7792e322015-01-30 23:24:40 +0000431 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS ||
Tom Stellard7ed0b522014-04-03 20:19:27 +0000432 N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(N))
433 break;
434
435 uint64_t Imm;
436 if (ConstantFPSDNode *FP = dyn_cast<ConstantFPSDNode>(N))
437 Imm = FP->getValueAPF().bitcastToAPInt().getZExtValue();
438 else {
Tom Stellard3cbe0142014-04-07 19:31:13 +0000439 ConstantSDNode *C = cast<ConstantSDNode>(N);
Tom Stellard7ed0b522014-04-03 20:19:27 +0000440 Imm = C->getZExtValue();
441 }
442
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000443 SDLoc DL(N);
444 SDNode *Lo = CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
445 CurDAG->getConstant(Imm & 0xFFFFFFFF, DL,
446 MVT::i32));
447 SDNode *Hi = CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
448 CurDAG->getConstant(Imm >> 32, DL, MVT::i32));
Tom Stellard7ed0b522014-04-03 20:19:27 +0000449 const SDValue Ops[] = {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000450 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32),
451 SDValue(Lo, 0), CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
452 SDValue(Hi, 0), CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32)
Tom Stellard7ed0b522014-04-03 20:19:27 +0000453 };
454
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000455 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
Tom Stellard7ed0b522014-04-03 20:19:27 +0000456 N->getValueType(0), Ops);
457 }
458
Tom Stellard20f6c072015-01-23 22:05:45 +0000459 case ISD::LOAD: {
Tom Stellard381a94a2015-05-12 15:00:49 +0000460 LoadSDNode *LD = cast<LoadSDNode>(N);
461 SDLoc SL(N);
462 EVT VT = N->getValueType(0);
463
464 if (VT != MVT::i64 || LD->getExtensionType() != ISD::NON_EXTLOAD) {
465 N = glueCopyToM0(N);
466 break;
467 }
468
Tom Stellard20f6c072015-01-23 22:05:45 +0000469 // To simplify the TableGen patters, we replace all i64 loads with
470 // v2i32 loads. Alternatively, we could promote i64 loads to v2i32
471 // during DAG legalization, however, so places (ExpandUnalignedLoad)
472 // in the DAG legalizer assume that if i64 is legal, so doing this
473 // promotion early can cause problems.
Tom Stellard20f6c072015-01-23 22:05:45 +0000474
475 SDValue NewLoad = CurDAG->getLoad(MVT::v2i32, SDLoc(N), LD->getChain(),
Tom Stellard381a94a2015-05-12 15:00:49 +0000476 LD->getBasePtr(), LD->getMemOperand());
477 SDValue BitCast = CurDAG->getNode(ISD::BITCAST, SL,
Tom Stellard20f6c072015-01-23 22:05:45 +0000478 MVT::i64, NewLoad);
479 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 1), NewLoad.getValue(1));
480 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), BitCast);
Tom Stellard381a94a2015-05-12 15:00:49 +0000481 SDNode *Load = glueCopyToM0(NewLoad.getNode());
482 SelectCode(Load);
Tom Stellard20f6c072015-01-23 22:05:45 +0000483 N = BitCast.getNode();
484 break;
485 }
486
Tom Stellard096b8c12015-02-04 20:49:49 +0000487 case ISD::STORE: {
488 // Handle i64 stores here for the same reason mentioned above for loads.
489 StoreSDNode *ST = cast<StoreSDNode>(N);
490 SDValue Value = ST->getValue();
Tom Stellard381a94a2015-05-12 15:00:49 +0000491 if (Value.getValueType() == MVT::i64 && !ST->isTruncatingStore()) {
Tom Stellard096b8c12015-02-04 20:49:49 +0000492
Tom Stellard381a94a2015-05-12 15:00:49 +0000493 SDValue NewValue = CurDAG->getNode(ISD::BITCAST, SDLoc(N),
494 MVT::v2i32, Value);
495 SDValue NewStore = CurDAG->getStore(ST->getChain(), SDLoc(N), NewValue,
496 ST->getBasePtr(), ST->getMemOperand());
Tom Stellard096b8c12015-02-04 20:49:49 +0000497
Tom Stellard381a94a2015-05-12 15:00:49 +0000498 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), NewStore);
Tom Stellard096b8c12015-02-04 20:49:49 +0000499
Tom Stellard381a94a2015-05-12 15:00:49 +0000500 if (NewValue.getOpcode() == ISD::BITCAST) {
501 Select(NewStore.getNode());
502 return SelectCode(NewValue.getNode());
503 }
504
505 // getNode() may fold the bitcast if its input was another bitcast. If that
506 // happens we should only select the new store.
507 N = NewStore.getNode();
Tom Stellard096b8c12015-02-04 20:49:49 +0000508 }
509
Tom Stellard381a94a2015-05-12 15:00:49 +0000510 N = glueCopyToM0(N);
Tom Stellard096b8c12015-02-04 20:49:49 +0000511 break;
512 }
513
Tom Stellard81d871d2013-11-13 23:36:50 +0000514 case AMDGPUISD::REGISTER_LOAD: {
Eric Christopher7792e322015-01-30 23:24:40 +0000515 if (Subtarget->getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
Tom Stellard81d871d2013-11-13 23:36:50 +0000516 break;
517 SDValue Addr, Offset;
518
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000519 SDLoc DL(N);
Tom Stellard81d871d2013-11-13 23:36:50 +0000520 SelectADDRIndirect(N->getOperand(1), Addr, Offset);
521 const SDValue Ops[] = {
522 Addr,
523 Offset,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000524 CurDAG->getTargetConstant(0, DL, MVT::i32),
Tom Stellard81d871d2013-11-13 23:36:50 +0000525 N->getOperand(0),
526 };
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000527 return CurDAG->getMachineNode(AMDGPU::SI_RegisterLoad, DL,
528 CurDAG->getVTList(MVT::i32, MVT::i64,
529 MVT::Other),
Tom Stellard81d871d2013-11-13 23:36:50 +0000530 Ops);
531 }
532 case AMDGPUISD::REGISTER_STORE: {
Eric Christopher7792e322015-01-30 23:24:40 +0000533 if (Subtarget->getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
Tom Stellard81d871d2013-11-13 23:36:50 +0000534 break;
535 SDValue Addr, Offset;
536 SelectADDRIndirect(N->getOperand(2), Addr, Offset);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000537 SDLoc DL(N);
Tom Stellard81d871d2013-11-13 23:36:50 +0000538 const SDValue Ops[] = {
539 N->getOperand(1),
540 Addr,
541 Offset,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000542 CurDAG->getTargetConstant(0, DL, MVT::i32),
Tom Stellard81d871d2013-11-13 23:36:50 +0000543 N->getOperand(0),
544 };
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000545 return CurDAG->getMachineNode(AMDGPU::SI_RegisterStorePseudo, DL,
Tom Stellard81d871d2013-11-13 23:36:50 +0000546 CurDAG->getVTList(MVT::Other),
547 Ops);
548 }
Matt Arsenault78b86702014-04-18 05:19:26 +0000549
550 case AMDGPUISD::BFE_I32:
551 case AMDGPUISD::BFE_U32: {
Eric Christopher7792e322015-01-30 23:24:40 +0000552 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS)
Matt Arsenault78b86702014-04-18 05:19:26 +0000553 break;
554
555 // There is a scalar version available, but unlike the vector version which
556 // has a separate operand for the offset and width, the scalar version packs
557 // the width and offset into a single operand. Try to move to the scalar
558 // version if the offsets are constant, so that we can try to keep extended
559 // loads of kernel arguments in SGPRs.
560
561 // TODO: Technically we could try to pattern match scalar bitshifts of
562 // dynamic values, but it's probably not useful.
563 ConstantSDNode *Offset = dyn_cast<ConstantSDNode>(N->getOperand(1));
564 if (!Offset)
565 break;
566
567 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2));
568 if (!Width)
569 break;
570
571 bool Signed = Opc == AMDGPUISD::BFE_I32;
572
Matt Arsenault78b86702014-04-18 05:19:26 +0000573 uint32_t OffsetVal = Offset->getZExtValue();
574 uint32_t WidthVal = Width->getZExtValue();
575
Marek Olsak9b728682015-03-24 13:40:27 +0000576 return getS_BFE(Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32, SDLoc(N),
577 N->getOperand(0), OffsetVal, WidthVal);
Matt Arsenault78b86702014-04-18 05:19:26 +0000578
579 }
Matt Arsenaultf2b0aeb2014-06-23 18:28:28 +0000580 case AMDGPUISD::DIV_SCALE: {
581 return SelectDIV_SCALE(N);
582 }
Tom Stellard3457a842014-10-09 19:06:00 +0000583 case ISD::CopyToReg: {
584 const SITargetLowering& Lowering =
585 *static_cast<const SITargetLowering*>(getTargetLowering());
586 Lowering.legalizeTargetIndependentNode(N, *CurDAG);
587 break;
588 }
Matt Arsenault3f981402014-09-15 15:41:53 +0000589 case ISD::ADDRSPACECAST:
590 return SelectAddrSpaceCast(N);
Marek Olsak9b728682015-03-24 13:40:27 +0000591 case ISD::AND:
592 case ISD::SRL:
593 case ISD::SRA:
594 if (N->getValueType(0) != MVT::i32 ||
595 Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS)
596 break;
597
598 return SelectS_BFE(N);
Tom Stellard75aadc22012-12-11 21:25:42 +0000599 }
Tom Stellard3457a842014-10-09 19:06:00 +0000600
Vincent Lejeune0167a312013-09-12 23:45:00 +0000601 return SelectCode(N);
Tom Stellard365366f2013-01-23 02:09:06 +0000602}
603
Tom Stellard75aadc22012-12-11 21:25:42 +0000604
Matt Arsenault209a7b92014-04-18 07:40:20 +0000605bool AMDGPUDAGToDAGISel::checkType(const Value *Ptr, unsigned AS) {
606 assert(AS != 0 && "Use checkPrivateAddress instead.");
607 if (!Ptr)
Tom Stellard75aadc22012-12-11 21:25:42 +0000608 return false;
Matt Arsenault209a7b92014-04-18 07:40:20 +0000609
610 return Ptr->getType()->getPointerAddressSpace() == AS;
Tom Stellard75aadc22012-12-11 21:25:42 +0000611}
612
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000613bool AMDGPUDAGToDAGISel::checkPrivateAddress(const MachineMemOperand *Op) {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000614 if (Op->getPseudoValue())
615 return true;
616
617 if (PointerType *PT = dyn_cast<PointerType>(Op->getValue()->getType()))
618 return PT->getAddressSpace() == AMDGPUAS::PRIVATE_ADDRESS;
619
620 return false;
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000621}
622
Tom Stellard75aadc22012-12-11 21:25:42 +0000623bool AMDGPUDAGToDAGISel::isGlobalStore(const StoreSDNode *N) {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000624 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::GLOBAL_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000625}
626
627bool AMDGPUDAGToDAGISel::isPrivateStore(const StoreSDNode *N) {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000628 const Value *MemVal = N->getMemOperand()->getValue();
629 return (!checkType(MemVal, AMDGPUAS::LOCAL_ADDRESS) &&
630 !checkType(MemVal, AMDGPUAS::GLOBAL_ADDRESS) &&
631 !checkType(MemVal, AMDGPUAS::REGION_ADDRESS));
Tom Stellard75aadc22012-12-11 21:25:42 +0000632}
633
634bool AMDGPUDAGToDAGISel::isLocalStore(const StoreSDNode *N) {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000635 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::LOCAL_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000636}
637
Matt Arsenault3f981402014-09-15 15:41:53 +0000638bool AMDGPUDAGToDAGISel::isFlatStore(const StoreSDNode *N) {
639 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::FLAT_ADDRESS);
640}
641
Tom Stellard75aadc22012-12-11 21:25:42 +0000642bool AMDGPUDAGToDAGISel::isRegionStore(const StoreSDNode *N) {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000643 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::REGION_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000644}
645
Tom Stellard1e803092013-07-23 01:48:18 +0000646bool AMDGPUDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int CbId) const {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000647 const Value *MemVal = N->getMemOperand()->getValue();
648 if (CbId == -1)
649 return checkType(MemVal, AMDGPUAS::CONSTANT_ADDRESS);
650
651 return checkType(MemVal, AMDGPUAS::CONSTANT_BUFFER_0 + CbId);
Tom Stellard75aadc22012-12-11 21:25:42 +0000652}
653
Matt Arsenault2aabb062013-06-18 23:37:58 +0000654bool AMDGPUDAGToDAGISel::isGlobalLoad(const LoadSDNode *N) const {
Eric Christopher7792e322015-01-30 23:24:40 +0000655 if (N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS)
656 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS ||
657 N->getMemoryVT().bitsLT(MVT::i32))
Tom Stellard8cb0e472013-07-23 23:54:56 +0000658 return true;
Eric Christopher7792e322015-01-30 23:24:40 +0000659
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000660 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::GLOBAL_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000661}
662
Matt Arsenault2aabb062013-06-18 23:37:58 +0000663bool AMDGPUDAGToDAGISel::isParamLoad(const LoadSDNode *N) const {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000664 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::PARAM_I_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000665}
666
Matt Arsenault2aabb062013-06-18 23:37:58 +0000667bool AMDGPUDAGToDAGISel::isLocalLoad(const LoadSDNode *N) const {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000668 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::LOCAL_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000669}
670
Matt Arsenault3f981402014-09-15 15:41:53 +0000671bool AMDGPUDAGToDAGISel::isFlatLoad(const LoadSDNode *N) const {
672 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::FLAT_ADDRESS);
673}
674
Matt Arsenault2aabb062013-06-18 23:37:58 +0000675bool AMDGPUDAGToDAGISel::isRegionLoad(const LoadSDNode *N) const {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000676 return checkType(N->getMemOperand()->getValue(), AMDGPUAS::REGION_ADDRESS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000677}
678
Matt Arsenault2aabb062013-06-18 23:37:58 +0000679bool AMDGPUDAGToDAGISel::isCPLoad(const LoadSDNode *N) const {
Tom Stellard75aadc22012-12-11 21:25:42 +0000680 MachineMemOperand *MMO = N->getMemOperand();
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000681 if (checkPrivateAddress(N->getMemOperand())) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000682 if (MMO) {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000683 const PseudoSourceValue *PSV = MMO->getPseudoValue();
Tom Stellard75aadc22012-12-11 21:25:42 +0000684 if (PSV && PSV == PseudoSourceValue::getConstantPool()) {
685 return true;
686 }
687 }
688 }
689 return false;
690}
691
Matt Arsenault2aabb062013-06-18 23:37:58 +0000692bool AMDGPUDAGToDAGISel::isPrivateLoad(const LoadSDNode *N) const {
Nick Lewyckyaad475b2014-04-15 07:22:52 +0000693 if (checkPrivateAddress(N->getMemOperand())) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000694 // Check to make sure we are not a constant pool load or a constant load
695 // that is marked as a private load
696 if (isCPLoad(N) || isConstantLoad(N, -1)) {
697 return false;
698 }
699 }
Matt Arsenault209a7b92014-04-18 07:40:20 +0000700
701 const Value *MemVal = N->getMemOperand()->getValue();
702 if (!checkType(MemVal, AMDGPUAS::LOCAL_ADDRESS) &&
703 !checkType(MemVal, AMDGPUAS::GLOBAL_ADDRESS) &&
Matt Arsenault3f981402014-09-15 15:41:53 +0000704 !checkType(MemVal, AMDGPUAS::FLAT_ADDRESS) &&
Matt Arsenault209a7b92014-04-18 07:40:20 +0000705 !checkType(MemVal, AMDGPUAS::REGION_ADDRESS) &&
706 !checkType(MemVal, AMDGPUAS::CONSTANT_ADDRESS) &&
707 !checkType(MemVal, AMDGPUAS::PARAM_D_ADDRESS) &&
Matt Arsenault3f981402014-09-15 15:41:53 +0000708 !checkType(MemVal, AMDGPUAS::PARAM_I_ADDRESS)) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000709 return true;
710 }
711 return false;
712}
713
714const char *AMDGPUDAGToDAGISel::getPassName() const {
715 return "AMDGPU DAG->DAG Pattern Instruction Selection";
716}
717
718#ifdef DEBUGTMP
719#undef INT64_C
720#endif
721#undef DEBUGTMP
722
Tom Stellard41fc7852013-07-23 01:48:42 +0000723//===----------------------------------------------------------------------===//
724// Complex Patterns
725//===----------------------------------------------------------------------===//
Tom Stellard75aadc22012-12-11 21:25:42 +0000726
Tom Stellard365366f2013-01-23 02:09:06 +0000727bool AMDGPUDAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr,
Matt Arsenault209a7b92014-04-18 07:40:20 +0000728 SDValue& IntPtr) {
Tom Stellard365366f2013-01-23 02:09:06 +0000729 if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Addr)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000730 IntPtr = CurDAG->getIntPtrConstant(Cst->getZExtValue() / 4, SDLoc(Addr),
731 true);
Tom Stellard365366f2013-01-23 02:09:06 +0000732 return true;
733 }
734 return false;
735}
736
737bool AMDGPUDAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr,
738 SDValue& BaseReg, SDValue &Offset) {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000739 if (!isa<ConstantSDNode>(Addr)) {
Tom Stellard365366f2013-01-23 02:09:06 +0000740 BaseReg = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000741 Offset = CurDAG->getIntPtrConstant(0, SDLoc(Addr), true);
Tom Stellard365366f2013-01-23 02:09:06 +0000742 return true;
743 }
744 return false;
745}
746
Tom Stellard75aadc22012-12-11 21:25:42 +0000747bool AMDGPUDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
748 SDValue &Offset) {
Matt Arsenault209a7b92014-04-18 07:40:20 +0000749 ConstantSDNode *IMMOffset;
Tom Stellard75aadc22012-12-11 21:25:42 +0000750
751 if (Addr.getOpcode() == ISD::ADD
752 && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
753 && isInt<16>(IMMOffset->getZExtValue())) {
754
755 Base = Addr.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000756 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr),
757 MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000758 return true;
759 // If the pointer address is constant, we can move it to the offset field.
760 } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr))
761 && isInt<16>(IMMOffset->getZExtValue())) {
762 Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
Andrew Trickef9de2a2013-05-25 02:42:55 +0000763 SDLoc(CurDAG->getEntryNode()),
Tom Stellard75aadc22012-12-11 21:25:42 +0000764 AMDGPU::ZERO, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000765 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr),
766 MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000767 return true;
768 }
769
770 // Default case, no offset
771 Base = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000772 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
Tom Stellard75aadc22012-12-11 21:25:42 +0000773 return true;
774}
775
Tom Stellardf3b2a1e2013-02-06 17:32:29 +0000776bool AMDGPUDAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base,
777 SDValue &Offset) {
778 ConstantSDNode *C;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000779 SDLoc DL(Addr);
Tom Stellardf3b2a1e2013-02-06 17:32:29 +0000780
781 if ((C = dyn_cast<ConstantSDNode>(Addr))) {
782 Base = CurDAG->getRegister(AMDGPU::INDIRECT_BASE_ADDR, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000783 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
Tom Stellardf3b2a1e2013-02-06 17:32:29 +0000784 } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) &&
785 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) {
786 Base = Addr.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000787 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
Tom Stellardf3b2a1e2013-02-06 17:32:29 +0000788 } else {
789 Base = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000790 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellardf3b2a1e2013-02-06 17:32:29 +0000791 }
792
793 return true;
794}
Christian Konigd910b7d2013-02-26 17:52:16 +0000795
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000796SDNode *AMDGPUDAGToDAGISel::SelectADD_SUB_I64(SDNode *N) {
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000797 SDLoc DL(N);
798 SDValue LHS = N->getOperand(0);
799 SDValue RHS = N->getOperand(1);
800
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000801 bool IsAdd = (N->getOpcode() == ISD::ADD);
802
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000803 SDValue Sub0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32);
804 SDValue Sub1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32);
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000805
806 SDNode *Lo0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
807 DL, MVT::i32, LHS, Sub0);
808 SDNode *Hi0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
809 DL, MVT::i32, LHS, Sub1);
810
811 SDNode *Lo1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
812 DL, MVT::i32, RHS, Sub0);
813 SDNode *Hi1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
814 DL, MVT::i32, RHS, Sub1);
815
816 SDVTList VTList = CurDAG->getVTList(MVT::i32, MVT::Glue);
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000817 SDValue AddLoArgs[] = { SDValue(Lo0, 0), SDValue(Lo1, 0) };
818
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000819
Tom Stellard80942a12014-09-05 14:07:59 +0000820 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000821 unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
822
Matt Arsenaultb8b51532014-06-23 18:00:38 +0000823 SDNode *AddLo = CurDAG->getMachineNode( Opc, DL, VTList, AddLoArgs);
824 SDValue Carry(AddLo, 1);
825 SDNode *AddHi
826 = CurDAG->getMachineNode(CarryOpc, DL, MVT::i32,
827 SDValue(Hi0, 0), SDValue(Hi1, 0), Carry);
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000828
829 SDValue Args[5] = {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000830 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32),
Matt Arsenault9fa3f932014-06-23 18:00:34 +0000831 SDValue(AddLo,0),
832 Sub0,
833 SDValue(AddHi,0),
834 Sub1,
835 };
836 return CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, MVT::i64, Args);
837}
838
Matt Arsenault044f1d12015-02-14 04:24:28 +0000839// We need to handle this here because tablegen doesn't support matching
840// instructions with multiple outputs.
Matt Arsenaultf2b0aeb2014-06-23 18:28:28 +0000841SDNode *AMDGPUDAGToDAGISel::SelectDIV_SCALE(SDNode *N) {
842 SDLoc SL(N);
843 EVT VT = N->getValueType(0);
844
845 assert(VT == MVT::f32 || VT == MVT::f64);
846
847 unsigned Opc
848 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64 : AMDGPU::V_DIV_SCALE_F32;
849
Matt Arsenault044f1d12015-02-14 04:24:28 +0000850 // src0_modifiers, src0, src1_modifiers, src1, src2_modifiers, src2, clamp, omod
851 SDValue Ops[8];
Matt Arsenaultf2b0aeb2014-06-23 18:28:28 +0000852
Matt Arsenault044f1d12015-02-14 04:24:28 +0000853 SelectVOP3Mods0(N->getOperand(0), Ops[1], Ops[0], Ops[6], Ops[7]);
854 SelectVOP3Mods(N->getOperand(1), Ops[3], Ops[2]);
855 SelectVOP3Mods(N->getOperand(2), Ops[5], Ops[4]);
Matt Arsenaultf2b0aeb2014-06-23 18:28:28 +0000856 return CurDAG->SelectNodeTo(N, Opc, VT, MVT::i1, Ops);
857}
858
Tom Stellard85e8b6d2014-08-22 18:49:33 +0000859bool AMDGPUDAGToDAGISel::isDSOffsetLegal(const SDValue &Base, unsigned Offset,
860 unsigned OffsetBits) const {
Tom Stellard85e8b6d2014-08-22 18:49:33 +0000861 if ((OffsetBits == 16 && !isUInt<16>(Offset)) ||
862 (OffsetBits == 8 && !isUInt<8>(Offset)))
863 return false;
864
Matt Arsenault706f9302015-07-06 16:01:58 +0000865 if (Subtarget->getGeneration() >= AMDGPUSubtarget::SEA_ISLANDS ||
866 Subtarget->unsafeDSOffsetFoldingEnabled())
Tom Stellard85e8b6d2014-08-22 18:49:33 +0000867 return true;
868
869 // On Southern Islands instruction with a negative base value and an offset
870 // don't seem to work.
871 return CurDAG->SignBitIsZero(Base);
872}
873
874bool AMDGPUDAGToDAGISel::SelectDS1Addr1Offset(SDValue Addr, SDValue &Base,
875 SDValue &Offset) const {
876 if (CurDAG->isBaseWithConstantOffset(Addr)) {
877 SDValue N0 = Addr.getOperand(0);
878 SDValue N1 = Addr.getOperand(1);
879 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
880 if (isDSOffsetLegal(N0, C1->getSExtValue(), 16)) {
881 // (add n0, c0)
882 Base = N0;
883 Offset = N1;
884 return true;
885 }
886 }
887
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000888 SDLoc DL(Addr);
889
Matt Arsenaulte775f5f2014-10-14 17:21:19 +0000890 // If we have a constant address, prefer to put the constant into the
891 // offset. This can save moves to load the constant address since multiple
892 // operations can share the zero base address register, and enables merging
893 // into read2 / write2 instructions.
894 if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) {
895 if (isUInt<16>(CAddr->getZExtValue())) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000896 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellardc8d79202014-10-15 21:08:59 +0000897 MachineSDNode *MovZero = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000898 DL, MVT::i32, Zero);
Tom Stellardc8d79202014-10-15 21:08:59 +0000899 Base = SDValue(MovZero, 0);
Matt Arsenaulte775f5f2014-10-14 17:21:19 +0000900 Offset = Addr;
901 return true;
902 }
903 }
904
Tom Stellard85e8b6d2014-08-22 18:49:33 +0000905 // default case
906 Base = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000907 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
Tom Stellard85e8b6d2014-08-22 18:49:33 +0000908 return true;
909}
910
Tom Stellardf3fc5552014-08-22 18:49:35 +0000911bool AMDGPUDAGToDAGISel::SelectDS64Bit4ByteAligned(SDValue Addr, SDValue &Base,
912 SDValue &Offset0,
913 SDValue &Offset1) const {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000914 SDLoc DL(Addr);
915
Tom Stellardf3fc5552014-08-22 18:49:35 +0000916 if (CurDAG->isBaseWithConstantOffset(Addr)) {
917 SDValue N0 = Addr.getOperand(0);
918 SDValue N1 = Addr.getOperand(1);
919 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
920 unsigned DWordOffset0 = C1->getZExtValue() / 4;
921 unsigned DWordOffset1 = DWordOffset0 + 1;
922 // (add n0, c0)
923 if (isDSOffsetLegal(N0, DWordOffset1, 8)) {
924 Base = N0;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000925 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8);
926 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8);
Tom Stellardf3fc5552014-08-22 18:49:35 +0000927 return true;
928 }
929 }
930
Matt Arsenault1a74aff2014-10-15 18:06:43 +0000931 if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) {
932 unsigned DWordOffset0 = CAddr->getZExtValue() / 4;
933 unsigned DWordOffset1 = DWordOffset0 + 1;
934 assert(4 * DWordOffset0 == CAddr->getZExtValue());
935
936 if (isUInt<8>(DWordOffset0) && isUInt<8>(DWordOffset1)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000937 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
Matt Arsenault1a74aff2014-10-15 18:06:43 +0000938 MachineSDNode *MovZero
939 = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000940 DL, MVT::i32, Zero);
Matt Arsenault1a74aff2014-10-15 18:06:43 +0000941 Base = SDValue(MovZero, 0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000942 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8);
943 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8);
Matt Arsenault1a74aff2014-10-15 18:06:43 +0000944 return true;
945 }
946 }
947
Tom Stellardf3fc5552014-08-22 18:49:35 +0000948 // default case
949 Base = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000950 Offset0 = CurDAG->getTargetConstant(0, DL, MVT::i8);
951 Offset1 = CurDAG->getTargetConstant(1, DL, MVT::i8);
Tom Stellardf3fc5552014-08-22 18:49:35 +0000952 return true;
953}
954
Tom Stellardb02094e2014-07-21 15:45:01 +0000955static bool isLegalMUBUFImmOffset(const ConstantSDNode *Imm) {
956 return isUInt<12>(Imm->getZExtValue());
957}
958
Tom Stellard155bbb72014-08-11 22:18:17 +0000959void AMDGPUDAGToDAGISel::SelectMUBUF(SDValue Addr, SDValue &Ptr,
960 SDValue &VAddr, SDValue &SOffset,
961 SDValue &Offset, SDValue &Offen,
962 SDValue &Idxen, SDValue &Addr64,
963 SDValue &GLC, SDValue &SLC,
964 SDValue &TFE) const {
Tom Stellardb02c2682014-06-24 23:33:07 +0000965 SDLoc DL(Addr);
966
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000967 GLC = CurDAG->getTargetConstant(0, DL, MVT::i1);
968 SLC = CurDAG->getTargetConstant(0, DL, MVT::i1);
969 TFE = CurDAG->getTargetConstant(0, DL, MVT::i1);
Tom Stellard155bbb72014-08-11 22:18:17 +0000970
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000971 Idxen = CurDAG->getTargetConstant(0, DL, MVT::i1);
972 Offen = CurDAG->getTargetConstant(0, DL, MVT::i1);
973 Addr64 = CurDAG->getTargetConstant(0, DL, MVT::i1);
974 SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellard155bbb72014-08-11 22:18:17 +0000975
Tom Stellardb02c2682014-06-24 23:33:07 +0000976 if (CurDAG->isBaseWithConstantOffset(Addr)) {
977 SDValue N0 = Addr.getOperand(0);
978 SDValue N1 = Addr.getOperand(1);
979 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
980
Tom Stellard94b72312015-02-11 00:34:35 +0000981 if (N0.getOpcode() == ISD::ADD) {
982 // (add (add N2, N3), C1) -> addr64
983 SDValue N2 = N0.getOperand(0);
984 SDValue N3 = N0.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000985 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1);
Tom Stellard94b72312015-02-11 00:34:35 +0000986 Ptr = N2;
987 VAddr = N3;
988 } else {
Tom Stellardb02c2682014-06-24 23:33:07 +0000989
Tom Stellard155bbb72014-08-11 22:18:17 +0000990 // (add N0, C1) -> offset
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000991 VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellard155bbb72014-08-11 22:18:17 +0000992 Ptr = N0;
Tom Stellard94b72312015-02-11 00:34:35 +0000993 }
994
995 if (isLegalMUBUFImmOffset(C1)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000996 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16);
Tom Stellard94b72312015-02-11 00:34:35 +0000997 return;
998 } else if (isUInt<32>(C1->getZExtValue())) {
999 // Illegal offset, store it in soffset.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001000 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
Tom Stellard94b72312015-02-11 00:34:35 +00001001 SOffset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001002 CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32)),
1003 0);
Tom Stellard155bbb72014-08-11 22:18:17 +00001004 return;
Tom Stellardb02c2682014-06-24 23:33:07 +00001005 }
1006 }
Tom Stellard94b72312015-02-11 00:34:35 +00001007
Tom Stellardb02c2682014-06-24 23:33:07 +00001008 if (Addr.getOpcode() == ISD::ADD) {
Tom Stellard155bbb72014-08-11 22:18:17 +00001009 // (add N0, N1) -> addr64
Tom Stellardb02c2682014-06-24 23:33:07 +00001010 SDValue N0 = Addr.getOperand(0);
1011 SDValue N1 = Addr.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001012 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1);
Tom Stellard155bbb72014-08-11 22:18:17 +00001013 Ptr = N0;
1014 VAddr = N1;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001015 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
Tom Stellard155bbb72014-08-11 22:18:17 +00001016 return;
Tom Stellardb02c2682014-06-24 23:33:07 +00001017 }
1018
Tom Stellard155bbb72014-08-11 22:18:17 +00001019 // default case -> offset
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001020 VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellard155bbb72014-08-11 22:18:17 +00001021 Ptr = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001022 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
Tom Stellard155bbb72014-08-11 22:18:17 +00001023
1024}
1025
1026bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
Tom Stellardc53861a2015-02-11 00:34:32 +00001027 SDValue &VAddr, SDValue &SOffset,
Tom Stellard1f9939f2015-02-27 14:59:41 +00001028 SDValue &Offset, SDValue &GLC,
1029 SDValue &SLC, SDValue &TFE) const {
1030 SDValue Ptr, Offen, Idxen, Addr64;
Tom Stellard155bbb72014-08-11 22:18:17 +00001031
1032 SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64,
1033 GLC, SLC, TFE);
1034
1035 ConstantSDNode *C = cast<ConstantSDNode>(Addr64);
1036 if (C->getSExtValue()) {
1037 SDLoc DL(Addr);
Matt Arsenault485defe2014-11-05 19:01:17 +00001038
1039 const SITargetLowering& Lowering =
1040 *static_cast<const SITargetLowering*>(getTargetLowering());
1041
1042 SRsrc = SDValue(Lowering.wrapAddr64Rsrc(*CurDAG, DL, Ptr), 0);
Tom Stellard155bbb72014-08-11 22:18:17 +00001043 return true;
1044 }
Matt Arsenault485defe2014-11-05 19:01:17 +00001045
Tom Stellard155bbb72014-08-11 22:18:17 +00001046 return false;
1047}
1048
Tom Stellard7980fc82014-09-25 18:30:26 +00001049bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
Tom Stellardc53861a2015-02-11 00:34:32 +00001050 SDValue &VAddr, SDValue &SOffset,
1051 SDValue &Offset,
1052 SDValue &SLC) const {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001053 SLC = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i1);
Tom Stellard1f9939f2015-02-27 14:59:41 +00001054 SDValue GLC, TFE;
Tom Stellard7980fc82014-09-25 18:30:26 +00001055
Tom Stellard1f9939f2015-02-27 14:59:41 +00001056 return SelectMUBUFAddr64(Addr, SRsrc, VAddr, SOffset, Offset, GLC, SLC, TFE);
Tom Stellard7980fc82014-09-25 18:30:26 +00001057}
1058
Tom Stellardb02094e2014-07-21 15:45:01 +00001059bool AMDGPUDAGToDAGISel::SelectMUBUFScratch(SDValue Addr, SDValue &Rsrc,
1060 SDValue &VAddr, SDValue &SOffset,
1061 SDValue &ImmOffset) const {
1062
1063 SDLoc DL(Addr);
1064 MachineFunction &MF = CurDAG->getMachineFunction();
Eric Christopherfc6de422014-08-05 02:39:49 +00001065 const SIRegisterInfo *TRI =
Eric Christopher7792e322015-01-30 23:24:40 +00001066 static_cast<const SIRegisterInfo *>(Subtarget->getRegisterInfo());
Tom Stellardb02094e2014-07-21 15:45:01 +00001067 MachineRegisterInfo &MRI = MF.getRegInfo();
Tom Stellard162a9472014-08-21 20:40:58 +00001068 const SITargetLowering& Lowering =
1069 *static_cast<const SITargetLowering*>(getTargetLowering());
Tom Stellardb02094e2014-07-21 15:45:01 +00001070
Tom Stellardb02094e2014-07-21 15:45:01 +00001071 unsigned ScratchOffsetReg =
1072 TRI->getPreloadedValue(MF, SIRegisterInfo::SCRATCH_WAVE_OFFSET);
Tom Stellard162a9472014-08-21 20:40:58 +00001073 Lowering.CreateLiveInRegister(*CurDAG, &AMDGPU::SReg_32RegClass,
1074 ScratchOffsetReg, MVT::i32);
Tom Stellard95292bb2015-01-20 17:49:47 +00001075 SDValue Sym0 = CurDAG->getExternalSymbol("SCRATCH_RSRC_DWORD0", MVT::i32);
1076 SDValue ScratchRsrcDword0 =
1077 SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, Sym0), 0);
Tom Stellardb02094e2014-07-21 15:45:01 +00001078
Tom Stellard95292bb2015-01-20 17:49:47 +00001079 SDValue Sym1 = CurDAG->getExternalSymbol("SCRATCH_RSRC_DWORD1", MVT::i32);
1080 SDValue ScratchRsrcDword1 =
1081 SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, Sym1), 0);
1082
1083 const SDValue RsrcOps[] = {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001084 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32),
Tom Stellard95292bb2015-01-20 17:49:47 +00001085 ScratchRsrcDword0,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001086 CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
Tom Stellard95292bb2015-01-20 17:49:47 +00001087 ScratchRsrcDword1,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001088 CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32),
Tom Stellard95292bb2015-01-20 17:49:47 +00001089 };
1090 SDValue ScratchPtr = SDValue(CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, DL,
1091 MVT::v2i32, RsrcOps), 0);
Matt Arsenaultf3cd4512014-11-05 19:01:19 +00001092 Rsrc = SDValue(Lowering.buildScratchRSRC(*CurDAG, DL, ScratchPtr), 0);
Tom Stellardb02094e2014-07-21 15:45:01 +00001093 SOffset = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
1094 MRI.getLiveInVirtReg(ScratchOffsetReg), MVT::i32);
1095
1096 // (add n0, c1)
1097 if (CurDAG->isBaseWithConstantOffset(Addr)) {
1098 SDValue N1 = Addr.getOperand(1);
1099 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
1100
1101 if (isLegalMUBUFImmOffset(C1)) {
1102 VAddr = Addr.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001103 ImmOffset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16);
Tom Stellardb02094e2014-07-21 15:45:01 +00001104 return true;
1105 }
1106 }
1107
Tom Stellardb02094e2014-07-21 15:45:01 +00001108 // (node)
1109 VAddr = Addr;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001110 ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i16);
Tom Stellardb02094e2014-07-21 15:45:01 +00001111 return true;
1112}
1113
Tom Stellard155bbb72014-08-11 22:18:17 +00001114bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc,
1115 SDValue &SOffset, SDValue &Offset,
1116 SDValue &GLC, SDValue &SLC,
1117 SDValue &TFE) const {
1118 SDValue Ptr, VAddr, Offen, Idxen, Addr64;
Tom Stellard794c8c02014-12-02 17:05:41 +00001119 const SIInstrInfo *TII =
Eric Christopher7792e322015-01-30 23:24:40 +00001120 static_cast<const SIInstrInfo *>(Subtarget->getInstrInfo());
Tom Stellardb02094e2014-07-21 15:45:01 +00001121
Tom Stellard155bbb72014-08-11 22:18:17 +00001122 SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64,
1123 GLC, SLC, TFE);
Tom Stellardb02094e2014-07-21 15:45:01 +00001124
Tom Stellard155bbb72014-08-11 22:18:17 +00001125 if (!cast<ConstantSDNode>(Offen)->getSExtValue() &&
1126 !cast<ConstantSDNode>(Idxen)->getSExtValue() &&
1127 !cast<ConstantSDNode>(Addr64)->getSExtValue()) {
Tom Stellard794c8c02014-12-02 17:05:41 +00001128 uint64_t Rsrc = TII->getDefaultRsrcDataFormat() |
Tom Stellard155bbb72014-08-11 22:18:17 +00001129 APInt::getAllOnesValue(32).getZExtValue(); // Size
1130 SDLoc DL(Addr);
Matt Arsenaultf3cd4512014-11-05 19:01:19 +00001131
1132 const SITargetLowering& Lowering =
1133 *static_cast<const SITargetLowering*>(getTargetLowering());
1134
1135 SRsrc = SDValue(Lowering.buildRSRC(*CurDAG, DL, Ptr, 0, Rsrc), 0);
Tom Stellard155bbb72014-08-11 22:18:17 +00001136 return true;
1137 }
1138 return false;
Tom Stellardb02094e2014-07-21 15:45:01 +00001139}
1140
Tom Stellard7980fc82014-09-25 18:30:26 +00001141bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc,
1142 SDValue &Soffset, SDValue &Offset,
1143 SDValue &GLC) const {
1144 SDValue SLC, TFE;
1145
1146 return SelectMUBUFOffset(Addr, SRsrc, Soffset, Offset, GLC, SLC, TFE);
1147}
1148
Matt Arsenault3f981402014-09-15 15:41:53 +00001149// FIXME: This is incorrect and only enough to be able to compile.
1150SDNode *AMDGPUDAGToDAGISel::SelectAddrSpaceCast(SDNode *N) {
1151 AddrSpaceCastSDNode *ASC = cast<AddrSpaceCastSDNode>(N);
1152 SDLoc DL(N);
1153
Eric Christopher7792e322015-01-30 23:24:40 +00001154 assert(Subtarget->hasFlatAddressSpace() &&
Matt Arsenault3f981402014-09-15 15:41:53 +00001155 "addrspacecast only supported with flat address space!");
1156
1157 assert((ASC->getSrcAddressSpace() != AMDGPUAS::CONSTANT_ADDRESS &&
1158 ASC->getDestAddressSpace() != AMDGPUAS::CONSTANT_ADDRESS) &&
1159 "Cannot cast address space to / from constant address!");
1160
1161 assert((ASC->getSrcAddressSpace() == AMDGPUAS::FLAT_ADDRESS ||
1162 ASC->getDestAddressSpace() == AMDGPUAS::FLAT_ADDRESS) &&
1163 "Can only cast to / from flat address space!");
1164
1165 // The flat instructions read the address as the index of the VGPR holding the
1166 // address, so casting should just be reinterpreting the base VGPR, so just
1167 // insert trunc / bitcast / zext.
1168
1169 SDValue Src = ASC->getOperand(0);
1170 EVT DestVT = ASC->getValueType(0);
1171 EVT SrcVT = Src.getValueType();
1172
1173 unsigned SrcSize = SrcVT.getSizeInBits();
1174 unsigned DestSize = DestVT.getSizeInBits();
1175
1176 if (SrcSize > DestSize) {
1177 assert(SrcSize == 64 && DestSize == 32);
1178 return CurDAG->getMachineNode(
1179 TargetOpcode::EXTRACT_SUBREG,
1180 DL,
1181 DestVT,
1182 Src,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001183 CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32));
Matt Arsenault3f981402014-09-15 15:41:53 +00001184 }
1185
1186
1187 if (DestSize > SrcSize) {
1188 assert(SrcSize == 32 && DestSize == 64);
1189
Tom Stellardb6550522015-01-12 19:33:18 +00001190 // FIXME: This is probably wrong, we should never be defining
1191 // a register class with both VGPRs and SGPRs
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001192 SDValue RC = CurDAG->getTargetConstant(AMDGPU::VS_64RegClassID, DL,
1193 MVT::i32);
Matt Arsenault3f981402014-09-15 15:41:53 +00001194
1195 const SDValue Ops[] = {
1196 RC,
1197 Src,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001198 CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
1199 SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
1200 CurDAG->getConstant(0, DL, MVT::i32)), 0),
1201 CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32)
Matt Arsenault3f981402014-09-15 15:41:53 +00001202 };
1203
1204 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001205 DL, N->getValueType(0), Ops);
Matt Arsenault3f981402014-09-15 15:41:53 +00001206 }
1207
1208 assert(SrcSize == 64 && DestSize == 64);
1209 return CurDAG->getNode(ISD::BITCAST, DL, DestVT, Src).getNode();
1210}
1211
Marek Olsak9b728682015-03-24 13:40:27 +00001212SDNode *AMDGPUDAGToDAGISel::getS_BFE(unsigned Opcode, SDLoc DL, SDValue Val,
1213 uint32_t Offset, uint32_t Width) {
1214 // Transformation function, pack the offset and width of a BFE into
1215 // the format expected by the S_BFE_I32 / S_BFE_U32. In the second
1216 // source, bits [5:0] contain the offset and bits [22:16] the width.
1217 uint32_t PackedVal = Offset | (Width << 16);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001218 SDValue PackedConst = CurDAG->getTargetConstant(PackedVal, DL, MVT::i32);
Marek Olsak9b728682015-03-24 13:40:27 +00001219
1220 return CurDAG->getMachineNode(Opcode, DL, MVT::i32, Val, PackedConst);
1221}
1222
1223SDNode *AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(SDNode *N) {
1224 // "(a << b) srl c)" ---> "BFE_U32 a, (c-b), (32-c)
1225 // "(a << b) sra c)" ---> "BFE_I32 a, (c-b), (32-c)
1226 // Predicate: 0 < b <= c < 32
1227
1228 const SDValue &Shl = N->getOperand(0);
1229 ConstantSDNode *B = dyn_cast<ConstantSDNode>(Shl->getOperand(1));
1230 ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1));
1231
1232 if (B && C) {
1233 uint32_t BVal = B->getZExtValue();
1234 uint32_t CVal = C->getZExtValue();
1235
1236 if (0 < BVal && BVal <= CVal && CVal < 32) {
1237 bool Signed = N->getOpcode() == ISD::SRA;
1238 unsigned Opcode = Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
1239
1240 return getS_BFE(Opcode, SDLoc(N), Shl.getOperand(0),
1241 CVal - BVal, 32 - CVal);
1242 }
1243 }
1244 return SelectCode(N);
1245}
1246
1247SDNode *AMDGPUDAGToDAGISel::SelectS_BFE(SDNode *N) {
1248 switch (N->getOpcode()) {
1249 case ISD::AND:
1250 if (N->getOperand(0).getOpcode() == ISD::SRL) {
1251 // "(a srl b) & mask" ---> "BFE_U32 a, b, popcount(mask)"
1252 // Predicate: isMask(mask)
1253 const SDValue &Srl = N->getOperand(0);
1254 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(Srl.getOperand(1));
1255 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(N->getOperand(1));
1256
1257 if (Shift && Mask) {
1258 uint32_t ShiftVal = Shift->getZExtValue();
1259 uint32_t MaskVal = Mask->getZExtValue();
1260
1261 if (isMask_32(MaskVal)) {
1262 uint32_t WidthVal = countPopulation(MaskVal);
1263
1264 return getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N), Srl.getOperand(0),
1265 ShiftVal, WidthVal);
1266 }
1267 }
1268 }
1269 break;
1270 case ISD::SRL:
1271 if (N->getOperand(0).getOpcode() == ISD::AND) {
1272 // "(a & mask) srl b)" ---> "BFE_U32 a, b, popcount(mask >> b)"
1273 // Predicate: isMask(mask >> b)
1274 const SDValue &And = N->getOperand(0);
1275 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N->getOperand(1));
1276 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(And->getOperand(1));
1277
1278 if (Shift && Mask) {
1279 uint32_t ShiftVal = Shift->getZExtValue();
1280 uint32_t MaskVal = Mask->getZExtValue() >> ShiftVal;
1281
1282 if (isMask_32(MaskVal)) {
1283 uint32_t WidthVal = countPopulation(MaskVal);
1284
1285 return getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N), And.getOperand(0),
1286 ShiftVal, WidthVal);
1287 }
1288 }
1289 } else if (N->getOperand(0).getOpcode() == ISD::SHL)
1290 return SelectS_BFEFromShifts(N);
1291 break;
1292 case ISD::SRA:
1293 if (N->getOperand(0).getOpcode() == ISD::SHL)
1294 return SelectS_BFEFromShifts(N);
1295 break;
1296 }
1297
1298 return SelectCode(N);
1299}
1300
Tom Stellardb4a313a2014-08-01 00:32:39 +00001301bool AMDGPUDAGToDAGISel::SelectVOP3Mods(SDValue In, SDValue &Src,
1302 SDValue &SrcMods) const {
1303
1304 unsigned Mods = 0;
1305
1306 Src = In;
1307
1308 if (Src.getOpcode() == ISD::FNEG) {
1309 Mods |= SISrcMods::NEG;
1310 Src = Src.getOperand(0);
1311 }
1312
1313 if (Src.getOpcode() == ISD::FABS) {
1314 Mods |= SISrcMods::ABS;
1315 Src = Src.getOperand(0);
1316 }
1317
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001318 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
Tom Stellardb4a313a2014-08-01 00:32:39 +00001319
1320 return true;
1321}
1322
Tom Stellarddb5a11f2015-07-13 15:47:57 +00001323bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(SDValue In, SDValue &Src,
1324 SDValue &SrcMods) const {
1325 bool Res = SelectVOP3Mods(In, Src, SrcMods);
1326 return Res && cast<ConstantSDNode>(SrcMods)->isNullValue();
1327}
1328
Tom Stellardb4a313a2014-08-01 00:32:39 +00001329bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(SDValue In, SDValue &Src,
1330 SDValue &SrcMods, SDValue &Clamp,
1331 SDValue &Omod) const {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001332 SDLoc DL(In);
Tom Stellardb4a313a2014-08-01 00:32:39 +00001333 // FIXME: Handle Clamp and Omod
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001334 Clamp = CurDAG->getTargetConstant(0, DL, MVT::i32);
1335 Omod = CurDAG->getTargetConstant(0, DL, MVT::i32);
Tom Stellardb4a313a2014-08-01 00:32:39 +00001336
1337 return SelectVOP3Mods(In, Src, SrcMods);
1338}
1339
Tom Stellarddb5a11f2015-07-13 15:47:57 +00001340bool AMDGPUDAGToDAGISel::SelectVOP3NoMods0(SDValue In, SDValue &Src,
1341 SDValue &SrcMods, SDValue &Clamp,
1342 SDValue &Omod) const {
1343 bool Res = SelectVOP3Mods0(In, Src, SrcMods, Clamp, Omod);
1344
1345 return Res && cast<ConstantSDNode>(SrcMods)->isNullValue() &&
1346 cast<ConstantSDNode>(Clamp)->isNullValue() &&
1347 cast<ConstantSDNode>(Omod)->isNullValue();
1348}
1349
Matt Arsenault1cffa4c2014-11-13 19:49:04 +00001350bool AMDGPUDAGToDAGISel::SelectVOP3Mods0Clamp(SDValue In, SDValue &Src,
1351 SDValue &SrcMods,
1352 SDValue &Omod) const {
1353 // FIXME: Handle Omod
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001354 Omod = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32);
Matt Arsenault1cffa4c2014-11-13 19:49:04 +00001355
1356 return SelectVOP3Mods(In, Src, SrcMods);
1357}
1358
Matt Arsenault4831ce52015-01-06 23:00:37 +00001359bool AMDGPUDAGToDAGISel::SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src,
1360 SDValue &SrcMods,
1361 SDValue &Clamp,
1362 SDValue &Omod) const {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001363 Clamp = Omod = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32);
Matt Arsenault4831ce52015-01-06 23:00:37 +00001364 return SelectVOP3Mods(In, Src, SrcMods);
1365}
1366
Christian Konigd910b7d2013-02-26 17:52:16 +00001367void AMDGPUDAGToDAGISel::PostprocessISelDAG() {
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001368 const AMDGPUTargetLowering& Lowering =
Matt Arsenault209a7b92014-04-18 07:40:20 +00001369 *static_cast<const AMDGPUTargetLowering*>(getTargetLowering());
Vincent Lejeuneab3baf82013-09-12 23:44:44 +00001370 bool IsModified = false;
1371 do {
1372 IsModified = false;
1373 // Go over all selected nodes and try to fold them a bit more
Pete Cooper65c69402015-07-14 22:10:54 +00001374 for (SDNode &Node : CurDAG->allnodes()) {
1375 MachineSDNode *MachineNode = dyn_cast<MachineSDNode>(&Node);
Vincent Lejeuneab3baf82013-09-12 23:44:44 +00001376 if (!MachineNode)
1377 continue;
Christian Konigd910b7d2013-02-26 17:52:16 +00001378
Vincent Lejeuneab3baf82013-09-12 23:44:44 +00001379 SDNode *ResNode = Lowering.PostISelFolding(MachineNode, *CurDAG);
Pete Cooper65c69402015-07-14 22:10:54 +00001380 if (ResNode != &Node) {
1381 ReplaceUses(&Node, ResNode);
Vincent Lejeuneab3baf82013-09-12 23:44:44 +00001382 IsModified = true;
1383 }
Tom Stellard2183b702013-06-03 17:39:46 +00001384 }
Vincent Lejeuneab3baf82013-09-12 23:44:44 +00001385 CurDAG->RemoveDeadNodes();
1386 } while (IsModified);
Christian Konigd910b7d2013-02-26 17:52:16 +00001387}