[llvm] [SPIRV] Fix constant materialization for width > 64bit (PR #180182)

Dmitry Sidorov via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 6 04:26:36 PST 2026


https://github.com/MrSidims created https://github.com/llvm/llvm-project/pull/180182

selectConst() was asserting for constants wider than 64 bits. Add APInt overloads of getOrCreateConstInt and getOrCreateConstVector that avoid the uint64_t truncation.

>From bca17af1ebcce4a48b29259c3a64cc70e20fe7d9 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Fri, 6 Feb 2026 00:09:28 +0100
Subject: [PATCH] [SPIRV] Fix constant materialization for width > 64bit

selectConst() was asserting for constants wider than 64 bits. Add APInt
overloads of getOrCreateConstInt and getOrCreateConstVector that avoid the
uint64_t truncation.
---
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 39 ++++++++++++++++++-
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h   |  6 +++
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  6 +--
 .../apint-constant.ll                         | 37 ++++++++++++++++++
 4 files changed, 83 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/apint-constant.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 5200f1ead9a13..b07dfbfcc164a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -387,6 +387,20 @@ Register SPIRVGlobalRegistry::getOrCreateConstInt(uint64_t Val, MachineInstr &I,
   return createConstInt(CI, I, SpvType, TII, ZeroAsNull);
 }
 
+Register SPIRVGlobalRegistry::getOrCreateConstInt(const APInt &Val,
+                                                  MachineInstr &I,
+                                                  SPIRVType *SpvType,
+                                                  const SPIRVInstrInfo &TII,
+                                                  bool ZeroAsNull) {
+  auto *const CI = ConstantInt::get(
+      cast<IntegerType>(getTypeForSPIRVType(SpvType))->getContext(), Val);
+  const MachineInstr *MI = findMI(CI, CurMF);
+  if (MI && (MI->getOpcode() == SPIRV::OpConstantNull ||
+             MI->getOpcode() == SPIRV::OpConstantI))
+    return MI->getOperand(0).getReg();
+  return createConstInt(CI, I, SpvType, TII, ZeroAsNull);
+}
+
 Register SPIRVGlobalRegistry::createConstInt(const ConstantInt *CI,
                                              MachineInstr &I,
                                              SPIRVType *SpvType,
@@ -525,8 +539,8 @@ Register SPIRVGlobalRegistry::getOrCreateBaseRegister(
   }
   assert(Type->getOpcode() == SPIRV::OpTypeInt);
   SPIRVType *SpvBaseType = getOrCreateSPIRVIntegerType(BitWidth, I, TII);
-  return getOrCreateConstInt(Val->getUniqueInteger().getZExtValue(), I,
-                             SpvBaseType, TII, ZeroAsNull);
+  return getOrCreateConstInt(Val->getUniqueInteger(), I, SpvBaseType, TII,
+                             ZeroAsNull);
 }
 
 Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull(
@@ -592,6 +606,27 @@ Register SPIRVGlobalRegistry::getOrCreateConstVector(uint64_t Val,
                                     ZeroAsNull);
 }
 
+Register SPIRVGlobalRegistry::getOrCreateConstVector(const APInt &Val,
+                                                     MachineInstr &I,
+                                                     SPIRVType *SpvType,
+                                                     const SPIRVInstrInfo &TII,
+                                                     bool ZeroAsNull) {
+  const Type *LLVMTy = getTypeForSPIRVType(SpvType);
+  assert(LLVMTy->isVectorTy() &&
+         "Expected vector type for constant vector creation");
+  const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
+  Type *LLVMBaseTy = LLVMVecTy->getElementType();
+  assert(LLVMBaseTy->isIntegerTy() &&
+         "Expected integer element type for APInt constant vector");
+  auto *ConstVal = cast<ConstantInt>(ConstantInt::get(LLVMBaseTy, Val));
+  auto *ConstVec =
+      ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
+  unsigned BW = getScalarOrVectorBitWidth(SpvType);
+  return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
+                                    SpvType->getOperand(2).getImm(),
+                                    ZeroAsNull);
+}
+
 Register SPIRVGlobalRegistry::getOrCreateConstVector(APFloat Val,
                                                      MachineInstr &I,
                                                      SPIRVType *SpvType,
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index fa45f169f8561..b401727a7b898 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -520,6 +520,9 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
   Register getOrCreateConstInt(uint64_t Val, MachineInstr &I,
                                SPIRVType *SpvType, const SPIRVInstrInfo &TII,
                                bool ZeroAsNull = true);
+  Register getOrCreateConstInt(const APInt &Val, MachineInstr &I,
+                               SPIRVType *SpvType, const SPIRVInstrInfo &TII,
+                               bool ZeroAsNull = true);
   Register createConstInt(const ConstantInt *CI, MachineInstr &I,
                           SPIRVType *SpvType, const SPIRVInstrInfo &TII,
                           bool ZeroAsNull);
@@ -535,6 +538,9 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
   Register getOrCreateConstVector(uint64_t Val, MachineInstr &I,
                                   SPIRVType *SpvType, const SPIRVInstrInfo &TII,
                                   bool ZeroAsNull = true);
+  Register getOrCreateConstVector(const APInt &Val, MachineInstr &I,
+                                  SPIRVType *SpvType, const SPIRVInstrInfo &TII,
+                                  bool ZeroAsNull = true);
   Register getOrCreateConstVector(APFloat Val, MachineInstr &I,
                                   SPIRVType *SpvType, const SPIRVInstrInfo &TII,
                                   bool ZeroAsNull = true);
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 2c3d7e9c0db44..8c0bf64e8fcd0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3261,8 +3261,8 @@ Register SPIRVInstructionSelector::buildOnesVal(bool AllOnes,
   APInt One =
       AllOnes ? APInt::getAllOnes(BitWidth) : APInt::getOneBitSet(BitWidth, 0);
   if (ResType->getOpcode() == SPIRV::OpTypeVector)
-    return GR.getOrCreateConstVector(One.getZExtValue(), I, ResType, TII);
-  return GR.getOrCreateConstInt(One.getZExtValue(), I, ResType, TII);
+    return GR.getOrCreateConstVector(One, I, ResType, TII);
+  return GR.getOrCreateConstInt(One, I, ResType, TII);
 }
 
 bool SPIRVInstructionSelector::selectSelect(Register ResVReg,
@@ -3484,7 +3484,7 @@ bool SPIRVInstructionSelector::selectConst(Register ResVReg,
     Reg = GR.getOrCreateConstFP(I.getOperand(1).getFPImm()->getValue(), I,
                                 ResType, TII, !STI.isShader());
   } else {
-    Reg = GR.getOrCreateConstInt(I.getOperand(1).getCImm()->getZExtValue(), I,
+    Reg = GR.getOrCreateConstInt(I.getOperand(1).getCImm()->getValue(), I,
                                  ResType, TII, !STI.isShader());
   }
   return Reg == ResVReg ? true : BuildCOPY(ResVReg, Reg, I);
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/apint-constant.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/apint-constant.ll
new file mode 100644
index 0000000000000..21c002664a918
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/apint-constant.ll
@@ -0,0 +1,37 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - | FileCheck %s
+
+; Verify that wide integer constants (>64 bits) are correctly encoded as
+; OpConstant with multi-word literals.
+
+; CHECK-DAG: %[[#INT128:]] = OpTypeInt 128 0
+; CHECK-DAG: %[[#INT96:]] = OpTypeInt 96 0
+; CHECK-DAG: %[[#NEG128:]] = OpConstant %[[#INT128]] 4294965247 4294967295 4294967295 4294967295
+; CHECK-DAG: %[[#ONE128:]] = OpConstant %[[#INT128]] 1 0 0 0
+; CHECK-DAG: %[[#BOUNDARY:]] = OpConstant %[[#INT128]] 4294967295 4294967295 0 0
+; CHECK-DAG: %[[#ZERO128:]] = OpConstantNull %[[#INT128]]
+; CHECK-DAG: %[[#NEG96:]] = OpConstant %[[#INT96]] 4294967295 4294967295 4294967295 0
+; CHECK-DAG: %[[#OVER64:]] = OpConstant %[[#INT96]] 1 0 1 0
+
+; CHECK: OpStore %[[#]] %[[#NEG128]] Aligned 16
+; CHECK: OpStore %[[#]] %[[#ONE128]] Aligned 16
+; CHECK: OpStore %[[#]] %[[#BOUNDARY]] Aligned 16
+; CHECK: OpStore %[[#]] %[[#ZERO128]] Aligned 16
+
+; CHECK: OpStore %[[#]] %[[#NEG96]] Aligned 16
+; CHECK: OpStore %[[#]] %[[#OVER64]] Aligned 16
+
+define spir_func void @test_i128_const(ptr addrspace(4) %p) addrspace(4) {
+entry:
+  store i128 -2049, ptr addrspace(4) %p, align 16
+  store i128 1, ptr addrspace(4) %p, align 16
+  store i128 18446744073709551615, ptr addrspace(4) %p, align 16
+  store i128 0, ptr addrspace(4) %p, align 16
+  ret void
+}
+
+define spir_func void @test_i96_const(ptr addrspace(4) %p) addrspace(4) {
+entry:
+  store i96 -1, ptr addrspace(4) %p, align 16
+  store i96 18446744073709551617, ptr addrspace(4) %p, align 16
+  ret void
+}



More information about the llvm-commits mailing list