Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LoongArch] Add a pass to rewrite rd to r0 for non-computational instrs whose return values are unused #94590

Merged
merged 1 commit into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions llvm/lib/Target/LoongArch/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ add_public_tablegen_target(LoongArchCommonTableGen)

add_llvm_target(LoongArchCodeGen
LoongArchAsmPrinter.cpp
LoongArchDeadRegisterDefinitions.cpp
LoongArchExpandAtomicPseudoInsts.cpp
LoongArchExpandPseudoInsts.cpp
LoongArchFrameLowering.cpp
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArch.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
MCOperand &MCOp,
const AsmPrinter &AP);

FunctionPass *createLoongArchDeadRegisterDefinitionsPass();
FunctionPass *createLoongArchExpandAtomicPseudoPass();
FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM);
FunctionPass *createLoongArchOptWInstrsPass();
FunctionPass *createLoongArchPreRAExpandPseudoPass();
FunctionPass *createLoongArchExpandPseudoPass();
void initializeLoongArchDAGToDAGISelLegacyPass(PassRegistry &);
void initializeLoongArchDeadRegisterDefinitionsPass(PassRegistry &);
void initializeLoongArchExpandAtomicPseudoPass(PassRegistry &);
void initializeLoongArchOptWInstrsPass(PassRegistry &);
void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &);
Expand Down
108 changes: 108 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchDeadRegisterDefinitions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//=== LoongArchDeadRegisterDefinitions.cpp - Replace dead defs w/ zero reg ===//
//
// 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 rewrites Rd to r0 for instrs whose return values are unused.
//
//===---------------------------------------------------------------------===//

#include "LoongArch.h"
#include "LoongArchInstrInfo.h"
#include "LoongArchSubtarget.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LiveDebugVariables.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/LiveStacks.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"

using namespace llvm;
#define DEBUG_TYPE "loongarch-dead-defs"
#define LoongArch_DEAD_REG_DEF_NAME "LoongArch Dead register definitions"

STATISTIC(NumDeadDefsReplaced, "Number of dead definitions replaced");

namespace {
class LoongArchDeadRegisterDefinitions : public MachineFunctionPass {
public:
static char ID;

LoongArchDeadRegisterDefinitions() : MachineFunctionPass(ID) {}
bool runOnMachineFunction(MachineFunction &MF) override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
AU.addRequired<LiveIntervals>();
AU.addPreserved<LiveIntervals>();
AU.addRequired<LiveIntervals>();
AU.addPreserved<SlotIndexes>();
AU.addPreserved<LiveDebugVariables>();
AU.addPreserved<LiveStacks>();
MachineFunctionPass::getAnalysisUsage(AU);
}

StringRef getPassName() const override { return LoongArch_DEAD_REG_DEF_NAME; }
};
} // end anonymous namespace

char LoongArchDeadRegisterDefinitions::ID = 0;
INITIALIZE_PASS(LoongArchDeadRegisterDefinitions, DEBUG_TYPE,
LoongArch_DEAD_REG_DEF_NAME, false, false)

FunctionPass *llvm::createLoongArchDeadRegisterDefinitionsPass() {
return new LoongArchDeadRegisterDefinitions();
}

bool LoongArchDeadRegisterDefinitions::runOnMachineFunction(
MachineFunction &MF) {
if (skipFunction(MF.getFunction()))
return false;

const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
LiveIntervals &LIS = getAnalysis<LiveIntervals>();
LLVM_DEBUG(dbgs() << "***** LoongArchDeadRegisterDefinitions *****\n");

bool MadeChange = false;
for (MachineBasicBlock &MBB : MF) {
for (MachineInstr &MI : MBB) {
// We only handle non-computational instructions.
const MCInstrDesc &Desc = MI.getDesc();
if (!Desc.mayLoad() && !Desc.mayStore() &&
!Desc.hasUnmodeledSideEffects())
continue;
for (int I = 0, E = Desc.getNumDefs(); I != E; ++I) {
MachineOperand &MO = MI.getOperand(I);
if (!MO.isReg() || !MO.isDef() || MO.isEarlyClobber())
continue;
// Be careful not to change the register if it's a tied operand.
if (MI.isRegTiedToUseOperand(I)) {
LLVM_DEBUG(dbgs() << " Ignoring, def is tied operand.\n");
continue;
}
Register Reg = MO.getReg();
if (!Reg.isVirtual() || !MO.isDead())
continue;
LLVM_DEBUG(dbgs() << " Dead def operand #" << I << " in:\n ";
MI.print(dbgs()));
const TargetRegisterClass *RC = TII->getRegClass(Desc, I, TRI, MF);
if (!(RC && RC->contains(LoongArch::R0))) {
LLVM_DEBUG(dbgs() << " Ignoring, register is not a GPR.\n");
continue;
}
assert(LIS.hasInterval(Reg));
LIS.removeInterval(Reg);
MO.setReg(LoongArch::R0);
LLVM_DEBUG(dbgs() << " Replacing with zero register. New:\n ";
MI.print(dbgs()));
++NumDeadDefsReplaced;
MadeChange = true;
}
}
}

return MadeChange;
}
24 changes: 24 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,19 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() {
RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target());
RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());
auto *PR = PassRegistry::getPassRegistry();
initializeLoongArchDeadRegisterDefinitionsPass(*PR);
initializeLoongArchOptWInstrsPass(*PR);
initializeLoongArchPreRAExpandPseudoPass(*PR);
initializeLoongArchDAGToDAGISelLegacyPass(*PR);
}

static cl::opt<bool> EnableLoongArchDeadRegisterElimination(
"loongarch-enable-dead-defs", cl::Hidden,
cl::desc("Enable the pass that removes dead"
" definitons and replaces stores to"
" them with stores to r0"),
cl::init(true));

static cl::opt<bool>
EnableLoopDataPrefetch("loongarch-enable-loop-data-prefetch", cl::Hidden,
cl::desc("Enable the loop data prefetch pass"),
Expand Down Expand Up @@ -148,6 +156,8 @@ class LoongArchPassConfig : public TargetPassConfig {
void addPreEmitPass2() override;
void addMachineSSAOptimization() override;
void addPreRegAlloc() override;
bool addRegAssignAndRewriteFast() override;
bool addRegAssignAndRewriteOptimized() override;
};
} // end namespace

Expand Down Expand Up @@ -200,3 +210,17 @@ void LoongArchPassConfig::addMachineSSAOptimization() {
void LoongArchPassConfig::addPreRegAlloc() {
addPass(createLoongArchPreRAExpandPseudoPass());
}

bool LoongArchPassConfig::addRegAssignAndRewriteFast() {
if (TM->getOptLevel() != CodeGenOptLevel::None &&
EnableLoongArchDeadRegisterElimination)
addPass(createLoongArchDeadRegisterDefinitionsPass());
return TargetPassConfig::addRegAssignAndRewriteFast();
}

bool LoongArchPassConfig::addRegAssignAndRewriteOptimized() {
if (TM->getOptLevel() != CodeGenOptLevel::None &&
EnableLoongArchDeadRegisterElimination)
addPass(createLoongArchDeadRegisterDefinitionsPass());
return TargetPassConfig::addRegAssignAndRewriteOptimized();
}
24 changes: 12 additions & 12 deletions llvm/test/CodeGen/LoongArch/global-address.ll
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,40 @@ define void @foo() nounwind {
; LA32NOPIC: # %bb.0:
; LA32NOPIC-NEXT: pcalau12i $a0, %got_pc_hi20(G)
; LA32NOPIC-NEXT: ld.w $a0, $a0, %got_pc_lo12(G)
; LA32NOPIC-NEXT: ld.w $a0, $a0, 0
; LA32NOPIC-NEXT: ld.w $zero, $a0, 0
; LA32NOPIC-NEXT: pcalau12i $a0, %pc_hi20(g)
; LA32NOPIC-NEXT: addi.w $a0, $a0, %pc_lo12(g)
; LA32NOPIC-NEXT: ld.w $a0, $a0, 0
; LA32NOPIC-NEXT: ld.w $zero, $a0, 0
; LA32NOPIC-NEXT: ret
;
; LA32PIC-LABEL: foo:
; LA32PIC: # %bb.0:
; LA32PIC-NEXT: pcalau12i $a0, %got_pc_hi20(G)
; LA32PIC-NEXT: ld.w $a0, $a0, %got_pc_lo12(G)
; LA32PIC-NEXT: ld.w $a0, $a0, 0
; LA32PIC-NEXT: ld.w $zero, $a0, 0
; LA32PIC-NEXT: pcalau12i $a0, %pc_hi20(.Lg$local)
; LA32PIC-NEXT: addi.w $a0, $a0, %pc_lo12(.Lg$local)
; LA32PIC-NEXT: ld.w $a0, $a0, 0
; LA32PIC-NEXT: ld.w $zero, $a0, 0
; LA32PIC-NEXT: ret
;
; LA64NOPIC-LABEL: foo:
; LA64NOPIC: # %bb.0:
; LA64NOPIC-NEXT: pcalau12i $a0, %got_pc_hi20(G)
; LA64NOPIC-NEXT: ld.d $a0, $a0, %got_pc_lo12(G)
; LA64NOPIC-NEXT: ld.w $a0, $a0, 0
; LA64NOPIC-NEXT: ld.w $zero, $a0, 0
; LA64NOPIC-NEXT: pcalau12i $a0, %pc_hi20(g)
; LA64NOPIC-NEXT: addi.d $a0, $a0, %pc_lo12(g)
; LA64NOPIC-NEXT: ld.w $a0, $a0, 0
; LA64NOPIC-NEXT: ld.w $zero, $a0, 0
; LA64NOPIC-NEXT: ret
;
; LA64PIC-LABEL: foo:
; LA64PIC: # %bb.0:
; LA64PIC-NEXT: pcalau12i $a0, %got_pc_hi20(G)
; LA64PIC-NEXT: ld.d $a0, $a0, %got_pc_lo12(G)
; LA64PIC-NEXT: ld.w $a0, $a0, 0
; LA64PIC-NEXT: ld.w $zero, $a0, 0
; LA64PIC-NEXT: pcalau12i $a0, %pc_hi20(.Lg$local)
; LA64PIC-NEXT: addi.d $a0, $a0, %pc_lo12(.Lg$local)
; LA64PIC-NEXT: ld.w $a0, $a0, 0
; LA64PIC-NEXT: ld.w $zero, $a0, 0
; LA64PIC-NEXT: ret
;
; LA64LARGENOPIC-LABEL: foo:
Expand All @@ -57,13 +57,13 @@ define void @foo() nounwind {
; LA64LARGENOPIC-NEXT: lu32i.d $t8, %got64_pc_lo20(G)
; LA64LARGENOPIC-NEXT: lu52i.d $t8, $t8, %got64_pc_hi12(G)
; LA64LARGENOPIC-NEXT: ldx.d $a0, $t8, $a0
; LA64LARGENOPIC-NEXT: ld.w $a0, $a0, 0
; LA64LARGENOPIC-NEXT: ld.w $zero, $a0, 0
; LA64LARGENOPIC-NEXT: pcalau12i $a0, %pc_hi20(g)
; LA64LARGENOPIC-NEXT: addi.d $t8, $zero, %pc_lo12(g)
; LA64LARGENOPIC-NEXT: lu32i.d $t8, %pc64_lo20(g)
; LA64LARGENOPIC-NEXT: lu52i.d $t8, $t8, %pc64_hi12(g)
; LA64LARGENOPIC-NEXT: add.d $a0, $t8, $a0
; LA64LARGENOPIC-NEXT: ld.w $a0, $a0, 0
; LA64LARGENOPIC-NEXT: ld.w $zero, $a0, 0
; LA64LARGENOPIC-NEXT: ret
;
; LA64LARGEPIC-LABEL: foo:
Expand All @@ -73,13 +73,13 @@ define void @foo() nounwind {
; LA64LARGEPIC-NEXT: lu32i.d $t8, %got64_pc_lo20(G)
; LA64LARGEPIC-NEXT: lu52i.d $t8, $t8, %got64_pc_hi12(G)
; LA64LARGEPIC-NEXT: ldx.d $a0, $t8, $a0
; LA64LARGEPIC-NEXT: ld.w $a0, $a0, 0
; LA64LARGEPIC-NEXT: ld.w $zero, $a0, 0
; LA64LARGEPIC-NEXT: pcalau12i $a0, %pc_hi20(.Lg$local)
; LA64LARGEPIC-NEXT: addi.d $t8, $zero, %pc_lo12(.Lg$local)
; LA64LARGEPIC-NEXT: lu32i.d $t8, %pc64_lo20(.Lg$local)
; LA64LARGEPIC-NEXT: lu52i.d $t8, $t8, %pc64_hi12(.Lg$local)
; LA64LARGEPIC-NEXT: add.d $a0, $t8, $a0
; LA64LARGEPIC-NEXT: ld.w $a0, $a0, 0
; LA64LARGEPIC-NEXT: ld.w $zero, $a0, 0
; LA64LARGEPIC-NEXT: ret
%V = load volatile i32, ptr @G
%v = load volatile i32, ptr @g
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ entry:
define void @csrrd_d_noret() {
; CHECK-LABEL: csrrd_d_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrrd $a0, 1
; CHECK-NEXT: csrrd $zero, 1
; CHECK-NEXT: ret
entry:
%0 = tail call i64 @llvm.loongarch.csrrd.d(i32 1)
Expand Down Expand Up @@ -240,7 +240,7 @@ entry:
define void @iocsrrd_d_noret(i32 %a) {
; CHECK-LABEL: iocsrrd_d_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: iocsrrd.d $a0, $a0
; CHECK-NEXT: iocsrrd.d $zero, $a0
; CHECK-NEXT: ret
entry:
%0 = tail call i64 @llvm.loongarch.iocsrrd.d(i32 %a)
Expand Down Expand Up @@ -290,7 +290,7 @@ entry:
define void @lddir_d_noret(i64 %a) {
; CHECK-LABEL: lddir_d_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: lddir $a0, $a0, 1
; CHECK-NEXT: lddir $zero, $a0, 1
; CHECK-NEXT: ret
entry:
%0 = tail call i64 @llvm.loongarch.lddir.d(i64 %a, i64 1)
Expand Down
10 changes: 5 additions & 5 deletions llvm/test/CodeGen/LoongArch/intrinsic.ll
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ entry:
define void @movfcsr2gr_noret() nounwind {
; CHECK-LABEL: movfcsr2gr_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movfcsr2gr $a0, $fcsr1
; CHECK-NEXT: movfcsr2gr $zero, $fcsr1
; CHECK-NEXT: ret
entry:
%res = call i32 @llvm.loongarch.movfcsr2gr(i32 1)
Expand Down Expand Up @@ -103,7 +103,7 @@ entry:
define void @csrrd_w_noret() {
; CHECK-LABEL: csrrd_w_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrrd $a0, 1
; CHECK-NEXT: csrrd $zero, 1
; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.loongarch.csrrd.w(i32 1)
Expand Down Expand Up @@ -185,7 +185,7 @@ entry:
define void @iocsrrd_b_noret(i32 %a) {
; CHECK-LABEL: iocsrrd_b_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: iocsrrd.b $a0, $a0
; CHECK-NEXT: iocsrrd.b $zero, $a0
; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.loongarch.iocsrrd.b(i32 %a)
Expand All @@ -195,7 +195,7 @@ entry:
define void @iocsrrd_h_noret(i32 %a) {
; CHECK-LABEL: iocsrrd_h_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: iocsrrd.h $a0, $a0
; CHECK-NEXT: iocsrrd.h $zero, $a0
; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.loongarch.iocsrrd.h(i32 %a)
Expand All @@ -205,7 +205,7 @@ entry:
define void @iocsrrd_w_noret(i32 %a) {
; CHECK-LABEL: iocsrrd_w_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: iocsrrd.w $a0, $a0
; CHECK-NEXT: iocsrrd.w $zero, $a0
; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.loongarch.iocsrrd.w(i32 %a)
Expand Down
Loading
Loading