[llvm] [SPIR-V] Ensure that cleaning of temporary constants doesn't purge tracked constants (PR #95303)
Vyacheslav Levytskyy via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 12 13:27:37 PDT 2024
https://github.com/VyacheslavLevytskyy created https://github.com/llvm/llvm-project/pull/95303
This PR fixes a problem in logics of cleaning unused constants, ensuring that cleaning of temporary constants doesn't purge tracked constants. On a rare occasion when this happens SPIR-V Backend emits a code that refers to a non-existent register, earlier related with a constant. Attached to the PR test case is a minimal reproducer where names of variables and instructions lead to such a rare coincidence.
>From da30d725b5324dedc64a034b4eda2e6ad10fe273 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Wed, 12 Jun 2024 13:22:53 -0700
Subject: [PATCH] ensure that cleaning of temporary constants doesn't purge
tracked ones
---
llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp | 16 ++++++++----
llvm/test/CodeGen/SPIRV/keep-tracked-const.ll | 25 +++++++++++++++++++
2 files changed, 36 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/CodeGen/SPIRV/keep-tracked-const.ll
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index 53e0432192ca9..d899dde3d1393 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -41,7 +41,8 @@ class SPIRVPreLegalizer : public MachineFunctionPass {
static void
addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR,
const SPIRVSubtarget &STI,
- DenseMap<MachineInstr *, Type *> &TargetExtConstTypes) {
+ DenseMap<MachineInstr *, Type *> &TargetExtConstTypes,
+ SmallSet<Register, 4> &TrackedConstRegs) {
MachineRegisterInfo &MRI = MF.getRegInfo();
DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
SmallVector<MachineInstr *, 10> ToErase, ToEraseComposites;
@@ -80,6 +81,7 @@ addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR,
}
}
GR->add(Const, &MF, SrcReg);
+ TrackedConstRegs.insert(SrcReg);
if (Const->getType()->isTargetExtTy()) {
// remember association so that we can restore it when assign types
MachineInstr *SrcMI = MRI.getVRegDef(SrcReg);
@@ -121,7 +123,8 @@ addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR,
MI->eraseFromParent();
}
-static void foldConstantsIntoIntrinsics(MachineFunction &MF) {
+static void foldConstantsIntoIntrinsics(MachineFunction &MF,
+ SmallSet<Register, 4> &TrackedConstRegs) {
SmallVector<MachineInstr *, 10> ToErase;
MachineRegisterInfo &MRI = MF.getRegInfo();
const unsigned AssignNameOperandShift = 2;
@@ -137,7 +140,8 @@ static void foldConstantsIntoIntrinsics(MachineFunction &MF) {
MI.removeOperand(NumOp);
MI.addOperand(MachineOperand::CreateImm(
ConstMI->getOperand(1).getCImm()->getZExtValue()));
- if (MRI.use_empty(ConstMI->getOperand(0).getReg()))
+ Register DefReg = ConstMI->getOperand(0).getReg();
+ if (MRI.use_empty(DefReg) && !TrackedConstRegs.contains(DefReg))
ToErase.push_back(ConstMI);
}
}
@@ -836,8 +840,10 @@ bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
MachineIRBuilder MIB(MF);
// a registry of target extension constants
DenseMap<MachineInstr *, Type *> TargetExtConstTypes;
- addConstantsToTrack(MF, GR, ST, TargetExtConstTypes);
- foldConstantsIntoIntrinsics(MF);
+ // to keep record of tracked constants
+ SmallSet<Register, 4> TrackedConstRegs;
+ addConstantsToTrack(MF, GR, ST, TargetExtConstTypes, TrackedConstRegs);
+ foldConstantsIntoIntrinsics(MF, TrackedConstRegs);
insertBitcasts(MF, GR, MIB);
generateAssignInstrs(MF, GR, MIB, TargetExtConstTypes);
processSwitches(MF, GR, MIB);
diff --git a/llvm/test/CodeGen/SPIRV/keep-tracked-const.ll b/llvm/test/CodeGen/SPIRV/keep-tracked-const.ll
new file mode 100644
index 0000000000000..0c25d8a67aca0
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/keep-tracked-const.ll
@@ -0,0 +1,25 @@
+; This test case ensures that cleaning of temporary constants doesn't purge tracked ones.
+
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-SPIRV: %[[#Int:]] = OpTypeInt 32 0
+; CHECK-SPIRV: %[[#C0:]] = OpConstant %[[#Int]] 0
+; CHECK-SPIRV: %[[#C1:]] = OpConstant %[[#Int]] 1
+; CHECK-SPIRV: OpSelect %[[#Int]] %[[#]] %[[#C1]] %[[#C0]]
+
+
+define spir_kernel void @foo() {
+entry:
+ %addr = alloca i32
+ %r1 = call i8 @_Z20__spirv_SpecConstantia(i32 0, i8 1)
+ ; The name '%conv17.i' is important for the test case,
+ ; because it includes i32 0 when encoded for SPIR-V usage.
+ %conv17.i = sext i8 %r1 to i64
+ %tobool = trunc i8 %r1 to i1
+ %r2 = zext i1 %tobool to i32
+ store i32 %r2, ptr %addr
+ ret void
+}
+
+declare i8 @_Z20__spirv_SpecConstantia(i32, i8)
More information about the llvm-commits
mailing list