blob: a3abb96fb949cfddd8bfaf44e9fe19c71e904cfd [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
Christian Konigf741fbf2013-02-26 17:52:42 +000026#define GET_INSTRMAP_INFO
Tom Stellard75aadc22012-12-11 21:25:42 +000027#include "AMDGPUGenInstrInfo.inc"
28
Juergen Ributzkad12ccbd2013-11-19 00:57:56 +000029// Pin the vtable to this file.
30void AMDGPUInstrInfo::anchor() {}
31
Matt Arsenault43e92fe2016-06-24 06:30:11 +000032AMDGPUInstrInfo::AMDGPUInstrInfo(const AMDGPUSubtarget &ST)
33 : AMDGPUGenInstrInfo(-1, -1), ST(ST) {}
Tom Stellard75aadc22012-12-11 21:25:42 +000034
Matt Arsenaultd5f4de22014-08-06 00:29:49 +000035// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
36// the first 16 loads will be interleaved with the stores, and the next 16 will
37// be clustered as expected. It should really split into 2 16 store batches.
38//
39// Loads are clustered until this returns false, rather than trying to schedule
40// groups of stores. This also means we have to deal with saying different
41// address space loads should be clustered, and ones which might cause bank
42// conflicts.
43//
44// This might be deprecated so it might not be worth that much effort to fix.
45bool AMDGPUInstrInfo::shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1,
46 int64_t Offset0, int64_t Offset1,
47 unsigned NumLoads) const {
48 assert(Offset1 > Offset0 &&
49 "Second offset should be larger than first offset!");
50 // If we have less than 16 loads in a row, and the offsets are within 64
51 // bytes, then schedule together.
52
53 // A cacheline is 64 bytes (for global memory).
54 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
Tom Stellard75aadc22012-12-11 21:25:42 +000055}
56
Tom Stellard682bfbc2013-10-10 17:11:24 +000057int AMDGPUInstrInfo::getMaskedMIMGOp(uint16_t Opcode, unsigned Channels) const {
58 switch (Channels) {
59 default: return Opcode;
60 case 1: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_1);
61 case 2: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_2);
62 case 3: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_3);
63 }
64}
Tom Stellardc721a232014-05-16 20:56:47 +000065
Matt Arsenault43e92fe2016-06-24 06:30:11 +000066// This must be kept in sync with the SIEncodingFamily class in SIInstrInfo.td
67enum SIEncodingFamily {
68 SI = 0,
69 VI = 1
70};
71
Tom Stellardc721a232014-05-16 20:56:47 +000072// Wrapper for Tablegen'd function. enum Subtarget is not defined in any
Matt Arsenault1f0227a2014-10-07 21:29:56 +000073// header files, so we need to wrap it in a function that takes unsigned
Tom Stellardc721a232014-05-16 20:56:47 +000074// instead.
75namespace llvm {
76namespace AMDGPU {
Marek Olsaka93603d2015-01-15 18:42:51 +000077static int getMCOpcode(uint16_t Opcode, unsigned Gen) {
Matt Arsenault43e92fe2016-06-24 06:30:11 +000078 return getMCOpcodeGen(Opcode, static_cast<Subtarget>(Gen));
Tom Stellardc721a232014-05-16 20:56:47 +000079}
80}
81}
Marek Olsaka93603d2015-01-15 18:42:51 +000082
Matt Arsenault43e92fe2016-06-24 06:30:11 +000083static SIEncodingFamily subtargetEncodingFamily(const AMDGPUSubtarget &ST) {
84 switch (ST.getGeneration()) {
85 case AMDGPUSubtarget::SOUTHERN_ISLANDS:
86 case AMDGPUSubtarget::SEA_ISLANDS:
87 return SIEncodingFamily::SI;
Marek Olsaka93603d2015-01-15 18:42:51 +000088 case AMDGPUSubtarget::VOLCANIC_ISLANDS:
Matt Arsenaulte823d922017-02-18 18:29:53 +000089 case AMDGPUSubtarget::GFX9:
Matt Arsenault43e92fe2016-06-24 06:30:11 +000090 return SIEncodingFamily::VI;
91
92 // FIXME: This should never be called for r600 GPUs.
93 case AMDGPUSubtarget::R600:
94 case AMDGPUSubtarget::R700:
95 case AMDGPUSubtarget::EVERGREEN:
96 case AMDGPUSubtarget::NORTHERN_ISLANDS:
97 return SIEncodingFamily::SI;
Marek Olsaka93603d2015-01-15 18:42:51 +000098 }
Simon Pilgrim634dde32016-06-27 12:58:10 +000099
100 llvm_unreachable("Unknown subtarget generation!");
Marek Olsaka93603d2015-01-15 18:42:51 +0000101}
102
103int AMDGPUInstrInfo::pseudoToMCOpcode(int Opcode) const {
Matt Arsenault43e92fe2016-06-24 06:30:11 +0000104 int MCOp = AMDGPU::getMCOpcode(Opcode, subtargetEncodingFamily(ST));
Marek Olsaka93603d2015-01-15 18:42:51 +0000105
106 // -1 means that Opcode is already a native instruction.
107 if (MCOp == -1)
108 return Opcode;
109
110 // (uint16_t)-1 means that Opcode is a pseudo instruction that has
111 // no encoding in the given subtarget generation.
112 if (MCOp == (uint16_t)-1)
113 return -1;
114
115 return MCOp;
116}