[llvm] [SPIR-V] Emit valid Lifestart/Lifestop instructions (PR #98475)

Vyacheslav Levytskyy via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 31 05:33:23 PDT 2024


https://github.com/VyacheslavLevytskyy updated https://github.com/llvm/llvm-project/pull/98475

>From 6235356210acce8568102c4d54c6dc2af1b651e5 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Thu, 11 Jul 2024 05:59:53 -0700
Subject: [PATCH 1/2] emit valid Lifestart/Lifestop instructions

---
 llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp   | 29 +++++++++++++++++++
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  4 +--
 .../CodeGen/SPIRV/llvm-intrinsics/lifetime.ll | 14 +++++++--
 3 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
index ae4e039744286..0691e86dad12d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -203,6 +203,30 @@ static void validateGroupWaitEventsPtr(const SPIRVSubtarget &STI,
   doInsertBitcast(STI, MRI, GR, I, OpReg, OpIdx, NewPtrType);
 }
 
+static void validateLifetimeStart(const SPIRVSubtarget &STI,
+                                  MachineRegisterInfo *MRI,
+                                  SPIRVGlobalRegistry &GR, MachineInstr &I) {
+  Register PtrReg = I.getOperand(0).getReg();
+  MachineFunction *MF = I.getParent()->getParent();
+  Register PtrTypeReg = getTypeReg(MRI, PtrReg);
+  SPIRVType *PtrType = GR.getSPIRVTypeForVReg(PtrTypeReg, MF);
+  SPIRVType *PonteeElemType = PtrType ? GR.getPointeeType(PtrType) : nullptr;
+  if (!PonteeElemType || PonteeElemType->getOpcode() == SPIRV::OpTypeVoid ||
+      (PonteeElemType->getOpcode() == SPIRV::OpTypeInt &&
+       PonteeElemType->getOperand(1).getImm() == 8))
+    return;
+  // To keep the code valid a bitcast must be inserted
+  SPIRV::StorageClass::StorageClass SC =
+      static_cast<SPIRV::StorageClass::StorageClass>(
+          PtrType->getOperand(1).getImm());
+  MachineIRBuilder MIB(I);
+  LLVMContext &Context = MF->getMMI().getModule()->getContext();
+  SPIRVType *ElemType =
+      GR.getOrCreateSPIRVType(IntegerType::getInt8Ty(Context), MIB);
+  SPIRVType *NewPtrType = GR.getOrCreateSPIRVPointerType(ElemType, MIB, SC);
+  doInsertBitcast(STI, MRI, GR, I, PtrReg, 0, NewPtrType);
+}
+
 static void validateGroupAsyncCopyPtr(const SPIRVSubtarget &STI,
                                       MachineRegisterInfo *MRI,
                                       SPIRVGlobalRegistry &GR, MachineInstr &I,
@@ -413,6 +437,11 @@ void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const {
                                       SPIRV::OpTypeBool))
           MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalNotEqual));
         break;
+      case SPIRV::OpLifetimeStart:
+      case SPIRV::OpLifetimeStop:
+        if (MI.getOperand(1).getImm() > 0)
+          validateLifetimeStart(STI, MRI, GR, MI);
+        break;
       case SPIRV::OpGroupAsyncCopy:
         validateGroupAsyncCopyPtr(STI, MRI, GR, MI, 3);
         validateGroupAsyncCopyPtr(STI, MRI, GR, MI, 4);
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index ed786bd33aa05..5b04cc6661e49 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -2088,9 +2088,7 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
                                                        : SPIRV::OpLifetimeStop;
     int64_t Size = I.getOperand(I.getNumExplicitDefs() + 1).getImm();
     Register PtrReg = I.getOperand(I.getNumExplicitDefs() + 2).getReg();
-    unsigned PonteeOpType = GR.getPointeeTypeOp(PtrReg);
-    bool IsNonvoidPtr = PonteeOpType != 0 && PonteeOpType != SPIRV::OpTypeVoid;
-    if (Size == -1 || IsNonvoidPtr)
+    if (Size == -1)
       Size = 0;
     BuildMI(BB, I, I.getDebugLoc(), TII.get(Op)).addUse(PtrReg).addImm(Size);
   } break;
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll
index 710a1581f760c..780521c5ebe26 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll
@@ -1,12 +1,20 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
 ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
+; CHECK-DAG: %[[#Char:]] = OpTypeInt 8 0
+; CHECK-DAG: %[[#PtrChar:]] = OpTypePointer Function %[[#Char]]
 ; CHECK: OpFunction
-; CHECK: %[[FooArg:.*]] = OpVariable
-; CHECK: OpLifetimeStart %[[FooArg]], 0
+; CHECK: %[[#FooArg:]] = OpVariable
+; CHECK: %[[#Casted1:]] = OpBitcast %[[#PtrChar]] %[[#FooArg]]
+; CHECK: OpLifetimeStart %[[#Casted1]], 72
 ; CHECK: OpCopyMemorySized
 ; CHECK: OpBitcast
 ; CHECK: OpInBoundsPtrAccessChain
-; CHECK: OpLifetimeStop %[[FooArg]], 0
+; CHECK: %[[#Casted2:]] = OpBitcast %[[#PtrChar]] %[[#FooArg]]
+; CHECK: OpLifetimeStop %[[#Casted2]], 72
 
 %tprange = type { %tparray }
 %tparray = type { [2 x i64] }

>From b48f5b304aafb6bea781afb393843ae48bfe1128 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Wed, 31 Jul 2024 05:33:10 -0700
Subject: [PATCH 2/2] fix getContext() and harden the test

---
 llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp   |  2 +-
 .../CodeGen/SPIRV/llvm-intrinsics/lifetime.ll | 49 +++++++++++++++----
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
index 0691e86dad12d..69d72a75a428a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -220,7 +220,7 @@ static void validateLifetimeStart(const SPIRVSubtarget &STI,
       static_cast<SPIRV::StorageClass::StorageClass>(
           PtrType->getOperand(1).getImm());
   MachineIRBuilder MIB(I);
-  LLVMContext &Context = MF->getMMI().getModule()->getContext();
+  LLVMContext &Context = MF->getFunction().getContext();
   SPIRVType *ElemType =
       GR.getOrCreateSPIRVType(IntegerType::getInt8Ty(Context), MIB);
   SPIRVType *NewPtrType = GR.getOrCreateSPIRVPointerType(ElemType, MIB, SC);
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll
index 780521c5ebe26..7fae8759c1f7d 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll
@@ -6,25 +6,56 @@
 
 ; CHECK-DAG: %[[#Char:]] = OpTypeInt 8 0
 ; CHECK-DAG: %[[#PtrChar:]] = OpTypePointer Function %[[#Char]]
+
+%tprange = type { %tparray }
+%tparray = type { [2 x i64] }
+
 ; CHECK: OpFunction
-; CHECK: %[[#FooArg:]] = OpVariable
-; CHECK: %[[#Casted1:]] = OpBitcast %[[#PtrChar]] %[[#FooArg]]
+; CHECK: %[[#FooVar:]] = OpVariable
+; CHECK: %[[#Casted1:]] = OpBitcast %[[#PtrChar]] %[[#FooVar]]
 ; CHECK: OpLifetimeStart %[[#Casted1]], 72
 ; CHECK: OpCopyMemorySized
 ; CHECK: OpBitcast
 ; CHECK: OpInBoundsPtrAccessChain
-; CHECK: %[[#Casted2:]] = OpBitcast %[[#PtrChar]] %[[#FooArg]]
+; CHECK: %[[#Casted2:]] = OpBitcast %[[#PtrChar]] %[[#FooVar]]
 ; CHECK: OpLifetimeStop %[[#Casted2]], 72
-
-%tprange = type { %tparray }
-%tparray = type { [2 x i64] }
-
 define spir_func void @foo(ptr noundef byval(%tprange) align 8 %_arg_UserRange) {
   %RoundedRangeKernel = alloca %tprange, align 8
-  call void @llvm.lifetime.start.p0(i64 72, ptr nonnull %RoundedRangeKernel) #7
+  call void @llvm.lifetime.start.p0(i64 72, ptr nonnull %RoundedRangeKernel)
+  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %RoundedRangeKernel, ptr align 8 %_arg_UserRange, i64 16, i1 false)
+  %KernelFunc = getelementptr inbounds i8, ptr %RoundedRangeKernel, i64 16
+  call void @llvm.lifetime.end.p0(i64 72, ptr nonnull %RoundedRangeKernel)
+  ret void
+}
+
+; CHECK: OpFunction
+; CHECK: %[[#BarVar:]] = OpVariable
+; CHECK: OpLifetimeStart %[[#BarVar]], 0
+; CHECK: OpCopyMemorySized
+; CHECK: OpBitcast
+; CHECK: OpInBoundsPtrAccessChain
+; CHECK: OpLifetimeStop %[[#BarVar]], 0
+define spir_func void @bar(ptr noundef byval(%tprange) align 8 %_arg_UserRange) {
+  %RoundedRangeKernel = alloca %tprange, align 8
+  call void @llvm.lifetime.start.p0(i64 -1, ptr nonnull %RoundedRangeKernel)
   call void @llvm.memcpy.p0.p0.i64(ptr align 8 %RoundedRangeKernel, ptr align 8 %_arg_UserRange, i64 16, i1 false)
   %KernelFunc = getelementptr inbounds i8, ptr %RoundedRangeKernel, i64 16
-  call void @llvm.lifetime.end.p0(i64 72, ptr nonnull %RoundedRangeKernel) #7
+  call void @llvm.lifetime.end.p0(i64 -1, ptr nonnull %RoundedRangeKernel)
+  ret void
+}
+
+; CHECK: OpFunction
+; CHECK: %[[#TestVar:]] = OpVariable
+; CHECK: OpLifetimeStart %[[#TestVar]], 1
+; CHECK: OpCopyMemorySized
+; CHECK: OpInBoundsPtrAccessChain
+; CHECK: OpLifetimeStop %[[#TestVar]], 1
+define spir_func void @test(ptr noundef align 8 %_arg) {
+  %var = alloca i8, align 8
+  call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %var)
+  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %var, ptr align 8 %_arg, i64 1, i1 false)
+  %KernelFunc = getelementptr inbounds i8, ptr %var, i64 0
+  call void @llvm.lifetime.end.p0(i64 1, ptr nonnull %var)
   ret void
 }
 



More information about the llvm-commits mailing list