[llvm] [SPIR-V] Support i64 smul.fix/umul.fix via SPV_ALTERA_arbitrary_precision_integers (PR #207405)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 3 07:51:42 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/207405
>From 290bd9a619364fae2a9cc0cfb777239b2db96e6f Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 3 Jul 2026 16:34:24 +0200
Subject: [PATCH] [SPIR-V] Support i64 smul.fix/umul.fix via
SPV_ALTERA_arbitrary_precision_integers
---
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 16 +++----
.../llvm-intrinsics/fixed-point-math-i64.ll | 42 +++++++++++++++++--
2 files changed, 47 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index e2e4a4a6ae799..d452c9815a86a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -159,9 +159,10 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
auto &allowedVectorTypes = ST.isShader() ? allShaderVectors : allVectors;
+ bool HasArbitraryPrecisionInts = ST.canUseExtension(
+ SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
bool IsExtendedInts =
- ST.canUseExtension(
- SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers) ||
+ HasArbitraryPrecisionInts ||
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions) ||
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4);
auto extendedScalarsAndVectors =
@@ -460,11 +461,12 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
getActionDefinitionsBuilder({G_SADDO, G_SSUBO}).lower();
- // s64 is unsupported because lowering widens to s128, which SPIR-V does not
- // have.
- getActionDefinitionsBuilder({G_SMULFIX, G_UMULFIX})
- .unsupportedFor({s64})
- .lower();
+ // Lowering widens s64 to s128, which needs
+ // SPV_ALTERA_arbitrary_precision_integers. Mark s64 unsupported otherwise.
+ auto &MulFix = getActionDefinitionsBuilder({G_SMULFIX, G_UMULFIX});
+ if (!HasArbitraryPrecisionInts)
+ MulFix.unsupportedFor({s64});
+ MulFix.lower();
getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
.legalForCartesianProduct(allFloatScalarsAndVectors,
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fixed-point-math-i64.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fixed-point-math-i64.ll
index 2e2f45c31365b..a3b731e342016 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fixed-point-math-i64.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fixed-point-math-i64.ll
@@ -1,10 +1,44 @@
-; i64 is unsupported for smul.fix/umul.fix because lowering widens to i128,
-; which SPIR-V does not have.
+; i64 smul.fix/umul.fix lowering widens to i128, which SPIR-V only has via
+; SPV_ALTERA_arbitrary_precision_integers. Without the extension s64 is marked
+; unsupported so the diagnostic comes from the legalizer.
-; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o -
-; XFAIL: *
+; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - | FileCheck %s
+; RUN: %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: unable to legalize instruction: {{.*}} = G_SMULFIX
+
+; CHECK: OpCapability ArbitraryPrecisionIntegersALTERA
+; CHECK: OpExtension "SPV_ALTERA_arbitrary_precision_integers"
+; CHECK-DAG: %[[#I64:]] = OpTypeInt 64 0
+; CHECK-DAG: %[[#I128:]] = OpTypeInt 128 0
+; CHECK-DAG: %[[#Scale:]] = OpConstant %[[#I128]] 3
+
+; CHECK: OpFunction
+; CHECK: %[[#A:]] = OpFunctionParameter %[[#I64]]
+; CHECK: %[[#B:]] = OpFunctionParameter %[[#I64]]
+; CHECK: %[[#WideA:]] = OpSConvert %[[#I128]] %[[#A]]
+; CHECK: %[[#WideB:]] = OpSConvert %[[#I128]] %[[#B]]
+; CHECK: %[[#Mul:]] = OpIMul %[[#I128]] %[[#WideA]] %[[#WideB]]
+; CHECK: %[[#Shift:]] = OpShiftRightArithmetic %[[#I128]] %[[#Mul]] %[[#Scale]]
+; CHECK: %[[#Res:]] = OpUConvert %[[#I64]] %[[#Shift]]
+; CHECK: OpReturnValue %[[#Res]]
define i64 @smulfix_i64(i64 %a, i64 %b) {
%r = call i64 @llvm.smul.fix.i64(i64 %a, i64 %b, i32 3)
ret i64 %r
}
+
+; CHECK: OpFunction
+; CHECK: %[[#A:]] = OpFunctionParameter %[[#I64]]
+; CHECK: %[[#B:]] = OpFunctionParameter %[[#I64]]
+; CHECK: %[[#WideA:]] = OpUConvert %[[#I128]] %[[#A]]
+; CHECK: %[[#WideB:]] = OpUConvert %[[#I128]] %[[#B]]
+; CHECK: %[[#Mul:]] = OpIMul %[[#I128]] %[[#WideA]] %[[#WideB]]
+; CHECK: %[[#Shift:]] = OpShiftRightLogical %[[#I128]] %[[#Mul]] %[[#Scale]]
+; CHECK: %[[#Res:]] = OpUConvert %[[#I64]] %[[#Shift]]
+; CHECK: OpReturnValue %[[#Res]]
+define i64 @umulfix_i64(i64 %a, i64 %b) {
+ %r = call i64 @llvm.umul.fix.i64(i64 %a, i64 %b, i32 3)
+ ret i64 %r
+}
More information about the llvm-commits
mailing list