[llvm] [SPIRV] Fix OpBuildNDRange (PR #186153)

via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 18 08:09:33 PDT 2026


https://github.com/idubinov updated https://github.com/llvm/llvm-project/pull/186153

>From 55e06937a650282e550685d0a9b050307b628c56 Mon Sep 17 00:00:00 2001
From: idubinov <igor.dubinov at amd.com>
Date: Wed, 11 Mar 2026 06:32:07 -0500
Subject: [PATCH 1/8] Fix buildNDRange

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp | 150 ++++++++++++++++--------
 llvm/lib/Target/SPIRV/SPIRVBuiltins.td  |   6 +-
 2 files changed, 106 insertions(+), 50 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index f9a9127446013..9a5d14276a321 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -2620,65 +2620,121 @@ static bool generatePredicatedLoadStoreInst(const SPIRV::IncomingCall *Call,
 static bool buildNDRange(const SPIRV::IncomingCall *Call,
                          MachineIRBuilder &MIRBuilder,
                          SPIRVGlobalRegistry *GR) {
+  // The OpenCL ndrange_*D functions are overloaded and support 1D, 2D, and 3D
+  // variants, accepting 1 to 3 arguments:
+  //   (global_work_size)
+  //   (global_work_size, local_work_size)
+  //   (global_work_offset, global_work_size, local_work_size)  -- note the
+  //   argument reordering
+  //
+  // SPIR-V's OpBuildNDRange takes all three arguments (GlobalWorkSize,
+  // LocalWorkSize, GlobalWorkOffset). For 1D kernels the values are scalars;
+  // for 2D/3D they are arrays of 2 or 3 elements. Any missing argument is
+  // set to zero.
+
+  unsigned NumArgs = Call->Arguments.size();
+  assert(NumArgs >= 2 && NumArgs <= 4);
+
+  const unsigned ReturnValueArgIdx = 0;
+  const unsigned IncorrectArgIdx = 5;
+  const unsigned GlobalWorkSizeArgIdx = NumArgs < 4 ? 1 : 2;
+  const unsigned LocalWorkSizeArgIdx =
+      NumArgs == 2 ? IncorrectArgIdx : (NumArgs == 3 ? 2 : 3);
+  const unsigned GlobalWorkOffsetArgIdx = NumArgs < 4 ? IncorrectArgIdx : 1;
+
+  // Return type is the nd_range struct pointed to by the first argument.
   MachineRegisterInfo *MRI = MIRBuilder.getMRI();
-  SPIRVTypeInst PtrType = GR->getSPIRVTypeForVReg(Call->Arguments[0]);
+  SPIRVTypeInst PtrType =
+      GR->getSPIRVTypeForVReg(Call->Arguments[ReturnValueArgIdx]);
   assert(PtrType->getOpcode() == SPIRV::OpTypePointer &&
-         PtrType->getOperand(2).isReg());
-  Register TypeReg = PtrType->getOperand(2).getReg();
-  SPIRVTypeInst StructType = GR->getSPIRVTypeForVReg(TypeReg);
+         PtrType->getOperand(2 /*Pointee*/).isReg());
+  Register ReturnTypeReg = PtrType->getOperand(2).getReg();
+  SPIRVTypeInst ReturnStructType = GR->getSPIRVTypeForVReg(ReturnTypeReg);
   MachineFunction &MF = MIRBuilder.getMF();
   Register TmpReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
-  GR->assignSPIRVTypeToVReg(StructType, TmpReg, MF);
-  // Skip the first arg, it's the destination pointer. OpBuildNDRange takes
-  // three other arguments, so pass zero constant on absence.
-  unsigned NumArgs = Call->Arguments.size();
-  assert(NumArgs >= 2);
-  Register GlobalWorkSize = Call->Arguments[NumArgs < 4 ? 1 : 2];
-  Register LocalWorkSize =
-      NumArgs == 2 ? Register(0) : Call->Arguments[NumArgs < 4 ? 2 : 3];
-  Register GlobalWorkOffset = NumArgs <= 3 ? Register(0) : Call->Arguments[1];
-  if (NumArgs < 4) {
-    Register Const;
-    SPIRVTypeInst SpvTy = GR->getSPIRVTypeForVReg(GlobalWorkSize);
-    if (SpvTy->getOpcode() == SPIRV::OpTypePointer) {
-      MachineInstr *DefInstr = MRI->getUniqueVRegDef(GlobalWorkSize);
-      assert(DefInstr && isSpvIntrinsic(*DefInstr, Intrinsic::spv_gep) &&
-             DefInstr->getOperand(3).isReg());
-      Register GWSPtr = DefInstr->getOperand(3).getReg();
-      // TODO: Maybe simplify generation of the type of the fields.
-      unsigned Size = Call->Builtin->Name == "ndrange_3D" ? 3 : 2;
-      unsigned BitWidth = GR->getPointerSize() == 64 ? 64 : 32;
-      Type *BaseTy = IntegerType::get(MF.getFunction().getContext(), BitWidth);
-      Type *FieldTy = ArrayType::get(BaseTy, Size);
-      SPIRVTypeInst SpvFieldTy = GR->getOrCreateSPIRVType(
-          FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite, true);
-      GlobalWorkSize = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
-      GR->assignSPIRVTypeToVReg(SpvFieldTy, GlobalWorkSize, MF);
-      MIRBuilder.buildInstr(SPIRV::OpLoad)
-          .addDef(GlobalWorkSize)
-          .addUse(GR->getSPIRVTypeID(SpvFieldTy))
-          .addUse(GWSPtr);
-      const SPIRVSubtarget &ST =
-          cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
-      Const = GR->getOrCreateConstIntArray(0, Size, *MIRBuilder.getInsertPt(),
-                                           SpvFieldTy, *ST.getInstrInfo());
-    } else {
-      Const = GR->buildConstantInt(0, MIRBuilder, SpvTy, true);
+  GR->assignSPIRVTypeToVReg(ReturnStructType, TmpReg, MF);
+
+  // Each nd_range field is an array of <Dimension> integers matching the
+  // address model width (32 or 64 bits).
+  const unsigned AddressModelBits = GR->getPointerSize();
+  assert(AddressModelBits == 64 || AddressModelBits == 32);
+
+
+  // The dimension is encoded in the function name as "ndrange_XD" where X is
+  // 1, 2, or 3.
+  unsigned Dimension = atoi(Call->Builtin->Name.substr(8, 1).data());
+  assert(Dimension <= 3 && Dimension >= 1);
+
+
+  // Get work size type; When fewer than 4 arguments are provided, build a zero constant for the
+  // missing one.
+  SPIRVTypeInst SpvFieldTy;
+  Register ConstZero;
+  if (Dimension == 1) {
+    SpvFieldTy =
+        GR->getSPIRVTypeForVReg(Call->Arguments[GlobalWorkSizeArgIdx]);
+    assert(SpvFieldTy && SpvFieldTy->getOpcode() == SPIRV::OpTypeInt &&
+            "Expected scalar integer type");
+
+    if (NumArgs < 4) 
+      ConstZero = GR->buildConstantInt(0, MIRBuilder, SpvFieldTy, true);
+  } else {
+    Type *BaseTy =
+        IntegerType::get(MF.getFunction().getContext(), AddressModelBits);
+    Type *FieldTy = ArrayType::get(BaseTy, Dimension);
+    SpvFieldTy = GR->getOrCreateSPIRVType(
+        FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadOnly, true);
+
+    if (NumArgs < 4) {
+      auto InsertIt = MIRBuilder.getInsertPt();
+      MachineBasicBlock &MBB = MIRBuilder.getMBB();
+      MachineInstr &InsertMI = (InsertIt != MBB.end()) ? *InsertIt : MBB.back();
+      const SPIRVSubtarget &ST = cast<SPIRVSubtarget>(MF.getSubtarget());
+      ConstZero = GR->getOrCreateConstIntArray(0, Dimension, InsertMI,
+                                               SpvFieldTy, *ST.getInstrInfo());
     }
-    if (!LocalWorkSize.isValid())
-      LocalWorkSize = Const;
-    if (!GlobalWorkOffset.isValid())
-      GlobalWorkOffset = Const;
   }
-  assert(LocalWorkSize.isValid() && GlobalWorkOffset.isValid());
+
+
+  Register GlobalWorkSize;
+  Register LocalWorkSize;
+  Register GlobalWorkOffset;
+
+  auto LoadRegisterData = [&](Register &Reg, unsigned Idx) {
+    Reg = (Idx == IncorrectArgIdx) ? ConstZero : Call->Arguments[Idx];
+
+    if (GR->getSPIRVTypeForVReg(Reg) == SpvFieldTy) {
+      // Already has the correct type
+      return;
+    }
+
+    assert(GR->getSPIRVTypeForVReg(Reg)->getOpcode() == SPIRV::OpTypePointer &&
+           "Only pointer types are supported for loading values");
+
+    Register Ptr = Reg;
+
+    Reg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
+    GR->assignSPIRVTypeToVReg(SpvFieldTy, Reg, MF);
+
+    MIRBuilder.buildInstr(SPIRV::OpLoad)
+        .addDef(Reg)
+        .addUse(GR->getSPIRVTypeID(SpvFieldTy))
+        .addUse(Ptr);
+    return;
+  };
+
+  LoadRegisterData(GlobalWorkSize, GlobalWorkSizeArgIdx);
+  LoadRegisterData(LocalWorkSize, LocalWorkSizeArgIdx);
+  LoadRegisterData(GlobalWorkOffset, GlobalWorkOffsetArgIdx);
+
   MIRBuilder.buildInstr(SPIRV::OpBuildNDRange)
       .addDef(TmpReg)
-      .addUse(TypeReg)
+      .addUse(ReturnTypeReg)
       .addUse(GlobalWorkSize)
       .addUse(LocalWorkSize)
       .addUse(GlobalWorkOffset);
   return MIRBuilder.buildInstr(SPIRV::OpStore)
-      .addUse(Call->Arguments[0])
+      .addUse(Call->Arguments[ReturnValueArgIdx])
       .addUse(TmpReg);
 }
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
index eb1b6c3185e7d..3820713db3e4a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
@@ -702,9 +702,9 @@ defm : DemangledNativeBuiltin<"capture_event_profiling_info", OpenCL_std, Enqueu
 defm : DemangledNativeBuiltin<"__spirv_CaptureEventProfilingInfo", OpenCL_std, Enqueue, 3, 3, OpCaptureEventProfilingInfo>;
 defm : DemangledNativeBuiltin<"get_default_queue", OpenCL_std, Enqueue, 0, 0, OpGetDefaultQueue>;
 defm : DemangledNativeBuiltin<"__spirv_GetDefaultQueue", OpenCL_std, Enqueue, 0, 0, OpGetDefaultQueue>;
-defm : DemangledNativeBuiltin<"ndrange_1D", OpenCL_std, Enqueue, 1, 3, OpBuildNDRange>;
-defm : DemangledNativeBuiltin<"ndrange_2D", OpenCL_std, Enqueue, 1, 3, OpBuildNDRange>;
-defm : DemangledNativeBuiltin<"ndrange_3D", OpenCL_std, Enqueue, 1, 3, OpBuildNDRange>;
+defm : DemangledNativeBuiltin<"ndrange_1D", OpenCL_std, Enqueue, 2, 4, OpBuildNDRange>;
+defm : DemangledNativeBuiltin<"ndrange_2D", OpenCL_std, Enqueue, 2, 4, OpBuildNDRange>;
+defm : DemangledNativeBuiltin<"ndrange_3D", OpenCL_std, Enqueue, 2, 4, OpBuildNDRange>;
 
 // Spec constant builtin records:
 defm : DemangledNativeBuiltin<"__spirv_SpecConstant", OpenCL_std, SpecConstant, 2, 2, OpSpecConstant>;

>From a5aa2470633d768516f6bf99172b7935a76a9452 Mon Sep 17 00:00:00 2001
From: idubinov <igor.dubinov at amd.com>
Date: Thu, 12 Mar 2026 10:20:07 -0500
Subject: [PATCH 2/8] tests

---
 .../CodeGen/SPIRV/transcoding/BuildNDRange.ll | 634 +++++++++++++++++-
 .../SPIRV/transcoding/BuildNDRange_2.ll       |  83 ---
 2 files changed, 623 insertions(+), 94 deletions(-)
 delete mode 100644 llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll

diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll
index 9258a3f23bf79..fac6aebfaa500 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll
@@ -1,17 +1,629 @@
-; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
-; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+;; Test that checks all variants of ndrange and what ndrange_1D, ndrange_2D and ndrange_3D can coexist in the same module
+;;
+;; bash$ cat BuildNDRange.cl
+;; void test_ndrange_2D3D() {
+;;   size_t GS1 = 1;
+;;   size_t LS1 = 2;
+;;   size_t WO1 = 3;
+;;   ndrange_1D(GS1);
+;;   ndrange_1D(GS1, LS1);
+;;   ndrange_1D(WO1, GS1, LS1);
+;;   ndrange_1D(GS1, GS1);
+;;   ndrange_1D(GS1, GS1, GS1);
+;;   size_t GS2[2] = {1, 1};
+;;   size_t LS2[2] = {2, 2};
+;;   size_t WO2[2] = {3, 3};
+;;   ndrange_2D(GS2);
+;;   ndrange_2D(GS2, LS2);
+;;   ndrange_2D(WO2, GS2, LS2);
+;;   ndrange_2D(GS2, GS2);
+;;   ndrange_2D(GS2, GS2, GS2);
+;;   size_t GS3[3] = {1, 1, 1};
+;;   size_t LS3[3] = {1, 2, 1};
+;;   size_t WO3[3] = {1, 3, 1};
+;;   ndrange_3D(GS3);
+;;   ndrange_2D(GS3, LS3);
+;;   ndrange_2D(WO3, GS3, LS3);
+;;   ndrange_2D(GS3, GS3);
+;;   ndrange_2D(GS3, GS3, GS3);
+;;   const size_t GS1c = 1;
+;;   const size_t LS1c = 2;
+;;   const size_t WO1c = 3;
+;;   ndrange_1D(GS1c);
+;;   ndrange_1D(GS1c, LS1c);
+;;   ndrange_1D(WO1c, GS1c, LS1c);
+;;   ndrange_1D(GS1c, GS1c);
+;;   ndrange_1D(GS1c, GS1c, GS1c);
+;;   const size_t GS2c[2] = {1, 1};
+;;   const size_t LS2c[2] = {1, 2};
+;;   const size_t WO2c[2] = {1, 3};
+;;   ndrange_2D(GS2c);
+;;   ndrange_2D(GS2c, LS2c);
+;;   ndrange_2D(WO2c, GS2c, LS2c);
+;;   ndrange_2D(GS2c, GS2c);
+;;   ndrange_2D(GS2c, GS2c, GS2c);
+;;   const size_t GS3c[3] = {1, 1, 1};
+;;   const size_t LS3c[3] = {1, 1, 2};
+;;   const size_t WO3c[3] = {1, 1, 3};
+;;   ndrange_3D(GS3c);
+;;   ndrange_2D(GS3c, LS3c);
+;;   ndrange_2D(WO3c, GS3c, LS3c);
+;;   ndrange_2D(GS3c, GS3c);
+;;   ndrange_2D(GS3c, GS3c, GS3c);
+;; }
+;; bash$ clang -cc1  -cl-std=CL2.0 -triple spirv64-unknown-unknown -emit-llvm -finclude-default-header -cl-single-precision-constant BuildNDRange.cl -o BuildNDRange.ll
 
-; CHECK-SPIRV-DAG: %[[#]] = OpBuildNDRange %[[#]] %[[#GWS:]] %[[#LWS:]] %[[#GWO:]]
-; CHECK-SPIRV-DAG: %[[#GWS]] = OpConstant %[[#]] 123
-; CHECK-SPIRV-DAG: %[[#LWS]] = OpConstant %[[#]] 456
-; CHECK-SPIRV-DAG: %[[#GWO]] = OpConstantNull %[[#]]
 
-%struct.ndrange_t = type { i32, [3 x i32], [3 x i32], [3 x i32] }
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
-define spir_kernel void @test() {
-  %ndrange = alloca %struct.ndrange_t, align 4
-  call spir_func void @_Z10ndrange_1Djj(ptr sret(ptr) %ndrange, i32 123, i32 456)
+%struct.ndrange_t = type { i32, [3 x i64], [3 x i64], [3 x i64] }
+
+ at __const.test_ndrange_2D3D.GS2 = private unnamed_addr addrspace(2) constant [2 x i64] [i64 1, i64 1], align 8
+ at __const.test_ndrange_2D3D.LS2 = private unnamed_addr addrspace(2) constant [2 x i64] [i64 2, i64 2], align 8
+ at __const.test_ndrange_2D3D.WO2 = private unnamed_addr addrspace(2) constant [2 x i64] [i64 3, i64 3], align 8
+ at __const.test_ndrange_2D3D.GS3 = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 1, i64 1], align 8
+ at __const.test_ndrange_2D3D.LS3 = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 2, i64 1], align 8
+ at __const.test_ndrange_2D3D.WO3 = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 3, i64 1], align 8
+ at __const.test_ndrange_2D3D.GS2c = private unnamed_addr addrspace(2) constant [2 x i64] [i64 1, i64 1], align 8
+ at __const.test_ndrange_2D3D.LS2c = private unnamed_addr addrspace(2) constant [2 x i64] [i64 1, i64 2], align 8
+ at __const.test_ndrange_2D3D.WO2c = private unnamed_addr addrspace(2) constant [2 x i64] [i64 1, i64 3], align 8
+ at __const.test_ndrange_2D3D.GS3c = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 1, i64 1], align 8
+ at __const.test_ndrange_2D3D.LS3c = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 1, i64 2], align 8
+ at __const.test_ndrange_2D3D.WO3c = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 1, i64 3], align 8
+
+define spir_func void @test_ndrange_2D3D() local_unnamed_addr #0 {
+; CHECK-LABEL: test_ndrange_2D3D
+; CHECK:       %50 = OpFunction %3 None %4 ; -- Begin function test_ndrange_2D3D
+; CHECK-NEXT:    %2 = OpLabel
+; CHECK-NEXT:    %51 = OpVariable %10 Function
+; CHECK-NEXT:    %52 = OpVariable %10 Function
+; CHECK-NEXT:    %53 = OpVariable %10 Function
+; CHECK-NEXT:    %54 = OpVariable %10 Function
+; CHECK-NEXT:    %55 = OpVariable %10 Function
+; CHECK-NEXT:    %56 = OpVariable %13 Function
+; CHECK-NEXT:    %57 = OpVariable %13 Function
+; CHECK-NEXT:    %58 = OpVariable %13 Function
+; CHECK-NEXT:    %59 = OpVariable %10 Function
+; CHECK-NEXT:    %60 = OpVariable %10 Function
+; CHECK-NEXT:    %61 = OpVariable %10 Function
+; CHECK-NEXT:    %62 = OpVariable %10 Function
+; CHECK-NEXT:    %63 = OpVariable %10 Function
+; CHECK-NEXT:    %64 = OpVariable %16 Function
+; CHECK-NEXT:    %65 = OpVariable %16 Function
+; CHECK-NEXT:    %66 = OpVariable %16 Function
+; CHECK-NEXT:    %67 = OpVariable %10 Function
+; CHECK-NEXT:    %68 = OpVariable %10 Function
+; CHECK-NEXT:    %69 = OpVariable %10 Function
+; CHECK-NEXT:    %70 = OpVariable %10 Function
+; CHECK-NEXT:    %71 = OpVariable %10 Function
+; CHECK-NEXT:    %72 = OpVariable %10 Function
+; CHECK-NEXT:    %73 = OpVariable %10 Function
+; CHECK-NEXT:    %74 = OpVariable %10 Function
+; CHECK-NEXT:    %75 = OpVariable %10 Function
+; CHECK-NEXT:    %76 = OpVariable %10 Function
+; CHECK-NEXT:    %77 = OpVariable %13 Function
+; CHECK-NEXT:    %78 = OpVariable %13 Function
+; CHECK-NEXT:    %79 = OpVariable %13 Function
+; CHECK-NEXT:    %80 = OpVariable %10 Function
+; CHECK-NEXT:    %81 = OpVariable %10 Function
+; CHECK-NEXT:    %82 = OpVariable %10 Function
+; CHECK-NEXT:    %83 = OpVariable %10 Function
+; CHECK-NEXT:    %84 = OpVariable %10 Function
+; CHECK-NEXT:    %85 = OpVariable %16 Function
+; CHECK-NEXT:    %86 = OpVariable %16 Function
+; CHECK-NEXT:    %87 = OpVariable %16 Function
+; CHECK-NEXT:    %88 = OpVariable %10 Function
+; CHECK-NEXT:    %89 = OpVariable %10 Function
+; CHECK-NEXT:    %90 = OpVariable %10 Function
+; CHECK-NEXT:    %91 = OpVariable %10 Function
+; CHECK-NEXT:    %92 = OpVariable %10 Function
+; CHECK-NEXT:    %93 = OpBitcast %27 %51
+; CHECK-NEXT:    OpLifetimeStart %93 80
+; CHECK-NEXT:    %94 = OpBuildNDRange %9 %24 %25 %25
+; CHECK-NEXT:    OpStore %51 %94
+; CHECK-NEXT:    %95 = OpBitcast %27 %51
+; CHECK-NEXT:    OpLifetimeStop %95 80
+; CHECK-NEXT:    %96 = OpBitcast %27 %52
+; CHECK-NEXT:    OpLifetimeStart %96 80
+; CHECK-NEXT:    %97 = OpBuildNDRange %9 %24 %23 %25
+; CHECK-NEXT:    OpStore %52 %97
+; CHECK-NEXT:    %98 = OpBitcast %27 %52
+; CHECK-NEXT:    OpLifetimeStop %98 80
+; CHECK-NEXT:    %99 = OpBitcast %27 %53
+; CHECK-NEXT:    OpLifetimeStart %99 80
+; CHECK-NEXT:    %100 = OpBuildNDRange %9 %24 %23 %22
+; CHECK-NEXT:    OpStore %53 %100
+; CHECK-NEXT:    %101 = OpBitcast %27 %53
+; CHECK-NEXT:    OpLifetimeStop %101 80
+; CHECK-NEXT:    %102 = OpBitcast %27 %54
+; CHECK-NEXT:    OpLifetimeStart %102 80
+; CHECK-NEXT:    %103 = OpBuildNDRange %9 %24 %24 %25
+; CHECK-NEXT:    OpStore %54 %103
+; CHECK-NEXT:    %104 = OpBitcast %27 %54
+; CHECK-NEXT:    OpLifetimeStop %104 80
+; CHECK-NEXT:    %105 = OpBitcast %27 %55
+; CHECK-NEXT:    OpLifetimeStart %105 80
+; CHECK-NEXT:    %106 = OpBuildNDRange %9 %24 %24 %24
+; CHECK-NEXT:    OpStore %55 %106
+; CHECK-NEXT:    %107 = OpBitcast %27 %55
+; CHECK-NEXT:    OpLifetimeStop %107 80
+; CHECK-NEXT:    %108 = OpBitcast %27 %56
+; CHECK-NEXT:    OpLifetimeStart %108 16
+; CHECK-NEXT:    OpCopyMemorySized %56 %29 %21 Aligned 8
+; CHECK-NEXT:    %109 = OpBitcast %27 %57
+; CHECK-NEXT:    OpLifetimeStart %109 16
+; CHECK-NEXT:    OpCopyMemorySized %57 %31 %21 Aligned 8
+; CHECK-NEXT:    %110 = OpBitcast %27 %58
+; CHECK-NEXT:    OpLifetimeStart %110 16
+; CHECK-NEXT:    OpCopyMemorySized %58 %33 %21 Aligned 8
+; CHECK-NEXT:    %111 = OpBitcast %27 %59
+; CHECK-NEXT:    OpLifetimeStart %111 80
+; CHECK-NEXT:    %112 = OpLoad %12 %56
+; CHECK-NEXT:    %113 = OpBuildNDRange %9 %112 %14 %14
+; CHECK-NEXT:    OpStore %59 %113
+; CHECK-NEXT:    %114 = OpBitcast %27 %59
+; CHECK-NEXT:    OpLifetimeStop %114 80
+; CHECK-NEXT:    %115 = OpBitcast %27 %60
+; CHECK-NEXT:    OpLifetimeStart %115 80
+; CHECK-NEXT:    %116 = OpBitcast %15 %56
+; CHECK-NEXT:    %117 = OpBitcast %13 %116
+; CHECK-NEXT:    %118 = OpLoad %12 %117
+; CHECK-NEXT:    %119 = OpLoad %12 %57
+; CHECK-NEXT:    %120 = OpBuildNDRange %9 %118 %119 %14
+; CHECK-NEXT:    OpStore %60 %120
+; CHECK-NEXT:    %121 = OpBitcast %27 %60
+; CHECK-NEXT:    OpLifetimeStop %121 80
+; CHECK-NEXT:    %122 = OpBitcast %27 %61
+; CHECK-NEXT:    OpLifetimeStart %122 80
+; CHECK-NEXT:    %123 = OpBitcast %15 %58
+; CHECK-NEXT:    %124 = OpBitcast %13 %116
+; CHECK-NEXT:    %125 = OpLoad %12 %124
+; CHECK-NEXT:    %126 = OpLoad %12 %57
+; CHECK-NEXT:    %127 = OpBitcast %13 %123
+; CHECK-NEXT:    %128 = OpLoad %12 %127
+; CHECK-NEXT:    %129 = OpBuildNDRange %9 %125 %126 %128
+; CHECK-NEXT:    OpStore %61 %129
+; CHECK-NEXT:    %130 = OpBitcast %27 %61
+; CHECK-NEXT:    OpLifetimeStop %130 80
+; CHECK-NEXT:    %131 = OpBitcast %27 %62
+; CHECK-NEXT:    OpLifetimeStart %131 80
+; CHECK-NEXT:    %132 = OpBitcast %13 %116
+; CHECK-NEXT:    %133 = OpLoad %12 %132
+; CHECK-NEXT:    %134 = OpLoad %12 %56
+; CHECK-NEXT:    %135 = OpBuildNDRange %9 %133 %134 %14
+; CHECK-NEXT:    OpStore %62 %135
+; CHECK-NEXT:    %136 = OpBitcast %27 %62
+; CHECK-NEXT:    OpLifetimeStop %136 80
+; CHECK-NEXT:    %137 = OpBitcast %27 %63
+; CHECK-NEXT:    OpLifetimeStart %137 80
+; CHECK-NEXT:    %138 = OpBitcast %13 %116
+; CHECK-NEXT:    %139 = OpLoad %12 %138
+; CHECK-NEXT:    %140 = OpLoad %12 %56
+; CHECK-NEXT:    %141 = OpBitcast %13 %116
+; CHECK-NEXT:    %142 = OpLoad %12 %141
+; CHECK-NEXT:    %143 = OpBuildNDRange %9 %139 %140 %142
+; CHECK-NEXT:    OpStore %63 %143
+; CHECK-NEXT:    %144 = OpBitcast %27 %63
+; CHECK-NEXT:    OpLifetimeStop %144 80
+; CHECK-NEXT:    %145 = OpBitcast %27 %64
+; CHECK-NEXT:    OpLifetimeStart %145 24
+; CHECK-NEXT:    OpCopyMemorySized %64 %35 %20 Aligned 8
+; CHECK-NEXT:    %146 = OpBitcast %27 %65
+; CHECK-NEXT:    OpLifetimeStart %146 24
+; CHECK-NEXT:    OpCopyMemorySized %65 %37 %20 Aligned 8
+; CHECK-NEXT:    %147 = OpBitcast %27 %66
+; CHECK-NEXT:    OpLifetimeStart %147 24
+; CHECK-NEXT:    OpCopyMemorySized %66 %39 %20 Aligned 8
+; CHECK-NEXT:    %148 = OpBitcast %27 %67
+; CHECK-NEXT:    OpLifetimeStart %148 80
+; CHECK-NEXT:    %149 = OpLoad %8 %64
+; CHECK-NEXT:    %150 = OpBuildNDRange %9 %149 %17 %17
+; CHECK-NEXT:    OpStore %67 %150
+; CHECK-NEXT:    %151 = OpBitcast %27 %67
+; CHECK-NEXT:    OpLifetimeStop %151 80
+; CHECK-NEXT:    %152 = OpBitcast %27 %68
+; CHECK-NEXT:    OpLifetimeStart %152 80
+; CHECK-NEXT:    %153 = OpBitcast %15 %64
+; CHECK-NEXT:    %154 = OpBitcast %13 %153
+; CHECK-NEXT:    %155 = OpLoad %12 %154
+; CHECK-NEXT:    %156 = OpBitcast %13 %65
+; CHECK-NEXT:    %157 = OpLoad %12 %156
+; CHECK-NEXT:    %158 = OpBuildNDRange %9 %155 %157 %14
+; CHECK-NEXT:    OpStore %68 %158
+; CHECK-NEXT:    %159 = OpBitcast %27 %68
+; CHECK-NEXT:    OpLifetimeStop %159 80
+; CHECK-NEXT:    %160 = OpBitcast %27 %69
+; CHECK-NEXT:    OpLifetimeStart %160 80
+; CHECK-NEXT:    %161 = OpBitcast %15 %66
+; CHECK-NEXT:    %162 = OpBitcast %13 %153
+; CHECK-NEXT:    %163 = OpLoad %12 %162
+; CHECK-NEXT:    %164 = OpBitcast %13 %65
+; CHECK-NEXT:    %165 = OpLoad %12 %164
+; CHECK-NEXT:    %166 = OpBitcast %13 %161
+; CHECK-NEXT:    %167 = OpLoad %12 %166
+; CHECK-NEXT:    %168 = OpBuildNDRange %9 %163 %165 %167
+; CHECK-NEXT:    OpStore %69 %168
+; CHECK-NEXT:    %169 = OpBitcast %27 %69
+; CHECK-NEXT:    OpLifetimeStop %169 80
+; CHECK-NEXT:    %170 = OpBitcast %27 %70
+; CHECK-NEXT:    OpLifetimeStart %170 80
+; CHECK-NEXT:    %171 = OpBitcast %13 %153
+; CHECK-NEXT:    %172 = OpLoad %12 %171
+; CHECK-NEXT:    %173 = OpBitcast %13 %64
+; CHECK-NEXT:    %174 = OpLoad %12 %173
+; CHECK-NEXT:    %175 = OpBuildNDRange %9 %172 %174 %14
+; CHECK-NEXT:    OpStore %70 %175
+; CHECK-NEXT:    %176 = OpBitcast %27 %70
+; CHECK-NEXT:    OpLifetimeStop %176 80
+; CHECK-NEXT:    %177 = OpBitcast %27 %71
+; CHECK-NEXT:    OpLifetimeStart %177 80
+; CHECK-NEXT:    %178 = OpBitcast %13 %153
+; CHECK-NEXT:    %179 = OpLoad %12 %178
+; CHECK-NEXT:    %180 = OpBitcast %13 %64
+; CHECK-NEXT:    %181 = OpLoad %12 %180
+; CHECK-NEXT:    %182 = OpBitcast %13 %153
+; CHECK-NEXT:    %183 = OpLoad %12 %182
+; CHECK-NEXT:    %184 = OpBuildNDRange %9 %179 %181 %183
+; CHECK-NEXT:    OpStore %71 %184
+; CHECK-NEXT:    %185 = OpBitcast %27 %71
+; CHECK-NEXT:    OpLifetimeStop %185 80
+; CHECK-NEXT:    %186 = OpBitcast %27 %72
+; CHECK-NEXT:    OpLifetimeStart %186 80
+; CHECK-NEXT:    %187 = OpBuildNDRange %9 %24 %25 %25
+; CHECK-NEXT:    OpStore %72 %187
+; CHECK-NEXT:    %188 = OpBitcast %27 %72
+; CHECK-NEXT:    OpLifetimeStop %188 80
+; CHECK-NEXT:    %189 = OpBitcast %27 %73
+; CHECK-NEXT:    OpLifetimeStart %189 80
+; CHECK-NEXT:    %190 = OpBuildNDRange %9 %24 %23 %25
+; CHECK-NEXT:    OpStore %73 %190
+; CHECK-NEXT:    %191 = OpBitcast %27 %73
+; CHECK-NEXT:    OpLifetimeStop %191 80
+; CHECK-NEXT:    %192 = OpBitcast %27 %74
+; CHECK-NEXT:    OpLifetimeStart %192 80
+; CHECK-NEXT:    %193 = OpBuildNDRange %9 %24 %23 %22
+; CHECK-NEXT:    OpStore %74 %193
+; CHECK-NEXT:    %194 = OpBitcast %27 %74
+; CHECK-NEXT:    OpLifetimeStop %194 80
+; CHECK-NEXT:    %195 = OpBitcast %27 %75
+; CHECK-NEXT:    OpLifetimeStart %195 80
+; CHECK-NEXT:    %196 = OpBuildNDRange %9 %24 %24 %25
+; CHECK-NEXT:    OpStore %75 %196
+; CHECK-NEXT:    %197 = OpBitcast %27 %75
+; CHECK-NEXT:    OpLifetimeStop %197 80
+; CHECK-NEXT:    %198 = OpBitcast %27 %76
+; CHECK-NEXT:    OpLifetimeStart %198 80
+; CHECK-NEXT:    %199 = OpBuildNDRange %9 %24 %24 %24
+; CHECK-NEXT:    OpStore %76 %199
+; CHECK-NEXT:    %200 = OpBitcast %27 %76
+; CHECK-NEXT:    OpLifetimeStop %200 80
+; CHECK-NEXT:    %201 = OpBitcast %27 %77
+; CHECK-NEXT:    OpLifetimeStart %201 16
+; CHECK-NEXT:    OpCopyMemorySized %77 %40 %21 Aligned 8
+; CHECK-NEXT:    %202 = OpBitcast %27 %78
+; CHECK-NEXT:    OpLifetimeStart %202 16
+; CHECK-NEXT:    OpCopyMemorySized %78 %42 %21 Aligned 8
+; CHECK-NEXT:    %203 = OpBitcast %27 %79
+; CHECK-NEXT:    OpLifetimeStart %203 16
+; CHECK-NEXT:    OpCopyMemorySized %79 %44 %21 Aligned 8
+; CHECK-NEXT:    %204 = OpBitcast %27 %80
+; CHECK-NEXT:    OpLifetimeStart %204 80
+; CHECK-NEXT:    %205 = OpLoad %12 %77
+; CHECK-NEXT:    %206 = OpBuildNDRange %9 %205 %14 %14
+; CHECK-NEXT:    OpStore %80 %206
+; CHECK-NEXT:    %207 = OpBitcast %27 %80
+; CHECK-NEXT:    OpLifetimeStop %207 80
+; CHECK-NEXT:    %208 = OpBitcast %27 %81
+; CHECK-NEXT:    OpLifetimeStart %208 80
+; CHECK-NEXT:    %209 = OpBitcast %15 %77
+; CHECK-NEXT:    %210 = OpBitcast %13 %209
+; CHECK-NEXT:    %211 = OpLoad %12 %210
+; CHECK-NEXT:    %212 = OpLoad %12 %78
+; CHECK-NEXT:    %213 = OpBuildNDRange %9 %211 %212 %14
+; CHECK-NEXT:    OpStore %81 %213
+; CHECK-NEXT:    %214 = OpBitcast %27 %81
+; CHECK-NEXT:    OpLifetimeStop %214 80
+; CHECK-NEXT:    %215 = OpBitcast %27 %82
+; CHECK-NEXT:    OpLifetimeStart %215 80
+; CHECK-NEXT:    %216 = OpBitcast %15 %79
+; CHECK-NEXT:    %217 = OpBitcast %13 %209
+; CHECK-NEXT:    %218 = OpLoad %12 %217
+; CHECK-NEXT:    %219 = OpLoad %12 %78
+; CHECK-NEXT:    %220 = OpBitcast %13 %216
+; CHECK-NEXT:    %221 = OpLoad %12 %220
+; CHECK-NEXT:    %222 = OpBuildNDRange %9 %218 %219 %221
+; CHECK-NEXT:    OpStore %82 %222
+; CHECK-NEXT:    %223 = OpBitcast %27 %82
+; CHECK-NEXT:    OpLifetimeStop %223 80
+; CHECK-NEXT:    %224 = OpBitcast %27 %83
+; CHECK-NEXT:    OpLifetimeStart %224 80
+; CHECK-NEXT:    %225 = OpBitcast %13 %209
+; CHECK-NEXT:    %226 = OpLoad %12 %225
+; CHECK-NEXT:    %227 = OpLoad %12 %77
+; CHECK-NEXT:    %228 = OpBuildNDRange %9 %226 %227 %14
+; CHECK-NEXT:    OpStore %83 %228
+; CHECK-NEXT:    %229 = OpBitcast %27 %83
+; CHECK-NEXT:    OpLifetimeStop %229 80
+; CHECK-NEXT:    %230 = OpBitcast %27 %84
+; CHECK-NEXT:    OpLifetimeStart %230 80
+; CHECK-NEXT:    %231 = OpBitcast %13 %209
+; CHECK-NEXT:    %232 = OpLoad %12 %231
+; CHECK-NEXT:    %233 = OpLoad %12 %77
+; CHECK-NEXT:    %234 = OpBitcast %13 %209
+; CHECK-NEXT:    %235 = OpLoad %12 %234
+; CHECK-NEXT:    %236 = OpBuildNDRange %9 %232 %233 %235
+; CHECK-NEXT:    OpStore %84 %236
+; CHECK-NEXT:    %237 = OpBitcast %27 %84
+; CHECK-NEXT:    OpLifetimeStop %237 80
+; CHECK-NEXT:    %238 = OpBitcast %27 %85
+; CHECK-NEXT:    OpLifetimeStart %238 24
+; CHECK-NEXT:    OpCopyMemorySized %85 %45 %20 Aligned 8
+; CHECK-NEXT:    %239 = OpBitcast %27 %86
+; CHECK-NEXT:    OpLifetimeStart %239 24
+; CHECK-NEXT:    OpCopyMemorySized %86 %47 %20 Aligned 8
+; CHECK-NEXT:    %240 = OpBitcast %27 %87
+; CHECK-NEXT:    OpLifetimeStart %240 24
+; CHECK-NEXT:    OpCopyMemorySized %87 %49 %20 Aligned 8
+; CHECK-NEXT:    %241 = OpBitcast %27 %88
+; CHECK-NEXT:    OpLifetimeStart %241 80
+; CHECK-NEXT:    %242 = OpLoad %8 %85
+; CHECK-NEXT:    %243 = OpBuildNDRange %9 %242 %17 %17
+; CHECK-NEXT:    OpStore %88 %243
+; CHECK-NEXT:    %244 = OpBitcast %27 %88
+; CHECK-NEXT:    OpLifetimeStop %244 80
+; CHECK-NEXT:    %245 = OpBitcast %27 %89
+; CHECK-NEXT:    OpLifetimeStart %245 80
+; CHECK-NEXT:    %246 = OpBitcast %15 %85
+; CHECK-NEXT:    %247 = OpBitcast %13 %246
+; CHECK-NEXT:    %248 = OpLoad %12 %247
+; CHECK-NEXT:    %249 = OpBitcast %13 %86
+; CHECK-NEXT:    %250 = OpLoad %12 %249
+; CHECK-NEXT:    %251 = OpBuildNDRange %9 %248 %250 %14
+; CHECK-NEXT:    OpStore %89 %251
+; CHECK-NEXT:    %252 = OpBitcast %27 %89
+; CHECK-NEXT:    OpLifetimeStop %252 80
+; CHECK-NEXT:    %253 = OpBitcast %27 %90
+; CHECK-NEXT:    OpLifetimeStart %253 80
+; CHECK-NEXT:    %254 = OpBitcast %15 %87
+; CHECK-NEXT:    %255 = OpBitcast %13 %246
+; CHECK-NEXT:    %256 = OpLoad %12 %255
+; CHECK-NEXT:    %257 = OpBitcast %13 %86
+; CHECK-NEXT:    %258 = OpLoad %12 %257
+; CHECK-NEXT:    %259 = OpBitcast %13 %254
+; CHECK-NEXT:    %260 = OpLoad %12 %259
+; CHECK-NEXT:    %261 = OpBuildNDRange %9 %256 %258 %260
+; CHECK-NEXT:    OpStore %90 %261
+; CHECK-NEXT:    %262 = OpBitcast %27 %90
+; CHECK-NEXT:    OpLifetimeStop %262 80
+; CHECK-NEXT:    %263 = OpBitcast %27 %91
+; CHECK-NEXT:    OpLifetimeStart %263 80
+; CHECK-NEXT:    %264 = OpBitcast %13 %246
+; CHECK-NEXT:    %265 = OpLoad %12 %264
+; CHECK-NEXT:    %266 = OpBitcast %13 %85
+; CHECK-NEXT:    %267 = OpLoad %12 %266
+; CHECK-NEXT:    %268 = OpBuildNDRange %9 %265 %267 %14
+; CHECK-NEXT:    OpStore %91 %268
+; CHECK-NEXT:    %269 = OpBitcast %27 %91
+; CHECK-NEXT:    OpLifetimeStop %269 80
+; CHECK-NEXT:    %270 = OpBitcast %27 %92
+; CHECK-NEXT:    OpLifetimeStart %270 80
+; CHECK-NEXT:    %271 = OpBitcast %13 %246
+; CHECK-NEXT:    %272 = OpLoad %12 %271
+; CHECK-NEXT:    %273 = OpBitcast %13 %85
+; CHECK-NEXT:    %274 = OpLoad %12 %273
+; CHECK-NEXT:    %275 = OpBitcast %13 %246
+; CHECK-NEXT:    %276 = OpLoad %12 %275
+; CHECK-NEXT:    %277 = OpBuildNDRange %9 %272 %274 %276
+; CHECK-NEXT:    OpStore %92 %277
+; CHECK-NEXT:    %278 = OpBitcast %27 %92
+; CHECK-NEXT:    OpLifetimeStop %278 80
+; CHECK-NEXT:    %279 = OpBitcast %27 %87
+; CHECK-NEXT:    OpLifetimeStop %279 24
+; CHECK-NEXT:    %280 = OpBitcast %27 %86
+; CHECK-NEXT:    OpLifetimeStop %280 24
+; CHECK-NEXT:    %281 = OpBitcast %27 %85
+; CHECK-NEXT:    OpLifetimeStop %281 24
+; CHECK-NEXT:    %282 = OpBitcast %27 %79
+; CHECK-NEXT:    OpLifetimeStop %282 16
+; CHECK-NEXT:    %283 = OpBitcast %27 %78
+; CHECK-NEXT:    OpLifetimeStop %283 16
+; CHECK-NEXT:    %284 = OpBitcast %27 %77
+; CHECK-NEXT:    OpLifetimeStop %284 16
+; CHECK-NEXT:    %285 = OpBitcast %27 %66
+; CHECK-NEXT:    OpLifetimeStop %285 24
+; CHECK-NEXT:    %286 = OpBitcast %27 %65
+; CHECK-NEXT:    OpLifetimeStop %286 24
+; CHECK-NEXT:    %287 = OpBitcast %27 %64
+; CHECK-NEXT:    OpLifetimeStop %287 24
+; CHECK-NEXT:    %288 = OpBitcast %27 %58
+; CHECK-NEXT:    OpLifetimeStop %288 16
+; CHECK-NEXT:    %289 = OpBitcast %27 %57
+; CHECK-NEXT:    OpLifetimeStop %289 16
+; CHECK-NEXT:    %290 = OpBitcast %27 %56
+; CHECK-NEXT:    OpLifetimeStop %290 16
+; CHECK-NEXT:    OpReturn
+; CHECK-NEXT:    OpFunctionEnd
+entry:
+  %tmp = alloca %struct.ndrange_t, align 8
+  %tmp1 = alloca %struct.ndrange_t, align 8
+  %tmp2 = alloca %struct.ndrange_t, align 8
+  %tmp3 = alloca %struct.ndrange_t, align 8
+  %tmp4 = alloca %struct.ndrange_t, align 8
+  %GS2 = alloca [2 x i64], align 8
+  %LS2 = alloca [2 x i64], align 8
+  %WO2 = alloca [2 x i64], align 8
+  %tmp5 = alloca %struct.ndrange_t, align 8
+  %tmp8 = alloca %struct.ndrange_t, align 8
+  %tmp12 = alloca %struct.ndrange_t, align 8
+  %tmp15 = alloca %struct.ndrange_t, align 8
+  %tmp19 = alloca %struct.ndrange_t, align 8
+  %GS3 = alloca [3 x i64], align 8
+  %LS3 = alloca [3 x i64], align 8
+  %WO3 = alloca [3 x i64], align 8
+  %tmp21 = alloca %struct.ndrange_t, align 8
+  %tmp24 = alloca %struct.ndrange_t, align 8
+  %tmp28 = alloca %struct.ndrange_t, align 8
+  %tmp31 = alloca %struct.ndrange_t, align 8
+  %tmp35 = alloca %struct.ndrange_t, align 8
+  %tmp36 = alloca %struct.ndrange_t, align 8
+  %tmp37 = alloca %struct.ndrange_t, align 8
+  %tmp38 = alloca %struct.ndrange_t, align 8
+  %tmp39 = alloca %struct.ndrange_t, align 8
+  %tmp40 = alloca %struct.ndrange_t, align 8
+  %GS2c = alloca [2 x i64], align 8
+  %LS2c = alloca [2 x i64], align 8
+  %WO2c = alloca [2 x i64], align 8
+  %tmp42 = alloca %struct.ndrange_t, align 8
+  %tmp45 = alloca %struct.ndrange_t, align 8
+  %tmp49 = alloca %struct.ndrange_t, align 8
+  %tmp52 = alloca %struct.ndrange_t, align 8
+  %tmp56 = alloca %struct.ndrange_t, align 8
+  %GS3c = alloca [3 x i64], align 8
+  %LS3c = alloca [3 x i64], align 8
+  %WO3c = alloca [3 x i64], align 8
+  %tmp58 = alloca %struct.ndrange_t, align 8
+  %tmp61 = alloca %struct.ndrange_t, align 8
+  %tmp65 = alloca %struct.ndrange_t, align 8
+  %tmp68 = alloca %struct.ndrange_t, align 8
+  %tmp72 = alloca %struct.ndrange_t, align 8
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp) #4
+  call spir_func void @_Z10ndrange_1Dm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp, i64 noundef 1) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp1) #4
+  call spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp1, i64 noundef 1, i64 noundef 2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp1) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp2) #4
+  call spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp2, i64 noundef 3, i64 noundef 1, i64 noundef 2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp2) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp3) #4
+  call spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp3, i64 noundef 1, i64 noundef 1) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp3) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp4) #4
+  call spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp4, i64 noundef 1, i64 noundef 1, i64 noundef 1) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp4) #4
+  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %GS2) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %GS2, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.GS2, i64 16, i1 false)
+  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %LS2) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %LS2, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.LS2, i64 16, i1 false)
+  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %WO2) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %WO2, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.WO2, i64 16, i1 false)
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp5) #4
+  call spir_func void @_Z10ndrange_2DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp5, ptr noundef nonnull %GS2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp5) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp8) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp8, ptr noundef nonnull %GS2, ptr noundef nonnull %LS2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp8) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp12) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp12, ptr noundef nonnull %WO2, ptr noundef nonnull %GS2, ptr noundef nonnull %LS2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp12) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp15) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp15, ptr noundef nonnull %GS2, ptr noundef nonnull %GS2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp15) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp19) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp19, ptr noundef nonnull %GS2, ptr noundef nonnull %GS2, ptr noundef nonnull %GS2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp19) #4
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %GS3) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %GS3, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.GS3, i64 24, i1 false)
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %LS3) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %LS3, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.LS3, i64 24, i1 false)
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %WO3) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %WO3, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.WO3, i64 24, i1 false)
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp21) #4
+  call spir_func void @_Z10ndrange_3DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp21, ptr noundef nonnull %GS3) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp21) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp24) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp24, ptr noundef nonnull %GS3, ptr noundef nonnull %LS3) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp24) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp28) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp28, ptr noundef nonnull %WO3, ptr noundef nonnull %GS3, ptr noundef nonnull %LS3) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp28) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp31) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp31, ptr noundef nonnull %GS3, ptr noundef nonnull %GS3) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp31) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp35) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp35, ptr noundef nonnull %GS3, ptr noundef nonnull %GS3, ptr noundef nonnull %GS3) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp35) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp36) #4
+  call spir_func void @_Z10ndrange_1Dm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp36, i64 noundef 1) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp36) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp37) #4
+  call spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp37, i64 noundef 1, i64 noundef 2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp37) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp38) #4
+  call spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp38, i64 noundef 3, i64 noundef 1, i64 noundef 2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp38) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp39) #4
+  call spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp39, i64 noundef 1, i64 noundef 1) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp39) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp40) #4
+  call spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp40, i64 noundef 1, i64 noundef 1, i64 noundef 1) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp40) #4
+  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %GS2c) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %GS2c, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.GS2c, i64 16, i1 false)
+  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %LS2c) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %LS2c, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.LS2c, i64 16, i1 false)
+  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %WO2c) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %WO2c, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.WO2c, i64 16, i1 false)
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp42) #4
+  call spir_func void @_Z10ndrange_2DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp42, ptr noundef nonnull %GS2c) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp42) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp45) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp45, ptr noundef nonnull %GS2c, ptr noundef nonnull %LS2c) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp45) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp49) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp49, ptr noundef nonnull %WO2c, ptr noundef nonnull %GS2c, ptr noundef nonnull %LS2c) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp49) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp52) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp52, ptr noundef nonnull %GS2c, ptr noundef nonnull %GS2c) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp52) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp56) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp56, ptr noundef nonnull %GS2c, ptr noundef nonnull %GS2c, ptr noundef nonnull %GS2c) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp56) #4
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %GS3c) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %GS3c, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.GS3c, i64 24, i1 false)
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %LS3c) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %LS3c, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.LS3c, i64 24, i1 false)
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %WO3c) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %WO3c, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.WO3c, i64 24, i1 false)
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp58) #4
+  call spir_func void @_Z10ndrange_3DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp58, ptr noundef nonnull %GS3c) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp58) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp61) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp61, ptr noundef nonnull %GS3c, ptr noundef nonnull %LS3c) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp61) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp65) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp65, ptr noundef nonnull %WO3c, ptr noundef nonnull %GS3c, ptr noundef nonnull %LS3c) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp65) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp68) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp68, ptr noundef nonnull %GS3c, ptr noundef nonnull %GS3c) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp68) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp72) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp72, ptr noundef nonnull %GS3c, ptr noundef nonnull %GS3c, ptr noundef nonnull %GS3c) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp72) #4
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %WO3c) #4
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %LS3c) #4
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %GS3c) #4
+  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %WO2c) #4
+  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %LS2c) #4
+  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %GS2c) #4
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %WO3) #4
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %LS3) #4
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %GS3) #4
+  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %WO2) #4
+  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %LS2) #4
+  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %GS2) #4
   ret void
 }
 
-declare spir_func void @_Z10ndrange_1Djj(ptr sret(ptr), i32, i32)
+declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
+declare spir_func void @_Z10ndrange_1Dm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, i64 noundef) local_unnamed_addr #2
+declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
+declare spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, i64 noundef, i64 noundef) local_unnamed_addr #2
+declare spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, i64 noundef, i64 noundef, i64 noundef) local_unnamed_addr #2
+declare void @llvm.memcpy.p0.p2.i64(ptr noalias nocapture writeonly, ptr addrspace(2) noalias nocapture readonly, i64, i1 immarg) #3
+declare spir_func void @_Z10ndrange_2DPKm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef) local_unnamed_addr #2
+declare spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef, ptr noundef) local_unnamed_addr #2
+declare spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef, ptr noundef, ptr noundef) local_unnamed_addr #2
+declare spir_func void @_Z10ndrange_3DPKm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef) local_unnamed_addr #2
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll
deleted file mode 100644
index 8ba5e99df52ae..0000000000000
--- a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll
+++ /dev/null
@@ -1,83 +0,0 @@
-;; Test what ndrange_2D and ndrange_3D can coexist in the same module
-;;
-;; bash$ cat BuildNDRange_2.cl
-;; void test_ndrange_2D3D() {
-;;   size_t lsize2[2] = {1, 1};
-;;   ndrange_2D(lsize2);
-;;
-;;   size_t lsize3[3] = {1, 1, 1};
-;;   ndrange_3D(lsize3);
-;; }
-;;
-;; void test_ndrange_const_2D3D() {
-;;   const size_t lsize2[2] = {1, 1};
-;;   ndrange_2D(lsize2);
-;;
-;;   const size_t lsize3[3] = {1, 1, 1};
-;;   ndrange_3D(lsize3);
-;; }
-;; bash$ $PATH_TO_GEN/bin/clang -cc1 -x cl -cl-std=CL2.0 -triple spir64-unknown-unknown -emit-llvm  -include opencl-20.h  BuildNDRange_2.cl -o BuildNDRange_2.ll
-
-; 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 %}
-
-; TODO(#60133): Requires updates following opaque pointer migration.
-; XFAIL: *
-; REQUIRES: asserts
-
-; CHECK-SPIRV-DAG:     %[[#LEN2_ID:]] = OpConstant %[[#]] 2
-; CHECK-SPIRV-DAG:     %[[#LEN3_ID:]] = OpConstant %[[#]] 3
-; CHECK-SPIRV-DAG:     %[[#ARRAY_T2:]] = OpTypeArray %[[#]] %[[#LEN2_ID]]
-; CHECK-SPIRV-DAG:     %[[#ARRAY_T3:]] = OpTypeArray %[[#]] %[[#LEN3_ID]]
-
-; CHECK-SPIRV-LABEL:   OpFunction
-; CHECK-SPIRV:         %[[#LOAD2_ID:]] = OpLoad %[[#ARRAY_T2]]
-; CHECK-SPIRV:         %[[#]] = OpBuildNDRange %[[#]] %[[#LOAD2_ID]]
-; CHECK-SPIRV:         %[[#LOAD3_ID:]] = OpLoad %[[#ARRAY_T3]]
-; CHECK-SPIRV:         %[[#]] = OpBuildNDRange %[[#]] %[[#LOAD3_ID]]
-; CHECK-SPIRV-LABEL:   OpFunctionEnd
-
-; CHECK-SPIRV-LABEL:   OpFunction
-; CHECK-SPIRV:         %[[#CONST_LOAD2_ID:]] = OpLoad %[[#ARRAY_T2]]
-; CHECK-SPIRV:         %[[#]] = OpBuildNDRange %[[#]] %[[#CONST_LOAD2_ID]]
-; CHECK-SPIRV:         %[[#CONST_LOAD3_ID:]] = OpLoad %[[#ARRAY_T3]]
-; CHECK-SPIRV:         %[[#]] = OpBuildNDRange %[[#]] %[[#CONST_LOAD3_ID]]
-; CHECK-SPIRV-LABEL:   OpFunctionEnd
-
-%struct.ndrange_t = type { i32, [3 x i64], [3 x i64], [3 x i64] }
-
- at test_ndrange_2D3D.lsize2 = private constant [2 x i64] [i64 1, i64 1], align 8
- at test_ndrange_2D3D.lsize3 = private constant [3 x i64] [i64 1, i64 1, i64 1], align 8
-
-
-define spir_func void @test_ndrange_2D3D() {
-entry:
-  %lsize2 = alloca [2 x i64], align 8
-  %tmp = alloca %struct.ndrange_t, align 8
-  %lsize3 = alloca [3 x i64], align 8
-  %tmp3 = alloca %struct.ndrange_t, align 8
-  %0 = bitcast ptr %lsize2 to ptr
-  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %0, ptr align 8 @test_ndrange_2D3D.lsize2, i64 16, i1 false)
-  %arraydecay = getelementptr inbounds [2 x i64], ptr %lsize2, i64 0, i64 0
-  call spir_func void @_Z10ndrange_2DPKm(ptr sret(ptr) %tmp, ptr %arraydecay)
-  %1 = bitcast ptr %lsize3 to ptr
-  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %1, ptr align 8 @test_ndrange_2D3D.lsize3, i64 24, i1 false)
-  %arraydecay2 = getelementptr inbounds [3 x i64], ptr %lsize3, i64 0, i64 0
-  call spir_func void @_Z10ndrange_3DPKm(ptr sret(ptr) %tmp3, ptr %arraydecay2)
-  ret void
-}
-
-declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1)
-
-declare spir_func void @_Z10ndrange_2DPKm(ptr sret(ptr), ptr)
-
-declare spir_func void @_Z10ndrange_3DPKm(ptr sret(ptr), ptr)
-
-define spir_func void @test_ndrange_const_2D3D() {
-entry:
-  %tmp = alloca %struct.ndrange_t, align 8
-  %tmp1 = alloca %struct.ndrange_t, align 8
-  call spir_func void @_Z10ndrange_2DPKm(ptr sret(ptr) %tmp, ptr @test_ndrange_2D3D.lsize2)
-  call spir_func void @_Z10ndrange_3DPKm(ptr sret(ptr) %tmp1, ptr @test_ndrange_2D3D.lsize3)
-  ret void
-}

>From 5a233bac8ad58524854493cb2a64bceb1198f25e Mon Sep 17 00:00:00 2001
From: idubinov <igor.dubinov at amd.com>
Date: Thu, 12 Mar 2026 10:25:22 -0500
Subject: [PATCH 3/8] code format

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index 9a5d14276a321..2677ad1b5ca3e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -2659,24 +2659,21 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
   const unsigned AddressModelBits = GR->getPointerSize();
   assert(AddressModelBits == 64 || AddressModelBits == 32);
 
-
   // The dimension is encoded in the function name as "ndrange_XD" where X is
   // 1, 2, or 3.
   unsigned Dimension = atoi(Call->Builtin->Name.substr(8, 1).data());
   assert(Dimension <= 3 && Dimension >= 1);
 
-
-  // Get work size type; When fewer than 4 arguments are provided, build a zero constant for the
-  // missing one.
+  // Get work size type; When fewer than 4 arguments are provided, build a zero
+  // constant for the missing one.
   SPIRVTypeInst SpvFieldTy;
   Register ConstZero;
   if (Dimension == 1) {
-    SpvFieldTy =
-        GR->getSPIRVTypeForVReg(Call->Arguments[GlobalWorkSizeArgIdx]);
+    SpvFieldTy = GR->getSPIRVTypeForVReg(Call->Arguments[GlobalWorkSizeArgIdx]);
     assert(SpvFieldTy && SpvFieldTy->getOpcode() == SPIRV::OpTypeInt &&
-            "Expected scalar integer type");
+           "Expected scalar integer type");
 
-    if (NumArgs < 4) 
+    if (NumArgs < 4)
       ConstZero = GR->buildConstantInt(0, MIRBuilder, SpvFieldTy, true);
   } else {
     Type *BaseTy =
@@ -2695,7 +2692,6 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
     }
   }
 
-
   Register GlobalWorkSize;
   Register LocalWorkSize;
   Register GlobalWorkOffset;

>From abb41d1516307ae6f2699aabb8aba5e6c9b670bb Mon Sep 17 00:00:00 2001
From: idubinov <igor.dubinov at amd.com>
Date: Tue, 17 Mar 2026 11:20:00 -0500
Subject: [PATCH 4/8] Add support of no sret calls

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp       | 81 +++++++++++--------
 llvm/lib/Target/SPIRV/SPIRVBuiltins.td        |  6 +-
 .../SPIRV/transcoding/BuildNDRange_no_sret.ll | 27 +++++++
 3 files changed, 76 insertions(+), 38 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_no_sret.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index 2677ad1b5ca3e..a28ba27365b2f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -2625,34 +2625,28 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
   //   (global_work_size)
   //   (global_work_size, local_work_size)
   //   (global_work_offset, global_work_size, local_work_size)  -- note the
-  //   argument reordering
+  //   argument reordering when max arguments presented
+  // The function can return data throught sret argument on position 0, while function return value is void - in that case other argument indexes should be adjusted accordingly. 
   //
   // SPIR-V's OpBuildNDRange takes all three arguments (GlobalWorkSize,
   // LocalWorkSize, GlobalWorkOffset). For 1D kernels the values are scalars;
   // for 2D/3D they are arrays of 2 or 3 elements. Any missing argument is
   // set to zero.
-
+  // 
+  // Lets calculate argument indexes based on that info:
   unsigned NumArgs = Call->Arguments.size();
-  assert(NumArgs >= 2 && NumArgs <= 4);
+  const unsigned maxArgs = Call->Builtin->MaxNumArgs;
+  const unsigned IncorrectArgIdx = maxArgs + 1;
 
-  const unsigned ReturnValueArgIdx = 0;
-  const unsigned IncorrectArgIdx = 5;
-  const unsigned GlobalWorkSizeArgIdx = NumArgs < 4 ? 1 : 2;
-  const unsigned LocalWorkSizeArgIdx =
-      NumArgs == 2 ? IncorrectArgIdx : (NumArgs == 3 ? 2 : 3);
-  const unsigned GlobalWorkOffsetArgIdx = NumArgs < 4 ? IncorrectArgIdx : 1;
+  const Type *RetTy = GR->getTypeForSPIRVType(Call->ReturnType);
+  bool hasSRetArg = RetTy->isVoidTy();
 
-  // Return type is the nd_range struct pointed to by the first argument.
-  MachineRegisterInfo *MRI = MIRBuilder.getMRI();
-  SPIRVTypeInst PtrType =
-      GR->getSPIRVTypeForVReg(Call->Arguments[ReturnValueArgIdx]);
-  assert(PtrType->getOpcode() == SPIRV::OpTypePointer &&
-         PtrType->getOperand(2 /*Pointee*/).isReg());
-  Register ReturnTypeReg = PtrType->getOperand(2).getReg();
-  SPIRVTypeInst ReturnStructType = GR->getSPIRVTypeForVReg(ReturnTypeReg);
-  MachineFunction &MF = MIRBuilder.getMF();
-  Register TmpReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
-  GR->assignSPIRVTypeToVReg(ReturnStructType, TmpReg, MF);
+  const unsigned SRetArgIdx = hasSRetArg ? 0 : IncorrectArgIdx;
+  const unsigned ArgBase = hasSRetArg ? 1 : 0;
+  const unsigned GlobalWorkSizeArgIdx = NumArgs < maxArgs ? ArgBase : ArgBase + 1;
+  const unsigned LocalWorkSizeArgIdx =
+      (NumArgs - ArgBase == 1) ? IncorrectArgIdx : (NumArgs == maxArgs ? ArgBase + 2 : ArgBase + 1);
+  const unsigned GlobalWorkOffsetArgIdx = NumArgs == maxArgs ? ArgBase : IncorrectArgIdx;
 
   // Each nd_range field is an array of <Dimension> integers matching the
   // address model width (32 or 64 bits).
@@ -2666,6 +2660,7 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
 
   // Get work size type; When fewer than 4 arguments are provided, build a zero
   // constant for the missing one.
+  MachineFunction &MF = MIRBuilder.getMF();
   SPIRVTypeInst SpvFieldTy;
   Register ConstZero;
   if (Dimension == 1) {
@@ -2673,7 +2668,7 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
     assert(SpvFieldTy && SpvFieldTy->getOpcode() == SPIRV::OpTypeInt &&
            "Expected scalar integer type");
 
-    if (NumArgs < 4)
+    if (NumArgs < maxArgs)
       ConstZero = GR->buildConstantInt(0, MIRBuilder, SpvFieldTy, true);
   } else {
     Type *BaseTy =
@@ -2682,7 +2677,7 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
     SpvFieldTy = GR->getOrCreateSPIRVType(
         FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadOnly, true);
 
-    if (NumArgs < 4) {
+    if (NumArgs < maxArgs) {
       auto InsertIt = MIRBuilder.getInsertPt();
       MachineBasicBlock &MBB = MIRBuilder.getMBB();
       MachineInstr &InsertMI = (InsertIt != MBB.end()) ? *InsertIt : MBB.back();
@@ -2692,16 +2687,14 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
     }
   }
 
-  Register GlobalWorkSize;
-  Register LocalWorkSize;
-  Register GlobalWorkOffset;
+  MachineRegisterInfo *MRI = MIRBuilder.getMRI();
 
-  auto LoadRegisterData = [&](Register &Reg, unsigned Idx) {
-    Reg = (Idx == IncorrectArgIdx) ? ConstZero : Call->Arguments[Idx];
+  auto CreateDataRegister = [&](unsigned Idx) -> Register {
+    Register Reg = (Idx == IncorrectArgIdx) ? ConstZero : Call->Arguments[Idx];
 
     if (GR->getSPIRVTypeForVReg(Reg) == SpvFieldTy) {
-      // Already has the correct type
-      return;
+      // Already has the correct type.
+      return Reg;
     }
 
     assert(GR->getSPIRVTypeForVReg(Reg)->getOpcode() == SPIRV::OpTypePointer &&
@@ -2716,21 +2709,39 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
         .addDef(Reg)
         .addUse(GR->getSPIRVTypeID(SpvFieldTy))
         .addUse(Ptr);
-    return;
+    return Reg;
   };
 
-  LoadRegisterData(GlobalWorkSize, GlobalWorkSizeArgIdx);
-  LoadRegisterData(LocalWorkSize, LocalWorkSizeArgIdx);
-  LoadRegisterData(GlobalWorkOffset, GlobalWorkOffsetArgIdx);
+  Register GlobalWorkSize = CreateDataRegister(GlobalWorkSizeArgIdx);
+  Register LocalWorkSize = CreateDataRegister(LocalWorkSizeArgIdx);
+  Register GlobalWorkOffset = CreateDataRegister(GlobalWorkOffsetArgIdx);
+
+  if (!hasSRetArg) {
+    return MIRBuilder.buildInstr(SPIRV::OpBuildNDRange)
+          .addDef(Call->ReturnRegister)
+          .addUse(GR->getSPIRVTypeID(Call->ReturnType))
+          .addUse(GlobalWorkSize)
+          .addUse(LocalWorkSize)
+          .addUse(GlobalWorkOffset);
+  }
+
+  // SRet argument presented - return type is the nd_range struct pointed to by the first argument.
+  Register SRetReg = Call->Arguments[SRetArgIdx];
+  SPIRVTypeInst SRetPtrType =
+      GR->getSPIRVTypeForVReg(SRetReg);
+  SPIRVTypeInst SRetType = GR->getPointeeType(SRetPtrType);
+
+  Register TmpReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
+  GR->assignSPIRVTypeToVReg(SRetType, TmpReg, MF);
 
   MIRBuilder.buildInstr(SPIRV::OpBuildNDRange)
       .addDef(TmpReg)
-      .addUse(ReturnTypeReg)
+      .addUse(GR->getSPIRVTypeID(SRetType))
       .addUse(GlobalWorkSize)
       .addUse(LocalWorkSize)
       .addUse(GlobalWorkOffset);
   return MIRBuilder.buildInstr(SPIRV::OpStore)
-      .addUse(Call->Arguments[ReturnValueArgIdx])
+      .addUse(Call->Arguments[SRetArgIdx])
       .addUse(TmpReg);
 }
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
index 3820713db3e4a..f3daf7c22674e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
@@ -702,9 +702,9 @@ defm : DemangledNativeBuiltin<"capture_event_profiling_info", OpenCL_std, Enqueu
 defm : DemangledNativeBuiltin<"__spirv_CaptureEventProfilingInfo", OpenCL_std, Enqueue, 3, 3, OpCaptureEventProfilingInfo>;
 defm : DemangledNativeBuiltin<"get_default_queue", OpenCL_std, Enqueue, 0, 0, OpGetDefaultQueue>;
 defm : DemangledNativeBuiltin<"__spirv_GetDefaultQueue", OpenCL_std, Enqueue, 0, 0, OpGetDefaultQueue>;
-defm : DemangledNativeBuiltin<"ndrange_1D", OpenCL_std, Enqueue, 2, 4, OpBuildNDRange>;
-defm : DemangledNativeBuiltin<"ndrange_2D", OpenCL_std, Enqueue, 2, 4, OpBuildNDRange>;
-defm : DemangledNativeBuiltin<"ndrange_3D", OpenCL_std, Enqueue, 2, 4, OpBuildNDRange>;
+defm : DemangledNativeBuiltin<"ndrange_1D", OpenCL_std, Enqueue, 1, 4, OpBuildNDRange>;
+defm : DemangledNativeBuiltin<"ndrange_2D", OpenCL_std, Enqueue, 1, 4, OpBuildNDRange>;
+defm : DemangledNativeBuiltin<"ndrange_3D", OpenCL_std, Enqueue, 1, 4, OpBuildNDRange>;
 
 // Spec constant builtin records:
 defm : DemangledNativeBuiltin<"__spirv_SpecConstant", OpenCL_std, SpecConstant, 2, 2, OpSpecConstant>;
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_no_sret.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_no_sret.ll
new file mode 100644
index 0000000000000..d13e7cba6d9bf
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_no_sret.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+
+%struct.ndrange_t = type { i32, [3 x i64], [3 x i64], [3 x i64] }
+
+define spir_func void @test_ndrange_2D3D() local_unnamed_addr #0 {
+; CHECK-LABEL: test_ndrange_2D3D
+; CHECK:       Begin function test_ndrange_2D3D
+; CHECK:       %[[#r18:]] = OpBuildNDRange %[[#r10:]] %[[#r11:]] %[[#r12:]] %[[#r13:]]
+; CHECK-NOT:    OpStore %[[#r19:]] %[[#r18]]
+entry:
+  %tmp = alloca %struct.ndrange_t, align 8
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp) #3
+  call spir_func %struct.ndrange_t @_Z10ndrange_1Dm(i64 noundef 1) #4
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp) #3
+  ret void
+}
+
+declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
+
+declare spir_func %struct.ndrange_t  @_Z10ndrange_1Dm(i64 noundef) local_unnamed_addr #2
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
+declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1

>From 231dd9ab7308a3e34a7017c16f3d432b71143646 Mon Sep 17 00:00:00 2001
From: idubinov <igor.dubinov at amd.com>
Date: Tue, 17 Mar 2026 11:24:39 -0500
Subject: [PATCH 5/8] code format

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp | 53 +++++++++++++++----------
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index a28ba27365b2f..a885da7118b82 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -2624,16 +2624,21 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
   // variants, accepting 1 to 3 arguments:
   //   (global_work_size)
   //   (global_work_size, local_work_size)
-  //   (global_work_offset, global_work_size, local_work_size)  -- note the
-  //   argument reordering when max arguments presented
-  // The function can return data throught sret argument on position 0, while function return value is void - in that case other argument indexes should be adjusted accordingly. 
+  //   (global_work_offset, global_work_size, local_work_size)
+  // Note: When all three arguments are provided, they are reordered compared
+  // to the one- or two-argument form.
   //
-  // SPIR-V's OpBuildNDRange takes all three arguments (GlobalWorkSize,
-  // LocalWorkSize, GlobalWorkOffset). For 1D kernels the values are scalars;
-  // for 2D/3D they are arrays of 2 or 3 elements. Any missing argument is
-  // set to zero.
-  // 
-  // Lets calculate argument indexes based on that info:
+  // The function may return data through an sret argument at position 0 (with
+  // a void function return type). When present, all other argument indices are
+  // adjusted accordingly.
+  //
+  // SPIR-V's OpBuildNDRange requires all three arguments (GlobalWorkSize,
+  // LocalWorkSize, GlobalWorkOffset). For 1D kernels, the values are scalars;
+  // for 2D/3D kernels, they are arrays of 2 or 3 elements. Missing arguments
+  // default to zero.
+  //
+  // Calculate argument indices based on the number of arguments and presence
+  // of sret:
   unsigned NumArgs = Call->Arguments.size();
   const unsigned maxArgs = Call->Builtin->MaxNumArgs;
   const unsigned IncorrectArgIdx = maxArgs + 1;
@@ -2643,10 +2648,14 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
 
   const unsigned SRetArgIdx = hasSRetArg ? 0 : IncorrectArgIdx;
   const unsigned ArgBase = hasSRetArg ? 1 : 0;
-  const unsigned GlobalWorkSizeArgIdx = NumArgs < maxArgs ? ArgBase : ArgBase + 1;
+  const unsigned GlobalWorkSizeArgIdx =
+      NumArgs < maxArgs ? ArgBase : ArgBase + 1;
   const unsigned LocalWorkSizeArgIdx =
-      (NumArgs - ArgBase == 1) ? IncorrectArgIdx : (NumArgs == maxArgs ? ArgBase + 2 : ArgBase + 1);
-  const unsigned GlobalWorkOffsetArgIdx = NumArgs == maxArgs ? ArgBase : IncorrectArgIdx;
+      (NumArgs - ArgBase == 1)
+          ? IncorrectArgIdx
+          : (NumArgs == maxArgs ? ArgBase + 2 : ArgBase + 1);
+  const unsigned GlobalWorkOffsetArgIdx =
+      NumArgs == maxArgs ? ArgBase : IncorrectArgIdx;
 
   // Each nd_range field is an array of <Dimension> integers matching the
   // address model width (32 or 64 bits).
@@ -2658,8 +2667,8 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
   unsigned Dimension = atoi(Call->Builtin->Name.substr(8, 1).data());
   assert(Dimension <= 3 && Dimension >= 1);
 
-  // Get work size type; When fewer than 4 arguments are provided, build a zero
-  // constant for the missing one.
+  // Determine the work size type based on the dimension. For missing arguments,
+  // create a zero constant of the appropriate type.
   MachineFunction &MF = MIRBuilder.getMF();
   SPIRVTypeInst SpvFieldTy;
   Register ConstZero;
@@ -2718,17 +2727,17 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
 
   if (!hasSRetArg) {
     return MIRBuilder.buildInstr(SPIRV::OpBuildNDRange)
-          .addDef(Call->ReturnRegister)
-          .addUse(GR->getSPIRVTypeID(Call->ReturnType))
-          .addUse(GlobalWorkSize)
-          .addUse(LocalWorkSize)
-          .addUse(GlobalWorkOffset);
+        .addDef(Call->ReturnRegister)
+        .addUse(GR->getSPIRVTypeID(Call->ReturnType))
+        .addUse(GlobalWorkSize)
+        .addUse(LocalWorkSize)
+        .addUse(GlobalWorkOffset);
   }
 
-  // SRet argument presented - return type is the nd_range struct pointed to by the first argument.
+  // When sret is used, store nd_range struct through the pointer in the first
+  // argument.
   Register SRetReg = Call->Arguments[SRetArgIdx];
-  SPIRVTypeInst SRetPtrType =
-      GR->getSPIRVTypeForVReg(SRetReg);
+  SPIRVTypeInst SRetPtrType = GR->getSPIRVTypeForVReg(SRetReg);
   SPIRVTypeInst SRetType = GR->getPointeeType(SRetPtrType);
 
   Register TmpReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);

>From bde1071469c19e4c872f059191388324080adb98 Mon Sep 17 00:00:00 2001
From: idubinov <igor.dubinov at amd.com>
Date: Tue, 17 Mar 2026 11:52:25 -0500
Subject: [PATCH 6/8] update test

---
 .../CodeGen/SPIRV/transcoding/BuildNDRange.ll | 737 +++++++++---------
 .../SPIRV/transcoding/BuildNDRange_no_sret.ll |   7 -
 2 files changed, 368 insertions(+), 376 deletions(-)

diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll
index fac6aebfaa500..68692084bbc4e 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ;; Test that checks all variants of ndrange and what ndrange_1D, ndrange_2D and ndrange_3D can coexist in the same module
 ;;
 ;; bash$ cat BuildNDRange.cl
@@ -75,374 +74,374 @@
 
 define spir_func void @test_ndrange_2D3D() local_unnamed_addr #0 {
 ; CHECK-LABEL: test_ndrange_2D3D
-; CHECK:       %50 = OpFunction %3 None %4 ; -- Begin function test_ndrange_2D3D
-; CHECK-NEXT:    %2 = OpLabel
-; CHECK-NEXT:    %51 = OpVariable %10 Function
-; CHECK-NEXT:    %52 = OpVariable %10 Function
-; CHECK-NEXT:    %53 = OpVariable %10 Function
-; CHECK-NEXT:    %54 = OpVariable %10 Function
-; CHECK-NEXT:    %55 = OpVariable %10 Function
-; CHECK-NEXT:    %56 = OpVariable %13 Function
-; CHECK-NEXT:    %57 = OpVariable %13 Function
-; CHECK-NEXT:    %58 = OpVariable %13 Function
-; CHECK-NEXT:    %59 = OpVariable %10 Function
-; CHECK-NEXT:    %60 = OpVariable %10 Function
-; CHECK-NEXT:    %61 = OpVariable %10 Function
-; CHECK-NEXT:    %62 = OpVariable %10 Function
-; CHECK-NEXT:    %63 = OpVariable %10 Function
-; CHECK-NEXT:    %64 = OpVariable %16 Function
-; CHECK-NEXT:    %65 = OpVariable %16 Function
-; CHECK-NEXT:    %66 = OpVariable %16 Function
-; CHECK-NEXT:    %67 = OpVariable %10 Function
-; CHECK-NEXT:    %68 = OpVariable %10 Function
-; CHECK-NEXT:    %69 = OpVariable %10 Function
-; CHECK-NEXT:    %70 = OpVariable %10 Function
-; CHECK-NEXT:    %71 = OpVariable %10 Function
-; CHECK-NEXT:    %72 = OpVariable %10 Function
-; CHECK-NEXT:    %73 = OpVariable %10 Function
-; CHECK-NEXT:    %74 = OpVariable %10 Function
-; CHECK-NEXT:    %75 = OpVariable %10 Function
-; CHECK-NEXT:    %76 = OpVariable %10 Function
-; CHECK-NEXT:    %77 = OpVariable %13 Function
-; CHECK-NEXT:    %78 = OpVariable %13 Function
-; CHECK-NEXT:    %79 = OpVariable %13 Function
-; CHECK-NEXT:    %80 = OpVariable %10 Function
-; CHECK-NEXT:    %81 = OpVariable %10 Function
-; CHECK-NEXT:    %82 = OpVariable %10 Function
-; CHECK-NEXT:    %83 = OpVariable %10 Function
-; CHECK-NEXT:    %84 = OpVariable %10 Function
-; CHECK-NEXT:    %85 = OpVariable %16 Function
-; CHECK-NEXT:    %86 = OpVariable %16 Function
-; CHECK-NEXT:    %87 = OpVariable %16 Function
-; CHECK-NEXT:    %88 = OpVariable %10 Function
-; CHECK-NEXT:    %89 = OpVariable %10 Function
-; CHECK-NEXT:    %90 = OpVariable %10 Function
-; CHECK-NEXT:    %91 = OpVariable %10 Function
-; CHECK-NEXT:    %92 = OpVariable %10 Function
-; CHECK-NEXT:    %93 = OpBitcast %27 %51
-; CHECK-NEXT:    OpLifetimeStart %93 80
-; CHECK-NEXT:    %94 = OpBuildNDRange %9 %24 %25 %25
-; CHECK-NEXT:    OpStore %51 %94
-; CHECK-NEXT:    %95 = OpBitcast %27 %51
-; CHECK-NEXT:    OpLifetimeStop %95 80
-; CHECK-NEXT:    %96 = OpBitcast %27 %52
-; CHECK-NEXT:    OpLifetimeStart %96 80
-; CHECK-NEXT:    %97 = OpBuildNDRange %9 %24 %23 %25
-; CHECK-NEXT:    OpStore %52 %97
-; CHECK-NEXT:    %98 = OpBitcast %27 %52
-; CHECK-NEXT:    OpLifetimeStop %98 80
-; CHECK-NEXT:    %99 = OpBitcast %27 %53
-; CHECK-NEXT:    OpLifetimeStart %99 80
-; CHECK-NEXT:    %100 = OpBuildNDRange %9 %24 %23 %22
-; CHECK-NEXT:    OpStore %53 %100
-; CHECK-NEXT:    %101 = OpBitcast %27 %53
-; CHECK-NEXT:    OpLifetimeStop %101 80
-; CHECK-NEXT:    %102 = OpBitcast %27 %54
-; CHECK-NEXT:    OpLifetimeStart %102 80
-; CHECK-NEXT:    %103 = OpBuildNDRange %9 %24 %24 %25
-; CHECK-NEXT:    OpStore %54 %103
-; CHECK-NEXT:    %104 = OpBitcast %27 %54
-; CHECK-NEXT:    OpLifetimeStop %104 80
-; CHECK-NEXT:    %105 = OpBitcast %27 %55
-; CHECK-NEXT:    OpLifetimeStart %105 80
-; CHECK-NEXT:    %106 = OpBuildNDRange %9 %24 %24 %24
-; CHECK-NEXT:    OpStore %55 %106
-; CHECK-NEXT:    %107 = OpBitcast %27 %55
-; CHECK-NEXT:    OpLifetimeStop %107 80
-; CHECK-NEXT:    %108 = OpBitcast %27 %56
-; CHECK-NEXT:    OpLifetimeStart %108 16
-; CHECK-NEXT:    OpCopyMemorySized %56 %29 %21 Aligned 8
-; CHECK-NEXT:    %109 = OpBitcast %27 %57
-; CHECK-NEXT:    OpLifetimeStart %109 16
-; CHECK-NEXT:    OpCopyMemorySized %57 %31 %21 Aligned 8
-; CHECK-NEXT:    %110 = OpBitcast %27 %58
-; CHECK-NEXT:    OpLifetimeStart %110 16
-; CHECK-NEXT:    OpCopyMemorySized %58 %33 %21 Aligned 8
-; CHECK-NEXT:    %111 = OpBitcast %27 %59
-; CHECK-NEXT:    OpLifetimeStart %111 80
-; CHECK-NEXT:    %112 = OpLoad %12 %56
-; CHECK-NEXT:    %113 = OpBuildNDRange %9 %112 %14 %14
-; CHECK-NEXT:    OpStore %59 %113
-; CHECK-NEXT:    %114 = OpBitcast %27 %59
-; CHECK-NEXT:    OpLifetimeStop %114 80
-; CHECK-NEXT:    %115 = OpBitcast %27 %60
-; CHECK-NEXT:    OpLifetimeStart %115 80
-; CHECK-NEXT:    %116 = OpBitcast %15 %56
-; CHECK-NEXT:    %117 = OpBitcast %13 %116
-; CHECK-NEXT:    %118 = OpLoad %12 %117
-; CHECK-NEXT:    %119 = OpLoad %12 %57
-; CHECK-NEXT:    %120 = OpBuildNDRange %9 %118 %119 %14
-; CHECK-NEXT:    OpStore %60 %120
-; CHECK-NEXT:    %121 = OpBitcast %27 %60
-; CHECK-NEXT:    OpLifetimeStop %121 80
-; CHECK-NEXT:    %122 = OpBitcast %27 %61
-; CHECK-NEXT:    OpLifetimeStart %122 80
-; CHECK-NEXT:    %123 = OpBitcast %15 %58
-; CHECK-NEXT:    %124 = OpBitcast %13 %116
-; CHECK-NEXT:    %125 = OpLoad %12 %124
-; CHECK-NEXT:    %126 = OpLoad %12 %57
-; CHECK-NEXT:    %127 = OpBitcast %13 %123
-; CHECK-NEXT:    %128 = OpLoad %12 %127
-; CHECK-NEXT:    %129 = OpBuildNDRange %9 %125 %126 %128
-; CHECK-NEXT:    OpStore %61 %129
-; CHECK-NEXT:    %130 = OpBitcast %27 %61
-; CHECK-NEXT:    OpLifetimeStop %130 80
-; CHECK-NEXT:    %131 = OpBitcast %27 %62
-; CHECK-NEXT:    OpLifetimeStart %131 80
-; CHECK-NEXT:    %132 = OpBitcast %13 %116
-; CHECK-NEXT:    %133 = OpLoad %12 %132
-; CHECK-NEXT:    %134 = OpLoad %12 %56
-; CHECK-NEXT:    %135 = OpBuildNDRange %9 %133 %134 %14
-; CHECK-NEXT:    OpStore %62 %135
-; CHECK-NEXT:    %136 = OpBitcast %27 %62
-; CHECK-NEXT:    OpLifetimeStop %136 80
-; CHECK-NEXT:    %137 = OpBitcast %27 %63
-; CHECK-NEXT:    OpLifetimeStart %137 80
-; CHECK-NEXT:    %138 = OpBitcast %13 %116
-; CHECK-NEXT:    %139 = OpLoad %12 %138
-; CHECK-NEXT:    %140 = OpLoad %12 %56
-; CHECK-NEXT:    %141 = OpBitcast %13 %116
-; CHECK-NEXT:    %142 = OpLoad %12 %141
-; CHECK-NEXT:    %143 = OpBuildNDRange %9 %139 %140 %142
-; CHECK-NEXT:    OpStore %63 %143
-; CHECK-NEXT:    %144 = OpBitcast %27 %63
-; CHECK-NEXT:    OpLifetimeStop %144 80
-; CHECK-NEXT:    %145 = OpBitcast %27 %64
-; CHECK-NEXT:    OpLifetimeStart %145 24
-; CHECK-NEXT:    OpCopyMemorySized %64 %35 %20 Aligned 8
-; CHECK-NEXT:    %146 = OpBitcast %27 %65
-; CHECK-NEXT:    OpLifetimeStart %146 24
-; CHECK-NEXT:    OpCopyMemorySized %65 %37 %20 Aligned 8
-; CHECK-NEXT:    %147 = OpBitcast %27 %66
-; CHECK-NEXT:    OpLifetimeStart %147 24
-; CHECK-NEXT:    OpCopyMemorySized %66 %39 %20 Aligned 8
-; CHECK-NEXT:    %148 = OpBitcast %27 %67
-; CHECK-NEXT:    OpLifetimeStart %148 80
-; CHECK-NEXT:    %149 = OpLoad %8 %64
-; CHECK-NEXT:    %150 = OpBuildNDRange %9 %149 %17 %17
-; CHECK-NEXT:    OpStore %67 %150
-; CHECK-NEXT:    %151 = OpBitcast %27 %67
-; CHECK-NEXT:    OpLifetimeStop %151 80
-; CHECK-NEXT:    %152 = OpBitcast %27 %68
-; CHECK-NEXT:    OpLifetimeStart %152 80
-; CHECK-NEXT:    %153 = OpBitcast %15 %64
-; CHECK-NEXT:    %154 = OpBitcast %13 %153
-; CHECK-NEXT:    %155 = OpLoad %12 %154
-; CHECK-NEXT:    %156 = OpBitcast %13 %65
-; CHECK-NEXT:    %157 = OpLoad %12 %156
-; CHECK-NEXT:    %158 = OpBuildNDRange %9 %155 %157 %14
-; CHECK-NEXT:    OpStore %68 %158
-; CHECK-NEXT:    %159 = OpBitcast %27 %68
-; CHECK-NEXT:    OpLifetimeStop %159 80
-; CHECK-NEXT:    %160 = OpBitcast %27 %69
-; CHECK-NEXT:    OpLifetimeStart %160 80
-; CHECK-NEXT:    %161 = OpBitcast %15 %66
-; CHECK-NEXT:    %162 = OpBitcast %13 %153
-; CHECK-NEXT:    %163 = OpLoad %12 %162
-; CHECK-NEXT:    %164 = OpBitcast %13 %65
-; CHECK-NEXT:    %165 = OpLoad %12 %164
-; CHECK-NEXT:    %166 = OpBitcast %13 %161
-; CHECK-NEXT:    %167 = OpLoad %12 %166
-; CHECK-NEXT:    %168 = OpBuildNDRange %9 %163 %165 %167
-; CHECK-NEXT:    OpStore %69 %168
-; CHECK-NEXT:    %169 = OpBitcast %27 %69
-; CHECK-NEXT:    OpLifetimeStop %169 80
-; CHECK-NEXT:    %170 = OpBitcast %27 %70
-; CHECK-NEXT:    OpLifetimeStart %170 80
-; CHECK-NEXT:    %171 = OpBitcast %13 %153
-; CHECK-NEXT:    %172 = OpLoad %12 %171
-; CHECK-NEXT:    %173 = OpBitcast %13 %64
-; CHECK-NEXT:    %174 = OpLoad %12 %173
-; CHECK-NEXT:    %175 = OpBuildNDRange %9 %172 %174 %14
-; CHECK-NEXT:    OpStore %70 %175
-; CHECK-NEXT:    %176 = OpBitcast %27 %70
-; CHECK-NEXT:    OpLifetimeStop %176 80
-; CHECK-NEXT:    %177 = OpBitcast %27 %71
-; CHECK-NEXT:    OpLifetimeStart %177 80
-; CHECK-NEXT:    %178 = OpBitcast %13 %153
-; CHECK-NEXT:    %179 = OpLoad %12 %178
-; CHECK-NEXT:    %180 = OpBitcast %13 %64
-; CHECK-NEXT:    %181 = OpLoad %12 %180
-; CHECK-NEXT:    %182 = OpBitcast %13 %153
-; CHECK-NEXT:    %183 = OpLoad %12 %182
-; CHECK-NEXT:    %184 = OpBuildNDRange %9 %179 %181 %183
-; CHECK-NEXT:    OpStore %71 %184
-; CHECK-NEXT:    %185 = OpBitcast %27 %71
-; CHECK-NEXT:    OpLifetimeStop %185 80
-; CHECK-NEXT:    %186 = OpBitcast %27 %72
-; CHECK-NEXT:    OpLifetimeStart %186 80
-; CHECK-NEXT:    %187 = OpBuildNDRange %9 %24 %25 %25
-; CHECK-NEXT:    OpStore %72 %187
-; CHECK-NEXT:    %188 = OpBitcast %27 %72
-; CHECK-NEXT:    OpLifetimeStop %188 80
-; CHECK-NEXT:    %189 = OpBitcast %27 %73
-; CHECK-NEXT:    OpLifetimeStart %189 80
-; CHECK-NEXT:    %190 = OpBuildNDRange %9 %24 %23 %25
-; CHECK-NEXT:    OpStore %73 %190
-; CHECK-NEXT:    %191 = OpBitcast %27 %73
-; CHECK-NEXT:    OpLifetimeStop %191 80
-; CHECK-NEXT:    %192 = OpBitcast %27 %74
-; CHECK-NEXT:    OpLifetimeStart %192 80
-; CHECK-NEXT:    %193 = OpBuildNDRange %9 %24 %23 %22
-; CHECK-NEXT:    OpStore %74 %193
-; CHECK-NEXT:    %194 = OpBitcast %27 %74
-; CHECK-NEXT:    OpLifetimeStop %194 80
-; CHECK-NEXT:    %195 = OpBitcast %27 %75
-; CHECK-NEXT:    OpLifetimeStart %195 80
-; CHECK-NEXT:    %196 = OpBuildNDRange %9 %24 %24 %25
-; CHECK-NEXT:    OpStore %75 %196
-; CHECK-NEXT:    %197 = OpBitcast %27 %75
-; CHECK-NEXT:    OpLifetimeStop %197 80
-; CHECK-NEXT:    %198 = OpBitcast %27 %76
-; CHECK-NEXT:    OpLifetimeStart %198 80
-; CHECK-NEXT:    %199 = OpBuildNDRange %9 %24 %24 %24
-; CHECK-NEXT:    OpStore %76 %199
-; CHECK-NEXT:    %200 = OpBitcast %27 %76
-; CHECK-NEXT:    OpLifetimeStop %200 80
-; CHECK-NEXT:    %201 = OpBitcast %27 %77
-; CHECK-NEXT:    OpLifetimeStart %201 16
-; CHECK-NEXT:    OpCopyMemorySized %77 %40 %21 Aligned 8
-; CHECK-NEXT:    %202 = OpBitcast %27 %78
-; CHECK-NEXT:    OpLifetimeStart %202 16
-; CHECK-NEXT:    OpCopyMemorySized %78 %42 %21 Aligned 8
-; CHECK-NEXT:    %203 = OpBitcast %27 %79
-; CHECK-NEXT:    OpLifetimeStart %203 16
-; CHECK-NEXT:    OpCopyMemorySized %79 %44 %21 Aligned 8
-; CHECK-NEXT:    %204 = OpBitcast %27 %80
-; CHECK-NEXT:    OpLifetimeStart %204 80
-; CHECK-NEXT:    %205 = OpLoad %12 %77
-; CHECK-NEXT:    %206 = OpBuildNDRange %9 %205 %14 %14
-; CHECK-NEXT:    OpStore %80 %206
-; CHECK-NEXT:    %207 = OpBitcast %27 %80
-; CHECK-NEXT:    OpLifetimeStop %207 80
-; CHECK-NEXT:    %208 = OpBitcast %27 %81
-; CHECK-NEXT:    OpLifetimeStart %208 80
-; CHECK-NEXT:    %209 = OpBitcast %15 %77
-; CHECK-NEXT:    %210 = OpBitcast %13 %209
-; CHECK-NEXT:    %211 = OpLoad %12 %210
-; CHECK-NEXT:    %212 = OpLoad %12 %78
-; CHECK-NEXT:    %213 = OpBuildNDRange %9 %211 %212 %14
-; CHECK-NEXT:    OpStore %81 %213
-; CHECK-NEXT:    %214 = OpBitcast %27 %81
-; CHECK-NEXT:    OpLifetimeStop %214 80
-; CHECK-NEXT:    %215 = OpBitcast %27 %82
-; CHECK-NEXT:    OpLifetimeStart %215 80
-; CHECK-NEXT:    %216 = OpBitcast %15 %79
-; CHECK-NEXT:    %217 = OpBitcast %13 %209
-; CHECK-NEXT:    %218 = OpLoad %12 %217
-; CHECK-NEXT:    %219 = OpLoad %12 %78
-; CHECK-NEXT:    %220 = OpBitcast %13 %216
-; CHECK-NEXT:    %221 = OpLoad %12 %220
-; CHECK-NEXT:    %222 = OpBuildNDRange %9 %218 %219 %221
-; CHECK-NEXT:    OpStore %82 %222
-; CHECK-NEXT:    %223 = OpBitcast %27 %82
-; CHECK-NEXT:    OpLifetimeStop %223 80
-; CHECK-NEXT:    %224 = OpBitcast %27 %83
-; CHECK-NEXT:    OpLifetimeStart %224 80
-; CHECK-NEXT:    %225 = OpBitcast %13 %209
-; CHECK-NEXT:    %226 = OpLoad %12 %225
-; CHECK-NEXT:    %227 = OpLoad %12 %77
-; CHECK-NEXT:    %228 = OpBuildNDRange %9 %226 %227 %14
-; CHECK-NEXT:    OpStore %83 %228
-; CHECK-NEXT:    %229 = OpBitcast %27 %83
-; CHECK-NEXT:    OpLifetimeStop %229 80
-; CHECK-NEXT:    %230 = OpBitcast %27 %84
-; CHECK-NEXT:    OpLifetimeStart %230 80
-; CHECK-NEXT:    %231 = OpBitcast %13 %209
-; CHECK-NEXT:    %232 = OpLoad %12 %231
-; CHECK-NEXT:    %233 = OpLoad %12 %77
-; CHECK-NEXT:    %234 = OpBitcast %13 %209
-; CHECK-NEXT:    %235 = OpLoad %12 %234
-; CHECK-NEXT:    %236 = OpBuildNDRange %9 %232 %233 %235
-; CHECK-NEXT:    OpStore %84 %236
-; CHECK-NEXT:    %237 = OpBitcast %27 %84
-; CHECK-NEXT:    OpLifetimeStop %237 80
-; CHECK-NEXT:    %238 = OpBitcast %27 %85
-; CHECK-NEXT:    OpLifetimeStart %238 24
-; CHECK-NEXT:    OpCopyMemorySized %85 %45 %20 Aligned 8
-; CHECK-NEXT:    %239 = OpBitcast %27 %86
-; CHECK-NEXT:    OpLifetimeStart %239 24
-; CHECK-NEXT:    OpCopyMemorySized %86 %47 %20 Aligned 8
-; CHECK-NEXT:    %240 = OpBitcast %27 %87
-; CHECK-NEXT:    OpLifetimeStart %240 24
-; CHECK-NEXT:    OpCopyMemorySized %87 %49 %20 Aligned 8
-; CHECK-NEXT:    %241 = OpBitcast %27 %88
-; CHECK-NEXT:    OpLifetimeStart %241 80
-; CHECK-NEXT:    %242 = OpLoad %8 %85
-; CHECK-NEXT:    %243 = OpBuildNDRange %9 %242 %17 %17
-; CHECK-NEXT:    OpStore %88 %243
-; CHECK-NEXT:    %244 = OpBitcast %27 %88
-; CHECK-NEXT:    OpLifetimeStop %244 80
-; CHECK-NEXT:    %245 = OpBitcast %27 %89
-; CHECK-NEXT:    OpLifetimeStart %245 80
-; CHECK-NEXT:    %246 = OpBitcast %15 %85
-; CHECK-NEXT:    %247 = OpBitcast %13 %246
-; CHECK-NEXT:    %248 = OpLoad %12 %247
-; CHECK-NEXT:    %249 = OpBitcast %13 %86
-; CHECK-NEXT:    %250 = OpLoad %12 %249
-; CHECK-NEXT:    %251 = OpBuildNDRange %9 %248 %250 %14
-; CHECK-NEXT:    OpStore %89 %251
-; CHECK-NEXT:    %252 = OpBitcast %27 %89
-; CHECK-NEXT:    OpLifetimeStop %252 80
-; CHECK-NEXT:    %253 = OpBitcast %27 %90
-; CHECK-NEXT:    OpLifetimeStart %253 80
-; CHECK-NEXT:    %254 = OpBitcast %15 %87
-; CHECK-NEXT:    %255 = OpBitcast %13 %246
-; CHECK-NEXT:    %256 = OpLoad %12 %255
-; CHECK-NEXT:    %257 = OpBitcast %13 %86
-; CHECK-NEXT:    %258 = OpLoad %12 %257
-; CHECK-NEXT:    %259 = OpBitcast %13 %254
-; CHECK-NEXT:    %260 = OpLoad %12 %259
-; CHECK-NEXT:    %261 = OpBuildNDRange %9 %256 %258 %260
-; CHECK-NEXT:    OpStore %90 %261
-; CHECK-NEXT:    %262 = OpBitcast %27 %90
-; CHECK-NEXT:    OpLifetimeStop %262 80
-; CHECK-NEXT:    %263 = OpBitcast %27 %91
-; CHECK-NEXT:    OpLifetimeStart %263 80
-; CHECK-NEXT:    %264 = OpBitcast %13 %246
-; CHECK-NEXT:    %265 = OpLoad %12 %264
-; CHECK-NEXT:    %266 = OpBitcast %13 %85
-; CHECK-NEXT:    %267 = OpLoad %12 %266
-; CHECK-NEXT:    %268 = OpBuildNDRange %9 %265 %267 %14
-; CHECK-NEXT:    OpStore %91 %268
-; CHECK-NEXT:    %269 = OpBitcast %27 %91
-; CHECK-NEXT:    OpLifetimeStop %269 80
-; CHECK-NEXT:    %270 = OpBitcast %27 %92
-; CHECK-NEXT:    OpLifetimeStart %270 80
-; CHECK-NEXT:    %271 = OpBitcast %13 %246
-; CHECK-NEXT:    %272 = OpLoad %12 %271
-; CHECK-NEXT:    %273 = OpBitcast %13 %85
-; CHECK-NEXT:    %274 = OpLoad %12 %273
-; CHECK-NEXT:    %275 = OpBitcast %13 %246
-; CHECK-NEXT:    %276 = OpLoad %12 %275
-; CHECK-NEXT:    %277 = OpBuildNDRange %9 %272 %274 %276
-; CHECK-NEXT:    OpStore %92 %277
-; CHECK-NEXT:    %278 = OpBitcast %27 %92
-; CHECK-NEXT:    OpLifetimeStop %278 80
-; CHECK-NEXT:    %279 = OpBitcast %27 %87
-; CHECK-NEXT:    OpLifetimeStop %279 24
-; CHECK-NEXT:    %280 = OpBitcast %27 %86
-; CHECK-NEXT:    OpLifetimeStop %280 24
-; CHECK-NEXT:    %281 = OpBitcast %27 %85
-; CHECK-NEXT:    OpLifetimeStop %281 24
-; CHECK-NEXT:    %282 = OpBitcast %27 %79
-; CHECK-NEXT:    OpLifetimeStop %282 16
-; CHECK-NEXT:    %283 = OpBitcast %27 %78
-; CHECK-NEXT:    OpLifetimeStop %283 16
-; CHECK-NEXT:    %284 = OpBitcast %27 %77
-; CHECK-NEXT:    OpLifetimeStop %284 16
-; CHECK-NEXT:    %285 = OpBitcast %27 %66
-; CHECK-NEXT:    OpLifetimeStop %285 24
-; CHECK-NEXT:    %286 = OpBitcast %27 %65
-; CHECK-NEXT:    OpLifetimeStop %286 24
-; CHECK-NEXT:    %287 = OpBitcast %27 %64
-; CHECK-NEXT:    OpLifetimeStop %287 24
-; CHECK-NEXT:    %288 = OpBitcast %27 %58
-; CHECK-NEXT:    OpLifetimeStop %288 16
-; CHECK-NEXT:    %289 = OpBitcast %27 %57
-; CHECK-NEXT:    OpLifetimeStop %289 16
-; CHECK-NEXT:    %290 = OpBitcast %27 %56
-; CHECK-NEXT:    OpLifetimeStop %290 16
+; CHECK:       %[[#r50:]] = OpFunction %[[#r3:]] None %[[#r4:]] ; -- Begin function test_ndrange_2D3D
+; CHECK-NEXT:    %[[#r2:]] = OpLabel
+; CHECK-NEXT:    %[[#r51:]] = OpVariable %[[#r10:]] Function
+; CHECK-NEXT:    %[[#r52:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r53:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r54:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r55:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r56:]] = OpVariable %[[#r13:]] Function
+; CHECK-NEXT:    %[[#r57:]] = OpVariable %[[#r13]] Function
+; CHECK-NEXT:    %[[#r58:]] = OpVariable %[[#r13]] Function
+; CHECK-NEXT:    %[[#r59:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r60:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r61:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r62:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r63:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r64:]] = OpVariable %[[#r16:]] Function
+; CHECK-NEXT:    %[[#r65:]] = OpVariable %[[#r16]] Function
+; CHECK-NEXT:    %[[#r66:]] = OpVariable %[[#r16]] Function
+; CHECK-NEXT:    %[[#r67:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r68:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r69:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r70:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r71:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r72:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r73:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r74:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r75:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r76:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r77:]] = OpVariable %[[#r13]] Function
+; CHECK-NEXT:    %[[#r78:]] = OpVariable %[[#r13]] Function
+; CHECK-NEXT:    %[[#r79:]] = OpVariable %[[#r13]] Function
+; CHECK-NEXT:    %[[#r80:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r81:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r82:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r83:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r84:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r85:]] = OpVariable %[[#r16]] Function
+; CHECK-NEXT:    %[[#r86:]] = OpVariable %[[#r16]] Function
+; CHECK-NEXT:    %[[#r87:]] = OpVariable %[[#r16]] Function
+; CHECK-NEXT:    %[[#r88:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r89:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r90:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r91:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r92:]] = OpVariable %[[#r10]] Function
+; CHECK-NEXT:    %[[#r93:]] = OpBitcast %[[#r27:]] %[[#r51]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r93]] 80
+; CHECK-NEXT:    %[[#r94:]] = OpBuildNDRange %[[#r9:]] %[[#r24:]] %[[#r25:]] %[[#r25:]]
+; CHECK-NEXT:    OpStore %[[#r51]] %[[#r94]]
+; CHECK-NEXT:    %[[#r95:]] = OpBitcast %[[#r27:]] %[[#r51]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r95]] 80
+; CHECK-NEXT:    %[[#r96:]] = OpBitcast %[[#r27]] %[[#r52]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r96]] 80
+; CHECK-NEXT:    %[[#r97:]] = OpBuildNDRange %[[#r9]] %[[#r24:]] %[[#r23:]] %[[#r25]]
+; CHECK-NEXT:    OpStore %[[#r52]] %[[#r97]]
+; CHECK-NEXT:    %[[#r98:]] = OpBitcast %[[#r27]] %[[#r52]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r98]] 80
+; CHECK-NEXT:    %[[#r99:]] = OpBitcast %[[#r27]] %[[#r53]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r99]] 80
+; CHECK-NEXT:    %[[#r100:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r23:]] %[[#r22:]]
+; CHECK-NEXT:    OpStore %[[#r53]] %[[#r100]]
+; CHECK-NEXT:    %[[#r101:]] = OpBitcast %[[#r27]] %[[#r53]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r101]] 80
+; CHECK-NEXT:    %[[#r102:]] = OpBitcast %[[#r27]] %[[#r54]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r102]] 80
+; CHECK-NEXT:    %[[#r103:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r24]] %[[#r25]]
+; CHECK-NEXT:    OpStore %[[#r54]] %[[#r103]]
+; CHECK-NEXT:    %[[#r104:]] = OpBitcast %[[#r27]] %[[#r54]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r104]] 80
+; CHECK-NEXT:    %[[#r105:]] = OpBitcast %[[#r27]] %[[#r55]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r105]] 80
+; CHECK-NEXT:    %[[#r106:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r24]] %[[#r24]]
+; CHECK-NEXT:    OpStore %[[#r55]] %[[#r106]]
+; CHECK-NEXT:    %[[#r107:]] = OpBitcast %[[#r27]] %[[#r55]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r107]] 80
+; CHECK-NEXT:    %[[#r108:]] = OpBitcast %[[#r27]] %[[#r56]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r108]] 16
+; CHECK-NEXT:    OpCopyMemorySized %[[#r56]] %[[#r29:]] %[[#r21:]] Aligned 8
+; CHECK-NEXT:    %[[#r109:]] = OpBitcast %[[#r27]] %[[#r57]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r109]] 16
+; CHECK-NEXT:    OpCopyMemorySized %[[#r57]] %[[#r31:]] %[[#r21]] Aligned 8
+; CHECK-NEXT:    %[[#r110:]] = OpBitcast %[[#r27]] %[[#r58]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r110]] 16
+; CHECK-NEXT:    OpCopyMemorySized %[[#r58]] %[[#r33:]] %[[#r21]] Aligned 8
+; CHECK-NEXT:    %[[#r111:]] = OpBitcast %[[#r27]] %[[#r59]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r111]] 80
+; CHECK-NEXT:    %[[#r112:]] = OpLoad %[[#r12:]] %[[#r56]]
+; CHECK-NEXT:    %[[#r113:]] = OpBuildNDRange %[[#r9]] %[[#r112]] %[[#r14:]] %[[#r14:]]
+; CHECK-NEXT:    OpStore %[[#r59]] %[[#r113]]
+; CHECK-NEXT:    %[[#r114:]] = OpBitcast %[[#r27]] %[[#r59]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r114]] 80
+; CHECK-NEXT:    %[[#r115:]] = OpBitcast %[[#r27]] %[[#r60]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r115]] 80
+; CHECK-NEXT:    %[[#r116:]] = OpBitcast %[[#r15:]] %[[#r56]]
+; CHECK-NEXT:    %[[#r117:]] = OpBitcast %[[#r13]] %[[#r116]]
+; CHECK-NEXT:    %[[#r118:]] = OpLoad %[[#r12]] %[[#r117]]
+; CHECK-NEXT:    %[[#r119:]] = OpLoad %[[#r12]] %[[#r57]]
+; CHECK-NEXT:    %[[#r120:]] = OpBuildNDRange %[[#r9]] %[[#r118]] %[[#r119]] %[[#r14]]
+; CHECK-NEXT:    OpStore %[[#r60]] %[[#r120]]
+; CHECK-NEXT:    %[[#r121:]] = OpBitcast %[[#r27]] %[[#r60]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r121]] 80
+; CHECK-NEXT:    %[[#r122:]] = OpBitcast %[[#r27]] %[[#r61]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r122]] 80
+; CHECK-NEXT:    %[[#r123:]] = OpBitcast %[[#r15]] %[[#r58]]
+; CHECK-NEXT:    %[[#r124:]] = OpBitcast %[[#r13]] %[[#r116]]
+; CHECK-NEXT:    %[[#r125:]] = OpLoad %[[#r12]] %[[#r124]]
+; CHECK-NEXT:    %[[#r126:]] = OpLoad %[[#r12]] %[[#r57]]
+; CHECK-NEXT:    %[[#r127:]] = OpBitcast %[[#r13]] %[[#r123]]
+; CHECK-NEXT:    %[[#r128:]] = OpLoad %[[#r12]] %[[#r127]]
+; CHECK-NEXT:    %[[#r129:]] = OpBuildNDRange %[[#r9]] %[[#r125]] %[[#r126]] %[[#r128]]
+; CHECK-NEXT:    OpStore %[[#r61]] %[[#r129]]
+; CHECK-NEXT:    %[[#r130:]] = OpBitcast %[[#r27]] %[[#r61]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r130]] 80
+; CHECK-NEXT:    %[[#r131:]] = OpBitcast %[[#r27]] %[[#r62]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r131]] 80
+; CHECK-NEXT:    %[[#r132:]] = OpBitcast %[[#r13]] %[[#r116]]
+; CHECK-NEXT:    %[[#r133:]] = OpLoad %[[#r12]] %[[#r132]]
+; CHECK-NEXT:    %[[#r134:]] = OpLoad %[[#r12]] %[[#r56]]
+; CHECK-NEXT:    %[[#r135:]] = OpBuildNDRange %[[#r9]] %[[#r133]] %[[#r134]] %[[#r14]]
+; CHECK-NEXT:    OpStore %[[#r62]] %[[#r135]]
+; CHECK-NEXT:    %[[#r136:]] = OpBitcast %[[#r27]] %[[#r62]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r136]] 80
+; CHECK-NEXT:    %[[#r137:]] = OpBitcast %[[#r27]] %[[#r63]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r137]] 80
+; CHECK-NEXT:    %[[#r138:]] = OpBitcast %[[#r13]] %[[#r116]]
+; CHECK-NEXT:    %[[#r139:]] = OpLoad %[[#r12]] %[[#r138]]
+; CHECK-NEXT:    %[[#r140:]] = OpLoad %[[#r12]] %[[#r56]]
+; CHECK-NEXT:    %[[#r141:]] = OpBitcast %[[#r13]] %[[#r116]]
+; CHECK-NEXT:    %[[#r142:]] = OpLoad %[[#r12]] %[[#r141]]
+; CHECK-NEXT:    %[[#r143:]] = OpBuildNDRange %[[#r9]] %[[#r139]] %[[#r140]] %[[#r142]]
+; CHECK-NEXT:    OpStore %[[#r63]] %[[#r143]]
+; CHECK-NEXT:    %[[#r144:]] = OpBitcast %[[#r27]] %[[#r63]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r144]] 80
+; CHECK-NEXT:    %[[#r145:]] = OpBitcast %[[#r27]] %[[#r64]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r145]] 24
+; CHECK-NEXT:    OpCopyMemorySized %[[#r64]] %[[#r35:]] %[[#r20:]] Aligned 8
+; CHECK-NEXT:    %[[#r146:]] = OpBitcast %[[#r27]] %[[#r65]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r146]] 24
+; CHECK-NEXT:    OpCopyMemorySized %[[#r65]] %[[#r37:]] %[[#r20]] Aligned 8
+; CHECK-NEXT:    %[[#r147:]] = OpBitcast %[[#r27]] %[[#r66]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r147]] 24
+; CHECK-NEXT:    OpCopyMemorySized %[[#r66]] %[[#r39:]] %[[#r20]] Aligned 8
+; CHECK-NEXT:    %[[#r148:]] = OpBitcast %[[#r27]] %[[#r67]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r148]] 80
+; CHECK-NEXT:    %[[#r149:]] = OpLoad %[[#r8:]] %[[#r64]]
+; CHECK-NEXT:    %[[#r150:]] = OpBuildNDRange %[[#r9]] %[[#r149]] %[[#r17:]] %[[#r17:]]
+; CHECK-NEXT:    OpStore %[[#r67]] %[[#r150]]
+; CHECK-NEXT:    %[[#r151:]] = OpBitcast %[[#r27]] %[[#r67]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r151]] 80
+; CHECK-NEXT:    %[[#r152:]] = OpBitcast %[[#r27]] %[[#r68]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r152]] 80
+; CHECK-NEXT:    %[[#r153:]] = OpBitcast %[[#r15]] %[[#r64]]
+; CHECK-NEXT:    %[[#r154:]] = OpBitcast %[[#r13]] %[[#r153]]
+; CHECK-NEXT:    %[[#r155:]] = OpLoad %[[#r12]] %[[#r154]]
+; CHECK-NEXT:    %[[#r156:]] = OpBitcast %[[#r13]] %[[#r65]]
+; CHECK-NEXT:    %[[#r157:]] = OpLoad %[[#r12]] %[[#r156]]
+; CHECK-NEXT:    %[[#r158:]] = OpBuildNDRange %[[#r9]] %[[#r155]] %[[#r157]] %[[#r14]]
+; CHECK-NEXT:    OpStore %[[#r68]] %[[#r158]]
+; CHECK-NEXT:    %[[#r159:]] = OpBitcast %[[#r27]] %[[#r68]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r159]] 80
+; CHECK-NEXT:    %[[#r160:]] = OpBitcast %[[#r27]] %[[#r69]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r160]] 80
+; CHECK-NEXT:    %[[#r161:]] = OpBitcast %[[#r15]] %[[#r66]]
+; CHECK-NEXT:    %[[#r162:]] = OpBitcast %[[#r13]] %[[#r153]]
+; CHECK-NEXT:    %[[#r163:]] = OpLoad %[[#r12]] %[[#r162]]
+; CHECK-NEXT:    %[[#r164:]] = OpBitcast %[[#r13]] %[[#r65]]
+; CHECK-NEXT:    %[[#r165:]] = OpLoad %[[#r12]] %[[#r164]]
+; CHECK-NEXT:    %[[#r166:]] = OpBitcast %[[#r13]] %[[#r161]]
+; CHECK-NEXT:    %[[#r167:]] = OpLoad %[[#r12]] %[[#r166]]
+; CHECK-NEXT:    %[[#r168:]] = OpBuildNDRange %[[#r9]] %[[#r163]] %[[#r165]] %[[#r167]]
+; CHECK-NEXT:    OpStore %[[#r69]] %[[#r168]]
+; CHECK-NEXT:    %[[#r169:]] = OpBitcast %[[#r27]] %[[#r69]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r169]] 80
+; CHECK-NEXT:    %[[#r170:]] = OpBitcast %[[#r27]] %[[#r70]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r170]] 80
+; CHECK-NEXT:    %[[#r171:]] = OpBitcast %[[#r13]] %[[#r153]]
+; CHECK-NEXT:    %[[#r172:]] = OpLoad %[[#r12]] %[[#r171]]
+; CHECK-NEXT:    %[[#r173:]] = OpBitcast %[[#r13]] %[[#r64]]
+; CHECK-NEXT:    %[[#r174:]] = OpLoad %[[#r12]] %[[#r173]]
+; CHECK-NEXT:    %[[#r175:]] = OpBuildNDRange %[[#r9]] %[[#r172]] %[[#r174]] %[[#r14]]
+; CHECK-NEXT:    OpStore %[[#r70]] %[[#r175]]
+; CHECK-NEXT:    %[[#r176:]] = OpBitcast %[[#r27]] %[[#r70]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r176]] 80
+; CHECK-NEXT:    %[[#r177:]] = OpBitcast %[[#r27]] %[[#r71]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r177]] 80
+; CHECK-NEXT:    %[[#r178:]] = OpBitcast %[[#r13]] %[[#r153]]
+; CHECK-NEXT:    %[[#r179:]] = OpLoad %[[#r12]] %[[#r178]]
+; CHECK-NEXT:    %[[#r180:]] = OpBitcast %[[#r13]] %[[#r64]]
+; CHECK-NEXT:    %[[#r181:]] = OpLoad %[[#r12]] %[[#r180]]
+; CHECK-NEXT:    %[[#r182:]] = OpBitcast %[[#r13]] %[[#r153]]
+; CHECK-NEXT:    %[[#r183:]] = OpLoad %[[#r12]] %[[#r182]]
+; CHECK-NEXT:    %[[#r184:]] = OpBuildNDRange %[[#r9]] %[[#r179]] %[[#r181]] %[[#r183]]
+; CHECK-NEXT:    OpStore %[[#r71]] %[[#r184]]
+; CHECK-NEXT:    %[[#r185:]] = OpBitcast %[[#r27]] %[[#r71]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r185]] 80
+; CHECK-NEXT:    %[[#r186:]] = OpBitcast %[[#r27]] %[[#r72]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r186]] 80
+; CHECK-NEXT:    %[[#r187:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r25]] %[[#r25]]
+; CHECK-NEXT:    OpStore %[[#r72]] %[[#r187]]
+; CHECK-NEXT:    %[[#r188:]] = OpBitcast %[[#r27]] %[[#r72]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r188]] 80
+; CHECK-NEXT:    %[[#r189:]] = OpBitcast %[[#r27]] %[[#r73]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r189]] 80
+; CHECK-NEXT:    %[[#r190:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r23]] %[[#r25]]
+; CHECK-NEXT:    OpStore %[[#r73]] %[[#r190]]
+; CHECK-NEXT:    %[[#r191:]] = OpBitcast %[[#r27]] %[[#r73]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r191]] 80
+; CHECK-NEXT:    %[[#r192:]] = OpBitcast %[[#r27]] %[[#r74]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r192]] 80
+; CHECK-NEXT:    %[[#r193:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r23]] %[[#r22]]
+; CHECK-NEXT:    OpStore %[[#r74]] %[[#r193]]
+; CHECK-NEXT:    %[[#r194:]] = OpBitcast %[[#r27]] %[[#r74]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r194]] 80
+; CHECK-NEXT:    %[[#r195:]] = OpBitcast %[[#r27]] %[[#r75]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r195]] 80
+; CHECK-NEXT:    %[[#r196:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r24]] %[[#r25]]
+; CHECK-NEXT:    OpStore %[[#r75]] %[[#r196]]
+; CHECK-NEXT:    %[[#r197:]] = OpBitcast %[[#r27]] %[[#r75]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r197]] 80
+; CHECK-NEXT:    %[[#r198:]] = OpBitcast %[[#r27]] %[[#r76]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r198]] 80
+; CHECK-NEXT:    %[[#r199:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r24]] %[[#r24]]
+; CHECK-NEXT:    OpStore %[[#r76]] %[[#r199]]
+; CHECK-NEXT:    %[[#r200:]] = OpBitcast %[[#r27]] %[[#r76]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r200]] 80
+; CHECK-NEXT:    %[[#r201:]] = OpBitcast %[[#r27]] %[[#r77]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r201]] 16
+; CHECK-NEXT:    OpCopyMemorySized %[[#r77]] %[[#r40:]] %[[#r21:]] Aligned 8
+; CHECK-NEXT:    %[[#r202:]] = OpBitcast %[[#r27]] %[[#r78]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r202]] 16
+; CHECK-NEXT:    OpCopyMemorySized %[[#r78]] %[[#r42:]] %[[#r21]] Aligned 8
+; CHECK-NEXT:    %[[#r203:]] = OpBitcast %[[#r27]] %[[#r79]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r203]] 16
+; CHECK-NEXT:    OpCopyMemorySized %[[#r79]] %[[#r44:]] %[[#r21]] Aligned 8
+; CHECK-NEXT:    %[[#r204:]] = OpBitcast %[[#r27]] %[[#r80]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r204]] 80
+; CHECK-NEXT:    %[[#r205:]] = OpLoad %[[#r12]] %[[#r77]]
+; CHECK-NEXT:    %[[#r206:]] = OpBuildNDRange %[[#r9]] %[[#r205]] %[[#r14]] %[[#r14]]
+; CHECK-NEXT:    OpStore %[[#r80]] %[[#r206]]
+; CHECK-NEXT:    %[[#r207:]] = OpBitcast %[[#r27]] %[[#r80]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r207]] 80
+; CHECK-NEXT:    %[[#r208:]] = OpBitcast %[[#r27]] %[[#r81]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r208]] 80
+; CHECK-NEXT:    %[[#r209:]] = OpBitcast %[[#r15]] %[[#r77]]
+; CHECK-NEXT:    %[[#r210:]] = OpBitcast %[[#r13]] %[[#r209]]
+; CHECK-NEXT:    %[[#r211:]] = OpLoad %[[#r12]] %[[#r210]]
+; CHECK-NEXT:    %[[#r212:]] = OpLoad %[[#r12]] %[[#r78]]
+; CHECK-NEXT:    %[[#r213:]] = OpBuildNDRange %[[#r9]] %[[#r211]] %[[#r212]] %[[#r14]]
+; CHECK-NEXT:    OpStore %[[#r81]] %[[#r213]]
+; CHECK-NEXT:    %[[#r214:]] = OpBitcast %[[#r27]] %[[#r81]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r214]] 80
+; CHECK-NEXT:    %[[#r215:]] = OpBitcast %[[#r27]] %[[#r82]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r215]] 80
+; CHECK-NEXT:    %[[#r216:]] = OpBitcast %[[#r15]] %[[#r79]]
+; CHECK-NEXT:    %[[#r217:]] = OpBitcast %[[#r13]] %[[#r209]]
+; CHECK-NEXT:    %[[#r218:]] = OpLoad %[[#r12]] %[[#r217]]
+; CHECK-NEXT:    %[[#r219:]] = OpLoad %[[#r12]] %[[#r78]]
+; CHECK-NEXT:    %[[#r220:]] = OpBitcast %[[#r13]] %[[#r216]]
+; CHECK-NEXT:    %[[#r221:]] = OpLoad %[[#r12]] %[[#r220]]
+; CHECK-NEXT:    %[[#r222:]] = OpBuildNDRange %[[#r9]] %[[#r218]] %[[#r219]] %[[#r221]]
+; CHECK-NEXT:    OpStore %[[#r82]] %[[#r222]]
+; CHECK-NEXT:    %[[#r223:]] = OpBitcast %[[#r27]] %[[#r82]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r223]] 80
+; CHECK-NEXT:    %[[#r224:]] = OpBitcast %[[#r27]] %[[#r83]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r224]] 80
+; CHECK-NEXT:    %[[#r225:]] = OpBitcast %[[#r13]] %[[#r209]]
+; CHECK-NEXT:    %[[#r226:]] = OpLoad %[[#r12]] %[[#r225]]
+; CHECK-NEXT:    %[[#r227:]] = OpLoad %[[#r12]] %[[#r77]]
+; CHECK-NEXT:    %[[#r228:]] = OpBuildNDRange %[[#r9]] %[[#r226]] %[[#r227]] %[[#r14]]
+; CHECK-NEXT:    OpStore %[[#r83]] %[[#r228]]
+; CHECK-NEXT:    %[[#r229:]] = OpBitcast %[[#r27]] %[[#r83]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r229]] 80
+; CHECK-NEXT:    %[[#r230:]] = OpBitcast %[[#r27]] %[[#r84]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r230]] 80
+; CHECK-NEXT:    %[[#r231:]] = OpBitcast %[[#r13]] %[[#r209]]
+; CHECK-NEXT:    %[[#r232:]] = OpLoad %[[#r12]] %[[#r231]]
+; CHECK-NEXT:    %[[#r233:]] = OpLoad %[[#r12]] %[[#r77]]
+; CHECK-NEXT:    %[[#r234:]] = OpBitcast %[[#r13]] %[[#r209]]
+; CHECK-NEXT:    %[[#r235:]] = OpLoad %[[#r12]] %[[#r234]]
+; CHECK-NEXT:    %[[#r236:]] = OpBuildNDRange %[[#r9]] %[[#r232]] %[[#r233]] %[[#r235]]
+; CHECK-NEXT:    OpStore %[[#r84]] %[[#r236]]
+; CHECK-NEXT:    %[[#r237:]] = OpBitcast %[[#r27]] %[[#r84]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r237]] 80
+; CHECK-NEXT:    %[[#r238:]] = OpBitcast %[[#r27]] %[[#r85]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r238]] 24
+; CHECK-NEXT:    OpCopyMemorySized %[[#r85]] %[[#r45:]] %[[#r20]] Aligned 8
+; CHECK-NEXT:    %[[#r239:]] = OpBitcast %[[#r27]] %[[#r86]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r239]] 24
+; CHECK-NEXT:    OpCopyMemorySized %[[#r86]] %[[#r47:]] %[[#r20]] Aligned 8
+; CHECK-NEXT:    %[[#r240:]] = OpBitcast %[[#r27]] %[[#r87]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r240]] 24
+; CHECK-NEXT:    OpCopyMemorySized %[[#r87]] %[[#r49:]] %[[#r20]] Aligned 8
+; CHECK-NEXT:    %[[#r241:]] = OpBitcast %[[#r27]] %[[#r88]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r241]] 80
+; CHECK-NEXT:    %[[#r242:]] = OpLoad %[[#r8]] %[[#r85]]
+; CHECK-NEXT:    %[[#r243:]] = OpBuildNDRange %[[#r9]] %[[#r242]] %[[#r17]] %[[#r17]]
+; CHECK-NEXT:    OpStore %[[#r88]] %[[#r243]]
+; CHECK-NEXT:    %[[#r244:]] = OpBitcast %[[#r27]] %[[#r88]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r244]] 80
+; CHECK-NEXT:    %[[#r245:]] = OpBitcast %[[#r27]] %[[#r89]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r245]] 80
+; CHECK-NEXT:    %[[#r246:]] = OpBitcast %[[#r15]] %[[#r85]]
+; CHECK-NEXT:    %[[#r247:]] = OpBitcast %[[#r13]] %[[#r246]]
+; CHECK-NEXT:    %[[#r248:]] = OpLoad %[[#r12]] %[[#r247]]
+; CHECK-NEXT:    %[[#r249:]] = OpBitcast %[[#r13]] %[[#r86]]
+; CHECK-NEXT:    %[[#r250:]] = OpLoad %[[#r12]] %[[#r249]]
+; CHECK-NEXT:    %[[#r251:]] = OpBuildNDRange %[[#r9]] %[[#r248]] %[[#r250]] %[[#r14]]
+; CHECK-NEXT:    OpStore %[[#r89]] %[[#r251]]
+; CHECK-NEXT:    %[[#r252:]] = OpBitcast %[[#r27]] %[[#r89]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r252]] 80
+; CHECK-NEXT:    %[[#r253:]] = OpBitcast %[[#r27]] %[[#r90]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r253]] 80
+; CHECK-NEXT:    %[[#r254:]] = OpBitcast %[[#r15]] %[[#r87]]
+; CHECK-NEXT:    %[[#r255:]] = OpBitcast %[[#r13]] %[[#r246]]
+; CHECK-NEXT:    %[[#r256:]] = OpLoad %[[#r12]] %[[#r255]]
+; CHECK-NEXT:    %[[#r257:]] = OpBitcast %[[#r13]] %[[#r86]]
+; CHECK-NEXT:    %[[#r258:]] = OpLoad %[[#r12]] %[[#r257]]
+; CHECK-NEXT:    %[[#r259:]] = OpBitcast %[[#r13]] %[[#r254]]
+; CHECK-NEXT:    %[[#r260:]] = OpLoad %[[#r12]] %[[#r259]]
+; CHECK-NEXT:    %[[#r261:]] = OpBuildNDRange %[[#r9]] %[[#r256]] %[[#r258]] %[[#r260]]
+; CHECK-NEXT:    OpStore %[[#r90]] %[[#r261]]
+; CHECK-NEXT:    %[[#r262:]] = OpBitcast %[[#r27]] %[[#r90]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r262]] 80
+; CHECK-NEXT:    %[[#r263:]] = OpBitcast %[[#r27]] %[[#r91]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r263]] 80
+; CHECK-NEXT:    %[[#r264:]] = OpBitcast %[[#r13]] %[[#r246]]
+; CHECK-NEXT:    %[[#r265:]] = OpLoad %[[#r12]] %[[#r264]]
+; CHECK-NEXT:    %[[#r266:]] = OpBitcast %[[#r13]] %[[#r85]]
+; CHECK-NEXT:    %[[#r267:]] = OpLoad %[[#r12]] %[[#r266]]
+; CHECK-NEXT:    %[[#r268:]] = OpBuildNDRange %[[#r9]] %[[#r265]] %[[#r267]] %[[#r14]]
+; CHECK-NEXT:    OpStore %[[#r91]] %[[#r268]]
+; CHECK-NEXT:    %[[#r269:]] = OpBitcast %[[#r27]] %[[#r91]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r269]] 80
+; CHECK-NEXT:    %[[#r270:]] = OpBitcast %[[#r27]] %[[#r92]]
+; CHECK-NEXT:    OpLifetimeStart %[[#r270]] 80
+; CHECK-NEXT:    %[[#r271:]] = OpBitcast %[[#r13]] %[[#r246]]
+; CHECK-NEXT:    %[[#r272:]] = OpLoad %[[#r12]] %[[#r271]]
+; CHECK-NEXT:    %[[#r273:]] = OpBitcast %[[#r13]] %[[#r85]]
+; CHECK-NEXT:    %[[#r274:]] = OpLoad %[[#r12]] %[[#r273]]
+; CHECK-NEXT:    %[[#r275:]] = OpBitcast %[[#r13]] %[[#r246]]
+; CHECK-NEXT:    %[[#r276:]] = OpLoad %[[#r12]] %[[#r275]]
+; CHECK-NEXT:    %[[#r277:]] = OpBuildNDRange %[[#r9]] %[[#r272]] %[[#r274]] %[[#r276]]
+; CHECK-NEXT:    OpStore %[[#r92]] %[[#r277]]
+; CHECK-NEXT:    %[[#r278:]] = OpBitcast %[[#r27]] %[[#r92]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r278]] 80
+; CHECK-NEXT:    %[[#r279:]] = OpBitcast %[[#r27]] %[[#r87]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r279]] 24
+; CHECK-NEXT:    %[[#r280:]] = OpBitcast %[[#r27]] %[[#r86]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r280]] 24
+; CHECK-NEXT:    %[[#r281:]] = OpBitcast %[[#r27]] %[[#r85]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r281]] 24
+; CHECK-NEXT:    %[[#r282:]] = OpBitcast %[[#r27]] %[[#r79]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r282]] 16
+; CHECK-NEXT:    %[[#r283:]] = OpBitcast %[[#r27]] %[[#r78]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r283]] 16
+; CHECK-NEXT:    %[[#r284:]] = OpBitcast %[[#r27]] %[[#r77]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r284]] 16
+; CHECK-NEXT:    %[[#r285:]] = OpBitcast %[[#r27]] %[[#r66]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r285]] 24
+; CHECK-NEXT:    %[[#r286:]] = OpBitcast %[[#r27]] %[[#r65]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r286]] 24
+; CHECK-NEXT:    %[[#r287:]] = OpBitcast %[[#r27]] %[[#r64]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r287]] 24
+; CHECK-NEXT:    %[[#r288:]] = OpBitcast %[[#r27]] %[[#r58]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r288]] 16
+; CHECK-NEXT:    %[[#r289:]] = OpBitcast %[[#r27]] %[[#r57]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r289]] 16
+; CHECK-NEXT:    %[[#r290:]] = OpBitcast %[[#r27]] %[[#r56]]
+; CHECK-NEXT:    OpLifetimeStop %[[#r290]] 16
 ; CHECK-NEXT:    OpReturn
 ; CHECK-NEXT:    OpFunctionEnd
 entry:
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_no_sret.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_no_sret.ll
index d13e7cba6d9bf..2425eb4462b71 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_no_sret.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_no_sret.ll
@@ -1,5 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-
 ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
 ; %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
@@ -19,9 +17,4 @@ entry:
   ret void
 }
 
-declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
-
 declare spir_func %struct.ndrange_t  @_Z10ndrange_1Dm(i64 noundef) local_unnamed_addr #2
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
-declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1

>From 5de9e3aac23c9072d4db755726d91db8c753ee4f Mon Sep 17 00:00:00 2001
From: idubinov <igor.dubinov at amd.com>
Date: Tue, 17 Mar 2026 12:00:01 -0500
Subject: [PATCH 7/8] string2int

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index a885da7118b82..3ba9f1b87f89c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -2664,7 +2664,8 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
 
   // The dimension is encoded in the function name as "ndrange_XD" where X is
   // 1, 2, or 3.
-  unsigned Dimension = atoi(Call->Builtin->Name.substr(8, 1).data());
+  unsigned Dimension = 0;
+  Call->Builtin->Name.substr(8, 1).getAsInteger(10, Dimension);
   assert(Dimension <= 3 && Dimension >= 1);
 
   // Determine the work size type based on the dimension. For missing arguments,

>From f571ec2255e7b0f65b69abc03120730f6f2f87a1 Mon Sep 17 00:00:00 2001
From: idubinov <igor.dubinov at amd.com>
Date: Wed, 18 Mar 2026 09:08:23 -0500
Subject: [PATCH 8/8] simplify test

---
 .../CodeGen/SPIRV/transcoding/BuildNDRange.ll | 714 +++---------------
 1 file changed, 117 insertions(+), 597 deletions(-)

diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll
index 68692084bbc4e..dcb69a9a4b2eb 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll
@@ -1,628 +1,148 @@
-;; Test that checks all variants of ndrange and what ndrange_1D, ndrange_2D and ndrange_3D can coexist in the same module
+;; Test that checks all variants of ndrange and what ndrange_2D and ndrange_3D can coexist in the same module
 ;;
-;; bash$ cat BuildNDRange.cl
-;; void test_ndrange_2D3D() {
-;;   size_t GS1 = 1;
-;;   size_t LS1 = 2;
-;;   size_t WO1 = 3;
-;;   ndrange_1D(GS1);
-;;   ndrange_1D(GS1, LS1);
-;;   ndrange_1D(WO1, GS1, LS1);
-;;   ndrange_1D(GS1, GS1);
-;;   ndrange_1D(GS1, GS1, GS1);
-;;   size_t GS2[2] = {1, 1};
-;;   size_t LS2[2] = {2, 2};
-;;   size_t WO2[2] = {3, 3};
-;;   ndrange_2D(GS2);
-;;   ndrange_2D(GS2, LS2);
-;;   ndrange_2D(WO2, GS2, LS2);
-;;   ndrange_2D(GS2, GS2);
-;;   ndrange_2D(GS2, GS2, GS2);
-;;   size_t GS3[3] = {1, 1, 1};
-;;   size_t LS3[3] = {1, 2, 1};
-;;   size_t WO3[3] = {1, 3, 1};
-;;   ndrange_3D(GS3);
-;;   ndrange_2D(GS3, LS3);
-;;   ndrange_2D(WO3, GS3, LS3);
-;;   ndrange_2D(GS3, GS3);
-;;   ndrange_2D(GS3, GS3, GS3);
-;;   const size_t GS1c = 1;
-;;   const size_t LS1c = 2;
-;;   const size_t WO1c = 3;
-;;   ndrange_1D(GS1c);
-;;   ndrange_1D(GS1c, LS1c);
-;;   ndrange_1D(WO1c, GS1c, LS1c);
-;;   ndrange_1D(GS1c, GS1c);
-;;   ndrange_1D(GS1c, GS1c, GS1c);
-;;   const size_t GS2c[2] = {1, 1};
-;;   const size_t LS2c[2] = {1, 2};
-;;   const size_t WO2c[2] = {1, 3};
-;;   ndrange_2D(GS2c);
-;;   ndrange_2D(GS2c, LS2c);
-;;   ndrange_2D(WO2c, GS2c, LS2c);
-;;   ndrange_2D(GS2c, GS2c);
-;;   ndrange_2D(GS2c, GS2c, GS2c);
-;;   const size_t GS3c[3] = {1, 1, 1};
-;;   const size_t LS3c[3] = {1, 1, 2};
-;;   const size_t WO3c[3] = {1, 1, 3};
-;;   ndrange_3D(GS3c);
-;;   ndrange_2D(GS3c, LS3c);
-;;   ndrange_2D(WO3c, GS3c, LS3c);
-;;   ndrange_2D(GS3c, GS3c);
-;;   ndrange_2D(GS3c, GS3c, GS3c);
-;; }
-;; bash$ clang -cc1  -cl-std=CL2.0 -triple spirv64-unknown-unknown -emit-llvm -finclude-default-header -cl-single-precision-constant BuildNDRange.cl -o BuildNDRange.ll
-
+;;void test_ndrange_1D(size_t GS1 , size_t LS1 , size_t WO1) {
+;;  ndrange_1D(GS1);
+;;  ndrange_1D(GS1, LS1);
+;;  ndrange_1D(WO1, GS1, LS1);
+;;  // test const argument
+;;  const size_t GS1c = 1;
+;;  ndrange_1D(GS1c);
+;;}
+;;
+;;void test_ndrange_2D(size_t GS2[2], size_t LS2[2], size_t WO2[2]) {
+;;  ndrange_2D(GS2);
+;;  ndrange_2D(GS2, LS2);
+;;  ndrange_2D(WO2, GS2, LS2);
+;;}
+;;
+;;void test_ndrange_3D(size_t GS3[3], size_t LS3[3], size_t WO3[3], size_t GS2[2]) {
+;;  ndrange_3D(GS3);
+;;  ndrange_3D(GS3, LS3);
+;;  ndrange_3D(WO3, GS3, LS3);
+;;  // test same argument
+;;  ndrange_3D(GS3, GS3);
+;;  ndrange_3D(GS3, GS3, GS3);
+;;  // test const argument
+;;  const size_t GS3c[3] = {1, 4, 7};
+;;  ndrange_3D(GS3c);
+;;  // test 2D and 3D can coexist in one funciton
+;;  ndrange_2D(GS2);
+;;}
+;;
+;; bash$ clang -cc1 -cl-std=CL2.0 -triple spirv64-unknown-unknown -emit-llvm -finclude-default-header -cl-single-precision-constant BuildNDRange.cl -o BuildNDRange.ll
 
 ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
 ; %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
 %struct.ndrange_t = type { i32, [3 x i64], [3 x i64], [3 x i64] }
 
- at __const.test_ndrange_2D3D.GS2 = private unnamed_addr addrspace(2) constant [2 x i64] [i64 1, i64 1], align 8
- at __const.test_ndrange_2D3D.LS2 = private unnamed_addr addrspace(2) constant [2 x i64] [i64 2, i64 2], align 8
- at __const.test_ndrange_2D3D.WO2 = private unnamed_addr addrspace(2) constant [2 x i64] [i64 3, i64 3], align 8
- at __const.test_ndrange_2D3D.GS3 = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 1, i64 1], align 8
- at __const.test_ndrange_2D3D.LS3 = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 2, i64 1], align 8
- at __const.test_ndrange_2D3D.WO3 = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 3, i64 1], align 8
- at __const.test_ndrange_2D3D.GS2c = private unnamed_addr addrspace(2) constant [2 x i64] [i64 1, i64 1], align 8
- at __const.test_ndrange_2D3D.LS2c = private unnamed_addr addrspace(2) constant [2 x i64] [i64 1, i64 2], align 8
- at __const.test_ndrange_2D3D.WO2c = private unnamed_addr addrspace(2) constant [2 x i64] [i64 1, i64 3], align 8
- at __const.test_ndrange_2D3D.GS3c = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 1, i64 1], align 8
- at __const.test_ndrange_2D3D.LS3c = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 1, i64 2], align 8
- at __const.test_ndrange_2D3D.WO3c = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 1, i64 3], align 8
+ at __const.test_ndrange_3D.GS3c = private unnamed_addr addrspace(2) constant [3 x i64] [i64 1, i64 4, i64 7], align 8
 
-define spir_func void @test_ndrange_2D3D() local_unnamed_addr #0 {
-; CHECK-LABEL: test_ndrange_2D3D
-; CHECK:       %[[#r50:]] = OpFunction %[[#r3:]] None %[[#r4:]] ; -- Begin function test_ndrange_2D3D
-; CHECK-NEXT:    %[[#r2:]] = OpLabel
-; CHECK-NEXT:    %[[#r51:]] = OpVariable %[[#r10:]] Function
-; CHECK-NEXT:    %[[#r52:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r53:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r54:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r55:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r56:]] = OpVariable %[[#r13:]] Function
-; CHECK-NEXT:    %[[#r57:]] = OpVariable %[[#r13]] Function
-; CHECK-NEXT:    %[[#r58:]] = OpVariable %[[#r13]] Function
-; CHECK-NEXT:    %[[#r59:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r60:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r61:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r62:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r63:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r64:]] = OpVariable %[[#r16:]] Function
-; CHECK-NEXT:    %[[#r65:]] = OpVariable %[[#r16]] Function
-; CHECK-NEXT:    %[[#r66:]] = OpVariable %[[#r16]] Function
-; CHECK-NEXT:    %[[#r67:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r68:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r69:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r70:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r71:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r72:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r73:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r74:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r75:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r76:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r77:]] = OpVariable %[[#r13]] Function
-; CHECK-NEXT:    %[[#r78:]] = OpVariable %[[#r13]] Function
-; CHECK-NEXT:    %[[#r79:]] = OpVariable %[[#r13]] Function
-; CHECK-NEXT:    %[[#r80:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r81:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r82:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r83:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r84:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r85:]] = OpVariable %[[#r16]] Function
-; CHECK-NEXT:    %[[#r86:]] = OpVariable %[[#r16]] Function
-; CHECK-NEXT:    %[[#r87:]] = OpVariable %[[#r16]] Function
-; CHECK-NEXT:    %[[#r88:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r89:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r90:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r91:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r92:]] = OpVariable %[[#r10]] Function
-; CHECK-NEXT:    %[[#r93:]] = OpBitcast %[[#r27:]] %[[#r51]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r93]] 80
-; CHECK-NEXT:    %[[#r94:]] = OpBuildNDRange %[[#r9:]] %[[#r24:]] %[[#r25:]] %[[#r25:]]
-; CHECK-NEXT:    OpStore %[[#r51]] %[[#r94]]
-; CHECK-NEXT:    %[[#r95:]] = OpBitcast %[[#r27:]] %[[#r51]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r95]] 80
-; CHECK-NEXT:    %[[#r96:]] = OpBitcast %[[#r27]] %[[#r52]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r96]] 80
-; CHECK-NEXT:    %[[#r97:]] = OpBuildNDRange %[[#r9]] %[[#r24:]] %[[#r23:]] %[[#r25]]
-; CHECK-NEXT:    OpStore %[[#r52]] %[[#r97]]
-; CHECK-NEXT:    %[[#r98:]] = OpBitcast %[[#r27]] %[[#r52]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r98]] 80
-; CHECK-NEXT:    %[[#r99:]] = OpBitcast %[[#r27]] %[[#r53]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r99]] 80
-; CHECK-NEXT:    %[[#r100:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r23:]] %[[#r22:]]
-; CHECK-NEXT:    OpStore %[[#r53]] %[[#r100]]
-; CHECK-NEXT:    %[[#r101:]] = OpBitcast %[[#r27]] %[[#r53]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r101]] 80
-; CHECK-NEXT:    %[[#r102:]] = OpBitcast %[[#r27]] %[[#r54]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r102]] 80
-; CHECK-NEXT:    %[[#r103:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r24]] %[[#r25]]
-; CHECK-NEXT:    OpStore %[[#r54]] %[[#r103]]
-; CHECK-NEXT:    %[[#r104:]] = OpBitcast %[[#r27]] %[[#r54]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r104]] 80
-; CHECK-NEXT:    %[[#r105:]] = OpBitcast %[[#r27]] %[[#r55]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r105]] 80
-; CHECK-NEXT:    %[[#r106:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r24]] %[[#r24]]
-; CHECK-NEXT:    OpStore %[[#r55]] %[[#r106]]
-; CHECK-NEXT:    %[[#r107:]] = OpBitcast %[[#r27]] %[[#r55]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r107]] 80
-; CHECK-NEXT:    %[[#r108:]] = OpBitcast %[[#r27]] %[[#r56]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r108]] 16
-; CHECK-NEXT:    OpCopyMemorySized %[[#r56]] %[[#r29:]] %[[#r21:]] Aligned 8
-; CHECK-NEXT:    %[[#r109:]] = OpBitcast %[[#r27]] %[[#r57]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r109]] 16
-; CHECK-NEXT:    OpCopyMemorySized %[[#r57]] %[[#r31:]] %[[#r21]] Aligned 8
-; CHECK-NEXT:    %[[#r110:]] = OpBitcast %[[#r27]] %[[#r58]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r110]] 16
-; CHECK-NEXT:    OpCopyMemorySized %[[#r58]] %[[#r33:]] %[[#r21]] Aligned 8
-; CHECK-NEXT:    %[[#r111:]] = OpBitcast %[[#r27]] %[[#r59]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r111]] 80
-; CHECK-NEXT:    %[[#r112:]] = OpLoad %[[#r12:]] %[[#r56]]
-; CHECK-NEXT:    %[[#r113:]] = OpBuildNDRange %[[#r9]] %[[#r112]] %[[#r14:]] %[[#r14:]]
-; CHECK-NEXT:    OpStore %[[#r59]] %[[#r113]]
-; CHECK-NEXT:    %[[#r114:]] = OpBitcast %[[#r27]] %[[#r59]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r114]] 80
-; CHECK-NEXT:    %[[#r115:]] = OpBitcast %[[#r27]] %[[#r60]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r115]] 80
-; CHECK-NEXT:    %[[#r116:]] = OpBitcast %[[#r15:]] %[[#r56]]
-; CHECK-NEXT:    %[[#r117:]] = OpBitcast %[[#r13]] %[[#r116]]
-; CHECK-NEXT:    %[[#r118:]] = OpLoad %[[#r12]] %[[#r117]]
-; CHECK-NEXT:    %[[#r119:]] = OpLoad %[[#r12]] %[[#r57]]
-; CHECK-NEXT:    %[[#r120:]] = OpBuildNDRange %[[#r9]] %[[#r118]] %[[#r119]] %[[#r14]]
-; CHECK-NEXT:    OpStore %[[#r60]] %[[#r120]]
-; CHECK-NEXT:    %[[#r121:]] = OpBitcast %[[#r27]] %[[#r60]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r121]] 80
-; CHECK-NEXT:    %[[#r122:]] = OpBitcast %[[#r27]] %[[#r61]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r122]] 80
-; CHECK-NEXT:    %[[#r123:]] = OpBitcast %[[#r15]] %[[#r58]]
-; CHECK-NEXT:    %[[#r124:]] = OpBitcast %[[#r13]] %[[#r116]]
-; CHECK-NEXT:    %[[#r125:]] = OpLoad %[[#r12]] %[[#r124]]
-; CHECK-NEXT:    %[[#r126:]] = OpLoad %[[#r12]] %[[#r57]]
-; CHECK-NEXT:    %[[#r127:]] = OpBitcast %[[#r13]] %[[#r123]]
-; CHECK-NEXT:    %[[#r128:]] = OpLoad %[[#r12]] %[[#r127]]
-; CHECK-NEXT:    %[[#r129:]] = OpBuildNDRange %[[#r9]] %[[#r125]] %[[#r126]] %[[#r128]]
-; CHECK-NEXT:    OpStore %[[#r61]] %[[#r129]]
-; CHECK-NEXT:    %[[#r130:]] = OpBitcast %[[#r27]] %[[#r61]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r130]] 80
-; CHECK-NEXT:    %[[#r131:]] = OpBitcast %[[#r27]] %[[#r62]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r131]] 80
-; CHECK-NEXT:    %[[#r132:]] = OpBitcast %[[#r13]] %[[#r116]]
-; CHECK-NEXT:    %[[#r133:]] = OpLoad %[[#r12]] %[[#r132]]
-; CHECK-NEXT:    %[[#r134:]] = OpLoad %[[#r12]] %[[#r56]]
-; CHECK-NEXT:    %[[#r135:]] = OpBuildNDRange %[[#r9]] %[[#r133]] %[[#r134]] %[[#r14]]
-; CHECK-NEXT:    OpStore %[[#r62]] %[[#r135]]
-; CHECK-NEXT:    %[[#r136:]] = OpBitcast %[[#r27]] %[[#r62]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r136]] 80
-; CHECK-NEXT:    %[[#r137:]] = OpBitcast %[[#r27]] %[[#r63]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r137]] 80
-; CHECK-NEXT:    %[[#r138:]] = OpBitcast %[[#r13]] %[[#r116]]
-; CHECK-NEXT:    %[[#r139:]] = OpLoad %[[#r12]] %[[#r138]]
-; CHECK-NEXT:    %[[#r140:]] = OpLoad %[[#r12]] %[[#r56]]
-; CHECK-NEXT:    %[[#r141:]] = OpBitcast %[[#r13]] %[[#r116]]
-; CHECK-NEXT:    %[[#r142:]] = OpLoad %[[#r12]] %[[#r141]]
-; CHECK-NEXT:    %[[#r143:]] = OpBuildNDRange %[[#r9]] %[[#r139]] %[[#r140]] %[[#r142]]
-; CHECK-NEXT:    OpStore %[[#r63]] %[[#r143]]
-; CHECK-NEXT:    %[[#r144:]] = OpBitcast %[[#r27]] %[[#r63]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r144]] 80
-; CHECK-NEXT:    %[[#r145:]] = OpBitcast %[[#r27]] %[[#r64]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r145]] 24
-; CHECK-NEXT:    OpCopyMemorySized %[[#r64]] %[[#r35:]] %[[#r20:]] Aligned 8
-; CHECK-NEXT:    %[[#r146:]] = OpBitcast %[[#r27]] %[[#r65]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r146]] 24
-; CHECK-NEXT:    OpCopyMemorySized %[[#r65]] %[[#r37:]] %[[#r20]] Aligned 8
-; CHECK-NEXT:    %[[#r147:]] = OpBitcast %[[#r27]] %[[#r66]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r147]] 24
-; CHECK-NEXT:    OpCopyMemorySized %[[#r66]] %[[#r39:]] %[[#r20]] Aligned 8
-; CHECK-NEXT:    %[[#r148:]] = OpBitcast %[[#r27]] %[[#r67]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r148]] 80
-; CHECK-NEXT:    %[[#r149:]] = OpLoad %[[#r8:]] %[[#r64]]
-; CHECK-NEXT:    %[[#r150:]] = OpBuildNDRange %[[#r9]] %[[#r149]] %[[#r17:]] %[[#r17:]]
-; CHECK-NEXT:    OpStore %[[#r67]] %[[#r150]]
-; CHECK-NEXT:    %[[#r151:]] = OpBitcast %[[#r27]] %[[#r67]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r151]] 80
-; CHECK-NEXT:    %[[#r152:]] = OpBitcast %[[#r27]] %[[#r68]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r152]] 80
-; CHECK-NEXT:    %[[#r153:]] = OpBitcast %[[#r15]] %[[#r64]]
-; CHECK-NEXT:    %[[#r154:]] = OpBitcast %[[#r13]] %[[#r153]]
-; CHECK-NEXT:    %[[#r155:]] = OpLoad %[[#r12]] %[[#r154]]
-; CHECK-NEXT:    %[[#r156:]] = OpBitcast %[[#r13]] %[[#r65]]
-; CHECK-NEXT:    %[[#r157:]] = OpLoad %[[#r12]] %[[#r156]]
-; CHECK-NEXT:    %[[#r158:]] = OpBuildNDRange %[[#r9]] %[[#r155]] %[[#r157]] %[[#r14]]
-; CHECK-NEXT:    OpStore %[[#r68]] %[[#r158]]
-; CHECK-NEXT:    %[[#r159:]] = OpBitcast %[[#r27]] %[[#r68]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r159]] 80
-; CHECK-NEXT:    %[[#r160:]] = OpBitcast %[[#r27]] %[[#r69]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r160]] 80
-; CHECK-NEXT:    %[[#r161:]] = OpBitcast %[[#r15]] %[[#r66]]
-; CHECK-NEXT:    %[[#r162:]] = OpBitcast %[[#r13]] %[[#r153]]
-; CHECK-NEXT:    %[[#r163:]] = OpLoad %[[#r12]] %[[#r162]]
-; CHECK-NEXT:    %[[#r164:]] = OpBitcast %[[#r13]] %[[#r65]]
-; CHECK-NEXT:    %[[#r165:]] = OpLoad %[[#r12]] %[[#r164]]
-; CHECK-NEXT:    %[[#r166:]] = OpBitcast %[[#r13]] %[[#r161]]
-; CHECK-NEXT:    %[[#r167:]] = OpLoad %[[#r12]] %[[#r166]]
-; CHECK-NEXT:    %[[#r168:]] = OpBuildNDRange %[[#r9]] %[[#r163]] %[[#r165]] %[[#r167]]
-; CHECK-NEXT:    OpStore %[[#r69]] %[[#r168]]
-; CHECK-NEXT:    %[[#r169:]] = OpBitcast %[[#r27]] %[[#r69]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r169]] 80
-; CHECK-NEXT:    %[[#r170:]] = OpBitcast %[[#r27]] %[[#r70]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r170]] 80
-; CHECK-NEXT:    %[[#r171:]] = OpBitcast %[[#r13]] %[[#r153]]
-; CHECK-NEXT:    %[[#r172:]] = OpLoad %[[#r12]] %[[#r171]]
-; CHECK-NEXT:    %[[#r173:]] = OpBitcast %[[#r13]] %[[#r64]]
-; CHECK-NEXT:    %[[#r174:]] = OpLoad %[[#r12]] %[[#r173]]
-; CHECK-NEXT:    %[[#r175:]] = OpBuildNDRange %[[#r9]] %[[#r172]] %[[#r174]] %[[#r14]]
-; CHECK-NEXT:    OpStore %[[#r70]] %[[#r175]]
-; CHECK-NEXT:    %[[#r176:]] = OpBitcast %[[#r27]] %[[#r70]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r176]] 80
-; CHECK-NEXT:    %[[#r177:]] = OpBitcast %[[#r27]] %[[#r71]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r177]] 80
-; CHECK-NEXT:    %[[#r178:]] = OpBitcast %[[#r13]] %[[#r153]]
-; CHECK-NEXT:    %[[#r179:]] = OpLoad %[[#r12]] %[[#r178]]
-; CHECK-NEXT:    %[[#r180:]] = OpBitcast %[[#r13]] %[[#r64]]
-; CHECK-NEXT:    %[[#r181:]] = OpLoad %[[#r12]] %[[#r180]]
-; CHECK-NEXT:    %[[#r182:]] = OpBitcast %[[#r13]] %[[#r153]]
-; CHECK-NEXT:    %[[#r183:]] = OpLoad %[[#r12]] %[[#r182]]
-; CHECK-NEXT:    %[[#r184:]] = OpBuildNDRange %[[#r9]] %[[#r179]] %[[#r181]] %[[#r183]]
-; CHECK-NEXT:    OpStore %[[#r71]] %[[#r184]]
-; CHECK-NEXT:    %[[#r185:]] = OpBitcast %[[#r27]] %[[#r71]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r185]] 80
-; CHECK-NEXT:    %[[#r186:]] = OpBitcast %[[#r27]] %[[#r72]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r186]] 80
-; CHECK-NEXT:    %[[#r187:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r25]] %[[#r25]]
-; CHECK-NEXT:    OpStore %[[#r72]] %[[#r187]]
-; CHECK-NEXT:    %[[#r188:]] = OpBitcast %[[#r27]] %[[#r72]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r188]] 80
-; CHECK-NEXT:    %[[#r189:]] = OpBitcast %[[#r27]] %[[#r73]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r189]] 80
-; CHECK-NEXT:    %[[#r190:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r23]] %[[#r25]]
-; CHECK-NEXT:    OpStore %[[#r73]] %[[#r190]]
-; CHECK-NEXT:    %[[#r191:]] = OpBitcast %[[#r27]] %[[#r73]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r191]] 80
-; CHECK-NEXT:    %[[#r192:]] = OpBitcast %[[#r27]] %[[#r74]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r192]] 80
-; CHECK-NEXT:    %[[#r193:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r23]] %[[#r22]]
-; CHECK-NEXT:    OpStore %[[#r74]] %[[#r193]]
-; CHECK-NEXT:    %[[#r194:]] = OpBitcast %[[#r27]] %[[#r74]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r194]] 80
-; CHECK-NEXT:    %[[#r195:]] = OpBitcast %[[#r27]] %[[#r75]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r195]] 80
-; CHECK-NEXT:    %[[#r196:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r24]] %[[#r25]]
-; CHECK-NEXT:    OpStore %[[#r75]] %[[#r196]]
-; CHECK-NEXT:    %[[#r197:]] = OpBitcast %[[#r27]] %[[#r75]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r197]] 80
-; CHECK-NEXT:    %[[#r198:]] = OpBitcast %[[#r27]] %[[#r76]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r198]] 80
-; CHECK-NEXT:    %[[#r199:]] = OpBuildNDRange %[[#r9]] %[[#r24]] %[[#r24]] %[[#r24]]
-; CHECK-NEXT:    OpStore %[[#r76]] %[[#r199]]
-; CHECK-NEXT:    %[[#r200:]] = OpBitcast %[[#r27]] %[[#r76]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r200]] 80
-; CHECK-NEXT:    %[[#r201:]] = OpBitcast %[[#r27]] %[[#r77]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r201]] 16
-; CHECK-NEXT:    OpCopyMemorySized %[[#r77]] %[[#r40:]] %[[#r21:]] Aligned 8
-; CHECK-NEXT:    %[[#r202:]] = OpBitcast %[[#r27]] %[[#r78]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r202]] 16
-; CHECK-NEXT:    OpCopyMemorySized %[[#r78]] %[[#r42:]] %[[#r21]] Aligned 8
-; CHECK-NEXT:    %[[#r203:]] = OpBitcast %[[#r27]] %[[#r79]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r203]] 16
-; CHECK-NEXT:    OpCopyMemorySized %[[#r79]] %[[#r44:]] %[[#r21]] Aligned 8
-; CHECK-NEXT:    %[[#r204:]] = OpBitcast %[[#r27]] %[[#r80]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r204]] 80
-; CHECK-NEXT:    %[[#r205:]] = OpLoad %[[#r12]] %[[#r77]]
-; CHECK-NEXT:    %[[#r206:]] = OpBuildNDRange %[[#r9]] %[[#r205]] %[[#r14]] %[[#r14]]
-; CHECK-NEXT:    OpStore %[[#r80]] %[[#r206]]
-; CHECK-NEXT:    %[[#r207:]] = OpBitcast %[[#r27]] %[[#r80]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r207]] 80
-; CHECK-NEXT:    %[[#r208:]] = OpBitcast %[[#r27]] %[[#r81]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r208]] 80
-; CHECK-NEXT:    %[[#r209:]] = OpBitcast %[[#r15]] %[[#r77]]
-; CHECK-NEXT:    %[[#r210:]] = OpBitcast %[[#r13]] %[[#r209]]
-; CHECK-NEXT:    %[[#r211:]] = OpLoad %[[#r12]] %[[#r210]]
-; CHECK-NEXT:    %[[#r212:]] = OpLoad %[[#r12]] %[[#r78]]
-; CHECK-NEXT:    %[[#r213:]] = OpBuildNDRange %[[#r9]] %[[#r211]] %[[#r212]] %[[#r14]]
-; CHECK-NEXT:    OpStore %[[#r81]] %[[#r213]]
-; CHECK-NEXT:    %[[#r214:]] = OpBitcast %[[#r27]] %[[#r81]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r214]] 80
-; CHECK-NEXT:    %[[#r215:]] = OpBitcast %[[#r27]] %[[#r82]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r215]] 80
-; CHECK-NEXT:    %[[#r216:]] = OpBitcast %[[#r15]] %[[#r79]]
-; CHECK-NEXT:    %[[#r217:]] = OpBitcast %[[#r13]] %[[#r209]]
-; CHECK-NEXT:    %[[#r218:]] = OpLoad %[[#r12]] %[[#r217]]
-; CHECK-NEXT:    %[[#r219:]] = OpLoad %[[#r12]] %[[#r78]]
-; CHECK-NEXT:    %[[#r220:]] = OpBitcast %[[#r13]] %[[#r216]]
-; CHECK-NEXT:    %[[#r221:]] = OpLoad %[[#r12]] %[[#r220]]
-; CHECK-NEXT:    %[[#r222:]] = OpBuildNDRange %[[#r9]] %[[#r218]] %[[#r219]] %[[#r221]]
-; CHECK-NEXT:    OpStore %[[#r82]] %[[#r222]]
-; CHECK-NEXT:    %[[#r223:]] = OpBitcast %[[#r27]] %[[#r82]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r223]] 80
-; CHECK-NEXT:    %[[#r224:]] = OpBitcast %[[#r27]] %[[#r83]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r224]] 80
-; CHECK-NEXT:    %[[#r225:]] = OpBitcast %[[#r13]] %[[#r209]]
-; CHECK-NEXT:    %[[#r226:]] = OpLoad %[[#r12]] %[[#r225]]
-; CHECK-NEXT:    %[[#r227:]] = OpLoad %[[#r12]] %[[#r77]]
-; CHECK-NEXT:    %[[#r228:]] = OpBuildNDRange %[[#r9]] %[[#r226]] %[[#r227]] %[[#r14]]
-; CHECK-NEXT:    OpStore %[[#r83]] %[[#r228]]
-; CHECK-NEXT:    %[[#r229:]] = OpBitcast %[[#r27]] %[[#r83]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r229]] 80
-; CHECK-NEXT:    %[[#r230:]] = OpBitcast %[[#r27]] %[[#r84]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r230]] 80
-; CHECK-NEXT:    %[[#r231:]] = OpBitcast %[[#r13]] %[[#r209]]
-; CHECK-NEXT:    %[[#r232:]] = OpLoad %[[#r12]] %[[#r231]]
-; CHECK-NEXT:    %[[#r233:]] = OpLoad %[[#r12]] %[[#r77]]
-; CHECK-NEXT:    %[[#r234:]] = OpBitcast %[[#r13]] %[[#r209]]
-; CHECK-NEXT:    %[[#r235:]] = OpLoad %[[#r12]] %[[#r234]]
-; CHECK-NEXT:    %[[#r236:]] = OpBuildNDRange %[[#r9]] %[[#r232]] %[[#r233]] %[[#r235]]
-; CHECK-NEXT:    OpStore %[[#r84]] %[[#r236]]
-; CHECK-NEXT:    %[[#r237:]] = OpBitcast %[[#r27]] %[[#r84]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r237]] 80
-; CHECK-NEXT:    %[[#r238:]] = OpBitcast %[[#r27]] %[[#r85]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r238]] 24
-; CHECK-NEXT:    OpCopyMemorySized %[[#r85]] %[[#r45:]] %[[#r20]] Aligned 8
-; CHECK-NEXT:    %[[#r239:]] = OpBitcast %[[#r27]] %[[#r86]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r239]] 24
-; CHECK-NEXT:    OpCopyMemorySized %[[#r86]] %[[#r47:]] %[[#r20]] Aligned 8
-; CHECK-NEXT:    %[[#r240:]] = OpBitcast %[[#r27]] %[[#r87]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r240]] 24
-; CHECK-NEXT:    OpCopyMemorySized %[[#r87]] %[[#r49:]] %[[#r20]] Aligned 8
-; CHECK-NEXT:    %[[#r241:]] = OpBitcast %[[#r27]] %[[#r88]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r241]] 80
-; CHECK-NEXT:    %[[#r242:]] = OpLoad %[[#r8]] %[[#r85]]
-; CHECK-NEXT:    %[[#r243:]] = OpBuildNDRange %[[#r9]] %[[#r242]] %[[#r17]] %[[#r17]]
-; CHECK-NEXT:    OpStore %[[#r88]] %[[#r243]]
-; CHECK-NEXT:    %[[#r244:]] = OpBitcast %[[#r27]] %[[#r88]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r244]] 80
-; CHECK-NEXT:    %[[#r245:]] = OpBitcast %[[#r27]] %[[#r89]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r245]] 80
-; CHECK-NEXT:    %[[#r246:]] = OpBitcast %[[#r15]] %[[#r85]]
-; CHECK-NEXT:    %[[#r247:]] = OpBitcast %[[#r13]] %[[#r246]]
-; CHECK-NEXT:    %[[#r248:]] = OpLoad %[[#r12]] %[[#r247]]
-; CHECK-NEXT:    %[[#r249:]] = OpBitcast %[[#r13]] %[[#r86]]
-; CHECK-NEXT:    %[[#r250:]] = OpLoad %[[#r12]] %[[#r249]]
-; CHECK-NEXT:    %[[#r251:]] = OpBuildNDRange %[[#r9]] %[[#r248]] %[[#r250]] %[[#r14]]
-; CHECK-NEXT:    OpStore %[[#r89]] %[[#r251]]
-; CHECK-NEXT:    %[[#r252:]] = OpBitcast %[[#r27]] %[[#r89]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r252]] 80
-; CHECK-NEXT:    %[[#r253:]] = OpBitcast %[[#r27]] %[[#r90]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r253]] 80
-; CHECK-NEXT:    %[[#r254:]] = OpBitcast %[[#r15]] %[[#r87]]
-; CHECK-NEXT:    %[[#r255:]] = OpBitcast %[[#r13]] %[[#r246]]
-; CHECK-NEXT:    %[[#r256:]] = OpLoad %[[#r12]] %[[#r255]]
-; CHECK-NEXT:    %[[#r257:]] = OpBitcast %[[#r13]] %[[#r86]]
-; CHECK-NEXT:    %[[#r258:]] = OpLoad %[[#r12]] %[[#r257]]
-; CHECK-NEXT:    %[[#r259:]] = OpBitcast %[[#r13]] %[[#r254]]
-; CHECK-NEXT:    %[[#r260:]] = OpLoad %[[#r12]] %[[#r259]]
-; CHECK-NEXT:    %[[#r261:]] = OpBuildNDRange %[[#r9]] %[[#r256]] %[[#r258]] %[[#r260]]
-; CHECK-NEXT:    OpStore %[[#r90]] %[[#r261]]
-; CHECK-NEXT:    %[[#r262:]] = OpBitcast %[[#r27]] %[[#r90]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r262]] 80
-; CHECK-NEXT:    %[[#r263:]] = OpBitcast %[[#r27]] %[[#r91]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r263]] 80
-; CHECK-NEXT:    %[[#r264:]] = OpBitcast %[[#r13]] %[[#r246]]
-; CHECK-NEXT:    %[[#r265:]] = OpLoad %[[#r12]] %[[#r264]]
-; CHECK-NEXT:    %[[#r266:]] = OpBitcast %[[#r13]] %[[#r85]]
-; CHECK-NEXT:    %[[#r267:]] = OpLoad %[[#r12]] %[[#r266]]
-; CHECK-NEXT:    %[[#r268:]] = OpBuildNDRange %[[#r9]] %[[#r265]] %[[#r267]] %[[#r14]]
-; CHECK-NEXT:    OpStore %[[#r91]] %[[#r268]]
-; CHECK-NEXT:    %[[#r269:]] = OpBitcast %[[#r27]] %[[#r91]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r269]] 80
-; CHECK-NEXT:    %[[#r270:]] = OpBitcast %[[#r27]] %[[#r92]]
-; CHECK-NEXT:    OpLifetimeStart %[[#r270]] 80
-; CHECK-NEXT:    %[[#r271:]] = OpBitcast %[[#r13]] %[[#r246]]
-; CHECK-NEXT:    %[[#r272:]] = OpLoad %[[#r12]] %[[#r271]]
-; CHECK-NEXT:    %[[#r273:]] = OpBitcast %[[#r13]] %[[#r85]]
-; CHECK-NEXT:    %[[#r274:]] = OpLoad %[[#r12]] %[[#r273]]
-; CHECK-NEXT:    %[[#r275:]] = OpBitcast %[[#r13]] %[[#r246]]
-; CHECK-NEXT:    %[[#r276:]] = OpLoad %[[#r12]] %[[#r275]]
-; CHECK-NEXT:    %[[#r277:]] = OpBuildNDRange %[[#r9]] %[[#r272]] %[[#r274]] %[[#r276]]
-; CHECK-NEXT:    OpStore %[[#r92]] %[[#r277]]
-; CHECK-NEXT:    %[[#r278:]] = OpBitcast %[[#r27]] %[[#r92]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r278]] 80
-; CHECK-NEXT:    %[[#r279:]] = OpBitcast %[[#r27]] %[[#r87]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r279]] 24
-; CHECK-NEXT:    %[[#r280:]] = OpBitcast %[[#r27]] %[[#r86]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r280]] 24
-; CHECK-NEXT:    %[[#r281:]] = OpBitcast %[[#r27]] %[[#r85]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r281]] 24
-; CHECK-NEXT:    %[[#r282:]] = OpBitcast %[[#r27]] %[[#r79]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r282]] 16
-; CHECK-NEXT:    %[[#r283:]] = OpBitcast %[[#r27]] %[[#r78]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r283]] 16
-; CHECK-NEXT:    %[[#r284:]] = OpBitcast %[[#r27]] %[[#r77]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r284]] 16
-; CHECK-NEXT:    %[[#r285:]] = OpBitcast %[[#r27]] %[[#r66]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r285]] 24
-; CHECK-NEXT:    %[[#r286:]] = OpBitcast %[[#r27]] %[[#r65]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r286]] 24
-; CHECK-NEXT:    %[[#r287:]] = OpBitcast %[[#r27]] %[[#r64]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r287]] 24
-; CHECK-NEXT:    %[[#r288:]] = OpBitcast %[[#r27]] %[[#r58]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r288]] 16
-; CHECK-NEXT:    %[[#r289:]] = OpBitcast %[[#r27]] %[[#r57]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r289]] 16
-; CHECK-NEXT:    %[[#r290:]] = OpBitcast %[[#r27]] %[[#r56]]
-; CHECK-NEXT:    OpLifetimeStop %[[#r290]] 16
-; CHECK-NEXT:    OpReturn
-; CHECK-NEXT:    OpFunctionEnd
+; CHECK: %[[#typeInt64:]] = OpTypeInt 64 0
+; CHECK: %[[#typeInt32:]] = OpTypeInt 32 0
+; CHECK: %[[#Num3:]] = OpConstant %[[#typeInt32]] 3
+; CHECK: %[[#Array3x64:]] = OpTypeArray %[[#typeInt64:]] %[[#Num3]]
+; CHECK: %[[#TypeNDRangeStruct:]] = OpTypeStruct %[[#typeInt32]] %[[#Array3x64]] %[[#Array3x64]] %[[#Array3x64]]
+define spir_func void @test_ndrange_1D(i64 noundef %GS1, i64 noundef %LS1, i64 noundef %WO1) local_unnamed_addr #0 {
 entry:
+; CHECK-LABEL: Begin function test_ndrange_1D
+; CHECK: %[[#ret1D_1:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS1D:]] %[[#Zero1D:]] %[[#Zero1D:]]
+; CHECK: %[[#ret1D_2:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS1D]] %[[#LS1D:]] %[[#Zero1D]]
+; CHECK: %[[#ret1D_3:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS1D]] %[[#LS1D]] %[[#GO1D:]]
+; CHECK: %[[#ret1D_4:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS1Dc:]] %[[#Zero1D]] %[[#Zero1D]]
+; CHECK: OpFunctionEnd
+  %tmp = alloca %struct.ndrange_t, align 8
+  %tmp1 = alloca %struct.ndrange_t, align 8
+  %tmp2 = alloca %struct.ndrange_t, align 8
+  %tmp3 = alloca %struct.ndrange_t, align 8
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp) #4
+  call spir_func void @_Z10ndrange_1Dm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp, i64 noundef %GS1) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp1) #4
+  call spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp1, i64 noundef %GS1, i64 noundef %LS1) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp1) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp2) #4
+  call spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp2, i64 noundef %WO1, i64 noundef %GS1, i64 noundef %LS1) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp2) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp3) #4
+  call spir_func void @_Z10ndrange_1Dm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp3, i64 noundef 1) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp3) #4
+  ret void
+}
+
+declare spir_func void @_Z10ndrange_1Dm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, i64 noundef) local_unnamed_addr #1
+declare spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, i64 noundef, i64 noundef) local_unnamed_addr #1
+declare spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, i64 noundef, i64 noundef, i64 noundef) local_unnamed_addr #1
+
+define spir_func void @test_ndrange_2D(ptr noundef %GS2, ptr noundef %LS2, ptr noundef %WO2) local_unnamed_addr #0 {
+entry:
+; CHECK-LABEL: Begin function test_ndrange_2D
+; CHECK: %[[#ret2D_1:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS2D_1:]] %[[#Zero2D:]] %[[#Zero2D:]]
+; CHECK: %[[#ret2D_2:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS2D_2:]] %[[#LS2D_2:]] %[[#Zero2D]]
+; CHECK: %[[#ret2D_3:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS2D_3:]] %[[#LS2D_3:]] %[[#GO2D_3:]]
+  %tmp = alloca %struct.ndrange_t, align 8
+  %tmp1 = alloca %struct.ndrange_t, align 8
+  %tmp2 = alloca %struct.ndrange_t, align 8
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp) #4
+  call spir_func void @_Z10ndrange_2DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp, ptr noundef %GS2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp1) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp1, ptr noundef %GS2, ptr noundef %LS2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp1) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp2) #4
+  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp2, ptr noundef %WO2, ptr noundef %GS2, ptr noundef %LS2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp2) #4
+  ret void
+}
+
+declare spir_func void @_Z10ndrange_2DPKm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef) local_unnamed_addr #1
+declare spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef, ptr noundef) local_unnamed_addr #1
+declare spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef, ptr noundef, ptr noundef) local_unnamed_addr #1
+
+define spir_func void @test_ndrange_3D(ptr noundef %GS3, ptr noundef %LS3, ptr noundef %WO3, ptr noundef %GS2) local_unnamed_addr #0 {
+entry:
+; CHECK-LABEL: Begin function test_ndrange_3D
+; CHECK: %[[#ret3D_1:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS3D_1:]] %[[#Zero3D:]] %[[#Zero3D:]]
+; CHECK: %[[#ret3D_2:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS3D_2:]] %[[#LS3D_2:]] %[[#Zero3D]]
+; CHECK: %[[#ret3D_3:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS3D_3:]] %[[#LS3D_3:]] %[[#GO3D_3:]]
+; CHECK: %[[#ret3D_4:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS3D_4:]] %[[#GS3D_4:]] %[[#Zero3D:]]
+; CHECK: %[[#ret3D_5:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS3D_5:]] %[[#GS3D_5:]] %[[#GS3D_5:]]
+; CHECK: %[[#ret3D_6:]] = OpBuildNDRange %[[#TypeNDRangeStruct]] %[[#GS2D_4:]] %[[#Zero2D]] %[[#Zero2D]]
   %tmp = alloca %struct.ndrange_t, align 8
   %tmp1 = alloca %struct.ndrange_t, align 8
   %tmp2 = alloca %struct.ndrange_t, align 8
   %tmp3 = alloca %struct.ndrange_t, align 8
   %tmp4 = alloca %struct.ndrange_t, align 8
-  %GS2 = alloca [2 x i64], align 8
-  %LS2 = alloca [2 x i64], align 8
-  %WO2 = alloca [2 x i64], align 8
-  %tmp5 = alloca %struct.ndrange_t, align 8
-  %tmp8 = alloca %struct.ndrange_t, align 8
-  %tmp12 = alloca %struct.ndrange_t, align 8
-  %tmp15 = alloca %struct.ndrange_t, align 8
-  %tmp19 = alloca %struct.ndrange_t, align 8
-  %GS3 = alloca [3 x i64], align 8
-  %LS3 = alloca [3 x i64], align 8
-  %WO3 = alloca [3 x i64], align 8
-  %tmp21 = alloca %struct.ndrange_t, align 8
-  %tmp24 = alloca %struct.ndrange_t, align 8
-  %tmp28 = alloca %struct.ndrange_t, align 8
-  %tmp31 = alloca %struct.ndrange_t, align 8
-  %tmp35 = alloca %struct.ndrange_t, align 8
-  %tmp36 = alloca %struct.ndrange_t, align 8
-  %tmp37 = alloca %struct.ndrange_t, align 8
-  %tmp38 = alloca %struct.ndrange_t, align 8
-  %tmp39 = alloca %struct.ndrange_t, align 8
-  %tmp40 = alloca %struct.ndrange_t, align 8
-  %GS2c = alloca [2 x i64], align 8
-  %LS2c = alloca [2 x i64], align 8
-  %WO2c = alloca [2 x i64], align 8
-  %tmp42 = alloca %struct.ndrange_t, align 8
-  %tmp45 = alloca %struct.ndrange_t, align 8
-  %tmp49 = alloca %struct.ndrange_t, align 8
-  %tmp52 = alloca %struct.ndrange_t, align 8
-  %tmp56 = alloca %struct.ndrange_t, align 8
   %GS3c = alloca [3 x i64], align 8
-  %LS3c = alloca [3 x i64], align 8
-  %WO3c = alloca [3 x i64], align 8
-  %tmp58 = alloca %struct.ndrange_t, align 8
-  %tmp61 = alloca %struct.ndrange_t, align 8
-  %tmp65 = alloca %struct.ndrange_t, align 8
-  %tmp68 = alloca %struct.ndrange_t, align 8
-  %tmp72 = alloca %struct.ndrange_t, align 8
+  %tmp5 = alloca %struct.ndrange_t, align 8
+  %tmp6 = alloca %struct.ndrange_t, align 8
   call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp) #4
-  call spir_func void @_Z10ndrange_1Dm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp, i64 noundef 1) #5
+  call spir_func void @_Z10ndrange_3DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp, ptr noundef %GS3) #5
   call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp) #4
   call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp1) #4
-  call spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp1, i64 noundef 1, i64 noundef 2) #5
+  call spir_func void @_Z10ndrange_3DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp1, ptr noundef %GS3, ptr noundef %LS3) #5
   call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp1) #4
   call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp2) #4
-  call spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp2, i64 noundef 3, i64 noundef 1, i64 noundef 2) #5
+  call spir_func void @_Z10ndrange_3DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp2, ptr noundef %WO3, ptr noundef %GS3, ptr noundef %LS3) #5
   call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp2) #4
   call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp3) #4
-  call spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp3, i64 noundef 1, i64 noundef 1) #5
+  call spir_func void @_Z10ndrange_3DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp3, ptr noundef %GS3, ptr noundef %GS3) #5
   call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp3) #4
   call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp4) #4
-  call spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp4, i64 noundef 1, i64 noundef 1, i64 noundef 1) #5
+  call spir_func void @_Z10ndrange_3DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp4, ptr noundef %GS3, ptr noundef %GS3, ptr noundef %GS3) #5
   call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp4) #4
-  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %GS2) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %GS2, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.GS2, i64 16, i1 false)
-  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %LS2) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %LS2, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.LS2, i64 16, i1 false)
-  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %WO2) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %WO2, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.WO2, i64 16, i1 false)
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %GS3c) #4
+  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %GS3c, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_3D.GS3c, i64 24, i1 false)
   call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp5) #4
-  call spir_func void @_Z10ndrange_2DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp5, ptr noundef nonnull %GS2) #5
+  call spir_func void @_Z10ndrange_3DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp5, ptr noundef nonnull %GS3c) #5
   call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp5) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp8) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp8, ptr noundef nonnull %GS2, ptr noundef nonnull %LS2) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp8) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp12) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp12, ptr noundef nonnull %WO2, ptr noundef nonnull %GS2, ptr noundef nonnull %LS2) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp12) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp15) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp15, ptr noundef nonnull %GS2, ptr noundef nonnull %GS2) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp15) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp19) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp19, ptr noundef nonnull %GS2, ptr noundef nonnull %GS2, ptr noundef nonnull %GS2) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp19) #4
-  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %GS3) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %GS3, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.GS3, i64 24, i1 false)
-  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %LS3) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %LS3, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.LS3, i64 24, i1 false)
-  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %WO3) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %WO3, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.WO3, i64 24, i1 false)
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp21) #4
-  call spir_func void @_Z10ndrange_3DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp21, ptr noundef nonnull %GS3) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp21) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp24) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp24, ptr noundef nonnull %GS3, ptr noundef nonnull %LS3) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp24) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp28) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp28, ptr noundef nonnull %WO3, ptr noundef nonnull %GS3, ptr noundef nonnull %LS3) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp28) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp31) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp31, ptr noundef nonnull %GS3, ptr noundef nonnull %GS3) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp31) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp35) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp35, ptr noundef nonnull %GS3, ptr noundef nonnull %GS3, ptr noundef nonnull %GS3) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp35) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp36) #4
-  call spir_func void @_Z10ndrange_1Dm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp36, i64 noundef 1) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp36) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp37) #4
-  call spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp37, i64 noundef 1, i64 noundef 2) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp37) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp38) #4
-  call spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp38, i64 noundef 3, i64 noundef 1, i64 noundef 2) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp38) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp39) #4
-  call spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp39, i64 noundef 1, i64 noundef 1) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp39) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp40) #4
-  call spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp40, i64 noundef 1, i64 noundef 1, i64 noundef 1) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp40) #4
-  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %GS2c) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %GS2c, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.GS2c, i64 16, i1 false)
-  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %LS2c) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %LS2c, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.LS2c, i64 16, i1 false)
-  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %WO2c) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(16) %WO2c, ptr addrspace(2) noundef align 8 dereferenceable(16) @__const.test_ndrange_2D3D.WO2c, i64 16, i1 false)
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp42) #4
-  call spir_func void @_Z10ndrange_2DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp42, ptr noundef nonnull %GS2c) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp42) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp45) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp45, ptr noundef nonnull %GS2c, ptr noundef nonnull %LS2c) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp45) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp49) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp49, ptr noundef nonnull %WO2c, ptr noundef nonnull %GS2c, ptr noundef nonnull %LS2c) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp49) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp52) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp52, ptr noundef nonnull %GS2c, ptr noundef nonnull %GS2c) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp52) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp56) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp56, ptr noundef nonnull %GS2c, ptr noundef nonnull %GS2c, ptr noundef nonnull %GS2c) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp56) #4
-  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %GS3c) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %GS3c, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.GS3c, i64 24, i1 false)
-  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %LS3c) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %LS3c, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.LS3c, i64 24, i1 false)
-  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %WO3c) #4
-  call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 8 dereferenceable(24) %WO3c, ptr addrspace(2) noundef align 8 dereferenceable(24) @__const.test_ndrange_2D3D.WO3c, i64 24, i1 false)
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp58) #4
-  call spir_func void @_Z10ndrange_3DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp58, ptr noundef nonnull %GS3c) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp58) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp61) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp61, ptr noundef nonnull %GS3c, ptr noundef nonnull %LS3c) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp61) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp65) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp65, ptr noundef nonnull %WO3c, ptr noundef nonnull %GS3c, ptr noundef nonnull %LS3c) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp65) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp68) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp68, ptr noundef nonnull %GS3c, ptr noundef nonnull %GS3c) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp68) #4
-  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp72) #4
-  call spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp72, ptr noundef nonnull %GS3c, ptr noundef nonnull %GS3c, ptr noundef nonnull %GS3c) #5
-  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp72) #4
-  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %WO3c) #4
-  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %LS3c) #4
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %tmp6) #4
+  call spir_func void @_Z10ndrange_2DPKm(ptr dead_on_unwind nonnull writable sret(%struct.ndrange_t) align 8 %tmp6, ptr noundef %GS2) #5
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %tmp6) #4
   call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %GS3c) #4
-  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %WO2c) #4
-  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %LS2c) #4
-  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %GS2c) #4
-  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %WO3) #4
-  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %LS3) #4
-  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %GS3) #4
-  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %WO2) #4
-  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %LS2) #4
-  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %GS2) #4
   ret void
 }
 
-declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
-declare spir_func void @_Z10ndrange_1Dm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, i64 noundef) local_unnamed_addr #2
-declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
-declare spir_func void @_Z10ndrange_1Dmm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, i64 noundef, i64 noundef) local_unnamed_addr #2
-declare spir_func void @_Z10ndrange_1Dmmm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, i64 noundef, i64 noundef, i64 noundef) local_unnamed_addr #2
-declare void @llvm.memcpy.p0.p2.i64(ptr noalias nocapture writeonly, ptr addrspace(2) noalias nocapture readonly, i64, i1 immarg) #3
-declare spir_func void @_Z10ndrange_2DPKm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef) local_unnamed_addr #2
-declare spir_func void @_Z10ndrange_2DPKmS0_(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef, ptr noundef) local_unnamed_addr #2
-declare spir_func void @_Z10ndrange_2DPKmS0_S0_(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef, ptr noundef, ptr noundef) local_unnamed_addr #2
-declare spir_func void @_Z10ndrange_3DPKm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef) local_unnamed_addr #2
+declare spir_func void @_Z10ndrange_3DPKm(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef) local_unnamed_addr #1
+declare spir_func void @_Z10ndrange_3DPKmS0_(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef, ptr noundef) local_unnamed_addr #1
+declare spir_func void @_Z10ndrange_3DPKmS0_S0_(ptr dead_on_unwind writable sret(%struct.ndrange_t) align 8, ptr noundef, ptr noundef, ptr noundef) local_unnamed_addr #1



More information about the llvm-commits mailing list