xref: /aosp_15_r20/external/llvm/lib/Target/AMDGPU/AMDGPUInstrInfo.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- AMDGPUInstrInfo.cpp - Base class for AMD GPU InstrInfo ------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// \brief Implementation of the TargetInstrInfo class that is common to all
12*9880d681SAndroid Build Coastguard Worker /// AMD GPUs.
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker 
16*9880d681SAndroid Build Coastguard Worker #include "AMDGPUInstrInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "AMDGPURegisterInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "AMDGPUTargetMachine.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
22*9880d681SAndroid Build Coastguard Worker 
23*9880d681SAndroid Build Coastguard Worker using namespace llvm;
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker #define GET_INSTRINFO_CTOR_DTOR
26*9880d681SAndroid Build Coastguard Worker #define GET_INSTRINFO_NAMED_OPS
27*9880d681SAndroid Build Coastguard Worker #define GET_INSTRMAP_INFO
28*9880d681SAndroid Build Coastguard Worker #include "AMDGPUGenInstrInfo.inc"
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker // Pin the vtable to this file.
anchor()31*9880d681SAndroid Build Coastguard Worker void AMDGPUInstrInfo::anchor() {}
32*9880d681SAndroid Build Coastguard Worker 
AMDGPUInstrInfo(const AMDGPUSubtarget & ST)33*9880d681SAndroid Build Coastguard Worker AMDGPUInstrInfo::AMDGPUInstrInfo(const AMDGPUSubtarget &ST)
34*9880d681SAndroid Build Coastguard Worker   : AMDGPUGenInstrInfo(-1, -1), ST(ST) {}
35*9880d681SAndroid Build Coastguard Worker 
enableClusterLoads() const36*9880d681SAndroid Build Coastguard Worker bool AMDGPUInstrInfo::enableClusterLoads() const {
37*9880d681SAndroid Build Coastguard Worker   return true;
38*9880d681SAndroid Build Coastguard Worker }
39*9880d681SAndroid Build Coastguard Worker 
40*9880d681SAndroid Build Coastguard Worker // FIXME: This behaves strangely. If, for example, you have 32 load + stores,
41*9880d681SAndroid Build Coastguard Worker // the first 16 loads will be interleaved with the stores, and the next 16 will
42*9880d681SAndroid Build Coastguard Worker // be clustered as expected. It should really split into 2 16 store batches.
43*9880d681SAndroid Build Coastguard Worker //
44*9880d681SAndroid Build Coastguard Worker // Loads are clustered until this returns false, rather than trying to schedule
45*9880d681SAndroid Build Coastguard Worker // groups of stores. This also means we have to deal with saying different
46*9880d681SAndroid Build Coastguard Worker // address space loads should be clustered, and ones which might cause bank
47*9880d681SAndroid Build Coastguard Worker // conflicts.
48*9880d681SAndroid Build Coastguard Worker //
49*9880d681SAndroid Build Coastguard Worker // This might be deprecated so it might not be worth that much effort to fix.
shouldScheduleLoadsNear(SDNode * Load0,SDNode * Load1,int64_t Offset0,int64_t Offset1,unsigned NumLoads) const50*9880d681SAndroid Build Coastguard Worker bool AMDGPUInstrInfo::shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1,
51*9880d681SAndroid Build Coastguard Worker                                               int64_t Offset0, int64_t Offset1,
52*9880d681SAndroid Build Coastguard Worker                                               unsigned NumLoads) const {
53*9880d681SAndroid Build Coastguard Worker   assert(Offset1 > Offset0 &&
54*9880d681SAndroid Build Coastguard Worker          "Second offset should be larger than first offset!");
55*9880d681SAndroid Build Coastguard Worker   // If we have less than 16 loads in a row, and the offsets are within 64
56*9880d681SAndroid Build Coastguard Worker   // bytes, then schedule together.
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker   // A cacheline is 64 bytes (for global memory).
59*9880d681SAndroid Build Coastguard Worker   return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
60*9880d681SAndroid Build Coastguard Worker }
61*9880d681SAndroid Build Coastguard Worker 
getMaskedMIMGOp(uint16_t Opcode,unsigned Channels) const62*9880d681SAndroid Build Coastguard Worker int AMDGPUInstrInfo::getMaskedMIMGOp(uint16_t Opcode, unsigned Channels) const {
63*9880d681SAndroid Build Coastguard Worker   switch (Channels) {
64*9880d681SAndroid Build Coastguard Worker   default: return Opcode;
65*9880d681SAndroid Build Coastguard Worker   case 1: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_1);
66*9880d681SAndroid Build Coastguard Worker   case 2: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_2);
67*9880d681SAndroid Build Coastguard Worker   case 3: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_3);
68*9880d681SAndroid Build Coastguard Worker   }
69*9880d681SAndroid Build Coastguard Worker }
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker // This must be kept in sync with the SIEncodingFamily class in SIInstrInfo.td
72*9880d681SAndroid Build Coastguard Worker enum SIEncodingFamily {
73*9880d681SAndroid Build Coastguard Worker   SI = 0,
74*9880d681SAndroid Build Coastguard Worker   VI = 1
75*9880d681SAndroid Build Coastguard Worker };
76*9880d681SAndroid Build Coastguard Worker 
77*9880d681SAndroid Build Coastguard Worker // Wrapper for Tablegen'd function.  enum Subtarget is not defined in any
78*9880d681SAndroid Build Coastguard Worker // header files, so we need to wrap it in a function that takes unsigned
79*9880d681SAndroid Build Coastguard Worker // instead.
80*9880d681SAndroid Build Coastguard Worker namespace llvm {
81*9880d681SAndroid Build Coastguard Worker namespace AMDGPU {
getMCOpcode(uint16_t Opcode,unsigned Gen)82*9880d681SAndroid Build Coastguard Worker static int getMCOpcode(uint16_t Opcode, unsigned Gen) {
83*9880d681SAndroid Build Coastguard Worker   return getMCOpcodeGen(Opcode, static_cast<Subtarget>(Gen));
84*9880d681SAndroid Build Coastguard Worker }
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker }
87*9880d681SAndroid Build Coastguard Worker 
subtargetEncodingFamily(const AMDGPUSubtarget & ST)88*9880d681SAndroid Build Coastguard Worker static SIEncodingFamily subtargetEncodingFamily(const AMDGPUSubtarget &ST) {
89*9880d681SAndroid Build Coastguard Worker   switch (ST.getGeneration()) {
90*9880d681SAndroid Build Coastguard Worker   case AMDGPUSubtarget::SOUTHERN_ISLANDS:
91*9880d681SAndroid Build Coastguard Worker   case AMDGPUSubtarget::SEA_ISLANDS:
92*9880d681SAndroid Build Coastguard Worker     return SIEncodingFamily::SI;
93*9880d681SAndroid Build Coastguard Worker   case AMDGPUSubtarget::VOLCANIC_ISLANDS:
94*9880d681SAndroid Build Coastguard Worker     return SIEncodingFamily::VI;
95*9880d681SAndroid Build Coastguard Worker 
96*9880d681SAndroid Build Coastguard Worker   // FIXME: This should never be called for r600 GPUs.
97*9880d681SAndroid Build Coastguard Worker   case AMDGPUSubtarget::R600:
98*9880d681SAndroid Build Coastguard Worker   case AMDGPUSubtarget::R700:
99*9880d681SAndroid Build Coastguard Worker   case AMDGPUSubtarget::EVERGREEN:
100*9880d681SAndroid Build Coastguard Worker   case AMDGPUSubtarget::NORTHERN_ISLANDS:
101*9880d681SAndroid Build Coastguard Worker     return SIEncodingFamily::SI;
102*9880d681SAndroid Build Coastguard Worker   }
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unknown subtarget generation!");
105*9880d681SAndroid Build Coastguard Worker }
106*9880d681SAndroid Build Coastguard Worker 
pseudoToMCOpcode(int Opcode) const107*9880d681SAndroid Build Coastguard Worker int AMDGPUInstrInfo::pseudoToMCOpcode(int Opcode) const {
108*9880d681SAndroid Build Coastguard Worker   int MCOp = AMDGPU::getMCOpcode(Opcode, subtargetEncodingFamily(ST));
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker   // -1 means that Opcode is already a native instruction.
111*9880d681SAndroid Build Coastguard Worker   if (MCOp == -1)
112*9880d681SAndroid Build Coastguard Worker     return Opcode;
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker   // (uint16_t)-1 means that Opcode is a pseudo instruction that has
115*9880d681SAndroid Build Coastguard Worker   // no encoding in the given subtarget generation.
116*9880d681SAndroid Build Coastguard Worker   if (MCOp == (uint16_t)-1)
117*9880d681SAndroid Build Coastguard Worker     return -1;
118*9880d681SAndroid Build Coastguard Worker 
119*9880d681SAndroid Build Coastguard Worker   return MCOp;
120*9880d681SAndroid Build Coastguard Worker }
121