From 698c6b0a099b902722d9e89234e0205ac240c13e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 4 Feb 2021 18:01:38 -0800 Subject: [PATCH] [WebAssembly] Support single-floating-point immediate value As mentioned in TODO comment, casting double to float causes NaNs to change bits. To avoid the change, this patch adds support for single-floating-point immediate value on MachineCode. Patch by Yuta Saito. Differential Revision: https://reviews.llvm.org/D77384 --- llvm/include/llvm/MC/MCInst.h | 51 +++++++++++++------ llvm/include/llvm/MC/MCInstBuilder.h | 10 +++- llvm/lib/MC/MCInst.cpp | 6 ++- .../MCTargetDesc/AArch64InstPrinter.cpp | 4 +- .../AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp | 17 ++++--- .../AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp | 2 +- llvm/lib/Target/ARM/ARMMCInstLower.cpp | 2 +- .../ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 8 +-- .../AVR/MCTargetDesc/AVRMCCodeEmitter.cpp | 7 +-- .../Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 5 +- .../AsmParser/WebAssemblyAsmParser.cpp | 13 ++++- .../Disassembler/WebAssemblyDisassembler.cpp | 2 +- .../MCTargetDesc/WebAssemblyInstPrinter.cpp | 15 ++---- .../MCTargetDesc/WebAssemblyMCCodeEmitter.cpp | 19 +++---- .../WebAssembly/WebAssemblyInstrInfo.td | 6 +-- .../WebAssembly/WebAssemblyMCInstLower.cpp | 8 +-- llvm/test/CodeGen/WebAssembly/immediates.ll | 5 +- llvm/test/CodeGen/WebAssembly/snan_literal.ll | 29 +++++++++++ .../llvm-exegesis/lib/BenchmarkResult.cpp | 6 +-- .../llvm-exegesis/lib/MCInstrDescView.cpp | 6 ++- .../llvm-exegesis/X86/BenchmarkResultTest.cpp | 2 +- 21 files changed, 137 insertions(+), 86 deletions(-) create mode 100644 llvm/test/CodeGen/WebAssembly/snan_literal.ll diff --git a/llvm/include/llvm/MC/MCInst.h b/llvm/include/llvm/MC/MCInst.h index 2ce2ee063daa..60d8334db9f5 100644 --- a/llvm/include/llvm/MC/MCInst.h +++ b/llvm/include/llvm/MC/MCInst.h @@ -17,6 +17,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/bit.h" #include "llvm/Support/SMLoc.h" #include #include @@ -33,30 +34,33 @@ class raw_ostream; /// This is a simple discriminated union. class MCOperand { enum MachineOperandType : unsigned char { - kInvalid, ///< Uninitialized. - kRegister, ///< Register operand. - kImmediate, ///< Immediate operand. - kFPImmediate, ///< Floating-point immediate operand. - kExpr, ///< Relocatable immediate operand. - kInst ///< Sub-instruction operand. + kInvalid, ///< Uninitialized. + kRegister, ///< Register operand. + kImmediate, ///< Immediate operand. + kSFPImmediate, ///< Single-floating-point immediate operand. + kDFPImmediate, ///< Double-Floating-point immediate operand. + kExpr, ///< Relocatable immediate operand. + kInst ///< Sub-instruction operand. }; MachineOperandType Kind = kInvalid; union { unsigned RegVal; int64_t ImmVal; - double FPImmVal; + uint32_t SFPImmVal; + uint64_t FPImmVal; const MCExpr *ExprVal; const MCInst *InstVal; }; public: - MCOperand() : FPImmVal(0.0) {} + MCOperand() : FPImmVal(0) {} bool isValid() const { return Kind != kInvalid; } bool isReg() const { return Kind == kRegister; } bool isImm() const { return Kind == kImmediate; } - bool isFPImm() const { return Kind == kFPImmediate; } + bool isSFPImm() const { return Kind == kSFPImmediate; } + bool isDFPImm() const { return Kind == kDFPImmediate; } bool isExpr() const { return Kind == kExpr; } bool isInst() const { return Kind == kInst; } @@ -82,13 +86,23 @@ public: ImmVal = Val; } - double getFPImm() const { - assert(isFPImm() && "This is not an FP immediate"); + uint32_t getSFPImm() const { + assert(isSFPImm() && "This is not an SFP immediate"); + return SFPImmVal; + } + + void setSFPImm(uint32_t Val) { + assert(isSFPImm() && "This is not an SFP immediate"); + SFPImmVal = Val; + } + + uint64_t getDFPImm() const { + assert(isDFPImm() && "This is not an FP immediate"); return FPImmVal; } - void setFPImm(double Val) { - assert(isFPImm() && "This is not an FP immediate"); + void setDFPImm(uint64_t Val) { + assert(isDFPImm() && "This is not an FP immediate"); FPImmVal = Val; } @@ -126,9 +140,16 @@ public: return Op; } - static MCOperand createFPImm(double Val) { + static MCOperand createSFPImm(uint32_t Val) { MCOperand Op; - Op.Kind = kFPImmediate; + Op.Kind = kSFPImmediate; + Op.SFPImmVal = Val; + return Op; + } + + static MCOperand createDFPImm(uint64_t Val) { + MCOperand Op; + Op.Kind = kDFPImmediate; Op.FPImmVal = Val; return Op; } diff --git a/llvm/include/llvm/MC/MCInstBuilder.h b/llvm/include/llvm/MC/MCInstBuilder.h index 0c8e01fdc412..6e5e9dd69018 100644 --- a/llvm/include/llvm/MC/MCInstBuilder.h +++ b/llvm/include/llvm/MC/MCInstBuilder.h @@ -39,9 +39,15 @@ public: return *this; } + /// Add a new single floating point immediate operand. + MCInstBuilder &addSFPImm(uint32_t Val) { + Inst.addOperand(MCOperand::createSFPImm(Val)); + return *this; + } + /// Add a new floating point immediate operand. - MCInstBuilder &addFPImm(double Val) { - Inst.addOperand(MCOperand::createFPImm(Val)); + MCInstBuilder &addDFPImm(uint64_t Val) { + Inst.addOperand(MCOperand::createDFPImm(Val)); return *this; } diff --git a/llvm/lib/MC/MCInst.cpp b/llvm/lib/MC/MCInst.cpp index f6f6edee5822..be312b9a8d33 100644 --- a/llvm/lib/MC/MCInst.cpp +++ b/llvm/lib/MC/MCInst.cpp @@ -25,8 +25,10 @@ void MCOperand::print(raw_ostream &OS) const { OS << "Reg:" << getReg(); else if (isImm()) OS << "Imm:" << getImm(); - else if (isFPImm()) - OS << "FPImm:" << getFPImm(); + else if (isSFPImm()) + OS << "SFPImm:" << bit_cast(getSFPImm()); + else if (isDFPImm()) + OS << "DFPImm:" << bit_cast(getDFPImm()); else if (isExpr()) { OS << "Expr:(" << *getExpr() << ")"; } else if (isInst()) { diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp index 340120d2b9e8..8204156d98a9 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp @@ -1164,8 +1164,8 @@ void AArch64InstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O) { const MCOperand &MO = MI->getOperand(OpNum); - float FPImm = - MO.isFPImm() ? MO.getFPImm() : AArch64_AM::getFPImmFloat(MO.getImm()); + float FPImm = MO.isDFPImm() ? bit_cast(MO.getDFPImm()) + : AArch64_AM::getFPImmFloat(MO.getImm()); // 8 decimal places are enough to perfectly represent permitted floats. O << format("#%.8f", FPImm); diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp index fbf7dc2a72db..00bc9b2b65db 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp @@ -656,18 +656,19 @@ void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, // custom printer. llvm_unreachable("unexpected immediate operand type"); } - } else if (Op.isFPImm()) { + } else if (Op.isDFPImm()) { + double Value = bit_cast(Op.getDFPImm()); // We special case 0.0 because otherwise it will be printed as an integer. - if (Op.getFPImm() == 0.0) + if (Value == 0.0) O << "0.0"; else { const MCInstrDesc &Desc = MII.get(MI->getOpcode()); int RCID = Desc.OpInfo[OpNo].RegClass; unsigned RCBits = AMDGPU::getRegBitWidth(MRI.getRegClass(RCID)); if (RCBits == 32) - printImmediate32(FloatToBits(Op.getFPImm()), STI, O); + printImmediate32(FloatToBits(Value), STI, O); else if (RCBits == 64) - printImmediate64(DoubleToBits(Op.getFPImm()), STI, O); + printImmediate64(DoubleToBits(Value), STI, O); else llvm_unreachable("Invalid register class size"); } @@ -727,7 +728,7 @@ void AMDGPUInstPrinter::printOperandAndFPInputMods(const MCInst *MI, if (OpNo + 1 < MI->getNumOperands() && (InputModifiers & SISrcMods::ABS) == 0) { const MCOperand &Op = MI->getOperand(OpNo + 1); - NegMnemo = Op.isImm() || Op.isFPImm(); + NegMnemo = Op.isImm() || Op.isDFPImm(); } if (NegMnemo) { O << "neg("; @@ -1560,12 +1561,12 @@ void R600InstPrinter::printOperand(const MCInst *MI, unsigned OpNo, } } else if (Op.isImm()) { O << Op.getImm(); - } else if (Op.isFPImm()) { + } else if (Op.isDFPImm()) { // We special case 0.0 because otherwise it will be printed as an integer. - if (Op.getFPImm() == 0.0) + if (Op.getDFPImm() == 0.0) O << "0.0"; else { - O << Op.getFPImm(); + O << bit_cast(Op.getDFPImm()); } } else if (Op.isExpr()) { const MCExpr *Exp = Op.getExpr(); diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp index 1a1ffcda3b4e..1aac821294db 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp @@ -219,7 +219,7 @@ uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO, Imm = C->getValue(); } else { - assert(!MO.isFPImm()); + assert(!MO.isDFPImm()); if (!MO.isImm()) return ~0; diff --git a/llvm/lib/Target/ARM/ARMMCInstLower.cpp b/llvm/lib/Target/ARM/ARMMCInstLower.cpp index f893faa4cf97..2c12e188049f 100644 --- a/llvm/lib/Target/ARM/ARMMCInstLower.cpp +++ b/llvm/lib/Target/ARM/ARMMCInstLower.cpp @@ -110,7 +110,7 @@ bool ARMAsmPrinter::lowerOperand(const MachineOperand &MO, APFloat Val = MO.getFPImm()->getValueAPF(); bool ignored; Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &ignored); - MCOp = MCOperand::createFPImm(Val.convertToDouble()); + MCOp = MCOperand::createDFPImm(Val.convertToDouble()); break; } case MachineOperand::MO_RegisterMask: diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp index 6df3af10fdcf..2396412996e1 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp @@ -576,9 +576,11 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, } } else if (MO.isImm()) { return static_cast(MO.getImm()); - } else if (MO.isFPImm()) { - return static_cast(APFloat(MO.getFPImm()) - .bitcastToAPInt().getHiBits(32).getLimitedValue()); + } else if (MO.isDFPImm()) { + return static_cast(APFloat(bit_cast(MO.getDFPImm())) + .bitcastToAPInt() + .getHiBits(32) + .getLimitedValue()); } llvm_unreachable("Unable to encode MCOperand!"); diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp index db995e247562..50872d6d7a92 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp @@ -254,11 +254,8 @@ unsigned AVRMCCodeEmitter::getMachineOpValue(const MCInst &MI, if (MO.isReg()) return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); if (MO.isImm()) return static_cast(MO.getImm()); - if (MO.isFPImm()) - return static_cast(APFloat(MO.getFPImm()) - .bitcastToAPInt() - .getHiBits(32) - .getLimitedValue()); + if (MO.isDFPImm()) + return static_cast(bit_cast(MO.getDFPImm())); // MO must be an Expr. assert(MO.isExpr()); diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 9de34cc0e787..b81ebedfb9c7 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -740,9 +740,8 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, return RegNo; } else if (MO.isImm()) { return static_cast(MO.getImm()); - } else if (MO.isFPImm()) { - return static_cast(APFloat(MO.getFPImm()) - .bitcastToAPInt().getHiBits(32).getLimitedValue()); + } else if (MO.isDFPImm()) { + return static_cast(bit_cast(MO.getDFPImm())); } // MO must be an Expr. assert(MO.isExpr()); diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index 60ac3248b9e7..7748bfa7f80f 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -125,10 +125,19 @@ struct WebAssemblyOperand : public MCParsedAsmOperand { llvm_unreachable("Should be integer immediate or symbol!"); } - void addFPImmOperands(MCInst &Inst, unsigned N) const { + void addFPImmf32Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); if (Kind == Float) - Inst.addOperand(MCOperand::createFPImm(Flt.Val)); + Inst.addOperand( + MCOperand::createSFPImm(bit_cast(float(Flt.Val)))); + else + llvm_unreachable("Should be float immediate!"); + } + + void addFPImmf64Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + if (Kind == Float) + Inst.addOperand(MCOperand::createDFPImm(bit_cast(Flt.Val))); else llvm_unreachable("Should be float immediate!"); } diff --git a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp index 1b7cc093f7ad..f2522562e535 100644 --- a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp +++ b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp @@ -114,7 +114,7 @@ bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef Bytes) { Bytes.data() + Size); Size += sizeof(T); if (std::is_floating_point::value) { - MI.addOperand(MCOperand::createFPImm(static_cast(Val))); + MI.addOperand(MCOperand::createDFPImm(static_cast(Val))); } else { MI.addOperand(MCOperand::createImm(static_cast(Val))); } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp index fb8b0c364f30..ee40b6d2adf7 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp @@ -235,17 +235,10 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, O << '='; } else if (Op.isImm()) { O << Op.getImm(); - } else if (Op.isFPImm()) { - const MCInstrDesc &Desc = MII.get(MI->getOpcode()); - const MCOperandInfo &Info = Desc.OpInfo[OpNo]; - if (Info.OperandType == WebAssembly::OPERAND_F32IMM) { - // TODO: MC converts all floating point immediate operands to double. - // This is fine for numeric values, but may cause NaNs to change bits. - O << ::toString(APFloat(float(Op.getFPImm()))); - } else { - assert(Info.OperandType == WebAssembly::OPERAND_F64IMM); - O << ::toString(APFloat(Op.getFPImm())); - } + } else if (Op.isSFPImm()) { + O << ::toString(APFloat(bit_cast(Op.getSFPImm()))); + } else if (Op.isDFPImm()) { + O << ::toString(APFloat(bit_cast(Op.getDFPImm()))); } else { assert(Op.isExpr() && "unknown operand kind in printOperand"); // call_indirect instructions have a TYPEINDEX operand that we print diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp index 55bf5d14fdac..e53c20203d35 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp @@ -130,19 +130,12 @@ void WebAssemblyMCCodeEmitter::encodeInstruction( encodeULEB128(uint64_t(MO.getImm()), OS); } - } else if (MO.isFPImm()) { - const MCOperandInfo &Info = Desc.OpInfo[I]; - if (Info.OperandType == WebAssembly::OPERAND_F32IMM) { - // TODO: MC converts all floating point immediate operands to double. - // This is fine for numeric values, but may cause NaNs to change bits. - auto F = float(MO.getFPImm()); - support::endian::write(OS, F, support::little); - } else { - assert(Info.OperandType == WebAssembly::OPERAND_F64IMM); - double D = MO.getFPImm(); - support::endian::write(OS, D, support::little); - } - + } else if (MO.isSFPImm()) { + uint32_t F = MO.getSFPImm(); + support::endian::write(OS, F, support::little); + } else if (MO.isDFPImm()) { + uint64_t D = MO.getDFPImm(); + support::endian::write(OS, D, support::little); } else if (MO.isExpr()) { const MCOperandInfo &Info = Desc.OpInfo[I]; llvm::MCFixupKind FixupKind; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index 2f5a64a87a59..a1173ce11647 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -117,13 +117,13 @@ def WebAssemblycatch : SDNode<"WebAssemblyISD::CATCH", SDT_WebAssemblyCatch, // Default Operand has AsmOperandClass "Imm" which is for integers (and // symbols), so specialize one for floats: -def FPImmAsmOperand : AsmOperandClass { - let Name = "FPImm"; +class FPImmAsmOperand : AsmOperandClass { + let Name = "FPImm" # ty; let PredicateMethod = "isFPImm"; } class FPOperand : Operand { - AsmOperandClass ParserMatchClass = FPImmAsmOperand; + AsmOperandClass ParserMatchClass = FPImmAsmOperand; } let OperandNamespace = "WebAssembly" in { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp index 86d59ef807ab..280fbf9d4dbb 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -285,13 +285,13 @@ void WebAssemblyMCInstLower::lower(const MachineInstr *MI, break; } case MachineOperand::MO_FPImmediate: { - // TODO: MC converts all floating point immediate operands to double. - // This is fine for numeric values, but may cause NaNs to change bits. const ConstantFP *Imm = MO.getFPImm(); + const uint64_t BitPattern = + Imm->getValueAPF().bitcastToAPInt().getZExtValue(); if (Imm->getType()->isFloatTy()) - MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToFloat()); + MCOp = MCOperand::createSFPImm(static_cast(BitPattern)); else if (Imm->getType()->isDoubleTy()) - MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToDouble()); + MCOp = MCOperand::createDFPImm(BitPattern); else llvm_unreachable("unknown floating point immediate type"); break; diff --git a/llvm/test/CodeGen/WebAssembly/immediates.ll b/llvm/test/CodeGen/WebAssembly/immediates.ll index b10b32915f23..33d55ab45613 100644 --- a/llvm/test/CodeGen/WebAssembly/immediates.ll +++ b/llvm/test/CodeGen/WebAssembly/immediates.ll @@ -146,12 +146,9 @@ define float @custom_nan_f32() { ret float 0xFFFD79BDE0000000 } -; TODO: LLVM's MC layer stores f32 operands as host doubles, requiring a -; conversion, so the bits of the NaN are not fully preserved. - ; CHECK-LABEL: custom_nans_f32: ; CHECK-NEXT: .functype custom_nans_f32 () -> (f32){{$}} -; CHECK-NEXT: f32.const $push[[NUM:[0-9]+]]=, -nan:0x6bcdef{{$}} +; CHECK-NEXT: f32.const $push[[NUM:[0-9]+]]=, -nan:0x2bcdef{{$}} ; CHECK-NEXT: return $pop[[NUM]]{{$}} define float @custom_nans_f32() { ret float 0xFFF579BDE0000000 diff --git a/llvm/test/CodeGen/WebAssembly/snan_literal.ll b/llvm/test/CodeGen/WebAssembly/snan_literal.ll new file mode 100644 index 000000000000..133f76b7292c --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/snan_literal.ll @@ -0,0 +1,29 @@ +; RUN: llc < %s --filetype=obj | llvm-objdump -d - | FileCheck %s +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +define float @float_sNaN() #0 { +entry: +; CHECK: 00 00 a0 7f + ret float 0x7ff4000000000000 +} + +define float @float_qNaN() #0 { +entry: +; CHECK: 00 00 e0 7f + ret float 0x7ffc000000000000 +} + + +define double @double_sNaN() #0 { +entry: +; CHECK: 00 00 00 00 00 00 f4 7f + ret double 0x7ff4000000000000 +} + +define double @double_qNaN() #0 { +entry: +; CHECK: 00 00 00 00 00 00 fc 7f + ret double 0x7ffc000000000000 +} + diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp index 5f22e2a998fb..819a062e9b6a 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp @@ -134,8 +134,8 @@ private: OS << getRegName(MCOperand.getReg()); } else if (MCOperand.isImm()) { serializeIntegerOperand(OS, MCOperand.getImm()); - } else if (MCOperand.isFPImm()) { - serializeFPOperand(OS, MCOperand.getFPImm()); + } else if (MCOperand.isDFPImm()) { + serializeFPOperand(OS, bit_cast(MCOperand.getDFPImm())); } else { OS << kInvalidOperand; } @@ -148,7 +148,7 @@ private: if (tryDeserializeIntegerOperand(String, IntValue)) return MCOperand::createImm(IntValue); if (tryDeserializeFPOperand(String, DoubleValue)) - return MCOperand::createFPImm(DoubleValue); + return MCOperand::createDFPImm(bit_cast(DoubleValue)); if (auto RegNo = getRegNo(String)) return MCOperand::createReg(*RegNo); if (String != kInvalidOperand) diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp index 674db3fe1598..049cc68b4fb9 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp @@ -374,8 +374,10 @@ void DumpMCOperand(const MCRegisterInfo &MCRegisterInfo, const MCOperand &Op, OS << MCRegisterInfo.getName(Op.getReg()); else if (Op.isImm()) OS << Op.getImm(); - else if (Op.isFPImm()) - OS << Op.getFPImm(); + else if (Op.isDFPImm()) + OS << bit_cast(Op.getDFPImm()); + else if (Op.isSFPImm()) + OS << bit_cast(Op.getSFPImm()); else if (Op.isExpr()) OS << "Expr"; else if (Op.isInst()) diff --git a/llvm/unittests/tools/llvm-exegesis/X86/BenchmarkResultTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/BenchmarkResultTest.cpp index 517d3ac5acb0..ac2002bb0eff 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/BenchmarkResultTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/BenchmarkResultTest.cpp @@ -67,7 +67,7 @@ TEST(BenchmarkResultTest, WriteToAndReadFromDisk) { .addReg(X86::AL) .addReg(X86::AH) .addImm(123) - .addFPImm(0.5)); + .addDFPImm(bit_cast(0.5))); ToDisk.Key.Config = "config"; ToDisk.Key.RegisterInitialValues = { RegisterValue{X86::AL, APInt(8, "-1", 10)},