[llvm] r260968 - [WebAssembly] Implement support for custom NaN bit patterns.
Dan Gohman via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 16 07:14:23 PST 2016
Author: djg
Date: Tue Feb 16 09:14:23 2016
New Revision: 260968
URL: http://llvm.org/viewvc/llvm-project?rev=260968&view=rev
Log:
[WebAssembly] Implement support for custom NaN bit patterns.
Modified:
llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
llvm/trunk/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
llvm/trunk/test/CodeGen/WebAssembly/immediates.ll
Modified: llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp?rev=260968&r1=260967&r2=260968&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp Tue Feb 16 09:14:23 2016
@@ -110,7 +110,8 @@ MCDisassembler::DecodeStatus WebAssembly
MI.addOperand(MCOperand::createReg(Reg));
break;
}
- case WebAssembly::OPERAND_FPIMM: {
+ case WebAssembly::OPERAND_FP32IMM:
+ case WebAssembly::OPERAND_FP64IMM: {
// TODO: MC converts all floating point immediate operands to double.
// This is fine for numeric values, but may cause NaNs to change bits.
if (Pos + sizeof(uint64_t) > Bytes.size())
Modified: llvm/trunk/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp?rev=260968&r1=260967&r2=260968&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp Tue Feb 16 09:14:23 2016
@@ -110,14 +110,22 @@ void WebAssemblyInstPrinter::printInst(c
}
static std::string toString(const APFloat &FP) {
+ // Print NaNs with custom payloads specially.
+ if (FP.isNaN() &&
+ !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) &&
+ !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) {
+ APInt AI = FP.bitcastToAPInt();
+ return
+ std::string(AI.isNegative() ? "-" : "") + "nan:0x" +
+ utohexstr(AI.getZExtValue() &
+ (AI.getBitWidth() == 32 ? INT64_C(0x007fffff) :
+ INT64_C(0x000fffffffffffff)),
+ /*LowerCase=*/true);
+ }
+
+ // Use C99's hexadecimal floating-point representation.
static const size_t BufBytes = 128;
char buf[BufBytes];
- if (FP.isNaN())
- assert((FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) ||
- FP.bitwiseIsEqual(
- APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) &&
- "convertToHexString handles neither SNaN nor NaN payloads");
- // Use C99's hexadecimal floating-point representation.
auto Written = FP.convertToHexString(
buf, /*hexDigits=*/0, /*upperCase=*/false, APFloat::rmNearestTiesToEven);
(void)Written;
@@ -157,10 +165,20 @@ void WebAssemblyInstPrinter::printOperan
// control flow stack, and it may be nice to pretty-print.
O << Op.getImm();
} else if (Op.isFPImm()) {
- assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
- MII.get(MI->getOpcode()).TSFlags == 0) &&
+ const MCInstrDesc &Desc = MII.get(MI->getOpcode());
+ assert(OpNo < Desc.getNumOperands() &&
+ "Unexpected floating-point immediate as a non-fixed operand");
+ assert(Desc.TSFlags == 0 &&
"WebAssembly variable_ops floating point ops don't use TSFlags");
- O << toString(APFloat(Op.getFPImm()));
+ const MCOperandInfo &Info = Desc.OpInfo[OpNo];
+ if (Info.OperandType == WebAssembly::OPERAND_FP32IMM) {
+ // 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_FP64IMM);
+ O << toString(APFloat(Op.getFPImm()));
+ }
} else {
assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
(MII.get(MI->getOpcode()).TSFlags &
Modified: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h?rev=260968&r1=260967&r2=260968&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h (original)
+++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h Tue Feb 16 09:14:23 2016
@@ -44,8 +44,10 @@ namespace WebAssembly {
enum OperandType {
/// Basic block label in a branch construct.
OPERAND_BASIC_BLOCK = MCOI::OPERAND_FIRST_TARGET,
- /// Floating-point immediate.
- OPERAND_FPIMM,
+ /// 32-bit floating-point immediates.
+ OPERAND_FP32IMM,
+ /// 64-bit floating-point immediates.
+ OPERAND_FP64IMM,
/// p2align immediate for load and store address alignment.
OPERAND_P2ALIGN
};
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.td?rev=260968&r1=260967&r2=260968&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.td Tue Feb 16 09:14:23 2016
@@ -71,10 +71,11 @@ let OperandNamespace = "WebAssembly" in
let OperandType = "OPERAND_BASIC_BLOCK" in
def bb_op : Operand<OtherVT>;
-let OperandType = "OPERAND_FPIMM" in {
+let OperandType = "OPERAND_FP32IMM" in
def f32imm_op : Operand<f32>;
+
+let OperandType = "OPERAND_FP64IMM" in
def f64imm_op : Operand<f64>;
-} // OperandType = "OPERAND_FPIMM"
let OperandType = "OPERAND_P2ALIGN" in {
def P2Align : Operand<i32> {
Modified: llvm/trunk/test/CodeGen/WebAssembly/immediates.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/immediates.ll?rev=260968&r1=260967&r2=260968&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/immediates.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/immediates.ll Tue Feb 16 09:14:23 2016
@@ -133,6 +133,25 @@ define float @neginf_f32() {
ret float 0xFFF0000000000000
}
+; CHECK-LABEL: custom_nan_f32:
+; CHECK-NEXT: .result f32{{$}}
+; CHECK-NEXT: f32.const $push[[NUM:[0-9]+]]=, -nan:0x6bcdef{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+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: .result f32{{$}}
+; CHECK-NEXT: f32.const $push[[NUM:[0-9]+]]=, -nan:0x6bcdef{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+define float @custom_nans_f32() {
+ ret float 0xFFF579BDE0000000
+}
+
; CHECK-LABEL: negzero_f64:
; CHECK-NEXT: .result f64{{$}}
; CHECK-NEXT: f64.const $push[[NUM:[0-9]+]]=, -0x0p0{{$}}
@@ -196,3 +215,19 @@ define double @inf_f64() {
define double @neginf_f64() {
ret double 0xFFF0000000000000
}
+
+; CHECK-LABEL: custom_nan_f64:
+; CHECK-NEXT: .result f64{{$}}
+; CHECK-NEXT: f64.const $push[[NUM:[0-9]+]]=, -nan:0xabcdef0123456{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+define double @custom_nan_f64() {
+ ret double 0xFFFABCDEF0123456
+}
+
+; CHECK-LABEL: custom_nans_f64:
+; CHECK-NEXT: .result f64{{$}}
+; CHECK-NEXT: f64.const $push[[NUM:[0-9]+]]=, -nan:0x2bcdef0123456{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+define double @custom_nans_f64() {
+ ret double 0xFFF2BCDEF0123456
+}
More information about the llvm-commits
mailing list