Skip to content

Commit 75e5d07

Browse files
committed
Add x64 codegen support for float extension/truncation
1 parent 2778b7d commit 75e5d07

File tree

5 files changed

+104
-0
lines changed

5 files changed

+104
-0
lines changed

crates/codegen/src/target/x64.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ pub enum X64Instr {
270270
F64ConstAddrAbs(f64),
271271
Cvtsi2s(OperandSize, SseFpuPrecision),
272272
Cvts2si(OperandSize, SseFpuPrecision),
273+
Cvtss2sd,
274+
Cvtsd2ss,
273275
PseudoUint64ToFloat(SseFpuPrecision),
274276
PseudoFloatToUint64Rel(SseFpuPrecision),
275277
PseudoFloatToUint64Abs(SseFpuPrecision),
@@ -332,6 +334,8 @@ impl X64Instr {
332334
X64Instr::F64ConstAddrAbs(..) => false,
333335
X64Instr::Cvtsi2s(..) => false,
334336
X64Instr::Cvts2si(..) => false,
337+
X64Instr::Cvtss2sd => false,
338+
X64Instr::Cvtsd2ss => false,
335339
X64Instr::PseudoUint64ToFloat(..) => false,
336340
X64Instr::PseudoFloatToUint64Rel(..) => false,
337341
X64Instr::PseudoFloatToUint64Abs(..) => false,
@@ -386,6 +390,8 @@ impl X64Instr {
386390
X64Instr::F64ConstAddrAbs(..) => false,
387391
X64Instr::Cvtsi2s(..) => false,
388392
X64Instr::Cvts2si(..) => false,
393+
X64Instr::Cvtss2sd => false,
394+
X64Instr::Cvtsd2ss => false,
389395
X64Instr::PseudoUint64ToFloat(..) => true,
390396
X64Instr::PseudoFloatToUint64Rel(..) => true,
391397
X64Instr::PseudoFloatToUint64Abs(..) => true,

crates/codegen/src/target/x64/emit.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,16 @@ impl MachineEmit for X64Machine {
402402
defs[0].as_reg().unwrap(),
403403
state.operand_reg_mem(uses[0]),
404404
),
405+
X64Instr::Cvtss2sd => emit_cvtss2sd(
406+
buffer,
407+
defs[0].as_reg().unwrap(),
408+
state.operand_reg_mem(uses[0]),
409+
),
410+
X64Instr::Cvtsd2ss => emit_cvtsd2ss(
411+
buffer,
412+
defs[0].as_reg().unwrap(),
413+
state.operand_reg_mem(uses[0]),
414+
),
405415
&X64Instr::PseudoUint64ToFloat(prec) => emit_uint64_to_float(
406416
buffer,
407417
prec,
@@ -1382,6 +1392,14 @@ fn emit_cvts2si(
13821392
emit_sse_fpu_with_mandatory_prefix_and_op_size(buffer, prec, op_size, 0x2d, dest, src);
13831393
}
13841394

1395+
fn emit_cvtss2sd(buffer: &mut CodeBuffer<X64Fixup>, dest: PhysReg, src: RegMem) {
1396+
emit_sse_fpu_with_mandatory_prefix(buffer, SseFpuPrecision::Single, 0x5a, dest, src);
1397+
}
1398+
1399+
fn emit_cvtsd2ss(buffer: &mut CodeBuffer<X64Fixup>, dest: PhysReg, src: RegMem) {
1400+
emit_sse_fpu_with_mandatory_prefix(buffer, SseFpuPrecision::Double, 0x5a, dest, src);
1401+
}
1402+
13851403
fn emit_mov_gprm_xmm(
13861404
buffer: &mut CodeBuffer<X64Fixup>,
13871405
op_size: OperandSize,

crates/codegen/src/target/x64/lower.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ impl MachineLower for X64Machine {
209209
NodeKind::Fsub => emit_fpu_rr(ctx, node, SseFpuBinOp::Sub),
210210
NodeKind::Fmul => emit_fpu_rr(ctx, node, SseFpuBinOp::Mul),
211211
NodeKind::Fdiv => emit_fpu_rr(ctx, node, SseFpuBinOp::Div),
212+
NodeKind::Fext => emit_cvtss2sd(ctx, node),
213+
NodeKind::Ftrunc => emit_cvtsd2ss(ctx, node),
212214
&NodeKind::Fcmp(kind) => select_direct_fcmp(ctx, node, kind),
213215
NodeKind::SintToFloat => emit_cvtsi2s(ctx, node),
214216
NodeKind::UintToFloat => select_uinttofloat(ctx, node),
@@ -1329,6 +1331,34 @@ fn emit_cvts2si(ctx: &mut IselContext<'_, '_, X64Machine>, node: Node) {
13291331
);
13301332
}
13311333

1334+
fn emit_cvtss2sd(ctx: &mut IselContext<'_, '_, X64Machine>, node: Node) {
1335+
let [output] = ctx.node_outputs_exact(node);
1336+
let [input] = ctx.node_inputs_exact(node);
1337+
1338+
let input = ctx.get_value_vreg(input);
1339+
let output = ctx.get_value_vreg(output);
1340+
1341+
ctx.emit_instr(
1342+
X64Instr::Cvtss2sd,
1343+
&[DefOperand::any_reg(output)],
1344+
&[UseOperand::any(input)],
1345+
);
1346+
}
1347+
1348+
fn emit_cvtsd2ss(ctx: &mut IselContext<'_, '_, X64Machine>, node: Node) {
1349+
let [output] = ctx.node_outputs_exact(node);
1350+
let [input] = ctx.node_inputs_exact(node);
1351+
1352+
let input = ctx.get_value_vreg(input);
1353+
let output = ctx.get_value_vreg(output);
1354+
1355+
ctx.emit_instr(
1356+
X64Instr::Cvtsd2ss,
1357+
&[DefOperand::any_reg(output)],
1358+
&[UseOperand::any(input)],
1359+
);
1360+
}
1361+
13321362
// Matching helpers
13331363

13341364
fn match_icmp_imm32(
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# run: codegen
2+
3+
func @fext:f64(f32) {
4+
# check: function `fext`:
5+
# nextln: 000000: 55 push rbp
6+
# nextln: 000001: 48 89 e5 mov rbp, rsp
7+
# nextln: 000004: f3 0f 5a c0 cvtss2sd xmm0, xmm0
8+
# nextln: 000008: 5d pop rbp
9+
# nextln: 000009: c3 ret
10+
11+
%0:ctrl, %1:f32 = entry
12+
%2:f64 = fext %1
13+
return %0, %2
14+
}
15+
16+
func @ftrunc:f32(f64) {
17+
# check: function `ftrunc`:
18+
# nextln: 000000: 55 push rbp
19+
# nextln: 000001: 48 89 e5 mov rbp, rsp
20+
# nextln: 000004: f2 0f 5a c0 cvtsd2ss xmm0, xmm0
21+
# nextln: 000008: 5d pop rbp
22+
# nextln: 000009: c3 ret
23+
24+
%0:ctrl, %1:f64 = entry
25+
%2:f32 = ftrunc %1
26+
return %0, %2
27+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# run: isel
2+
3+
func @fext:f64(f32) {
4+
# check: function `fext`:
5+
# nextln: block0[%1:xmm32($$xmm0)]:
6+
# nextln: 0000: %0:xmm64(reg)[late] = Cvtss2sd %1(any)[early]
7+
# nextln: 0001: Ret %0($$xmm0)[early]
8+
9+
%0:ctrl, %1:f32 = entry
10+
%2:f64 = fext %1
11+
return %0, %2
12+
}
13+
14+
func @ftrunc:f32(f64) {
15+
# check: function `ftrunc`:
16+
# nextln: block0[%1:xmm64($$xmm0)]:
17+
# nextln: 0000: %0:xmm32(reg)[late] = Cvtsd2ss %1(any)[early]
18+
# nextln: 0001: Ret %0($$xmm0)[early]
19+
20+
%0:ctrl, %1:f64 = entry
21+
%2:f32 = ftrunc %1
22+
return %0, %2
23+
}

0 commit comments

Comments
 (0)