diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp @@ -13,6 +13,7 @@ #include "SPIRVInstPrinter.h" #include "SPIRV.h" #include "SPIRVBaseInfo.h" +#include "llvm/ADT/APFloat.h" #include "llvm/CodeGen/Register.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" @@ -49,14 +50,49 @@ void SPIRVInstPrinter::printOpConstantVarOps(const MCInst *MI, unsigned StartIndex, raw_ostream &O) { + const unsigned NumVarOps = MI->getNumOperands() - StartIndex; + + assert((NumVarOps == 1 || NumVarOps == 2) && + "Unsupported number of bits for literal variable"); + O << ' '; - if (MI->getNumOperands() - StartIndex == 2) { // Handle 64 bit literals. - uint64_t Imm = MI->getOperand(StartIndex).getImm(); + + uint64_t Imm = MI->getOperand(StartIndex).getImm(); + + // Handle 64 bit literals. + if (NumVarOps == 2) { Imm |= (MI->getOperand(StartIndex + 1).getImm() << 32); - O << Imm; - } else { - printRemainingVariableOps(MI, StartIndex, O, true, false); } + + // Format and print float values. + if (MI->getOpcode() == SPIRV::OpConstantF) { + APFloat FP = NumVarOps == 1 ? APFloat(APInt(32, Imm).bitsToFloat()) + : APFloat(APInt(64, Imm).bitsToDouble()); + + // Print infinity and NaN as hex floats. + // TODO: Make sure subnormal numbers are handled correctly as they may also + // require hex float notation. + if (FP.isInfinity()) { + if (FP.isNegative()) + O << '-'; + O << "0x1p+128"; + return; + } + if (FP.isNaN()) { + O << "0x1.8p+128"; + return; + } + + // Format val as a decimal floating point or scientific notation (whichever + // is shorter), with enough digits of precision to produce the exact value. + O << format("%.*g", std::numeric_limits::max_digits10, + FP.convertToDouble()); + + return; + } + + // Print integer values directly. + O << Imm; } void SPIRVInstPrinter::recordOpExtInstImport(const MCInst *MI) { diff --git a/llvm/test/CodeGen/SPIRV/AtomicBuiltinsFloat.ll b/llvm/test/CodeGen/SPIRV/AtomicBuiltinsFloat.ll --- a/llvm/test/CodeGen/SPIRV/AtomicBuiltinsFloat.ll +++ b/llvm/test/CodeGen/SPIRV/AtomicBuiltinsFloat.ll @@ -3,7 +3,7 @@ ;; Types: ; CHECK: %[[#F32:]] = OpTypeFloat 32 ;; Constants: -; CHECK: %[[#CONST:]] = OpConstant %[[#F32]] 1065353216 +; CHECK: %[[#CONST:]] = OpConstant %[[#F32]] 1 ;; Atomic instructions: ; CHECK: OpStore %[[#]] %[[#CONST]] ; CHECK-COUNT-3: OpAtomicStore diff --git a/llvm/test/CodeGen/SPIRV/atomicrmw.ll b/llvm/test/CodeGen/SPIRV/atomicrmw.ll --- a/llvm/test/CodeGen/SPIRV/atomicrmw.ll +++ b/llvm/test/CodeGen/SPIRV/atomicrmw.ll @@ -13,7 +13,7 @@ ; CHECK-DAG: %[[#FPPointerType:]] = OpTypePointer CrossWorkgroup %[[#Float]] ; CHECK-DAG: %[[#Pointer:]] = OpVariable %[[#PointerType]] CrossWorkgroup ; CHECK-DAG: %[[#FPPointer:]] = OpVariable %[[#FPPointerType]] CrossWorkgroup -; CHECK-DAG: %[[#FPValue:]] = OpConstant %[[#Float]] 1109917696 +; CHECK-DAG: %[[#FPValue:]] = OpConstant %[[#Float]] 42 @ui = common dso_local addrspace(1) global i32 0, align 4 @f = common dso_local local_unnamed_addr addrspace(1) global float 0.000000e+00, align 4 diff --git a/llvm/test/CodeGen/SPIRV/literals.ll b/llvm/test/CodeGen/SPIRV/literals.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/literals.ll @@ -0,0 +1,36 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s + +; CHECK: %[[#F32:]] = OpTypeFloat 32 +; CHECK: %[[#F64:]] = OpTypeFloat 64 + +define void @main() { +entry: + +; CHECK: OpConstant %[[#F32]] 0.5 + %f = alloca float, align 4 + store float 5.000000e-01, ptr %f, align 4 + +; CHECK: OpConstant %[[#F64]] 0.5 + %d = alloca double, align 8 + store double 5.000000e-01, ptr %d, align 8 + +; CHECK: OpConstant %[[#F32]] 1.0000016166037976e-39 + %hexf = alloca float, align 4 + store float 0x37D5C73200000000, ptr %hexf, align 4 + +; CHECK: OpConstant %[[#F32]] 0x1p+128 + %inf = alloca float, align 4 + store float 0x7FF0000000000000, ptr %inf, align 4 + +; CHECK: OpConstant %[[#F32]] -0x1p+128 + %ninf = alloca float, align 4 + store float 0xFFF0000000000000, ptr %ninf, align 4 + +; CHECK: OpConstant %[[#F32]] 0x1.8p+128 + %nan = alloca float, align 4 + store float 0x7FF8000000000000, ptr %nan, align 4 + + ret void +}