LLVM  8.0.1
SIAddIMGInit.cpp
Go to the documentation of this file.
1 //===-- SIAddIMGInit.cpp - Add any required IMG inits ---------------------===//
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 /// Any MIMG instructions that use tfe or lwe require an initialization of the
12 /// result register that will be written in the case of a memory access failure
13 /// The required code is also added to tie this init code to the result of the
14 /// img instruction
15 ///
16 //===----------------------------------------------------------------------===//
17 //
18 
19 #include "AMDGPU.h"
20 #include "AMDGPUSubtarget.h"
22 #include "SIInstrInfo.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/Support/Debug.h"
29 
30 #define DEBUG_TYPE "si-img-init"
31 
32 using namespace llvm;
33 
34 namespace {
35 
36 class SIAddIMGInit : public MachineFunctionPass {
37 public:
38  static char ID;
39 
40 public:
41  SIAddIMGInit() : MachineFunctionPass(ID) {
43  }
44 
45  bool runOnMachineFunction(MachineFunction &MF) override;
46 
47  void getAnalysisUsage(AnalysisUsage &AU) const override {
48  AU.setPreservesCFG();
50  }
51 };
52 
53 } // End anonymous namespace.
54 
55 INITIALIZE_PASS(SIAddIMGInit, DEBUG_TYPE, "SI Add IMG Init", false, false)
56 
57 char SIAddIMGInit::ID = 0;
58 
60 
61 FunctionPass *llvm::createSIAddIMGInitPass() { return new SIAddIMGInit(); }
62 
63 bool SIAddIMGInit::runOnMachineFunction(MachineFunction &MF) {
66  const SIInstrInfo *TII = ST.getInstrInfo();
67  const SIRegisterInfo *RI = ST.getRegisterInfo();
68  bool Changed = false;
69 
70  for (MachineFunction::iterator BI = MF.begin(), BE = MF.end(); BI != BE;
71  ++BI) {
72  MachineBasicBlock &MBB = *BI;
74  for (I = MBB.begin(); I != MBB.end(); I = Next) {
75  Next = std::next(I);
76  MachineInstr &MI = *I;
77 
78  auto Opcode = MI.getOpcode();
79  if (TII->isMIMG(Opcode) && !MI.mayStore()) {
80  MachineOperand *TFE = TII->getNamedOperand(MI, AMDGPU::OpName::tfe);
81  MachineOperand *LWE = TII->getNamedOperand(MI, AMDGPU::OpName::lwe);
82  MachineOperand *D16 = TII->getNamedOperand(MI, AMDGPU::OpName::d16);
83 
84  // Check for instructions that don't have tfe or lwe fields
85  // There shouldn't be any at this point.
86  assert( (TFE && LWE) && "Expected tfe and lwe operands in instruction");
87 
88  unsigned TFEVal = TFE->getImm();
89  unsigned LWEVal = LWE->getImm();
90  unsigned D16Val = D16 ? D16->getImm() : 0;
91 
92  if (TFEVal || LWEVal) {
93  // At least one of TFE or LWE are non-zero
94  // We have to insert a suitable initialization of the result value and
95  // tie this to the dest of the image instruction.
96 
97  const DebugLoc &DL = MI.getDebugLoc();
98 
99  int DstIdx =
100  AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
101 
102  // Calculate which dword we have to initialize to 0.
103  MachineOperand *MO_Dmask =
104  TII->getNamedOperand(MI, AMDGPU::OpName::dmask);
105 
106  // check that dmask operand is found.
107  assert(MO_Dmask && "Expected dmask operand in instruction");
108 
109  unsigned dmask = MO_Dmask->getImm();
110  // Determine the number of active lanes taking into account the
111  // Gather4 special case
112  unsigned ActiveLanes =
113  TII->isGather4(Opcode) ? 4 : countPopulation(dmask);
114 
115  // Subreg indices are counted from 1
116  // When D16 then we want next whole VGPR after write data.
117  static_assert(AMDGPU::sub0 == 1 && AMDGPU::sub4 == 5, "Subreg indices different from expected");
118 
119  bool Packed = !ST.hasUnpackedD16VMem();
120 
121  unsigned InitIdx =
122  D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
123 
124  // Abandon attempt if the dst size isn't large enough
125  // - this is in fact an error but this is picked up elsewhere and
126  // reported correctly.
127  uint32_t DstSize =
128  RI->getRegSizeInBits(*TII->getOpRegClass(MI, DstIdx)) / 32;
129  if (DstSize < InitIdx)
130  continue;
131 
132  // Create a register for the intialization value.
133  unsigned PrevDst =
134  MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx));
135  unsigned NewDst = 0; // Final initialized value will be in here
136 
137  // If PRTStrictNull feature is enabled (the default) then initialize
138  // all the result registers to 0, otherwise just the error indication
139  // register (VGPRn+1)
140  unsigned SizeLeft = ST.usePRTStrictNull() ? InitIdx : 1;
141  unsigned CurrIdx = ST.usePRTStrictNull() ? 1 : InitIdx;
142 
143  if (DstSize == 1) {
144  // In this case we can just initialize the result directly
145  BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), PrevDst)
146  .addImm(0);
147  NewDst = PrevDst;
148  } else {
149  BuildMI(MBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), PrevDst);
150  for (; SizeLeft; SizeLeft--, CurrIdx++) {
151  NewDst =
152  MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx));
153  // Initialize dword
154  unsigned SubReg =
155  MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
156  BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), SubReg)
157  .addImm(0);
158  // Insert into the super-reg
159  BuildMI(MBB, I, DL, TII->get(TargetOpcode::INSERT_SUBREG), NewDst)
160  .addReg(PrevDst)
161  .addReg(SubReg)
162  .addImm(CurrIdx);
163 
164  PrevDst = NewDst;
165  }
166  }
167 
168  // Add as an implicit operand
170 
171  // Tie the just added implicit operand to the dst
172  MI.tieOperands(DstIdx, MI.getNumOperands() - 1);
173 
174  Changed = true;
175  }
176  }
177  }
178  }
179 
180  return Changed;
181 }
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
AMDGPU specific subclass of TargetSubtarget.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:383
const SIInstrInfo * getInstrInfo() const override
A debug info location.
Definition: DebugLoc.h:34
FunctionPass * createSIAddIMGInitPass()
LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:412
unsigned SubReg
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata *> MDs)
Definition: Metadata.h:1166
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
Definition: MachineInstr.h:820
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool usePRTStrictNull() const
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
void initializeSIAddIMGInitPass(PassRegistry &)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:34
bool hasUnpackedD16VMem() const
Iterator for intrusive lists based on ilist_node.
unsigned countPopulation(T Value)
Count the number of set bits in a value.
Definition: MathExtras.h:520
MachineOperand class - Representation of each machine instruction operand.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:286
int64_t getImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Provides AMDGPU specific target descriptions.
Representation of each machine instruction.
Definition: MachineInstr.h:64
Interface definition for SIInstrInfo.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
#define I(x, y, z)
Definition: MD5.cpp:58
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
IRTranslator LLVM IR MI
#define DEBUG_TYPE
char & SIAddIMGInitID
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
const SIRegisterInfo * getRegisterInfo() const override