Files
clang-p2996/llvm/lib/Target/SystemZ/SystemZCopyPhysRegs.cpp
Dominik Steenken e9a3ea2218 [SystemZ, DebugInfo] Instrument SystemZ backend passes for Instr-Ref DebugInfo (#133061)
This PR instruments the optimization passes in the SystemZ backend with
calls to `MachineFunction::substituteDebugValuesForInst` where
instruction substitutions are made to instructions that may compute
tracked values.

Tests are also added for each of the substitutions that were inserted.
Details on the individual passes follow.

### systemz-copy-physregs
When a copy targets an access register, we redirect the copy via an
auxiliary register. This leads to the final result being written by a
newly inserted SAR instruction, rather than the original MI, so we need
to update the debug value tracking to account for this.

### systemz-long-branch
This pass relaxes relative branch instructions based on the actual
locations of blocks. Only one of the branch instructions qualifies for
debug value tracking: BRCT, i.e. branch-relative-on-count, which
subtracts 1 from a register and branches if the result is not zero. This
is relaxed into an add-immediate and a conditional branch, so any
`debug-instr-number` present must move to the add-immediate instruction.

### systemz-post-rewrite
This pass replaces `LOCRMux` and `SELRMux` pseudoinstructions with
either the real versions of those instructions, or with branching
programs that implement the intent of the Pseudo. In all these cases,
any `debug-instr-number` attached to the pseudo needs to be reallocated
to the appropriate instruction in the result, either LOCR, SELR, or a
COPY.

### systemz-elim-compare
Similar to systemz-long-branch, for this pass, only few substitutions
are necessary, since it mainly deals with conditional branch
instructions. The only exceptiona are again branch-relative-on-count, as
it modifies a counter as part of the instruction, as well as any of the
load instructions that are affected.
2025-03-31 19:30:06 +02:00

115 lines
3.7 KiB
C++

//===---------- SystemZPhysRegCopy.cpp - Handle phys reg copies -----------===//
//
// Part of the LLVM Project, 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
//
//===----------------------------------------------------------------------===//
//
// This pass makes sure that a COPY of a physical register will be
// implementable after register allocation in copyPhysReg() (this could be
// done in EmitInstrWithCustomInserter() instead if COPY instructions would
// be passed to it).
//
//===----------------------------------------------------------------------===//
#include "SystemZTargetMachine.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
using namespace llvm;
namespace {
class SystemZCopyPhysRegs : public MachineFunctionPass {
public:
static char ID;
SystemZCopyPhysRegs()
: MachineFunctionPass(ID), TII(nullptr), MRI(nullptr) {
initializeSystemZCopyPhysRegsPass(*PassRegistry::getPassRegistry());
}
bool runOnMachineFunction(MachineFunction &MF) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
private:
bool visitMBB(MachineBasicBlock &MBB);
const SystemZInstrInfo *TII;
MachineRegisterInfo *MRI;
};
char SystemZCopyPhysRegs::ID = 0;
} // end anonymous namespace
INITIALIZE_PASS(SystemZCopyPhysRegs, "systemz-copy-physregs",
"SystemZ Copy Physregs", false, false)
FunctionPass *llvm::createSystemZCopyPhysRegsPass(SystemZTargetMachine &TM) {
return new SystemZCopyPhysRegs();
}
void SystemZCopyPhysRegs::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
MachineFunctionPass::getAnalysisUsage(AU);
}
bool SystemZCopyPhysRegs::visitMBB(MachineBasicBlock &MBB) {
bool Modified = false;
// Certain special registers can only be copied from a subset of the
// default register class of the type. It is therefore necessary to create
// the target copy instructions before regalloc instead of in copyPhysReg().
for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
MBBI != E; ) {
MachineInstr *MI = &*MBBI++;
if (!MI->isCopy())
continue;
DebugLoc DL = MI->getDebugLoc();
Register SrcReg = MI->getOperand(1).getReg();
Register DstReg = MI->getOperand(0).getReg();
if (DstReg.isVirtual() &&
(SrcReg == SystemZ::CC || SystemZ::AR32BitRegClass.contains(SrcReg))) {
Register Tmp = MRI->createVirtualRegister(&SystemZ::GR32BitRegClass);
if (SrcReg == SystemZ::CC)
BuildMI(MBB, MI, DL, TII->get(SystemZ::IPM), Tmp);
else
BuildMI(MBB, MI, DL, TII->get(SystemZ::EAR), Tmp).addReg(SrcReg);
MI->getOperand(1).setReg(Tmp);
Modified = true;
}
else if (SrcReg.isVirtual() &&
SystemZ::AR32BitRegClass.contains(DstReg)) {
Register Tmp = MRI->createVirtualRegister(&SystemZ::GR32BitRegClass);
MI->getOperand(0).setReg(Tmp);
MachineInstr *NMI =
BuildMI(MBB, MBBI, DL, TII->get(SystemZ::SAR), DstReg).addReg(Tmp);
// SAR now writes the final value to DstReg, so update debug values.
MBB.getParent()->substituteDebugValuesForInst(*MI, *NMI);
Modified = true;
}
}
return Modified;
}
bool SystemZCopyPhysRegs::runOnMachineFunction(MachineFunction &F) {
TII = F.getSubtarget<SystemZSubtarget>().getInstrInfo();
MRI = &F.getRegInfo();
bool Modified = false;
for (auto &MBB : F)
Modified |= visitMBB(MBB);
return Modified;
}