Skip to content

[SPIR-V] Support printing OpConstantF literals wider than 64 bits#208219

Open
aobolensk wants to merge 2 commits into
llvm:mainfrom
aobolensk:llvm-spirv-sp128-fix-printer
Open

[SPIR-V] Support printing OpConstantF literals wider than 64 bits#208219
aobolensk wants to merge 2 commits into
llvm:mainfrom
aobolensk:llvm-spirv-sp128-fix-printer

Conversation

@aobolensk

Copy link
Copy Markdown
Contributor

printOpConstantVarOps asserted for OpConstantF with more than two 32-bit literal words (e.g. fp128), which the fixed createConstFP now produces

Reconstruct the APFloat and print it exactly

printOpConstantVarOps asserted for OpConstantF with more than two 32-bit literal words (e.g. fp128), which the fixed createConstFP now produces

Reconstruct the APFloat and print it exactly
@llvmorg-github-actions

Copy link
Copy Markdown

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

Author: Arseniy Obolenskiy (aobolensk)

Changes

printOpConstantVarOps asserted for OpConstantF with more than two 32-bit literal words (e.g. fp128), which the fixed createConstFP now produces

Reconstruct the APFloat and print it exactly


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

2 Files Affected:

  • (modified) llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp (+18)
  • (added) llvm/test/CodeGen/SPIRV/constant/wide-float-literal-printer.mir (+29)
diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
index b7dcd10bac809..ad47a9333ab08 100644
--- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
@@ -14,6 +14,7 @@
 #include "SPIRV.h"
 #include "SPIRVBaseInfo.h"
 #include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
@@ -70,6 +71,23 @@ void SPIRVInstPrinter::printOpConstantVarOps(const MCInst *MI,
     return;
   }
 
+  if (MI->getOpcode() == SPIRV::OpConstantF && NumVarOps > 2) {
+    // Wide floating-point literals (e.g. fp128) are encoded via more than two
+    // 32-bit words. Reconstruct the value and print it exactly.
+    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);
+    }
+    assert(TotalBits == 128 && "Unsupported floating-point literal width");
+    APFloat FP(APFloat::IEEEquad(), Val);
+    SmallString<40> Str;
+    FP.toString(Str);
+    O << ' ' << Str;
+    return;
+  }
+
   assert((NumVarOps == 1 || NumVarOps == 2) &&
          "Unsupported number of bits for literal variable");
 
diff --git a/llvm/test/CodeGen/SPIRV/constant/wide-float-literal-printer.mir b/llvm/test/CodeGen/SPIRV/constant/wide-float-literal-printer.mir
new file mode 100644
index 0000000000000..98e9ef18408f0
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/constant/wide-float-literal-printer.mir
@@ -0,0 +1,29 @@
+# RUN: llc -O0 -mtriple=spirv32-unknown-unknown -start-after=finalize-isel -verify-machineinstrs %s -o - | FileCheck %s
+
+# Exercises the SPIRVInstPrinter's OpConstantF path for literals wider than
+# 64 bits (e.g. fp128), independent of how the OpConstantF instruction with
+# more than two literal words was produced.
+
+--- |
+  define fp128 @getConstantFP128() {
+    ret fp128 0xL00000000000000004001000000000000
+  }
+...
+---
+name:            getConstantFP128
+legalized:       true
+regBankSelected: true
+selected:        true
+tracksRegLiveness: true
+body:             |
+  bb.1 (%ir-block.0):
+    %0:type = OpTypeFloat 128
+    %1:fid = OpConstantF %0, 0, 0, 0, 1073807360
+    %2:type = OpTypeFunction %0, %0
+    %3:iid = OpFunction %0, 0, %2
+    OpFunctionEnd
+    OpReturnValue %1
+
+# CHECK: %[[#FP128:]] = OpTypeFloat 128
+# CHECK: %[[#CST_FP128:]] = OpConstant %[[#FP128]] 4
+# CHECK: OpReturnValue %[[#CST_FP128]]

@aobolensk aobolensk requested a review from jmmartinez July 8, 2026 13:27
Comment on lines +8 to +10
define fp128 @getConstantFP128() {
ret fp128 0xL00000000000000004001000000000000
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why not write the test starting from the IR instead of the MIR ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, there is another issue: there is a miscompilation of fp128 constant literals. I decided to split them gotta be done in the following patch

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You may peek here: 0e27cc3

return;
}

if (MI->getOpcode() == SPIRV::OpConstantF && NumVarOps > 2) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think you can just check for NumVarOps == 4. Any other case will hit the assert(TotalBits == 128 && "Unsupported floating-point literal width"); anyways.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, thanks, done

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.

2 participants