Skip to content

Commit bae1529

Browse files
[WebAssembly] Support single-floating-point literal
As mentioned in TODO comment, casting double to float causes NaNs to change bits. To avoid the change, this patch adds a support for single float floating point literal value.
1 parent 933a544 commit bae1529

File tree

6 files changed

+64
-25
lines changed

6 files changed

+64
-25
lines changed

llvm/include/llvm/MC/MCInst.h

+20
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class MCOperand {
3636
kInvalid, ///< Uninitialized.
3737
kRegister, ///< Register operand.
3838
kImmediate, ///< Immediate operand.
39+
kSFPImmediate, ///< Single-floating-point immediate operand.
3940
kFPImmediate, ///< Floating-point immediate operand.
4041
kExpr, ///< Relocatable immediate operand.
4142
kInst ///< Sub-instruction operand.
@@ -45,6 +46,7 @@ class MCOperand {
4546
union {
4647
unsigned RegVal;
4748
int64_t ImmVal;
49+
float SFPImmVal;
4850
double FPImmVal;
4951
const MCExpr *ExprVal;
5052
const MCInst *InstVal;
@@ -56,6 +58,7 @@ class MCOperand {
5658
bool isValid() const { return Kind != kInvalid; }
5759
bool isReg() const { return Kind == kRegister; }
5860
bool isImm() const { return Kind == kImmediate; }
61+
bool isSFPImm() const { return Kind == kSFPImmediate; }
5962
bool isFPImm() const { return Kind == kFPImmediate; }
6063
bool isExpr() const { return Kind == kExpr; }
6164
bool isInst() const { return Kind == kInst; }
@@ -82,6 +85,16 @@ class MCOperand {
8285
ImmVal = Val;
8386
}
8487

88+
float getSFPImm() const {
89+
assert(isSFPImm() && "This is not an SFP immediate");
90+
return SFPImmVal;
91+
}
92+
93+
void setSFPImm(float Val) {
94+
assert(isSFPImm() && "This is not an SFP immediate");
95+
SFPImmVal = Val;
96+
}
97+
8598
double getFPImm() const {
8699
assert(isFPImm() && "This is not an FP immediate");
87100
return FPImmVal;
@@ -126,6 +139,13 @@ class MCOperand {
126139
return Op;
127140
}
128141

142+
static MCOperand createSFPImm(float Val) {
143+
MCOperand Op;
144+
Op.Kind = kSFPImmediate;
145+
Op.SFPImmVal = Val;
146+
return Op;
147+
}
148+
129149
static MCOperand createFPImm(double Val) {
130150
MCOperand Op;
131151
Op.Kind = kFPImmediate;

llvm/include/llvm/MC/MCInstBuilder.h

+6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ class MCInstBuilder {
3939
return *this;
4040
}
4141

42+
/// Add a new single floating point immediate operand.
43+
MCInstBuilder &addSFPImm(float Val) {
44+
Inst.addOperand(MCOperand::createSFPImm(Val));
45+
return *this;
46+
}
47+
4248
/// Add a new floating point immediate operand.
4349
MCInstBuilder &addFPImm(double Val) {
4450
Inst.addOperand(MCOperand::createFPImm(Val));

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp

+3-10
Original file line numberDiff line numberDiff line change
@@ -224,17 +224,10 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
224224
O << '=';
225225
} else if (Op.isImm()) {
226226
O << Op.getImm();
227+
} else if (Op.isSFPImm()) {
228+
O << ::toString(APFloat(Op.getSFPImm()));
227229
} else if (Op.isFPImm()) {
228-
const MCInstrDesc &Desc = MII.get(MI->getOpcode());
229-
const MCOperandInfo &Info = Desc.OpInfo[OpNo];
230-
if (Info.OperandType == WebAssembly::OPERAND_F32IMM) {
231-
// TODO: MC converts all floating point immediate operands to double.
232-
// This is fine for numeric values, but may cause NaNs to change bits.
233-
O << ::toString(APFloat(float(Op.getFPImm())));
234-
} else {
235-
assert(Info.OperandType == WebAssembly::OPERAND_F64IMM);
236-
O << ::toString(APFloat(Op.getFPImm()));
237-
}
230+
O << ::toString(APFloat(Op.getFPImm()));
238231
} else {
239232
assert(Op.isExpr() && "unknown operand kind in printOperand");
240233
// call_indirect instructions have a TYPEINDEX operand that we print

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp

+5-12
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,12 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
125125
encodeULEB128(uint64_t(MO.getImm()), OS);
126126
}
127127

128+
} else if (MO.isSFPImm()) {
129+
auto F = MO.getSFPImm();
130+
support::endian::write<float>(OS, F, support::little);
128131
} else if (MO.isFPImm()) {
129-
const MCOperandInfo &Info = Desc.OpInfo[I];
130-
if (Info.OperandType == WebAssembly::OPERAND_F32IMM) {
131-
// TODO: MC converts all floating point immediate operands to double.
132-
// This is fine for numeric values, but may cause NaNs to change bits.
133-
auto F = float(MO.getFPImm());
134-
support::endian::write<float>(OS, F, support::little);
135-
} else {
136-
assert(Info.OperandType == WebAssembly::OPERAND_F64IMM);
137-
double D = MO.getFPImm();
138-
support::endian::write<double>(OS, D, support::little);
139-
}
140-
132+
double D = MO.getFPImm();
133+
support::endian::write<double>(OS, D, support::little);
141134
} else if (MO.isExpr()) {
142135
const MCOperandInfo &Info = Desc.OpInfo[I];
143136
llvm::MCFixupKind FixupKind;

llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -291,11 +291,9 @@ void WebAssemblyMCInstLower::lower(const MachineInstr *MI,
291291
MCOp = MCOperand::createImm(MO.getImm());
292292
break;
293293
case MachineOperand::MO_FPImmediate: {
294-
// TODO: MC converts all floating point immediate operands to double.
295-
// This is fine for numeric values, but may cause NaNs to change bits.
296294
const ConstantFP *Imm = MO.getFPImm();
297295
if (Imm->getType()->isFloatTy())
298-
MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToFloat());
296+
MCOp = MCOperand::createSFPImm(Imm->getValueAPF().convertToFloat());
299297
else if (Imm->getType()->isDoubleTy())
300298
MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToDouble());
301299
else
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
; RUN: llc < %s --filetype=obj | llvm-objdump -d - | FileCheck %s
2+
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
3+
target triple = "wasm32-unknown-unknown"
4+
5+
define float @float_sNaN() #0 {
6+
entry:
7+
; CHECK: 00 00 a0 7f
8+
ret float 0x7ff4000000000000
9+
}
10+
11+
define float @float_qNaN() #0 {
12+
entry:
13+
; CHECK: 00 00 e0 7f
14+
ret float 0x7ffc000000000000
15+
}
16+
17+
18+
define double @double_sNaN() #0 {
19+
entry:
20+
; CHECK: 00 00 00 00 00 00 f4 7f
21+
ret double 0x7ff4000000000000
22+
}
23+
24+
define double @double_qNaN() #0 {
25+
entry:
26+
; CHECK: 00 00 00 00 00 00 fc 7f
27+
ret double 0x7ffc000000000000
28+
}
29+

0 commit comments

Comments
 (0)