[llvm] 9c29217 - [SPIR-V] Ensure that cleaning of temporary constants doesn't purge tracked constants (#95303)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 13 00:28:24 PDT 2024
Author: Vyacheslav Levytskyy
Date: 2024-06-13T09:28:19+02:00
New Revision: 9c29217a170566890d76b56ccfbbf9ceaa1193ab
URL: https://github.com/llvm/llvm-project/commit/9c29217a170566890d76b56ccfbbf9ceaa1193ab
DIFF: https://github.com/llvm/llvm-project/commit/9c29217a170566890d76b56ccfbbf9ceaa1193ab.diff
LOG: [SPIR-V] Ensure that cleaning of temporary constants doesn't purge tracked constants (#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.
Added:
llvm/test/CodeGen/SPIRV/keep-tracked-const.ll
Modified:
llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index 53e0432192ca9..2df96c45b4a88 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,9 @@ addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR,
MI->eraseFromParent();
}
-static void foldConstantsIntoIntrinsics(MachineFunction &MF) {
+static void
+foldConstantsIntoIntrinsics(MachineFunction &MF,
+ const SmallSet<Register, 4> &TrackedConstRegs) {
SmallVector<MachineInstr *, 10> ToErase;
MachineRegisterInfo &MRI = MF.getRegInfo();
const unsigned AssignNameOperandShift = 2;
@@ -137,7 +141,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 +841,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