[llvm] [CodeGen] Introduce MIR-level target-independent rematerialization helper (PR #177080)
Quentin Colombet via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 12 17:54:44 PST 2026
================
@@ -0,0 +1,737 @@
+//=====-- Rematerializer.cpp - MIR rematerialization support ----*- C++ -*-===//
+//
+// 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
+//
+//==-----------------------------------------------------------------------===//
+//
+/// \file
+/// Implements helpers for target-independent rematerialization at the MIR
+/// level.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/Rematerializer.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/LiveIntervals.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Register.h"
+#include "llvm/CodeGen/TargetOpcodes.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "rematerializer"
+
+using namespace llvm;
+
+static bool isAvailableAtUse(const VNInfo *OVNI, LaneBitmask Mask,
+ SlotIndex UseIdx, const LiveInterval &LI) {
+ assert(OVNI);
+ if (OVNI != LI.getVNInfoAt(UseIdx))
+ return false;
+
+ // Check that subrange is live at user.
+ if (LI.hasSubRanges()) {
+ for (const LiveInterval::SubRange &SR : LI.subranges()) {
+ if ((SR.LaneMask & Mask).none())
+ continue;
+ if (!SR.liveAt(UseIdx))
+ return false;
+
+ // Early exit if all used lanes are checked. No need to continue.
+ Mask &= ~SR.LaneMask;
+ if (Mask.none())
+ break;
+ }
+ }
+ return true;
+}
+
+static Register isRegDependency(const MachineOperand &MO) {
+ if (!MO.isReg() || !MO.readsReg())
+ return Register();
+ Register Reg = MO.getReg();
+ if (Reg.isPhysical()) {
+ // By the requirements on trivially rematerializable instructions, a
+ // physical register use is either constant or ignorable.
+ return Register();
+ }
+ return Reg;
+}
+
+unsigned Rematerializer::rematerializeToRegion(unsigned RootIdx,
+ unsigned UseRegion,
+ DependencyReuseInfo &DRI) {
+
+ MachineInstr *FirstMI =
+ getReg(RootIdx).getRegionUseBounds(UseRegion, LIS).first;
+ unsigned NewRegIdx = rematerializeToPos(RootIdx, FirstMI, DRI);
+ transferRegionUsers(RootIdx, NewRegIdx, UseRegion);
+ return NewRegIdx;
+}
+
+unsigned
+Rematerializer::rematerializeToPos(unsigned RootIdx,
+ MachineBasicBlock::iterator InsertPos,
+ DependencyReuseInfo &DRI) {
+ LLVM_DEBUG({
+ rdbgs() << "Rematerializing " << printID(RootIdx) << " to "
+ << printUser(&*InsertPos) << '\n';
+ ++CallDepth;
+ });
+
+ // Create/identify dependencies for the new register. Copy the dependencies
+ // vector because underlying updates to the backing vector of registers may
+ // invalidate references.
+ SmallVector<Reg::Dependency, 2> NewDeps, Deps(Regs[RootIdx].Dependencies);
+ for (const Reg::Dependency &Dep : Deps) {
+ if (auto NewDep = DRI.DependencyMap.find(Dep.RegIdx);
+ NewDep != DRI.DependencyMap.end()) {
----------------
qcolombet wrote:
Could you do the assignment outside of the `if`?
Having 2 statements in the `if` looks wrong to me
https://github.com/llvm/llvm-project/pull/177080
More information about the llvm-commits
mailing list