Skip to content

Conversation

@AlexVlx
Copy link
Contributor

@AlexVlx AlexVlx commented Dec 5, 2025

LLVM has pretty thorough support for int128, and it has started seeing some use. Even thouth we already have support for the SPV_ALTERA_arbitrary_precision_integers extension, the BE was oddly capping integer width to 64-bits. This patch adds partial support for lowering 128-bit integers to OpTypeInt 128. Some work remains to be done around legalisation support and validating constant uses (e.g. cases that get lowered to OpSpecConstantOp).

@llvmbot
Copy link
Member

llvmbot commented Dec 5, 2025

@llvm/pr-subscribers-backend-spir-v

Author: Alex Voicu (AlexVlx)

Changes

LLVM has pretty thorough support for int128, and it has started seeing some use. Even thouth we already have support for the SPV_ALTERA_arbitrary_precision_integers extension, the BE was oddly capping integer width to 64-bits. This patch adds partial support for lowering 128-bit integers to OpTypeInt 128. Some work remains to be done around legalisation support and validating constant uses (e.g. cases that get lowered to OpSpecConstantOp).


Full diff: https://github.com/llvm/llvm-project/pull/170798.diff

8 Files Affected:

  • (modified) llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp (+8)
  • (modified) llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp (+9-14)
  • (modified) llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp (+2-1)
  • (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp (+11)
  • (modified) llvm/lib/Target/SPIRV/SPIRVUtils.cpp (+7)
  • (added) llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll (+67)
  • (added) llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-arith.ll (+27)
  • (added) llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-switch-lower.ll (+27)
diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
index 62f5e47c5ea3b..42de884840dc9 100644
--- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
@@ -50,6 +50,14 @@ void SPIRVInstPrinter::printOpConstantVarOps(const MCInst *MI,
   unsigned IsBitwidth16 = MI->getFlags() & SPIRV::INST_PRINTER_WIDTH16;
   const unsigned NumVarOps = MI->getNumOperands() - StartIndex;
 
+  if (MI->getOpcode() == SPIRV::OpConstantI && NumVarOps > 2) {
+    // SPV_ALTERA_arbitrary_precision_integers allows for integer widths greater
+    // than 64, which will be encoded via multiple operands.
+    for (unsigned I = StartIndex; I != MI->getNumOperands(); ++I)
+      O << ' ' << MI->getOperand(I).getImm();
+    return;
+  }
+
   assert((NumVarOps == 1 || NumVarOps == 2) &&
          "Unsupported number of bits for literal variable");
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 0fb44052527f0..693795d09dacd 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -151,22 +151,17 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {
 }
 
 unsigned SPIRVGlobalRegistry::adjustOpTypeIntWidth(unsigned Width) const {
-  if (Width > 64)
-    report_fatal_error("Unsupported integer width!");
-  const SPIRVSubtarget &ST = cast<SPIRVSubtarget>(CurMF->getSubtarget());
-  if (ST.canUseExtension(
-          SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers) ||
-      ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4))
-    return Width;
   if (Width <= 8)
-    Width = 8;
+    return 8;
   else if (Width <= 16)
-    Width = 16;
+    return 16;
   else if (Width <= 32)
-    Width = 32;
-  else
-    Width = 64;
-  return Width;
+    return 32;
+  else if (Width <= 64)
+    return 64;
+  else if (Width <= 128)
+    return 128;
+  reportFatalUsageError("Unsupported Integer width!");
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(unsigned Width,
@@ -413,7 +408,7 @@ Register SPIRVGlobalRegistry::createConstInt(const ConstantInt *CI,
           MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
                     .addDef(Res)
                     .addUse(getSPIRVTypeID(SpvType));
-          addNumImm(APInt(BitWidth, CI->getZExtValue()), MIB);
+          addNumImm(CI->getValue(), MIB);
         } else {
           MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
                     .addDef(Res)
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index b5912c27316c9..38d4f7d706083 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -48,6 +48,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
   const LLT s16 = LLT::scalar(16);
   const LLT s32 = LLT::scalar(32);
   const LLT s64 = LLT::scalar(64);
+  const LLT s128 = LLT::scalar(128);
 
   const LLT v16s64 = LLT::fixed_vector(16, 64);
   const LLT v16s32 = LLT::fixed_vector(16, 32);
@@ -307,7 +308,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
           typeInSet(1, allPtrsScalarsAndVectors)));
 
   getActionDefinitionsBuilder({G_IMPLICIT_DEF, G_FREEZE})
-      .legalFor({s1})
+      .legalFor({s1, s128})
       .legalFor(allFloatAndIntScalarsAndPtrs)
       .legalFor(allowedVectorTypes)
       .moreElementsToNextPow2(0)
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 2feb73d8dedfa..832139f7d7354 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1395,6 +1395,17 @@ void addInstrRequirements(const MachineInstr &MI,
       Reqs.addCapability(SPIRV::Capability::Int16);
     else if (BitWidth == 8)
       Reqs.addCapability(SPIRV::Capability::Int8);
+    else {
+      if (!ST.canUseExtension(
+              SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
+        reportFatalUsageError(
+            "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
+            "requires the following SPIR-V extension: "
+            "SPV_ALTERA_arbitrary_precision_integers");
+      Reqs.addExtension(
+              SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
+      Reqs.addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
+    }
     break;
   }
   case SPIRV::OpDot: {
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index 7fdb0fafa3719..6feae31c8370f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -108,6 +108,13 @@ void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB) {
     // Asm Printer needs this info to print 64-bit operands correctly
     MIB.getInstr()->setAsmPrinterFlag(SPIRV::ASM_PRINTER_WIDTH64);
     return;
+  } else if (Bitwidth <= 128) {
+    uint32_t LowBits = Imm.getRawData()[0] & 0xffffffff;
+    uint32_t MidBits0 = (Imm.getRawData()[0] >> 32) & 0xffffffff;
+    uint32_t MidBits1 = Imm.getRawData()[1] & 0xffffffff;
+    uint32_t HighBits = (Imm.getRawData()[1] >> 32) & 0xffffffff;
+    MIB.addImm(LowBits).addImm(MidBits0).addImm(MidBits1).addImm(HighBits);
+    return;
   }
   report_fatal_error("Unsupported constant bitwidth");
 }
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll
new file mode 100644
index 0000000000000..c90ffdd17996c
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll
@@ -0,0 +1,67 @@
+; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-ERROR: LLVM ERROR: OpTypeInt type with a width other than 8, 16, 32 or 64 bits requires the following SPIR-V extension: SPV_ALTERA_arbitrary_precision_integers
+
+; CHECK: OpCapability ArbitraryPrecisionIntegersALTERA
+; CHECK: OpExtension "SPV_ALTERA_arbitrary_precision_integers"
+; CHECK: OpName %[[#TestAdd:]] "test_add"
+; CHECK: OpName %[[#TestSub:]] "test_sub"
+; CHECK: %[[#Int128Ty:]] = OpTypeInt 128 0
+; CHECK: %[[#Const64Int128:]] = OpConstant %[[#Int128Ty]] 64 0 0 0
+
+; CHECK: %[[#TestAdd]] = OpFunction
+define spir_func void @test_add(i64 %AL, i64 %AH, i64 %BL, i64 %BH, ptr %RL, ptr %RH) {
+entry:
+; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]]
+; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]]
+; CHECK: {{.*}} = OpShiftLeftLogical %[[#Int128Ty]] {{%[0-9]+}} %[[#Const64Int128]]
+; CHECK: {{.*}} = OpBitwiseOr %[[#Int128Ty]]
+; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]]
+; CHECK: {{.*}} = OpIAdd %[[#Int128Ty]]
+	%tmp1 = zext i64 %AL to i128
+	%tmp23 = zext i64 %AH to i128
+	%tmp4 = shl i128 %tmp23, 64
+	%tmp5 = or i128 %tmp4, %tmp1
+	%tmp67 = zext i64 %BL to i128
+	%tmp89 = zext i64 %BH to i128
+	%tmp11 = shl i128 %tmp89, 64
+	%tmp12 = or i128 %tmp11, %tmp67
+	%tmp15 = add i128 %tmp12, %tmp5
+	%tmp1617 = trunc i128 %tmp15 to i64
+	store i64 %tmp1617, ptr %RL
+	%tmp21 = lshr i128 %tmp15, 64
+	%tmp2122 = trunc i128 %tmp21 to i64
+	store i64 %tmp2122, ptr %RH
+	ret void
+; CHECK: OpFunctionEnd
+}
+
+; CHECK: %[[#TestSub]] = OpFunction
+define spir_func void @test_sub(i64 %AL, i64 %AH, i64 %BL, i64 %BH, ptr %RL, ptr %RH) {
+entry:
+; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]]
+; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]]
+; CHECK: {{.*}} = OpShiftLeftLogical %[[#Int128Ty]] {{%[0-9]+}} %[[#Const64Int128]]
+; CHECK: {{.*}} = OpBitwiseOr %[[#Int128Ty]]
+; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]]
+; CHECK: {{.*}} = OpISub %[[#Int128Ty]]
+	%tmp1 = zext i64 %AL to i128
+	%tmp23 = zext i64 %AH to i128
+	%tmp4 = shl i128 %tmp23, 64
+	%tmp5 = or i128 %tmp4, %tmp1
+	%tmp67 = zext i64 %BL to i128
+	%tmp89 = zext i64 %BH to i128
+	%tmp11 = shl i128 %tmp89, 64
+	%tmp12 = or i128 %tmp11, %tmp67
+	%tmp15 = sub i128 %tmp5, %tmp12
+	%tmp1617 = trunc i128 %tmp15 to i64
+	store i64 %tmp1617, ptr %RL
+	%tmp21 = lshr i128 %tmp15, 64
+	%tmp2122 = trunc i128 %tmp21 to i64
+	store i64 %tmp2122, ptr %RH
+	ret void
+; CHECK: OpFunctionEnd
+}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-arith.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-arith.ll
new file mode 100644
index 0000000000000..d1de5df499566
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-arith.ll
@@ -0,0 +1,27 @@
+; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-ERROR: LLVM ERROR: OpTypeInt type with a width other than 8, 16, 32 or 64 bits requires the following SPIR-V extension: SPV_ALTERA_arbitrary_precision_integers
+
+; CHECK: OpCapability ArbitraryPrecisionIntegersALTERA
+; CHECK: OpExtension "SPV_ALTERA_arbitrary_precision_integers"
+; CHECK: OpName %[[#Foo:]] "foo"
+; CHECK: %[[#Int128Ty:]] = OpTypeInt 128 0
+
+; CHECK: %[[#Foo]] = OpFunction
+define i64 @foo(i64 %x, i64 %y, i32 %amt) {
+; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]]
+; CHECK: {{.*}} = OpSConvert %[[#Int128Ty]]
+; CHECK: {{.*}} = OpBitwiseOr %[[#Int128Ty]]
+; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]]
+; CHECK: {{.*}} = OpShiftRightLogical %[[#Int128Ty]]
+  %tmp0 = zext i64 %x to i128
+  %tmp1 = sext i64 %y to i128
+  %tmp2 = or i128 %tmp0, %tmp1
+  %tmp7 = zext i32 13 to i128
+  %tmp3 = lshr i128 %tmp2, %tmp7
+  %tmp4 = trunc i128 %tmp3 to i64
+  ret i64 %tmp4
+}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-switch-lower.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-switch-lower.ll
new file mode 100644
index 0000000000000..669e9362605a5
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-switch-lower.ll
@@ -0,0 +1,27 @@
+; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-ERROR: LLVM ERROR: OpTypeInt type with a width other than 8, 16, 32 or 64 bits requires the following SPIR-V extension: SPV_ALTERA_arbitrary_precision_integers
+
+; CHECK: OpCapability ArbitraryPrecisionIntegersALTERA
+; CHECK: OpExtension "SPV_ALTERA_arbitrary_precision_integers"
+; CHECK: OpName %[[#Test:]] "test"
+; CHECK: OpName %[[#Exit:]] "exit"
+; CHECK: %[[#Int128Ty:]] = OpTypeInt 128 0
+; CHECK: %[[#UndefInt128:]] = OpUndef %[[#Int128Ty]]
+
+; CHECK: %[[#Test]] = OpFunction
+define void @test() {
+entry:
+; CHECK: OpSwitch %[[#UndefInt128]] %[[#Exit]] 0 0 3 0 %[[#Exit]] 0 0 5 0 %[[#Exit]] 0 0 4 0 %[[#Exit]] 0 0 8 0 %[[#Exit]]
+  switch i128 poison, label %exit [
+    i128 55340232221128654848, label %exit
+    i128 92233720368547758080, label %exit
+    i128 73786976294838206464, label %exit
+    i128 147573952589676412928, label %exit
+  ]
+exit:
+  unreachable
+}

@github-actions
Copy link

github-actions bot commented Dec 5, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@github-actions
Copy link

github-actions bot commented Dec 5, 2025

🐧 Linux x64 Test Results

  • 187197 tests passed
  • 4935 tests skipped

✅ The build succeeded and all tests passed.

@mgcarrasco
Copy link
Contributor

@AlexVlx The PR fixes this failing test case I had. Would it be worth adding it? It does test a different int width.

target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n32:64-S32-G1-P4-A0"
target triple = "spirv64-amd-amdhsa"

define spir_func i72 @_Z1dv() addrspace(4) {
entry:
  ret i72 0
}

Copy link
Contributor

@MrSidims MrSidims left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

BTW, Slava no longer works on SPIR-V backend. Don't think he'd object tagging him, but just FYI.

; CHECK: OpName %[[#TestAdd:]] "test_add"
; CHECK: OpName %[[#TestSub:]] "test_sub"
; CHECK: %[[#Int128Ty:]] = OpTypeInt 128 0
; CHECK: %[[#Const64Int128:]] = OpConstant %[[#Int128Ty]] 64 0 0 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious (potentially thinking about, what we might be missing): what happens with i126 scalars?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question! Today it fails opaquely, with Unsupported integer width. With this patch it'd either pass if the required extension is present, or fail at module analysis with a slightly more informative message around needing to add the extension.

@AlexVlx
Copy link
Contributor Author

AlexVlx commented Dec 9, 2025

@AlexVlx The PR fixes this failing test case I had. Would it be worth adding it? It does test a different int width.

target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n32:64-S32-G1-P4-A0"
target triple = "spirv64-amd-amdhsa"

define spir_func i72 @_Z1dv() addrspace(4) {
entry:
  ret i72 0
}

We should probably add the test under the extension itself, in a separate PR, that actually sweeps sizes (we have some of these elsewhere, they're needed for _BitInt).

@AlexVlx AlexVlx merged commit ef47462 into llvm:main Dec 9, 2025
11 checks passed
@AlexVlx AlexVlx deleted the spirv_be_staging_11 branch December 9, 2025 17:11
@vvereschaka
Copy link
Contributor

Hi @AlexVlx ,

https://lab.llvm.org/buildbot/#/builders/187/builds/14435
there are failed tests on the expensive test builder, looks like because of this PR

# executed command: not /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/build/bin/llc -O0 -mtriple=spirv64-unknown-unknown /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll -o /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/build/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/Output/i128-addsub.ll.tmp.spvt
# executed command: /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/build/bin/FileCheck /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll --check-prefix=CHECK-ERROR
# .---command stderr------------
# | /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll:6:16: error: CHECK-ERROR: expected string not found in input
# | ; CHECK-ERROR: LLVM ERROR: OpTypeInt type with a width other than 8, 16, 32 or 64 bits requires the following SPIR-V extension: SPV_ALTERA_arbitrary_precision_integers
# |                ^
# | <stdin>:1:1: note: scanning from here
# | 
...

would yo take care of it?

@AlexVlx
Copy link
Contributor Author

AlexVlx commented Dec 9, 2025

Hi @AlexVlx ,

https://lab.llvm.org/buildbot/#/builders/187/builds/14435 there are failed tests on the expensive test builder, looks like because of this PR

# executed command: not /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/build/bin/llc -O0 -mtriple=spirv64-unknown-unknown /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll -o /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/build/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/Output/i128-addsub.ll.tmp.spvt
# executed command: /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/build/bin/FileCheck /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll --check-prefix=CHECK-ERROR
# .---command stderr------------
# | /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll:6:16: error: CHECK-ERROR: expected string not found in input
# | ; CHECK-ERROR: LLVM ERROR: OpTypeInt type with a width other than 8, 16, 32 or 64 bits requires the following SPIR-V extension: SPV_ALTERA_arbitrary_precision_integers
# |                ^
# | <stdin>:1:1: note: scanning from here
# | 
...

would yo take care of it?

Yes, apologies for the inconvenience, I'll have a PR up in a few minutes, it was a bit sneaky.

@AlexVlx AlexVlx restored the spirv_be_staging_11 branch December 9, 2025 21:38
@AlexVlx
Copy link
Contributor Author

AlexVlx commented Dec 9, 2025

Hi @AlexVlx ,
https://lab.llvm.org/buildbot/#/builders/187/builds/14435 there are failed tests on the expensive test builder, looks like because of this PR

# executed command: not /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/build/bin/llc -O0 -mtriple=spirv64-unknown-unknown /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll -o /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/build/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/Output/i128-addsub.ll.tmp.spvt
# executed command: /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/build/bin/FileCheck /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll --check-prefix=CHECK-ERROR
# .---command stderr------------
# | /home/buildbot/worker/as-builder-4/ramdisk/expensive-checks/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll:6:16: error: CHECK-ERROR: expected string not found in input
# | ; CHECK-ERROR: LLVM ERROR: OpTypeInt type with a width other than 8, 16, 32 or 64 bits requires the following SPIR-V extension: SPV_ALTERA_arbitrary_precision_integers
# |                ^
# | <stdin>:1:1: note: scanning from here
# | 
...

would yo take care of it?

Yes, apologies for the inconvenience, I'll have a PR up in a few minutes, it was a bit sneaky.

#171513 fixes it, will merge once checks complete.

AlexVlx added a commit that referenced this pull request Dec 9, 2025
Adding support for i128 missed a few quirks of legalisation, which were
masked previously by early erroring out on bitwidth > 64. i128 uses
should be legal, we decide whether or not the resulting module is viable
(i.e. if the required extensions are present) in the ModuleAnalysis
pass.
@llvm-ci
Copy link
Collaborator

llvm-ci commented Dec 10, 2025

LLVM Buildbot has detected a new failure on builder ppc64le-mlir-rhel-clang running on ppc64le-mlir-rhel-test while building llvm at step 3 "clean-build-dir".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/129/builds/34692

Here is the relevant piece of the build log for the reference
Step 3 (clean-build-dir) failure: Delete failed. (failure) (timed out)
Step 4 (cmake-configure) failure: cmake (failure) (timed out)
command timed out: 1200 seconds without output running [b'cmake', b'-DLLVM_TARGETS_TO_BUILD=PowerPC', b'-DLLVM_INSTALL_UTILS=ON', b'-DCMAKE_CXX_STANDARD=17', b'-DLLVM_ENABLE_PROJECTS=mlir', b'-DLLVM_LIT_ARGS=-vj 256', b'-DCMAKE_C_COMPILER_LAUNCHER=ccache', b'-DCMAKE_CXX_COMPILER_LAUNCHER=ccache', b'-DCMAKE_BUILD_TYPE=Release', b'-DLLVM_ENABLE_ASSERTIONS=ON', b'-GNinja', b'../llvm-project/llvm'], attempting to kill
process killed by signal 9
program finished with exit code -1
elapsedTime=1200.432680

@mikaelholmen
Copy link
Collaborator

Hi @AlexVlx

I noticed that if I build with gcc and -DLLVM_ENABLE_EXPENSIVE_CHECKS=ON many SPIRV lit tests fail with this patch.

E.g. build-all-gcc132-expensive/bin/llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers,+SPV_KHR_bit_instructions test/CodeGen/SPIRV/llvm-intrinsics/bitreverse_small_type.ll -o - fails with

[...]/gcc/13.2.0/include/c++/13.2.0/bits/stl_algo.h:4892:
In function:
    void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter =
    llvm::StringRef*; _Compare =
    llvm::SPIRVExtensionsParser::parse(llvm::cl::Option&, llvm::StringRef,
    llvm::StringRef, std::
    debug::set<llvm::SPIRV::Extension::Extension>&)::<lambda(auto:4&&,
    auto:5&&)>]

Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).

Objects involved in the operation:
    instance "functor" @ 0x7ffd92e1a6a0 {
    }
    iterator::value_type "ordered type"  {
    }
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.      Program arguments: build-all-gcc132-expensive/bin/llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers,+SPV_KHR_bit_instructions test/CodeGen/SPIRV/llvm-intrinsics/bitreverse_small_type.ll -o -
 #0 0x0000000004e8fc6e llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (build-all-gcc132-expensive/bin/llc+0x4e8fc6e)
 #1 0x0000000004e8c5cb llvm::sys::RunSignalHandlers() (build-all-gcc132-expensive/bin/llc+0x4e8c5cb)
 #2 0x0000000004e8c70e SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x00007fa6f7f28990 __restore_rt (/lib64/libpthread.so.0+0x12990)
 #4 0x00007fa6f58bf52f raise (/lib64/libc.so.6+0x4e52f)
 #5 0x00007fa6f5892e65 abort (/lib64/libc.so.6+0x21e65)
 #6 0x000000000080410d (build-all-gcc132-expensive/bin/llc+0x80410d)
 #7 0x000000000246ef29 llvm::SPIRVExtensionsParser::parse(llvm::cl::Option&, llvm::StringRef, llvm::StringRef, std::__debug::set<llvm::SPIRV::Extension::Extension, std::less<llvm::SPIRV::Extension::Extension>, std::allocator<llvm::SPIRV::Extension::Extension>>&) crtstuff.c:0:0
 #8 0x00000000024257e5 llvm::cl::opt<std::__debug::set<llvm::SPIRV::Extension::Extension, std::less<llvm::SPIRV::Extension::Extension>, std::allocator<llvm::SPIRV::Extension::Extension>>, false, llvm::SPIRVExtensionsParser>::handleOccurrence(unsigned int, llvm::StringRef, llvm::StringRef) crtstuff.c:0:0
 #9 0x0000000004d4b5c1 llvm::cl::ParseCommandLineOptions(int, char const* const*, llvm::StringRef, llvm::raw_ostream*, llvm::vfs::FileSystem*, char const*, bool) (build-all-gcc132-expensive/bin/llc+0x4d4b5c1)
#10 0x0000000000806968 main (build-all-gcc132-expensive/bin/llc+0x806968)
#11 0x00007fa6f58ab7e5 __libc_start_main (/lib64/libc.so.6+0x3a7e5)
#12 0x00000000009510ee _start (build-all-gcc132-expensive/bin/llc+0x9510ee)
Abort (core dumped)

I guess it's this change that cause this

 bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
                                   StringRef ArgValue,
                                   std::set<SPIRV::Extension::Extension> &Vals) {
   SmallVector<StringRef, 10> Tokens;
   ArgValue.split(Tokens, ",", -1, false);
-  std::sort(Tokens.begin(), Tokens.end());
+  llvm::sort(Tokens, [](auto &&LHS, auto &&RHS) {
+    // We want to ensure that we handle "all" first, to ensure that any
+    // subsequent disablement actually behaves as expected i.e. given
+    // --spv-ext=all,-foo, we first enable all and then disable foo; this should
+    // be revisited and simplified.
+    if (LHS == "all")
+      return true;
+    if (RHS == "all")
+      return false;
+    return !(RHS < LHS);
+  });

@mikaelholmen
Copy link
Collaborator

Hi @AlexVlx

I noticed that if I build with gcc and -DLLVM_ENABLE_EXPENSIVE_CHECKS=ON many SPIRV lit tests fail with this patch.

E.g. build-all-gcc132-expensive/bin/llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers,+SPV_KHR_bit_instructions test/CodeGen/SPIRV/llvm-intrinsics/bitreverse_small_type.ll -o - fails with

[...]/gcc/13.2.0/include/c++/13.2.0/bits/stl_algo.h:4892:
In function:
    void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter =
    llvm::StringRef*; _Compare =
    llvm::SPIRVExtensionsParser::parse(llvm::cl::Option&, llvm::StringRef,
    llvm::StringRef, std::
    debug::set<llvm::SPIRV::Extension::Extension>&)::<lambda(auto:4&&,
    auto:5&&)>]

Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).

Objects involved in the operation:
    instance "functor" @ 0x7ffd92e1a6a0 {
    }
    iterator::value_type "ordered type"  {
    }
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.      Program arguments: build-all-gcc132-expensive/bin/llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers,+SPV_KHR_bit_instructions test/CodeGen/SPIRV/llvm-intrinsics/bitreverse_small_type.ll -o -
 #0 0x0000000004e8fc6e llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (build-all-gcc132-expensive/bin/llc+0x4e8fc6e)
 #1 0x0000000004e8c5cb llvm::sys::RunSignalHandlers() (build-all-gcc132-expensive/bin/llc+0x4e8c5cb)
 #2 0x0000000004e8c70e SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x00007fa6f7f28990 __restore_rt (/lib64/libpthread.so.0+0x12990)
 #4 0x00007fa6f58bf52f raise (/lib64/libc.so.6+0x4e52f)
 #5 0x00007fa6f5892e65 abort (/lib64/libc.so.6+0x21e65)
 #6 0x000000000080410d (build-all-gcc132-expensive/bin/llc+0x80410d)
 #7 0x000000000246ef29 llvm::SPIRVExtensionsParser::parse(llvm::cl::Option&, llvm::StringRef, llvm::StringRef, std::__debug::set<llvm::SPIRV::Extension::Extension, std::less<llvm::SPIRV::Extension::Extension>, std::allocator<llvm::SPIRV::Extension::Extension>>&) crtstuff.c:0:0
 #8 0x00000000024257e5 llvm::cl::opt<std::__debug::set<llvm::SPIRV::Extension::Extension, std::less<llvm::SPIRV::Extension::Extension>, std::allocator<llvm::SPIRV::Extension::Extension>>, false, llvm::SPIRVExtensionsParser>::handleOccurrence(unsigned int, llvm::StringRef, llvm::StringRef) crtstuff.c:0:0
 #9 0x0000000004d4b5c1 llvm::cl::ParseCommandLineOptions(int, char const* const*, llvm::StringRef, llvm::raw_ostream*, llvm::vfs::FileSystem*, char const*, bool) (build-all-gcc132-expensive/bin/llc+0x4d4b5c1)
#10 0x0000000000806968 main (build-all-gcc132-expensive/bin/llc+0x806968)
#11 0x00007fa6f58ab7e5 __libc_start_main (/lib64/libc.so.6+0x3a7e5)
#12 0x00000000009510ee _start (build-all-gcc132-expensive/bin/llc+0x9510ee)
Abort (core dumped)

I guess it's this change that cause this

 bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
                                   StringRef ArgValue,
                                   std::set<SPIRV::Extension::Extension> &Vals) {
   SmallVector<StringRef, 10> Tokens;
   ArgValue.split(Tokens, ",", -1, false);
-  std::sort(Tokens.begin(), Tokens.end());
+  llvm::sort(Tokens, [](auto &&LHS, auto &&RHS) {
+    // We want to ensure that we handle "all" first, to ensure that any
+    // subsequent disablement actually behaves as expected i.e. given
+    // --spv-ext=all,-foo, we first enable all and then disable foo; this should
+    // be revisited and simplified.
+    if (LHS == "all")
+      return true;
+    if (RHS == "all")
+      return false;
+    return !(RHS < LHS);
+  });

@AlexVlx
https://en.cppreference.com/w/cpp/algorithm/sort.html says the following:

comp 	- 	comparison function object (i.e. an object that satisfies the requirements of [Compare](https://en.cppreference.com/w/cpp/named_req/Compare.html)) which returns ​true if the first argument is less than (i.e. is ordered before) the second.

and then https://en.cppreference.com/w/cpp/named_req/Compare.html has the following requirement

 For all a, comp(a, a) == false. 

And with this patch we instead do

+    if (LHS == "all")
+      return true;
+    if (RHS == "all")
+      return false;

so comp("all","all") == true which doesn't follow the requirement.

@AlexVlx
Copy link
Contributor Author

AlexVlx commented Dec 11, 2025

Hi @AlexVlx
I noticed that if I build with gcc and -DLLVM_ENABLE_EXPENSIVE_CHECKS=ON many SPIRV lit tests fail with this patch.
E.g. build-all-gcc132-expensive/bin/llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers,+SPV_KHR_bit_instructions test/CodeGen/SPIRV/llvm-intrinsics/bitreverse_small_type.ll -o - fails with

[...]/gcc/13.2.0/include/c++/13.2.0/bits/stl_algo.h:4892:
In function:
    void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter =
    llvm::StringRef*; _Compare =
    llvm::SPIRVExtensionsParser::parse(llvm::cl::Option&, llvm::StringRef,
    llvm::StringRef, std::
    debug::set<llvm::SPIRV::Extension::Extension>&)::<lambda(auto:4&&,
    auto:5&&)>]

Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).

Objects involved in the operation:
    instance "functor" @ 0x7ffd92e1a6a0 {
    }
    iterator::value_type "ordered type"  {
    }
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.      Program arguments: build-all-gcc132-expensive/bin/llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers,+SPV_KHR_bit_instructions test/CodeGen/SPIRV/llvm-intrinsics/bitreverse_small_type.ll -o -
 #0 0x0000000004e8fc6e llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (build-all-gcc132-expensive/bin/llc+0x4e8fc6e)
 #1 0x0000000004e8c5cb llvm::sys::RunSignalHandlers() (build-all-gcc132-expensive/bin/llc+0x4e8c5cb)
 #2 0x0000000004e8c70e SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x00007fa6f7f28990 __restore_rt (/lib64/libpthread.so.0+0x12990)
 #4 0x00007fa6f58bf52f raise (/lib64/libc.so.6+0x4e52f)
 #5 0x00007fa6f5892e65 abort (/lib64/libc.so.6+0x21e65)
 #6 0x000000000080410d (build-all-gcc132-expensive/bin/llc+0x80410d)
 #7 0x000000000246ef29 llvm::SPIRVExtensionsParser::parse(llvm::cl::Option&, llvm::StringRef, llvm::StringRef, std::__debug::set<llvm::SPIRV::Extension::Extension, std::less<llvm::SPIRV::Extension::Extension>, std::allocator<llvm::SPIRV::Extension::Extension>>&) crtstuff.c:0:0
 #8 0x00000000024257e5 llvm::cl::opt<std::__debug::set<llvm::SPIRV::Extension::Extension, std::less<llvm::SPIRV::Extension::Extension>, std::allocator<llvm::SPIRV::Extension::Extension>>, false, llvm::SPIRVExtensionsParser>::handleOccurrence(unsigned int, llvm::StringRef, llvm::StringRef) crtstuff.c:0:0
 #9 0x0000000004d4b5c1 llvm::cl::ParseCommandLineOptions(int, char const* const*, llvm::StringRef, llvm::raw_ostream*, llvm::vfs::FileSystem*, char const*, bool) (build-all-gcc132-expensive/bin/llc+0x4d4b5c1)
#10 0x0000000000806968 main (build-all-gcc132-expensive/bin/llc+0x806968)
#11 0x00007fa6f58ab7e5 __libc_start_main (/lib64/libc.so.6+0x3a7e5)
#12 0x00000000009510ee _start (build-all-gcc132-expensive/bin/llc+0x9510ee)
Abort (core dumped)

I guess it's this change that cause this

 bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
                                   StringRef ArgValue,
                                   std::set<SPIRV::Extension::Extension> &Vals) {
   SmallVector<StringRef, 10> Tokens;
   ArgValue.split(Tokens, ",", -1, false);
-  std::sort(Tokens.begin(), Tokens.end());
+  llvm::sort(Tokens, [](auto &&LHS, auto &&RHS) {
+    // We want to ensure that we handle "all" first, to ensure that any
+    // subsequent disablement actually behaves as expected i.e. given
+    // --spv-ext=all,-foo, we first enable all and then disable foo; this should
+    // be revisited and simplified.
+    if (LHS == "all")
+      return true;
+    if (RHS == "all")
+      return false;
+    return !(RHS < LHS);
+  });

@AlexVlx https://en.cppreference.com/w/cpp/algorithm/sort.html says the following:

comp 	- 	comparison function object (i.e. an object that satisfies the requirements of [Compare](https://en.cppreference.com/w/cpp/named_req/Compare.html)) which returns ​true if the first argument is less than (i.e. is ordered before) the second.

and then https://en.cppreference.com/w/cpp/named_req/Compare.html has the following requirement

 For all a, comp(a, a) == false. 

And with this patch we instead do

+    if (LHS == "all")
+      return true;
+    if (RHS == "all")
+      return false;

so comp("all","all") == true which doesn't follow the requirement.

Thank you for the analysis. #171826 addresses this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants