[llvm] ef47462 - [SPIRV] Start adding support for `int128` (#170798)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 9 09:11:32 PST 2025
Author: Alex Voicu
Date: 2025-12-09T17:11:28Z
New Revision: ef47462ce9f1ade501da011a18869ea2a653d2cb
URL: https://github.com/llvm/llvm-project/commit/ef47462ce9f1ade501da011a18869ea2a653d2cb
DIFF: https://github.com/llvm/llvm-project/commit/ef47462ce9f1ade501da011a18869ea2a653d2cb.diff
LOG: [SPIRV] Start adding support for `int128` (#170798)
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`).
Added:
llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll
llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-arith.ll
llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-switch-lower.ll
Modified:
llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
llvm/lib/Target/SPIRV/SPIRVUtils.cpp
llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll
Removed:
################################################################################
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/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
index d2a8fddc5d8e4..42edad255ce82 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -13,9 +13,14 @@
#include "SPIRVCommandLine.h"
#include "MCTargetDesc/SPIRVBaseInfo.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/TargetParser/Triple.h"
-#include <algorithm>
+
+#include <functional>
#include <map>
+#include <string>
+#include <utility>
+#include <vector>
#define DEBUG_TYPE "spirv-commandline"
@@ -176,7 +181,17 @@ bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
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);
+ });
std::set<SPIRV::Extension::Extension> EnabledExtensions;
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 0fb44052527f0..5d96a67500dff 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -151,22 +151,22 @@ 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))
+ (Width == 4 && 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 +413,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 71df4cced434e..2078bfee2e767 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 73432279c3306..7717f18d14a34 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1436,6 +1436,21 @@ void addInstrRequirements(const MachineInstr &MI,
Reqs.addCapability(SPIRV::Capability::Int16);
else if (BitWidth == 8)
Reqs.addCapability(SPIRV::Capability::Int8);
+ else if (BitWidth == 4 &&
+ ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
+ Reqs.addExtension(SPIRV::Extension::SPV_INTEL_int4);
+ Reqs.addCapability(SPIRV::Capability::Int4TypeINTEL);
+ } else if (BitWidth != 32) {
+ 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 d4dd897647cfc..c32ecfb3ef7ac 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -171,6 +171,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
+}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll b/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll
index 5ddfc85702540..ecf4807a1d5fc 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll
@@ -1,4 +1,5 @@
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=all,-SPV_ALTERA_arbitrary_precision_integers %s -o - | FileCheck %s
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=-SPV_ALTERA_arbitrary_precision_integers,all %s -o - | FileCheck %s
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=KHR %s -o - | FileCheck %s
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=khr %s -o - | FileCheck %s
More information about the llvm-commits
mailing list