LLVM  14.0.0git
R600ExpandSpecialInstrs.cpp
Go to the documentation of this file.
1 //===- R600ExpandSpecialInstrs.cpp - Expand special instructions ----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// \file
10 /// Vector, Reduction, and Cube instructions need to fill the entire instruction
11 /// group to work correctly. This pass expands these individual instructions
12 /// into several instructions that will completely fill the instruction group.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "AMDGPU.h"
18 #include "R600Defines.h"
19 #include "R600Subtarget.h"
20 
21 using namespace llvm;
22 
23 #define DEBUG_TYPE "r600-expand-special-instrs"
24 
25 namespace {
26 
27 class R600ExpandSpecialInstrsPass : public MachineFunctionPass {
28 private:
29  const R600InstrInfo *TII = nullptr;
30 
31  void SetFlagInNewMI(MachineInstr *NewMI, const MachineInstr *OldMI,
32  unsigned Op);
33 
34 public:
35  static char ID;
36 
37  R600ExpandSpecialInstrsPass() : MachineFunctionPass(ID) {}
38 
39  bool runOnMachineFunction(MachineFunction &MF) override;
40 
41  StringRef getPassName() const override {
42  return "R600 Expand special instructions pass";
43  }
44 };
45 
46 } // end anonymous namespace
47 
48 INITIALIZE_PASS_BEGIN(R600ExpandSpecialInstrsPass, DEBUG_TYPE,
49  "R600 Expand Special Instrs", false, false)
50 INITIALIZE_PASS_END(R600ExpandSpecialInstrsPass, DEBUG_TYPE,
52 
53 char R600ExpandSpecialInstrsPass::ID = 0;
54 
55 char &llvm::R600ExpandSpecialInstrsPassID = R600ExpandSpecialInstrsPass::ID;
56 
58  return new R600ExpandSpecialInstrsPass();
59 }
60 
61 void R600ExpandSpecialInstrsPass::SetFlagInNewMI(MachineInstr *NewMI,
62  const MachineInstr *OldMI, unsigned Op) {
63  int OpIdx = TII->getOperandIdx(*OldMI, Op);
64  if (OpIdx > -1) {
65  uint64_t Val = OldMI->getOperand(OpIdx).getImm();
66  TII->setImmOperand(*NewMI, Op, Val);
67  }
68 }
69 
70 bool R600ExpandSpecialInstrsPass::runOnMachineFunction(MachineFunction &MF) {
72  TII = ST.getInstrInfo();
73 
74  const R600RegisterInfo &TRI = TII->getRegisterInfo();
75 
76  for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
77  BB != BB_E; ++BB) {
80  while (I != MBB.end()) {
81  MachineInstr &MI = *I;
82  I = std::next(I);
83 
84  // Expand LDS_*_RET instructions
85  if (TII->isLDSRetInstr(MI.getOpcode())) {
86  int DstIdx = TII->getOperandIdx(MI.getOpcode(), R600::OpName::dst);
87  assert(DstIdx != -1);
88  MachineOperand &DstOp = MI.getOperand(DstIdx);
89  MachineInstr *Mov = TII->buildMovInstr(&MBB, I,
90  DstOp.getReg(), R600::OQAP);
91  DstOp.setReg(R600::OQAP);
92  int LDSPredSelIdx = TII->getOperandIdx(MI.getOpcode(),
93  R600::OpName::pred_sel);
94  int MovPredSelIdx = TII->getOperandIdx(Mov->getOpcode(),
95  R600::OpName::pred_sel);
96  // Copy the pred_sel bit
97  Mov->getOperand(MovPredSelIdx).setReg(
98  MI.getOperand(LDSPredSelIdx).getReg());
99  }
100 
101  switch (MI.getOpcode()) {
102  default: break;
103  // Expand PRED_X to one of the PRED_SET instructions.
104  case R600::PRED_X: {
105  uint64_t Flags = MI.getOperand(3).getImm();
106  // The native opcode used by PRED_X is stored as an immediate in the
107  // third operand.
108  MachineInstr *PredSet = TII->buildDefaultInstruction(MBB, I,
109  MI.getOperand(2).getImm(), // opcode
110  MI.getOperand(0).getReg(), // dst
111  MI.getOperand(1).getReg(), // src0
112  R600::ZERO); // src1
113  TII->addFlag(*PredSet, 0, MO_FLAG_MASK);
114  if (Flags & MO_FLAG_PUSH) {
115  TII->setImmOperand(*PredSet, R600::OpName::update_exec_mask, 1);
116  } else {
117  TII->setImmOperand(*PredSet, R600::OpName::update_pred, 1);
118  }
119  MI.eraseFromParent();
120  continue;
121  }
122  case R600::DOT_4: {
123 
124  const R600RegisterInfo &TRI = TII->getRegisterInfo();
125 
126  Register DstReg = MI.getOperand(0).getReg();
127  unsigned DstBase = TRI.getEncodingValue(DstReg) & HW_REG_MASK;
128 
129  for (unsigned Chan = 0; Chan < 4; ++Chan) {
130  bool Mask = (Chan != TRI.getHWRegChan(DstReg));
131  unsigned SubDstReg =
132  R600::R600_TReg32RegClass.getRegister((DstBase * 4) + Chan);
133  MachineInstr *BMI =
134  TII->buildSlotOfVectorInstruction(MBB, &MI, Chan, SubDstReg);
135  if (Chan > 0) {
136  BMI->bundleWithPred();
137  }
138  if (Mask) {
139  TII->addFlag(*BMI, 0, MO_FLAG_MASK);
140  }
141  if (Chan != 3)
142  TII->addFlag(*BMI, 0, MO_FLAG_NOT_LAST);
143  unsigned Opcode = BMI->getOpcode();
144  // While not strictly necessary from hw point of view, we force
145  // all src operands of a dot4 inst to belong to the same slot.
146  Register Src0 =
147  BMI->getOperand(TII->getOperandIdx(Opcode, R600::OpName::src0))
148  .getReg();
149  Register Src1 =
150  BMI->getOperand(TII->getOperandIdx(Opcode, R600::OpName::src1))
151  .getReg();
152  (void) Src0;
153  (void) Src1;
154  if ((TRI.getEncodingValue(Src0) & 0xff) < 127 &&
155  (TRI.getEncodingValue(Src1) & 0xff) < 127)
156  assert(TRI.getHWRegChan(Src0) == TRI.getHWRegChan(Src1));
157  }
158  MI.eraseFromParent();
159  continue;
160  }
161  }
162 
163  bool IsReduction = TII->isReductionOp(MI.getOpcode());
164  bool IsVector = TII->isVector(MI);
165  bool IsCube = TII->isCubeOp(MI.getOpcode());
166  if (!IsReduction && !IsVector && !IsCube) {
167  continue;
168  }
169 
170  // Expand the instruction
171  //
172  // Reduction instructions:
173  // T0_X = DP4 T1_XYZW, T2_XYZW
174  // becomes:
175  // TO_X = DP4 T1_X, T2_X
176  // TO_Y (write masked) = DP4 T1_Y, T2_Y
177  // TO_Z (write masked) = DP4 T1_Z, T2_Z
178  // TO_W (write masked) = DP4 T1_W, T2_W
179  //
180  // Vector instructions:
181  // T0_X = MULLO_INT T1_X, T2_X
182  // becomes:
183  // T0_X = MULLO_INT T1_X, T2_X
184  // T0_Y (write masked) = MULLO_INT T1_X, T2_X
185  // T0_Z (write masked) = MULLO_INT T1_X, T2_X
186  // T0_W (write masked) = MULLO_INT T1_X, T2_X
187  //
188  // Cube instructions:
189  // T0_XYZW = CUBE T1_XYZW
190  // becomes:
191  // TO_X = CUBE T1_Z, T1_Y
192  // T0_Y = CUBE T1_Z, T1_X
193  // T0_Z = CUBE T1_X, T1_Z
194  // T0_W = CUBE T1_Y, T1_Z
195  for (unsigned Chan = 0; Chan < 4; Chan++) {
196  Register DstReg =
197  MI.getOperand(TII->getOperandIdx(MI, R600::OpName::dst)).getReg();
198  Register Src0 =
199  MI.getOperand(TII->getOperandIdx(MI, R600::OpName::src0)).getReg();
200  unsigned Src1 = 0;
201 
202  // Determine the correct source registers
203  if (!IsCube) {
204  int Src1Idx = TII->getOperandIdx(MI, R600::OpName::src1);
205  if (Src1Idx != -1) {
206  Src1 = MI.getOperand(Src1Idx).getReg();
207  }
208  }
209  if (IsReduction) {
210  unsigned SubRegIndex = R600RegisterInfo::getSubRegFromChannel(Chan);
211  Src0 = TRI.getSubReg(Src0, SubRegIndex);
212  Src1 = TRI.getSubReg(Src1, SubRegIndex);
213  } else if (IsCube) {
214  static const int CubeSrcSwz[] = {2, 2, 0, 1};
215  unsigned SubRegIndex0 = R600RegisterInfo::getSubRegFromChannel(CubeSrcSwz[Chan]);
216  unsigned SubRegIndex1 = R600RegisterInfo::getSubRegFromChannel(CubeSrcSwz[3 - Chan]);
217  Src1 = TRI.getSubReg(Src0, SubRegIndex1);
218  Src0 = TRI.getSubReg(Src0, SubRegIndex0);
219  }
220 
221  // Determine the correct destination registers;
222  bool Mask = false;
223  bool NotLast = true;
224  if (IsCube) {
225  unsigned SubRegIndex = R600RegisterInfo::getSubRegFromChannel(Chan);
226  DstReg = TRI.getSubReg(DstReg, SubRegIndex);
227  } else {
228  // Mask the write if the original instruction does not write to
229  // the current Channel.
230  Mask = (Chan != TRI.getHWRegChan(DstReg));
231  unsigned DstBase = TRI.getEncodingValue(DstReg) & HW_REG_MASK;
232  DstReg = R600::R600_TReg32RegClass.getRegister((DstBase * 4) + Chan);
233  }
234 
235  // Set the IsLast bit
236  NotLast = (Chan != 3 );
237 
238  // Add the new instruction
239  unsigned Opcode = MI.getOpcode();
240  switch (Opcode) {
241  case R600::CUBE_r600_pseudo:
242  Opcode = R600::CUBE_r600_real;
243  break;
244  case R600::CUBE_eg_pseudo:
245  Opcode = R600::CUBE_eg_real;
246  break;
247  default:
248  break;
249  }
250 
251  MachineInstr *NewMI =
252  TII->buildDefaultInstruction(MBB, I, Opcode, DstReg, Src0, Src1);
253 
254  if (Chan != 0)
255  NewMI->bundleWithPred();
256  if (Mask) {
257  TII->addFlag(*NewMI, 0, MO_FLAG_MASK);
258  }
259  if (NotLast) {
260  TII->addFlag(*NewMI, 0, MO_FLAG_NOT_LAST);
261  }
262  SetFlagInNewMI(NewMI, &MI, R600::OpName::clamp);
263  SetFlagInNewMI(NewMI, &MI, R600::OpName::literal);
264  SetFlagInNewMI(NewMI, &MI, R600::OpName::src0_abs);
265  SetFlagInNewMI(NewMI, &MI, R600::OpName::src1_abs);
266  SetFlagInNewMI(NewMI, &MI, R600::OpName::src0_neg);
267  SetFlagInNewMI(NewMI, &MI, R600::OpName::src1_neg);
268  }
269  MI.eraseFromParent();
270  }
271  }
272  return false;
273 }
llvm::createR600ExpandSpecialInstrsPass
FunctionPass * createR600ExpandSpecialInstrsPass()
Definition: R600ExpandSpecialInstrs.cpp:57
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:102
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::MachineFunction::end
iterator end()
Definition: MachineFunction.h:806
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(R600ExpandSpecialInstrsPass, DEBUG_TYPE, "R600 Expand Special Instrs", false, false) INITIALIZE_PASS_END(R600ExpandSpecialInstrsPass
llvm::MachineInstr::bundleWithPred
void bundleWithPred()
Bundle this instruction with its predecessor.
Definition: MachineInstr.cpp:759
llvm::MCRegisterInfo::getEncodingValue
uint16_t getEncodingValue(MCRegister RegNo) const
Returns the encoding for RegNo.
Definition: MCRegisterInfo.h:553
llvm::R600RegisterInfo::getSubRegFromChannel
static unsigned getSubRegFromChannel(unsigned Channel)
Definition: R600RegisterInfo.cpp:24
llvm::BitmaskEnumDetail::Mask
std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:80
TRI
unsigned const TargetRegisterInfo * TRI
Definition: MachineSink.cpp:1567
llvm::R600RegisterInfo
Definition: R600RegisterInfo.h:22
llvm::MachineOperand::getImm
int64_t getImm() const
Definition: MachineOperand.h:537
MO_FLAG_PUSH
#define MO_FLAG_PUSH
Definition: R600Defines.h:18
llvm::DstOp::getReg
Register getReg() const
Definition: MachineIRBuilder.h:99
llvm::MachineInstr::getOperand
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:499
false
Definition: StackSlotColoring.cpp:142
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:129
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
MO_FLAG_MASK
#define MO_FLAG_MASK
Definition: R600Defines.h:17
llvm::MachineFunction::begin
iterator begin()
Definition: MachineFunction.h:804
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:622
MO_FLAG_NOT_LAST
#define MO_FLAG_NOT_LAST
Definition: R600Defines.h:19
llvm::R600Subtarget
Definition: R600Subtarget.h:36
AMDGPUMCTargetDesc.h
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
uint64_t
llvm::ARM_MB::ST
@ ST
Definition: ARMBaseInfo.h:73
DEBUG_TYPE
#define DEBUG_TYPE
Definition: R600ExpandSpecialInstrs.cpp:23
I
#define I(x, y, z)
Definition: MD5.cpp:59
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MachineFunction
Definition: MachineFunction.h:230
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
AMDGPU.h
llvm::MachineInstr::getOpcode
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:489
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::R600ExpandSpecialInstrsPassID
char & R600ExpandSpecialInstrsPassID
Definition: R600ExpandSpecialInstrs.cpp:55
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:314
llvm::ilist_iterator
Iterator for intrusive lists based on ilist_node.
Definition: ilist_iterator.h:57
R600Subtarget.h
llvm::R600InstrInfo
Definition: R600InstrInfo.h:39
R600ExpandSpecialInstrs
R600ExpandSpecialInstrs
Definition: R600ExpandSpecialInstrs.cpp:51
R600Defines.h
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:268
llvm::DstOp
Definition: MachineIRBuilder.h:58
llvm::MachineOperand::setReg
void setReg(Register Reg)
Change the register this operand corresponds to.
Definition: MachineOperand.cpp:55
llvm::TargetRegisterInfo::getSubReg
MCRegister getSubReg(MCRegister Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo.
Definition: TargetRegisterInfo.h:1096
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::MachineInstrBundleIterator< MachineInstr >
llvm::MachineBasicBlock::end
iterator end()
Definition: MachineBasicBlock.h:270
getReg
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
Definition: MipsDisassembler.cpp:580
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38
HW_REG_MASK
#define HW_REG_MASK
Defines for extracting register information from register encoding.
Definition: R600Defines.h:53