[llvm] [RISCV] Add a pass to eliminate special copies in order to facilitate shrink-wrap optimization (PR #140716)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Tue May 20 10:55:49 PDT 2025
================
@@ -0,0 +1,150 @@
+//===- RISCVCopyCombine.cpp - Remove special copy for RISC-V --===//
+//
+// 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 attempts a shrink-wrap optimization for special cases, which is
+// effective when data types require extension.
+//
+// After finalize-isel:
+// bb0:
+// liveins: $x10, $x11
+// %1:gpr = COPY $x11 ---- will be delete in this pass
+// %0:gpr = COPY $x10
+// %2:gpr = COPY %1:gpr ---- without this pass, sink to bb1 in machine-sink,
+// then delete at regalloc
+// BEQ %0:gpr, killed %3:gpr, %bb.3 PseudoBR %bb1
+//
+// bb1:
+// bb2:
+// BNE %2:gpr, killed %5:gpr, %bb.2
+// ...
+// After regalloc
+// bb0:
+// liveins: $x10, $x11
+// renamable $x8 = COPY $x11
+// renamable $x11 = ADDI $x0, 57 --- def x11, so COPY can not be sink
+// BEQ killed renamable $x10, killed renamable $x11, %bb.4
+// PseudoBR %bb.1
+//
+// bb1:
+// bb2:
+// BEQ killed renamable $x8, killed renamable $x10, %bb.4
+//
+// ----->
+//
+// After this pass:
+// bb0:
+// liveins: $x10, $x11
+// %0:gpr = COPY $x10
+// %2:gpr = COPY $x11
+// BEQ %0:gpr, killed %3:gpr, %bb.3
+// PseudoBR %bb1
+//
+// bb1:
+// bb2:
+// BNE %2:gpr, killed %5:gpr, %bb.2
+// ...
+// After regalloc
+// bb0:
+// liveins: $x10, $x11
+// renamable $x12 = ADDI $x0, 57
+// renamable $x8 = COPY $x11
+// BEQ killed renamable $x10, killed renamable $x11, %bb.4
+// PseudoBR %bb.1
+//
+// bb1:
+// bb2:
+// BEQ killed renamable $x8, killed renamable $x10, %bb.4
+//===---------------------------------------------------------------------===//
+
+#include "RISCV.h"
+#include "RISCVSubtarget.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+
+using namespace llvm;
+#define DEBUG_TYPE "riscv-copy-combine"
+#define RISCV_COPY_COMBINE "RISC-V Copy Combine"
+
+STATISTIC(NumCopyDeleted, "Number of copy deleted");
+
+namespace {
+class RISCVCopyCombine : public MachineFunctionPass {
+public:
+ static char ID;
+ const TargetInstrInfo *TII;
+ MachineRegisterInfo *MRI;
+ const TargetRegisterInfo *TRI;
+ const RISCVSubtarget *ST;
+
+ RISCVCopyCombine() : MachineFunctionPass(ID) {}
+ bool runOnMachineFunction(MachineFunction &MF) override;
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::IsSSA);
+ }
+
+ StringRef getPassName() const override { return RISCV_COPY_COMBINE; }
+
+private:
+ bool optimizeBlock(MachineBasicBlock &MBB);
+};
+} // end anonymous namespace
+
+char RISCVCopyCombine::ID = 0;
+INITIALIZE_PASS(RISCVCopyCombine, DEBUG_TYPE, RISCV_COPY_COMBINE, false, false)
+
+bool RISCVCopyCombine::optimizeBlock(MachineBasicBlock &MBB) {
+ MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
+ SmallVector<MachineOperand, 3> Cond;
+ if (TII->analyzeBranch(MBB, TBB, FBB, Cond, /*AllowModify*/ false) ||
+ Cond.empty())
+ return false;
+
+ if (!TBB || Cond.size() != 3)
+ return false;
+
+ MachineInstr *MI = MRI->getVRegDef(Cond[1].getReg());
+ if (MI->getOpcode() == RISCV::COPY) {
+ if (MRI->hasOneUse(MI->getOperand(1).getReg()) &&
+ MI->getOperand(1).getReg().isVirtual() &&
+ MI->getOperand(0).getReg().isVirtual()) {
+ MachineInstr *Src = MRI->getVRegDef(MI->getOperand(1).getReg());
+ if (Src && Src->getOpcode() == RISCV::COPY &&
+ Src->getParent() == MI->getParent()) {
+ MRI->replaceRegWith(MI->getOperand(1).getReg(),
+ Src->getOperand(1).getReg());
+ LLVM_DEBUG(dbgs() << "Deleting this copy instruction ";
----------------
topperc wrote:
Do we need to update any kill flags here?
https://github.com/llvm/llvm-project/pull/140716
More information about the llvm-commits
mailing list