Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions llvm/lib/Target/AIE/AIE.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ MachineFunctionPass *createAIEEliminateDuplicatePHI();
FunctionPass *createAIEOutlineMemoryGEP();
FunctionPass *createAIESuperRegRewriter();
FunctionPass *createAIEWawRegRewriter();
FunctionPass *createAIEUnallocatedSuperRegRewriter();
FunctionPass *createAIEPostSelectOptimize();
MachineFunctionPass *
createDeadMachineInstructionElim(bool KeepLifetimeInstructions);
Expand All @@ -84,6 +85,8 @@ extern char &AIESuperRegRewriterID;
void initializeAIESuperRegRewriterPass(PassRegistry &);
extern char &AIEWawRegRewriterID;
void initializeAIEWawRegRewriterPass(PassRegistry &);
extern char &AIEUnallocatedSuperRegRewriterID;
void initializeAIEUnallocatedSuperRegRewriterPass(PassRegistry &);
extern char &AIEOutlineMemoryGEPID;
void initializeAIEOutlineMemoryGEPPass(PassRegistry &);

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/AIE/AIEBaseTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAIETarget() {
initializeAIEPseudoBranchExpansionPass(*PR);
initializeAIESubRegConstrainerPass(*PR);
initializeAIESuperRegRewriterPass(*PR);
initializeAIEUnallocatedSuperRegRewriterPass(*PR);
initializeAIEWawRegRewriterPass(*PR);
initializeAIEOutlineMemoryGEPPass(*PR);
initializeAIEFinalizeBundlePass(*PR);
Expand Down
25 changes: 16 additions & 9 deletions llvm/lib/Target/AIE/AIESuperRegUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,21 +184,26 @@ LaneBitmask getLiveLanesAt(SlotIndex Index, Register Reg,
return LiveLanes;
}

void rewriteSuperReg(Register Reg, Register AssignedPhysReg,
void rewriteSuperReg(Register Reg, std::optional<Register> AssignedPhysReg,
SmallSet<int, 8> &SubRegs, MachineRegisterInfo &MRI,
const AIEBaseRegisterInfo &TRI, VirtRegMap &VRM,
LiveRegMatrix &LRM, LiveIntervals &LIS,
SlotIndexes &Indexes, LiveDebugVariables &DebugVars) {
LLVM_DEBUG(dbgs() << "Rewriting " << printReg(Reg, &TRI, 0, &MRI) << '\n');
auto *TII = static_cast<const AIEBaseInstrInfo *>(
VRM.getMachineFunction().getSubtarget().getInstrInfo());
MachineFunction &MF = VRM.getMachineFunction();
auto *TII =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: const

static_cast<const AIEBaseInstrInfo *>(MF.getSubtarget().getInstrInfo());

// Collect all the subreg indices to rewrite as independent vregs.
SmallMapVector<int, Register, 8> SubRegToVReg;
const TargetRegisterClass *SuperRC = MRI.getRegClass(Reg);
assert(!SubRegs.empty());
for (int SubReg : SubRegs) {
const TargetRegisterClass *SubRC = TRI.getSubRegisterClass(SuperRC, SubReg);
const TargetRegisterClass *SubRC =
AssignedPhysReg.has_value()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we care if the AssignedPhysReg is passed?
If we go for largestLegalSuperclass, we aren't really going for subreg rewriting, but for a regular copy.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the check be if a subregisterClass exists and if we fail to retrieve it we should go for largestlegalSuperclass?
In the failure to get a subregClass should we still iterate through all the subregs?
Don't group multiple together if we use a superclass?

? TRI.getSubRegisterClass(SuperRC, SubReg)
: TRI.getLargestLegalSuperClass(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

TRI.getSubRegisterClass(SuperRC, SubReg), MF);
SubRegToVReg[SubReg] = MRI.createVirtualRegister(SubRC);
}

Expand Down Expand Up @@ -246,7 +251,6 @@ void rewriteSuperReg(Register Reg, Register AssignedPhysReg,
LIS.removeInterval(Reg);

for (auto &[SubRegIdx, VReg] : SubRegToVReg) {
MCRegister SubPhysReg = TRI.getSubReg(AssignedPhysReg, SubRegIdx);
LiveInterval &SubRegLI = LIS.getInterval(VReg);
LLVM_DEBUG(dbgs() << " Assigning Range: " << SubRegLI << '\n');

Expand All @@ -257,10 +261,13 @@ void rewriteSuperReg(Register Reg, Register AssignedPhysReg,
LIComponents.push_back(&SubRegLI);
VRM.grow();

for (LiveInterval *LI : LIComponents) {
LRM.assign(*LI, SubPhysReg);
VRM.setRequiredPhys(LI->reg(), SubPhysReg);
LLVM_DEBUG(dbgs() << " Assigned " << printReg(LI->reg()) << "\n");
if (AssignedPhysReg.has_value()) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

early return.

MCRegister SubPhysReg = TRI.getSubReg(*AssignedPhysReg, SubRegIdx);
for (LiveInterval *LI : LIComponents) {
LRM.assign(*LI, SubPhysReg);
VRM.setRequiredPhys(LI->reg(), SubPhysReg);
LLVM_DEBUG(dbgs() << " Assigned " << printReg(LI->reg()) << "\n");
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AIE/AIESuperRegUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define LLVM_LIB_TARGET_AIE_AIESUPERREGUTILS_H

#include "llvm/ADT/SmallSet.h"
#include <optional>

namespace llvm {
class Register;
Expand Down Expand Up @@ -63,7 +64,7 @@ void rewriteFullCopy(MachineInstr &MI, const std::set<int> &CopySubRegs,
LaneBitmask getLiveLanesAt(SlotIndex Index, Register Reg,
const LiveIntervals &LIS);

void rewriteSuperReg(Register Reg, Register AssignedPhysReg,
void rewriteSuperReg(Register Reg, std::optional<Register> AssignedPhysReg,
SmallSet<int, 8> &SubRegs, MachineRegisterInfo &MRI,
const AIEBaseRegisterInfo &TRI, VirtRegMap &VRM,
LiveRegMatrix &LRM, LiveIntervals &LIS,
Expand Down
171 changes: 171 additions & 0 deletions llvm/lib/Target/AIE/AIEUnallocatedSuperRegRewriter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
//===-- AIEUnallocatedSuperRegRewriter.cpp - Constrain tied sub-registers -===//
//
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// (c) Copyright 2025 Advanced Micro Devices, Inc. or its affiliates
//
//===----------------------------------------------------------------------===//

#include "AIEBaseInstrInfo.h"
#include "AIEBaseRegisterInfo.h"
#include "AIESuperRegUtils.h"

#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/CodeGen/LiveDebugVariables.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/LiveRegMatrix.h"
#include "llvm/CodeGen/LiveStacks.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#define DEBUG_TYPE "aie-ra-prepare"

namespace {

using RegRewriteInfo = std::vector<std::pair<Register, SmallSet<int, 8>>>;

/// Split large unallocated compound registers into multiple new smaller vregs
/// Than can be allocated to scalar registers.
class AIEUnallocatedSuperRegRewriter : public MachineFunctionPass {

public:
static char ID;
AIEUnallocatedSuperRegRewriter() : MachineFunctionPass(ID) {}

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
AU.addPreserved<MachineBlockFrequencyInfoWrapperPass>();
AU.addRequired<VirtRegMapWrapperLegacy>();
AU.addPreserved<VirtRegMapWrapperLegacy>();
AU.addRequired<SlotIndexesWrapperPass>();
AU.addPreserved<SlotIndexesWrapperPass>();
AU.addRequired<LiveDebugVariablesWrapperLegacy>();
AU.addPreserved<LiveDebugVariablesWrapperLegacy>();
AU.addRequired<LiveStacksWrapperLegacy>();
AU.addPreserved<LiveStacksWrapperLegacy>();
AU.addRequired<LiveIntervalsWrapperPass>();
AU.addPreserved<LiveIntervalsWrapperPass>();
AU.addRequired<LiveRegMatrixWrapperLegacy>();
AU.addPreserved<LiveRegMatrixWrapperLegacy>();
MachineFunctionPass::getAnalysisUsage(AU);
}

bool runOnMachineFunction(MachineFunction &Fn) override;
};

/// Identify unallocated virtual registers that can be split into subregisters.
/// Returns a list of candidate registers with their rewritable subregister
/// indices, excluding unused registers and those already assigned to physical
/// registers.
static RegRewriteInfo getRewriteCandidates(MachineRegisterInfo &MRI,
const AIEBaseRegisterInfo &TRI,
VirtRegMap &VRM) {
RegRewriteInfo RegistersToRewrite;
for (unsigned VRegIdx = 0, End = MRI.getNumVirtRegs(); VRegIdx != End;
++VRegIdx) {
const Register Reg = Register::index2VirtReg(VRegIdx);

// Ignore un-used registers
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complete the comment.

if (MRI.reg_nodbg_empty(Reg) || VRM.hasPhys(Reg))
continue;

SmallSet<int, 8> RewritableSubRegs =
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

AIESuperRegUtils::getRewritableSubRegs(Reg, MRI, TRI);

if (RewritableSubRegs.empty())
continue;

LLVM_DEBUG(dbgs() << "Candidate " << printReg(Reg, &TRI, 0, &MRI) << ":"
<< printRegClassOrBank(Reg, MRI, &TRI) << '\n');

RegistersToRewrite.push_back({Reg, RewritableSubRegs});
}

LLVM_DEBUG(dbgs() << "Found " << RegistersToRewrite.size()
<< " candidate register(s) for rewriting\n");

return RegistersToRewrite;
}

/// Split candidate registers into independent virtual registers for each
/// subregister. Each composite register is rewritten using its subregister
/// indices, with live intervals and debug information updated accordingly.
void rewriteCandidates(RegRewriteInfo &RegistersToRewrite,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these the candidates to rewrite?
nit: rename for clarity

MachineRegisterInfo &MRI, const AIEBaseRegisterInfo &TRI,
VirtRegMap &VRM, LiveRegMatrix &LRM, LiveIntervals &LIS,
SlotIndexes &Indexes, LiveDebugVariables &DebugVars) {

LLVM_DEBUG(dbgs() << "Rewriting " << RegistersToRewrite.size()
<< " candidate register(s)\n");

for (auto [VReg, SubRegs] : RegistersToRewrite) {
LLVM_DEBUG(dbgs() << " Rewriting " << printReg(VReg, &TRI, 0, &MRI)
<< " into " << SubRegs.size() << " subregister(s)\n");
AIESuperRegUtils::rewriteSuperReg(
VReg, /*std::optional<Register> AssignedPhysReg = */ {}, SubRegs, MRI,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Local var for Assign...

TRI, VRM, LRM, LIS, Indexes, DebugVars);
}
}

bool AIEUnallocatedSuperRegRewriter::runOnMachineFunction(MachineFunction &MF) {
LLVM_DEBUG(llvm::dbgs() << "*** Splitting unallocated super-registers: "
<< MF.getName() << " ***\n");

MachineRegisterInfo &MRI = MF.getRegInfo();
VirtRegMap &VRM = getAnalysis<VirtRegMapWrapperLegacy>().getVRM();
LiveRegMatrix &LRM = getAnalysis<LiveRegMatrixWrapperLegacy>().getLRM();
LiveIntervals &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
SlotIndexes &Indexes = getAnalysis<SlotIndexesWrapperPass>().getSI();
LiveDebugVariables &DebugVars =
getAnalysis<LiveDebugVariablesWrapperLegacy>().getLDV();
auto &TRI =
*static_cast<const AIEBaseRegisterInfo *>(MRI.getTargetRegisterInfo());

LLVM_DEBUG(dbgs() << "Identifying rewrite candidates...\n");
RegRewriteInfo RegistersToRewrite = getRewriteCandidates(MRI, TRI, VRM);

if (RegistersToRewrite.empty()) {
LLVM_DEBUG(dbgs() << "No candidates found, skipping rewrite\n");
return false;
}

LLVM_DEBUG(dbgs() << "Performing register rewrites...\n");
rewriteCandidates(RegistersToRewrite, MRI, TRI, VRM, LRM, LIS, Indexes,
DebugVars);

LLVM_DEBUG(dbgs() << "Successfully rewrote " << RegistersToRewrite.size()
<< " register(s)\n");

return !RegistersToRewrite.empty();
}

} // end anonymous namespace

char AIEUnallocatedSuperRegRewriter::ID = 0;
char &llvm::AIEUnallocatedSuperRegRewriterID =
AIEUnallocatedSuperRegRewriter::ID;

INITIALIZE_PASS(AIEUnallocatedSuperRegRewriter,
"aie-unallocated-superreg-rewrite",
"AIE unallocated super-reg rewrite", false, false)

llvm::FunctionPass *llvm::createAIEUnallocatedSuperRegRewriter() {
return new AIEUnallocatedSuperRegRewriter();
}
1 change: 1 addition & 0 deletions llvm/lib/Target/AIE/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ add_llvm_target(AIECodeGen
AIE2TargetMachine.cpp
AIE2TargetTransformInfo.cpp
AIETiedRegOperands.cpp
AIEUnallocatedSuperRegRewriter.cpp
ReservedRegsLICM.cpp
AIEOutlineMemoryGEP.cpp
AIEWawRegRewriter.cpp
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/AIE/aie2p/AIE2PTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ bool AIE2PPassConfig::addRegAssignAndRewriteOptimized() {
addPass(createAIESuperRegRewriter());
addPass(createGreedyRegisterAllocator(onlyAllocate3D2DRegisters));
addPass(createAIESuperRegRewriter());
if (EnableFineGrainedStagedRA)
addPass(createAIEUnallocatedSuperRegRewriter());
}
addPass(createGreedyRegisterAllocator());
if (EnableWAWRegRewrite) {
Expand Down
2 changes: 2 additions & 0 deletions llvm/test/CodeGen/AIE/aie2p/llc-pipeline-aie2p.ll
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@
; AIE-O1-NEXT: AIE super-reg rewrite
; AIE-O1-NEXT: Greedy Register Allocator
; AIE-O1-NEXT: AIE super-reg rewrite
; AIE-O1-NEXT: AIE unallocated super-reg rewrite
; AIE-O1-NEXT: Greedy Register Allocator
; AIE-O1-NEXT: AIE waw-reg rewrite
; AIE-O1-NEXT: Greedy Register Allocator
Expand Down Expand Up @@ -472,6 +473,7 @@
; AIE-O23-NEXT: AIE super-reg rewrite
; AIE-O23-NEXT: Greedy Register Allocator
; AIE-O23-NEXT: AIE super-reg rewrite
; AIE-O23-NEXT: AIE unallocated super-reg rewrite
; AIE-O23-NEXT: Greedy Register Allocator
; AIE-O23-NEXT: AIE waw-reg rewrite
; AIE-O23-NEXT: Greedy Register Allocator
Expand Down
Loading