Skip to content

[WebAssembly] Support single-floating-point immediate value #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions llvm/include/llvm/MC/MCInst.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class MCOperand {
kInvalid, ///< Uninitialized.
kRegister, ///< Register operand.
kImmediate, ///< Immediate operand.
kSFPImmediate, ///< Single-floating-point immediate operand.
kFPImmediate, ///< Floating-point immediate operand.
kExpr, ///< Relocatable immediate operand.
kInst ///< Sub-instruction operand.
Expand All @@ -45,6 +46,7 @@ class MCOperand {
union {
unsigned RegVal;
int64_t ImmVal;
float SFPImmVal;
double FPImmVal;
const MCExpr *ExprVal;
const MCInst *InstVal;
Expand All @@ -56,6 +58,7 @@ class MCOperand {
bool isValid() const { return Kind != kInvalid; }
bool isReg() const { return Kind == kRegister; }
bool isImm() const { return Kind == kImmediate; }
bool isSFPImm() const { return Kind == kSFPImmediate; }
bool isFPImm() const { return Kind == kFPImmediate; }
bool isExpr() const { return Kind == kExpr; }
bool isInst() const { return Kind == kInst; }
Expand All @@ -82,6 +85,16 @@ class MCOperand {
ImmVal = Val;
}

float getSFPImm() const {
assert(isSFPImm() && "This is not an SFP immediate");
return SFPImmVal;
}

void setSFPImm(float Val) {
assert(isSFPImm() && "This is not an SFP immediate");
SFPImmVal = Val;
}

double getFPImm() const {
assert(isFPImm() && "This is not an FP immediate");
return FPImmVal;
Expand Down Expand Up @@ -126,6 +139,13 @@ class MCOperand {
return Op;
}

static MCOperand createSFPImm(float Val) {
MCOperand Op;
Op.Kind = kSFPImmediate;
Op.SFPImmVal = Val;
return Op;
}

static MCOperand createFPImm(double Val) {
MCOperand Op;
Op.Kind = kFPImmediate;
Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/MC/MCInstBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ class MCInstBuilder {
return *this;
}

/// Add a new single floating point immediate operand.
MCInstBuilder &addSFPImm(float Val) {
Inst.addOperand(MCOperand::createSFPImm(Val));
return *this;
}

/// Add a new floating point immediate operand.
MCInstBuilder &addFPImm(double Val) {
Inst.addOperand(MCOperand::createFPImm(Val));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,17 +224,10 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
O << '=';
} else if (Op.isImm()) {
O << Op.getImm();
} else if (Op.isSFPImm()) {
O << ::toString(APFloat(Op.getSFPImm()));
} 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()));
}
O << ::toString(APFloat(Op.getFPImm()));
} else {
assert(Op.isExpr() && "unknown operand kind in printOperand");
// call_indirect instructions have a TYPEINDEX operand that we print
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,12 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
encodeULEB128(uint64_t(MO.getImm()), OS);
}

} else if (MO.isSFPImm()) {
auto F = MO.getSFPImm();
support::endian::write<float>(OS, F, support::little);
} 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<float>(OS, F, support::little);
} else {
assert(Info.OperandType == WebAssembly::OPERAND_F64IMM);
double D = MO.getFPImm();
support::endian::write<double>(OS, D, support::little);
}

double D = MO.getFPImm();
support::endian::write<double>(OS, D, support::little);
} else if (MO.isExpr()) {
const MCOperandInfo &Info = Desc.OpInfo[I];
llvm::MCFixupKind FixupKind;
Expand Down
4 changes: 1 addition & 3 deletions llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,11 +291,9 @@ void WebAssemblyMCInstLower::lower(const MachineInstr *MI,
MCOp = MCOperand::createImm(MO.getImm());
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();
if (Imm->getType()->isFloatTy())
MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToFloat());
MCOp = MCOperand::createSFPImm(Imm->getValueAPF().convertToFloat());
else if (Imm->getType()->isDoubleTy())
MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToDouble());
else
Expand Down
29 changes: 29 additions & 0 deletions llvm/test/CodeGen/WebAssembly/snan_literal.ll
Original file line number Diff line number Diff line change
@@ -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
}