blob: 60dba1a063ace862ba604efcaee82abc805199dc [file] [log] [blame]
Tom Stellard75aadc22012-12-11 21:25:42 +00001//===-- AMDGPUInstrInfo.cpp - Base class for AMD GPU InstrInfo ------------===//
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 Implementation of the TargetInstrInfo class that is common to all
12/// AMD GPUs.
13//
14//===----------------------------------------------------------------------===//
15
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPURegisterInfo.h"
18#include "AMDGPUTargetMachine.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000019#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineInstrBuilder.h"
21#include "llvm/CodeGen/MachineRegisterInfo.h"
22
Chandler Carruthd174b722014-04-22 02:03:14 +000023using namespace llvm;
24
Juergen Ributzkad12ccbd2013-11-19 00:57:56 +000025#define GET_INSTRINFO_CTOR_DTOR
Tom Stellard02661d92013-06-25 21:22:18 +000026#define GET_INSTRINFO_NAMED_OPS
Christian Konigf741fbf2013-02-26 17:52:42 +000027#define GET_INSTRMAP_INFO
Tom Stellard75aadc22012-12-11 21:25:42 +000028#include "AMDGPUGenInstrInfo.inc"
29
Juergen Ributzkad12ccbd2013-11-19 00:57:56 +000030// Pin the vtable to this file.
31void AMDGPUInstrInfo::anchor() {}
32
Tom Stellard2e59a452014-06-13 01:32:00 +000033AMDGPUInstrInfo::AMDGPUInstrInfo(const AMDGPUSubtarget &st)
Eric Christopher6c5b5112015-03-11 18:43:21 +000034 : AMDGPUGenInstrInfo(-1, -1), ST(st) {}
Tom Stellard75aadc22012-12-11 21:25:42 +000035
36const AMDGPURegisterInfo &AMDGPUInstrInfo::getRegisterInfo() const {
37 return RI;
38}
39
Matt Arsenault034d6662014-07-24 02:10:17 +000040bool AMDGPUInstrInfo::enableClusterLoads() const {
41 return true;
42}
43
Matt Arsenaultd5f4de22014-08-06 00:29:49 +000044// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
45// the first 16 loads will be interleaved with the stores, and the next 16 will
46// be clustered as expected. It should really split into 2 16 store batches.
47//
48// Loads are clustered until this returns false, rather than trying to schedule
49// groups of stores. This also means we have to deal with saying different
50// address space loads should be clustered, and ones which might cause bank
51// conflicts.
52//
53// This might be deprecated so it might not be worth that much effort to fix.
54bool AMDGPUInstrInfo::shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1,
55 int64_t Offset0, int64_t Offset1,
56 unsigned NumLoads) const {
57 assert(Offset1 > Offset0 &&
58 "Second offset should be larger than first offset!");
59 // If we have less than 16 loads in a row, and the offsets are within 64
60 // bytes, then schedule together.
61
62 // A cacheline is 64 bytes (for global memory).
63 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
Tom Stellard75aadc22012-12-11 21:25:42 +000064}
65
Tom Stellard81d871d2013-11-13 23:36:50 +000066int AMDGPUInstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
67 const MachineRegisterInfo &MRI = MF.getRegInfo();
68 const MachineFrameInfo *MFI = MF.getFrameInfo();
69 int Offset = -1;
70
71 if (MFI->getNumObjects() == 0) {
72 return -1;
73 }
74
75 if (MRI.livein_empty()) {
76 return 0;
77 }
78
79 const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();
80 for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(),
81 LE = MRI.livein_end();
82 LI != LE; ++LI) {
83 unsigned Reg = LI->first;
84 if (TargetRegisterInfo::isVirtualRegister(Reg) ||
85 !IndirectRC->contains(Reg))
86 continue;
87
88 unsigned RegIndex;
89 unsigned RegEnd;
90 for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
91 ++RegIndex) {
92 if (IndirectRC->getRegister(RegIndex) == Reg)
93 break;
94 }
95 Offset = std::max(Offset, (int)RegIndex);
96 }
97
98 return Offset + 1;
99}
100
101int AMDGPUInstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
102 int Offset = 0;
103 const MachineFrameInfo *MFI = MF.getFrameInfo();
104
105 // Variable sized objects are not supported
Diana Picuse440f992016-06-23 09:19:16 +0000106 if (MFI->hasVarSizedObjects()) {
107 return -1;
108 }
Tom Stellard81d871d2013-11-13 23:36:50 +0000109
110 if (MFI->getNumObjects() == 0) {
111 return -1;
112 }
113
James Y Knight5567baf2015-08-15 02:32:35 +0000114 unsigned IgnoredFrameReg;
115 Offset = MF.getSubtarget().getFrameLowering()->getFrameIndexReference(
116 MF, -1, IgnoredFrameReg);
Tom Stellard81d871d2013-11-13 23:36:50 +0000117
118 return getIndirectIndexBegin(MF) + Offset;
119}
120
Tom Stellard682bfbc2013-10-10 17:11:24 +0000121int AMDGPUInstrInfo::getMaskedMIMGOp(uint16_t Opcode, unsigned Channels) const {
122 switch (Channels) {
123 default: return Opcode;
124 case 1: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_1);
125 case 2: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_2);
126 case 3: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_3);
127 }
128}
Tom Stellardc721a232014-05-16 20:56:47 +0000129
130// Wrapper for Tablegen'd function. enum Subtarget is not defined in any
Matt Arsenault1f0227a2014-10-07 21:29:56 +0000131// header files, so we need to wrap it in a function that takes unsigned
Tom Stellardc721a232014-05-16 20:56:47 +0000132// instead.
133namespace llvm {
134namespace AMDGPU {
Marek Olsaka93603d2015-01-15 18:42:51 +0000135static int getMCOpcode(uint16_t Opcode, unsigned Gen) {
Marek Olsak5df00d62014-12-07 12:18:57 +0000136 return getMCOpcodeGen(Opcode, (enum Subtarget)Gen);
Tom Stellardc721a232014-05-16 20:56:47 +0000137}
138}
139}
Marek Olsaka93603d2015-01-15 18:42:51 +0000140
141// This must be kept in sync with the SISubtarget class in SIInstrInfo.td
142enum SISubtarget {
143 SI = 0,
144 VI = 1
145};
146
Benjamin Kramer970eac42015-02-06 17:51:54 +0000147static enum SISubtarget AMDGPUSubtargetToSISubtarget(unsigned Gen) {
Marek Olsaka93603d2015-01-15 18:42:51 +0000148 switch (Gen) {
149 default:
150 return SI;
151 case AMDGPUSubtarget::VOLCANIC_ISLANDS:
152 return VI;
153 }
154}
155
156int AMDGPUInstrInfo::pseudoToMCOpcode(int Opcode) const {
Eric Christopher6c5b5112015-03-11 18:43:21 +0000157 int MCOp = AMDGPU::getMCOpcode(
158 Opcode, AMDGPUSubtargetToSISubtarget(ST.getGeneration()));
Marek Olsaka93603d2015-01-15 18:42:51 +0000159
160 // -1 means that Opcode is already a native instruction.
161 if (MCOp == -1)
162 return Opcode;
163
164 // (uint16_t)-1 means that Opcode is a pseudo instruction that has
165 // no encoding in the given subtarget generation.
166 if (MCOp == (uint16_t)-1)
167 return -1;
168
169 return MCOp;
170}