llvm.org GIT mirror llvm / 9787e8c
R600/SI: Add instruction shrinking pass This pass converts 64-bit instructions to 32-bit when possible. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213561 91177308-0d34-0410-b5e6-96231b3b80d8 Tom Stellard 5 years ago
13 changed file(s) with 223 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
3838 FunctionPass *createSITypeRewriter();
3939 FunctionPass *createSIAnnotateControlFlowPass();
4040 FunctionPass *createSILowerI1CopiesPass();
41 FunctionPass *createSIShrinkInstructionsPass();
4142 FunctionPass *createSILowerControlFlowPass(TargetMachine &tm);
4243 FunctionPass *createSIFixSGPRCopiesPass(TargetMachine &tm);
4344 FunctionPass *createSIFixSGPRLiveRangesPass();
175175 // SIFixSGPRCopies can generate a lot of duplicate instructions,
176176 // so we need to run MachineCSE afterwards.
177177 addPass(&MachineCSEID);
178 addPass(createSIShrinkInstructionsPass());
178179 initializeSIFixSGPRLiveRangesPass(*PassRegistry::getPassRegistry());
179180 insertPass(&RegisterCoalescerID, &SIFixSGPRLiveRangesID);
180181 }
184185 bool AMDGPUPassConfig::addPostRegAlloc() {
185186 const AMDGPUSubtarget &ST = TM->getSubtarget();
186187
188 addPass(createSIShrinkInstructionsPass());
187189 if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
188190 addPass(createSIInsertWaits(*TM));
189191 }
4747 SILowerI1Copies.cpp
4848 SIMachineFunctionInfo.cpp
4949 SIRegisterInfo.cpp
50 SIShrinkInstructions.cpp
5051 SITypeRewriter.cpp
5152 )
5253
287287 let mayLoad = 0;
288288 let mayStore = 0;
289289 let hasSideEffects = 0;
290 let UseNamedOperandTable = 1;
290291 let VOPC = 1;
291292 }
292293
16381638 for (int Index = std::max(0, Begin - 15); Index <= End; ++Index)
16391639 Reserved.set(AMDGPU::VReg_512RegClass.getRegister(Index));
16401640 }
1641
1642 const MachineOperand *SIInstrInfo::getNamedOperand(const MachineInstr& MI,
1643 unsigned OperandName) const {
1644 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
1645 if (Idx == -1)
1646 return nullptr;
1647
1648 return &MI.getOperand(Idx);
1649 }
173173 unsigned SavReg, unsigned IndexReg) const;
174174
175175 void insertNOPs(MachineBasicBlock::iterator MI, int Count) const;
176
177 /// \brief Returns the operand named \p Op. If \p MI does not have an
178 /// operand named \c Op, this function returns nullptr.
179 const MachineOperand *getNamedOperand(const MachineInstr& MI,
180 unsigned OperandName) const;
176181 };
177182
178183 namespace AMDGPU {
179184
180185 int getVOPe64(uint16_t Opcode);
186 int getVOPe32(uint16_t Opcode);
181187 int getCommuteRev(uint16_t Opcode);
182188 int getCommuteOrig(uint16_t Opcode);
183189 int getMCOpcode(uint16_t Opcode, unsigned Gen);
828828 let ValueCols = [["8"]];
829829 }
830830
831 // Maps an opcode in e64 form to its e32 equivalent
832 def getVOPe32 : InstrMapping {
833 let FilterClass = "VOP";
834 let RowFields = ["OpName"];
835 let ColFields = ["Size"];
836 let KeyCol = ["8"];
837 let ValueCols = [["4"]];
838 }
839
831840 // Maps an original opcode to its commuted version
832841 def getCommuteRev : InstrMapping {
833842 let FilterClass = "VOP2_REV";
0 //===-- SIShrinkInstructions.cpp - Shrink Instructions --------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 /// The pass tries to use the 32-bit encoding for instructions when possible.
8 //===----------------------------------------------------------------------===//
9 //
10
11 #include "AMDGPU.h"
12 #include "SIInstrInfo.h"
13 #include "llvm/ADT/Statistic.h"
14 #include "llvm/CodeGen/MachineFunctionPass.h"
15 #include "llvm/CodeGen/MachineInstrBuilder.h"
16 #include "llvm/CodeGen/MachineRegisterInfo.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "llvm/IR/Function.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Target/TargetMachine.h"
21
22 #define DEBUG_TYPE "si-shrink-instructions"
23
24 STATISTIC(NumInstructionsShrunk,
25 "Number of 64-bit instruction reduced to 32-bit.");
26
27 namespace llvm {
28 void initializeSIShrinkInstructionsPass(PassRegistry&);
29 }
30
31 using namespace llvm;
32
33 namespace {
34
35 class SIShrinkInstructions : public MachineFunctionPass {
36 public:
37 static char ID;
38
39 public:
40 SIShrinkInstructions() : MachineFunctionPass(ID) {
41 }
42
43 virtual bool runOnMachineFunction(MachineFunction &MF) override;
44
45 virtual const char *getPassName() const override {
46 return "SI Shrink Instructions";
47 }
48
49 virtual void getAnalysisUsage(AnalysisUsage &AU) const override {
50 AU.setPreservesCFG();
51 MachineFunctionPass::getAnalysisUsage(AU);
52 }
53 };
54
55 } // End anonymous namespace.
56
57 INITIALIZE_PASS_BEGIN(SIShrinkInstructions, DEBUG_TYPE,
58 "SI Lower il Copies", false, false)
59 INITIALIZE_PASS_END(SIShrinkInstructions, DEBUG_TYPE,
60 "SI Lower il Copies", false, false)
61
62 char SIShrinkInstructions::ID = 0;
63
64 FunctionPass *llvm::createSIShrinkInstructionsPass() {
65 return new SIShrinkInstructions();
66 }
67
68 static bool isVGPR(const MachineOperand *MO, const SIRegisterInfo &TRI,
69 const MachineRegisterInfo &MRI) {
70 if (!MO->isReg())
71 return false;
72
73 if (TargetRegisterInfo::isVirtualRegister(MO->getReg()))
74 return TRI.hasVGPRs(MRI.getRegClass(MO->getReg()));
75
76 return TRI.hasVGPRs(TRI.getPhysRegClass(MO->getReg()));
77 }
78
79 static bool canShrink(MachineInstr &MI, const SIInstrInfo *TII,
80 const SIRegisterInfo &TRI,
81 const MachineRegisterInfo &MRI) {
82
83 const MachineOperand *Src2 = TII->getNamedOperand(MI, AMDGPU::OpName::src2);
84 // Can't shrink instruction with three operands.
85 if (Src2)
86 return false;
87
88 const MachineOperand *Src1 = TII->getNamedOperand(MI, AMDGPU::OpName::src1);
89 const MachineOperand *Src1Mod =
90 TII->getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
91
92 if (Src1 && (!isVGPR(Src1, TRI, MRI) || Src1Mod->getImm() != 0))
93 return false;
94
95 // We don't need to check src0, all input types are legal, so just make
96 // sure src0 isn't using any modifiers.
97 const MachineOperand *Src0Mod =
98 TII->getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
99 if (Src0Mod && Src0Mod->getImm() != 0)
100 return false;
101
102 // Check output modifiers
103 const MachineOperand *Omod = TII->getNamedOperand(MI, AMDGPU::OpName::omod);
104 if (Omod && Omod->getImm() != 0)
105 return false;
106
107 const MachineOperand *Clamp = TII->getNamedOperand(MI, AMDGPU::OpName::clamp);
108 return !Clamp || Clamp->getImm() == 0;
109 }
110
111 bool SIShrinkInstructions::runOnMachineFunction(MachineFunction &MF) {
112 MachineRegisterInfo &MRI = MF.getRegInfo();
113 const SIInstrInfo *TII = static_cast(
114 MF.getTarget().getInstrInfo());
115 const SIRegisterInfo &TRI = TII->getRegisterInfo();
116 std::vector I1Defs;
117
118 for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
119 BI != BE; ++BI) {
120
121 MachineBasicBlock &MBB = *BI;
122 MachineBasicBlock::iterator I, Next;
123 for (I = MBB.begin(); I != MBB.end(); I = Next) {
124 Next = std::next(I);
125 MachineInstr &MI = *I;
126
127 int Op32 = AMDGPU::getVOPe32(MI.getOpcode());
128
129 if (Op32 == -1)
130 continue;
131
132 if (!canShrink(MI, TII, TRI, MRI)) {
133 // Try commtuing the instruction and see if that enables us to shrink
134 // it.
135 if (!MI.isCommutable() || !TII->commuteInstruction(&MI) ||
136 !canShrink(MI, TII, TRI, MRI))
137 continue;
138 }
139
140 if (TII->isVOPC(Op32)) {
141 unsigned DstReg = MI.getOperand(0).getReg();
142 if (TargetRegisterInfo::isVirtualRegister(DstReg)) {
143 // VOPC instructions can only write to the VCC register. We can't
144 // force them to use VCC here, because the register allocator
145 // has trouble with sequences like this, which cause the allocator
146 // to run out of registes if vreg0 and vreg1 belong to the VCCReg
147 // register class:
148 // vreg0 = VOPC;
149 // vreg1 = VOPC;
150 // S_AND_B64 vreg0, vreg1
151 //
152 // So, instead of forcing the instruction to write to VCC, we provide a
153 // hint to the register allocator to use VCC and then we
154 // we will run this pass again after RA and shrink it if it outpus to
155 // VCC.
156 MRI.setRegAllocationHint(MI.getOperand(0).getReg(), 0, AMDGPU::VCC);
157 continue;
158 }
159 if (DstReg != AMDGPU::VCC)
160 continue;
161 }
162
163 // We can shrink this instruction
164 DEBUG(dbgs() << "Shrinking "; MI.dump(); dbgs() << "\n";);
165
166 MachineInstrBuilder MIB =
167 BuildMI(MBB, I, MI.getDebugLoc(), TII->get(Op32));
168
169 // dst
170 MIB.addOperand(MI.getOperand(0));
171
172 MIB.addOperand(*TII->getNamedOperand(MI, AMDGPU::OpName::src0));
173
174 const MachineOperand *Src1 =
175 TII->getNamedOperand(MI, AMDGPU::OpName::src1);
176 if (Src1)
177 MIB.addOperand(*Src1);
178
179 for (const MachineOperand &MO : MI.implicit_operands())
180 MIB.addOperand(MO);
181
182 DEBUG(dbgs() << "e32 MI = "; MI.dump(); dbgs() << "\n";);
183 ++NumInstructionsShrunk;
184 MI.eraseFromParent();
185 }
186 }
187 return false;
188 }
3737 ; R600-CHECK: @bfi_sha256_ma
3838 ; R600-CHECK: XOR_INT * [[DST:T[0-9]+\.[XYZW]]], KC0[2].Z, KC0[2].W
3939 ; R600-CHECK: BFI_INT * {{T[0-9]+\.[XYZW]}}, {{[[DST]]|PV\.[XYZW]}}, KC0[3].X, KC0[2].W
40 ; SI-CHECK: V_XOR_B32_e64 [[DST:v[0-9]+]], {{[sv][0-9]+, v[0-9]+}}
40 ; SI-CHECK: V_XOR_B32_e32 [[DST:v[0-9]+]], {{[sv][0-9]+, v[0-9]+}}
4141 ; SI-CHECK: V_BFI_B32 {{v[0-9]+}}, [[DST]], {{[sv][0-9]+, [sv][0-9]+}}
4242
4343 define void @bfi_sha256_ma(i32 addrspace(1)* %out, i32 %x, i32 %y, i32 %z) {
4242 ; SI: V_MOV_B32_e32 [[VZERO:v[0-9]+]], 0
4343 ; SI: V_BCNT_U32_B32_e32 [[MIDRESULT:v[0-9]+]], [[VAL1]], [[VZERO]]
4444 ; SI-NOT: ADD
45 ; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]], [[VAL0]], [[MIDRESULT]]
45 ; SI: V_BCNT_U32_B32_e32 [[RESULT:v[0-9]+]], [[VAL0]], [[MIDRESULT]]
4646 ; SI: BUFFER_STORE_DWORD [[RESULT]],
4747 ; SI: S_ENDPGM
4848
5252 }
5353
5454 ; CHECK: @fne_f64
55 ; CHECK: V_CMP_NEQ_F64_e64 {{s[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]}}
55 ; CHECK: V_CMP_NEQ_F64_e32 vcc, {{v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]}}
5656
5757 define void @fne_f64(double addrspace(1)* %out, double addrspace(1)* %in1,
5858 double addrspace(1)* %in2) {
0 ;RUN: llc < %s -march=r600 -mcpu=verde -verify-machineinstrs | FileCheck %s
11
22 ;CHECK-LABEL: @main
3 ;CHECK: V_CMP_O_F32_e64 s[0:1], {{[sv][0-9]+, [sv][0-9]+}}, 0, 0
3 ;CHECK: V_CMP_O_F32_e32 vcc, {{[sv][0-9]+, v[0-9]+}}
44
55 define void @main(float %p) {
66 main_body:
0 ;RUN: llc < %s -march=r600 -mcpu=verde -verify-machineinstrs | FileCheck %s
11
22 ;CHECK-LABEL: @main
3 ;CHECK: V_CMP_U_F32_e64 s[0:1], {{[sv][0-9]+, [sv][0-9]+}}, 0, 0
3 ;CHECK: V_CMP_U_F32_e32 vcc, {{[sv][0-9]+, v[0-9]+}}
44
55 define void @main(float %p) {
66 main_body: