Skip to content

Commit 4c9997f

Browse files
committed
CodeGen: Record tied virtual register operands in finalizeBundle
This is in preparation of a future AMDGPU change where we are going to create bundles before register allocation and want to rely on the TwoAddressInstructionPass handling those bundles correctly. commit-id:64872792 Pull Request: nhaehnle#8
1 parent 4ac74fc commit 4c9997f

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

llvm/lib/CodeGen/MachineInstrBundle.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ void llvm::finalizeBundle(MachineBasicBlock &MBB,
136136
SmallSetVector<Register, 8> ExternUses;
137137
SmallSet<Register, 8> KilledUseSet;
138138
SmallSet<Register, 8> UndefUseSet;
139+
SmallVector<std::pair<Register, Register>> TiedOperands;
139140
for (auto MII = FirstMI; MII != LastMI; ++MII) {
140141
// Debug instructions have no effects to track.
141142
if (MII->isDebugInstr())
@@ -161,6 +162,16 @@ void llvm::finalizeBundle(MachineBasicBlock &MBB,
161162
// External def is now killed.
162163
KilledUseSet.insert(Reg);
163164
}
165+
if (MO.isTied()) {
166+
// Record tied operand constraints that involve virtual registers so
167+
// that bundles that are formed pre-register allocation reflect the
168+
// relevant constraints.
169+
unsigned TiedIdx = MII->findTiedOperandIdx(MO.getOperandNo());
170+
MachineOperand &TiedMO = MII->getOperand(TiedIdx);
171+
Register DefReg = TiedMO.getReg();
172+
if (Reg.isVirtual() || DefReg.isVirtual())
173+
TiedOperands.emplace_back(DefReg, Reg);
174+
}
164175
}
165176
}
166177

@@ -203,7 +214,17 @@ void llvm::finalizeBundle(MachineBasicBlock &MBB,
203214
bool isKill = KilledUseSet.contains(Reg);
204215
bool isUndef = UndefUseSet.contains(Reg);
205216
MIB.addReg(Reg, getKillRegState(isKill) | getUndefRegState(isUndef) |
206-
getImplRegState(true));
217+
getImplRegState(true));
218+
}
219+
220+
for (auto [DefReg, UseReg] : TiedOperands) {
221+
unsigned DefIdx =
222+
std::distance(LocalDefs.begin(), llvm::find(LocalDefs, DefReg));
223+
unsigned UseIdx =
224+
std::distance(ExternUses.begin(), llvm::find(ExternUses, UseReg));
225+
assert(DefIdx < LocalDefs.size());
226+
assert(UseIdx < ExternUses.size());
227+
MIB->tieOperands(DefIdx, LocalDefs.size() + UseIdx);
207228
}
208229
}
209230

llvm/unittests/Target/AMDGPU/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ add_llvm_target_unittest(AMDGPUTests
2424
DwarfRegMappings.cpp
2525
ExecMayBeModifiedBeforeAnyUse.cpp
2626
LiveRegUnits.cpp
27+
MachineInstrBundleTest.cpp
2728
PALMetadata.cpp
2829
)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//===- MachineInstrBundleTest.cpp -----------------------------------------===//
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+
#include "AMDGPUTargetMachine.h"
10+
#include "AMDGPUUnitTests.h"
11+
#include "llvm/CodeGen/MachineFunction.h"
12+
#include "llvm/CodeGen/MachineInstrBuilder.h"
13+
#include "llvm/CodeGen/MachineModuleInfo.h"
14+
#include "gtest/gtest.h"
15+
16+
using namespace llvm;
17+
18+
namespace {
19+
20+
TEST(AMDGPU, TiedOperandsBundle) {
21+
auto TM = createAMDGPUTargetMachine("amdgcn-amd-", "gfx1100", "");
22+
23+
GCNSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
24+
std::string(TM->getTargetFeatureString()), *TM);
25+
26+
LLVMContext Ctx;
27+
Module Mod("Module", Ctx);
28+
Mod.setDataLayout(TM->createDataLayout());
29+
30+
auto *Type = FunctionType::get(Type::getVoidTy(Ctx), false);
31+
auto *F = Function::Create(Type, GlobalValue::ExternalLinkage, "Test", &Mod);
32+
33+
MachineModuleInfo MMI(TM.get());
34+
auto MF =
35+
std::make_unique<MachineFunction>(*F, *TM, ST, MMI.getContext(), 42);
36+
auto *BB = MF->CreateMachineBasicBlock();
37+
MF->push_back(BB);
38+
39+
const auto &TII = *ST.getInstrInfo();
40+
auto &MRI = MF->getRegInfo();
41+
42+
Register RX = MRI.createVirtualRegister(&AMDGPU::SReg_32_XEXEC_HIRegClass);
43+
Register RY = MRI.createVirtualRegister(&AMDGPU::SReg_32_XEXEC_HIRegClass);
44+
45+
MachineInstr *MI =
46+
BuildMI(*BB, BB->begin(), {}, TII.get(AMDGPU::COPY), RX).addReg(RY);
47+
MI->tieOperands(0, 1);
48+
49+
finalizeBundle(*BB, MI->getIterator(), std::next(MI->getIterator()));
50+
51+
MachineInstr *Bundle = &*BB->begin();
52+
EXPECT_TRUE(Bundle->getOpcode() == AMDGPU::BUNDLE);
53+
EXPECT_EQ(Bundle->getNumOperands(), 2u);
54+
EXPECT_EQ(Bundle->getOperand(0).getReg(), RX);
55+
EXPECT_EQ(Bundle->getOperand(1).getReg(), RY);
56+
EXPECT_TRUE(Bundle->getOperand(0).isTied());
57+
EXPECT_TRUE(Bundle->getOperand(1).isTied());
58+
EXPECT_EQ(Bundle->findTiedOperandIdx(0), 1u);
59+
}
60+
61+
} // end namespace

0 commit comments

Comments
 (0)