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 @@ -22,6 +22,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" +#include using namespace llvm; using namespace llvm::SPIRV; @@ -258,19 +259,47 @@ void SPIRVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, const char *Modifier) { assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); - if (OpNo < MI->getNumOperands()) { - const MCOperand &Op = MI->getOperand(OpNo); - if (Op.isReg()) - O << '%' << (Register::virtReg2Index(Op.getReg()) + 1); - else if (Op.isImm()) - O << formatImm((int64_t)Op.getImm()); - else if (Op.isDFPImm()) - O << formatImm((double)Op.getDFPImm()); - else if (Op.isExpr()) - printExpr(Op.getExpr(), O); - else - llvm_unreachable("Unexpected operand type"); + if (OpNo >= MI->getNumOperands()) + return; + + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + O << '%' << (Register::virtReg2Index(Op.getReg()) + 1); + return; + } + + if (Op.isImm()) { + O << formatImm((int64_t)Op.getImm()); + return; + } + + if (Op.isDFPImm()) { + double val = bit_cast(Op.getDFPImm()); + + // Print infinity and NaN as hex floats. + // TODO: Make sure subnormal numbers are handled correctly as they may also + // require hex float notation. + if (isinf(val)) { + if (val < 0) + O << '-'; + O << "0x1p+128"; + return; + } + if (isnan(val)) { + 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, val); + return; } + + if (Op.isExpr()) + return printExpr(Op.getExpr(), O); + + llvm_unreachable("Unexpected operand type"); } void SPIRVInstPrinter::printStringImm(const MCInst *MI, unsigned OpNo, diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -1026,7 +1026,7 @@ assert(I.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 && "Expected G_FCONSTANT"); const ConstantFP *FPImm = I.getOperand(1).getFPImm(); - addNumImm(FPImm->getValueAPF().bitcastToAPInt(), MIB); + MIB.addFPImm(FPImm); } void SPIRVInstructionSelector::renderImm32(MachineInstrBuilder &MIB, diff --git a/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp b/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp --- a/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp @@ -53,8 +53,8 @@ } break; case MachineOperand::MO_FPImmediate: - MCOp = MCOperand::createDFPImm( - MO.getFPImm()->getValueAPF().convertToFloat()); + APFloat Val = MO.getFPImm()->getValueAPF(); + MCOp = MCOperand::createDFPImm(bit_cast(Val.convertToDouble())); break; } 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/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,34 @@ +; RUN: llc -O0 -mtriple=spirv32-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 +}