[SPIR-V] Add support for arbitrary precision integer constants in instruction printer (#185306)
This PR improves the SPIR-V instruction printer output for integer
constants using `SPV_ALTERA_arbitrary_precision_integers` extension.
Previously, when `OpConstantI` was encoded with multiple 32-bit words
(for integer widths > 64), the inst printer printed the raw per-word
immediates. This was hard to read and did not reflect the actual value
at the declared integer bitwidth.
Now, with the change in this patch, the instruction printer reconstructs
the multi-word literal into a single `APInt`, truncates it to the
bitwidth declared by the corresponding `OpTypeInt`, and prints the
resulting value as one readable integer (including correct negative
values where applicable).
---------
Co-authored-by: yixing.zhang <yixingzh@smtp.igk.intel.com>
diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
index 66500f5..6a3bc39 100644
--- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
@@ -51,10 +51,22 @@
const unsigned NumVarOps = MI->getNumOperands() - StartIndex;
if (MI->getOpcode() == SPIRV::OpConstantI && NumVarOps > 2) {
+ // Look up the bitwidth of this int type register from
+ // IntTypeBitwidths map.
+ MCRegister IntTypeReg = MI->getOperand(1).getReg();
+ unsigned Bitwidth = IntTypeBitwidths.at(IntTypeReg);
+
// 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();
+ const unsigned TotalBits = NumVarOps * 32;
+ APInt Val(TotalBits, 0);
+ for (unsigned i = 0; i < NumVarOps; ++i) {
+ uint64_t Word = MI->getOperand(StartIndex + i).getImm();
+ Val |= APInt(TotalBits, Word) << (i * 32);
+ }
+ APInt ActualVal = Val.trunc(Bitwidth);
+ O << ' ';
+ ActualVal.print(O, /*isSigned=*/false);
return;
}
@@ -101,6 +113,12 @@
O << Imm;
}
+void SPIRVInstPrinter::recordIntType(const MCInst *MI) {
+ MCRegister IntTypeReg = MI->getOperand(0).getReg();
+ unsigned Bitwidth = MI->getOperand(1).getImm();
+ IntTypeBitwidths[IntTypeReg] = Bitwidth;
+}
+
void SPIRVInstPrinter::recordOpExtInstImport(const MCInst *MI) {
MCRegister Reg = MI->getOperand(0).getReg();
auto Name = getSPIRVStringOperand(*MI, 1);
@@ -113,6 +131,9 @@
raw_ostream &OS) {
const unsigned OpCode = MI->getOpcode();
printInstruction(MI, Address, OS);
+ if (OpCode == SPIRV::OpTypeInt) {
+ recordIntType(MI);
+ }
if (OpCode == SPIRV::OpDecorate) {
printOpDecorate(MI, OS);
diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h
index 8f2ad48..13d69c0 100644
--- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h
@@ -22,7 +22,9 @@
class SPIRVInstPrinter : public MCInstPrinter {
private:
SmallDenseMap<MCRegister, SPIRV::InstructionSet::InstructionSet> ExtInstSetIDs;
+ SmallDenseMap<MCRegister, unsigned> IntTypeBitwidths;
void recordOpExtInstImport(const MCInst *MI);
+ void recordIntType(const MCInst *MI);
public:
using MCInstPrinter::MCInstPrinter;
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/SPV_ALTERA_arbitrary_precision_integers.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/SPV_ALTERA_arbitrary_precision_integers.ll
index 9ea8a57..a045127 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/SPV_ALTERA_arbitrary_precision_integers.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/SPV_ALTERA_arbitrary_precision_integers.ll
@@ -8,6 +8,14 @@
ret i13 42
}
+define i96 @getConstantI96() {
+ ret i96 18446744073709551620
+}
+
+define i160 @getConstantI160() {
+ ret i160 3363637389930338837376336738763689377839373638
+}
+
;; Capabilities:
; CHECK-DAG: OpExtension "SPV_ALTERA_arbitrary_precision_integers"
; CHECK-DAG: OpCapability ArbitraryPrecisionIntegersALTERA
@@ -17,14 +25,20 @@
;; Names:
; CHECK-DAG: OpName %[[#GET_I6:]] "getConstantI6"
; CHECK-DAG: OpName %[[#GET_I13:]] "getConstantI13"
+; CHECK-DAG: OpName %[[#GET_I96:]] "getConstantI96"
+; CHECK-DAG: OpName %[[#GET_I160:]] "getConstantI160"
; CHECK-NOT: DAG-FENCE
;; Types and Constants:
; CHECK-DAG: %[[#I6:]] = OpTypeInt 6 0
; CHECK-DAG: %[[#I13:]] = OpTypeInt 13 0
+; CHECK-DAG: %[[#I96:]] = OpTypeInt 96 0
+; CHECK-DAG: %[[#I160:]] = OpTypeInt 160 0
; CHECK-DAG: %[[#CST_I6:]] = OpConstant %[[#I6]] 2
; CHECK-DAG: %[[#CST_I13:]] = OpConstant %[[#I13]] 42
+; CHECK-DAG: %[[#CST_I96:]] = OpConstant %[[#I96]] 18446744073709551620
+; CHECK-DAG: %[[#CST_I160:]] = OpConstant %[[#I160]] 3363637389930338837376336738763689377839373638
; CHECK: %[[#GET_I6]] = OpFunction %[[#I6]]
; CHECK: OpReturnValue %[[#CST_I6]]
@@ -33,3 +47,11 @@
; CHECK: %[[#GET_I13]] = OpFunction %[[#I13]]
; CHECK: OpReturnValue %[[#CST_I13]]
; CHECK: OpFunctionEnd
+
+; CHECK: %[[#GET_I96]] = OpFunction %[[#I96]]
+; CHECK: OpReturnValue %[[#CST_I96]]
+; CHECK: OpFunctionEnd
+
+; CHECK: %[[#GET_I160]] = OpFunction %[[#I160]]
+; CHECK: OpReturnValue %[[#CST_I160]]
+; CHECK: OpFunctionEnd
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
index 6ed6228..342ae8d 100644
--- 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
@@ -6,15 +6,15 @@
; CHECK-DAG: %[[#INT128:]] = OpTypeInt 128 0
; CHECK-DAG: %[[#INT96:]] = OpTypeInt 96 0
; CHECK-DAG: %[[#INT97:]] = OpTypeInt 97 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: %[[#BOUNDARY:]] = OpConstant %[[#INT128]] 18446744073709551615
+; CHECK-DAG: %[[#ONE128:]] = OpConstant %[[#INT128]] 1
+; CHECK-DAG: %[[#NEG128:]] = OpConstant %[[#INT128]] 340282366920938463463374607431768209407
; CHECK-DAG: %[[#ZERO128:]] = OpConstantNull %[[#INT128]]
-; CHECK-DAG: %[[#NEG96:]] = OpConstant %[[#INT96]] 4294967295 4294967295 4294967295
-; CHECK-DAG: %[[#OVER64:]] = OpConstant %[[#INT96]] 1 0 1
-; CHECK-DAG: %[[#NEG97:]] = OpConstant %[[#INT97]] 4294967295 4294967295 4294967295 1
-; CHECK-DAG: %[[#OVER64_I97:]] = OpConstant %[[#INT97]] 1 0 1 0
-; CHECK-DAG: %[[#I97_MAX:]] = OpConstant %[[#INT97]] 0 0 0 1
+; CHECK-DAG: %[[#OVER64:]] = OpConstant %[[#INT96]] 18446744073709551617
+; CHECK-DAG: %[[#NEG96:]] = OpConstant %[[#INT96]] 79228162514264337593543950335
+; CHECK-DAG: %[[#I97_MAX:]] = OpConstant %[[#INT97]] 79228162514264337593543950336
+; CHECK-DAG: %[[#OVER64_I97:]] = OpConstant %[[#INT97]] 18446744073709551617
+; CHECK-DAG: %[[#NEG97:]] = OpConstant %[[#INT97]] 158456325028528675187087900671
; CHECK: OpStore %[[#]] %[[#NEG128]] Aligned 16
; CHECK: OpStore %[[#]] %[[#ONE128]] Aligned 16
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
index c90ffdd..f733c8f 100644
--- 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
@@ -10,7 +10,7 @@
; CHECK: OpName %[[#TestAdd:]] "test_add"
; CHECK: OpName %[[#TestSub:]] "test_sub"
; CHECK: %[[#Int128Ty:]] = OpTypeInt 128 0
-; CHECK: %[[#Const64Int128:]] = OpConstant %[[#Int128Ty]] 64 0 0 0
+; CHECK: %[[#Const64Int128:]] = OpConstant %[[#Int128Ty]] 64
; CHECK: %[[#TestAdd]] = OpFunction
define spir_func void @test_add(i64 %AL, i64 %AH, i64 %BL, i64 %BH, ptr %RL, ptr %RH) {