Skip to content

Commit 859eede

Browse files
committed
Add x64 codegen support for large-code-model float constants
These use an absolute relocation to access the constant pool rather than a PC32 relocation.
1 parent 82bd336 commit 859eede

File tree

5 files changed

+111
-15
lines changed

5 files changed

+111
-15
lines changed

crates/codegen/src/target/x64.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ pub enum X64Instr {
249249
Ucomi(SseFpuPrecision),
250250
SseMovRZ,
251251
MovsdConstRel(f64),
252+
F64ConstAddrAbs(f64),
252253
MovGprmXmm(OperandSize),
253254
/// Load from [rbp + offset]
254255
MovRRbp {
@@ -299,6 +300,7 @@ impl X64Instr {
299300
X64Instr::Ucomi(..) => false,
300301
X64Instr::SseMovRZ => false,
301302
X64Instr::MovsdConstRel(..) => false,
303+
X64Instr::F64ConstAddrAbs(..) => false,
302304
X64Instr::MovGprmXmm(..) => false,
303305
X64Instr::MovRRbp { .. } => false,
304306
X64Instr::MovsRRbp { .. } => false,
@@ -341,6 +343,7 @@ impl X64Instr {
341343
X64Instr::Ucomi(..) => true,
342344
X64Instr::SseMovRZ => false,
343345
X64Instr::MovsdConstRel(..) => false,
346+
X64Instr::F64ConstAddrAbs(..) => false,
344347
X64Instr::MovGprmXmm(..) => false,
345348
X64Instr::Setcc(..) => false,
346349
X64Instr::MovRRbp { .. } => false,

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

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,11 @@ impl MachineEmit for X64Machine {
296296
BufferRelocTarget::Constant(src),
297297
);
298298
}
299+
&X64Instr::F64ConstAddrAbs(val) => {
300+
let dest = defs[0].as_reg().unwrap();
301+
let src = buffer.get_constant(8, &val.to_le_bytes());
302+
emit_movabs_r_i_reloc(buffer, dest, BufferRelocTarget::Constant(src));
303+
}
299304
&X64Instr::MovGprmXmm(op_size) => emit_mov_gprm_xmm(
300305
buffer,
301306
op_size,
@@ -368,7 +373,11 @@ impl MachineEmit for X64Machine {
368373
emit_lea_rip_reloc(buffer, defs[0].as_reg().unwrap(), target);
369374
}
370375
&X64Instr::FuncAddrAbs(target) => {
371-
emit_movabs_r_i_reloc(buffer, defs[0].as_reg().unwrap(), target);
376+
emit_movabs_r_i_reloc(
377+
buffer,
378+
defs[0].as_reg().unwrap(),
379+
BufferRelocTarget::Function(target),
380+
);
372381
}
373382
&X64Instr::CallRel(target) => {
374383
emit_call_rel(buffer, target);
@@ -587,13 +596,14 @@ fn emit_movabs_r_i(buffer: &mut CodeBuffer<X64Fixup>, dest: PhysReg, imm: u64) {
587596
});
588597
}
589598

590-
fn emit_movabs_r_i_reloc(buffer: &mut CodeBuffer<X64Fixup>, dest: PhysReg, target: FunctionRef) {
591-
buffer.instr_with_reloc(
592-
BufferRelocTarget::Function(target),
593-
0,
594-
RELOC_ABS64,
595-
|sink| emit_movabs_r_i_instr(sink, dest, 0),
596-
);
599+
fn emit_movabs_r_i_reloc(
600+
buffer: &mut CodeBuffer<X64Fixup>,
601+
dest: PhysReg,
602+
target: BufferRelocTarget,
603+
) {
604+
buffer.instr_with_reloc(target, 0, RELOC_ABS64, |sink| {
605+
emit_movabs_r_i_instr(sink, dest, 0)
606+
});
597607
}
598608

599609
fn emit_movabs_r_i_instr(sink: &mut InstrSink<'_>, dest: PhysReg, imm: u64) -> InstrAnchor {

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

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ impl MachineLower for X64Machine {
194194
// `setcc` output register.
195195
emit_setcc_sequence(ctx, output, |ctx| select_icmp(ctx, node, kind));
196196
}
197-
&NodeKind::Fconst64(val) => select_fconst64(ctx, node, val),
197+
&NodeKind::Fconst64(val) => select_fconst64(self, ctx, node, val),
198198
NodeKind::Fadd => emit_fpu_rr(ctx, node, SseFpuBinOp::Add),
199199
NodeKind::Fsub => emit_fpu_rr(ctx, node, SseFpuBinOp::Sub),
200200
NodeKind::Fmul => emit_fpu_rr(ctx, node, SseFpuBinOp::Mul),
@@ -405,18 +405,47 @@ fn select_icmp(ctx: &mut IselContext<'_, '_, X64Machine>, node: Node, kind: Icmp
405405
cond_code_for_icmp(kind)
406406
}
407407

408-
fn select_fconst64(ctx: &mut IselContext<'_, '_, X64Machine>, node: Node, val: BitwiseF64) {
408+
fn select_fconst64(
409+
machine: &X64Machine,
410+
ctx: &mut IselContext<'_, '_, X64Machine>,
411+
node: Node,
412+
val: BitwiseF64,
413+
) {
409414
let [output] = ctx.node_outputs_exact(node);
410415
let output = ctx.get_value_vreg(output);
411416

412417
if val.bits() == 0 {
413418
ctx.emit_instr(X64Instr::SseMovRZ, &[DefOperand::any_reg(output)], &[]);
414419
} else {
415-
ctx.emit_instr(
416-
X64Instr::MovsdConstRel(val.0),
417-
&[DefOperand::any_reg(output)],
418-
&[],
419-
);
420+
match machine.config.internal_code_model {
421+
CodeModel::SmallPic => {
422+
ctx.emit_instr(
423+
X64Instr::MovsdConstRel(val.0),
424+
&[DefOperand::any_reg(output)],
425+
&[],
426+
);
427+
}
428+
CodeModel::LargeAbs => {
429+
let addr = ctx.create_temp_vreg(RC_GPR);
430+
ctx.emit_instr(
431+
X64Instr::F64ConstAddrAbs(val.0),
432+
&[DefOperand::any_reg(addr)],
433+
&[],
434+
);
435+
ctx.emit_instr(
436+
X64Instr::MovsRM(
437+
SseFpuPrecision::Double,
438+
AddrMode {
439+
base: Some(AddrBase::Reg),
440+
index: None,
441+
offset: 0,
442+
},
443+
),
444+
&[DefOperand::any_reg(output)],
445+
&[UseOperand::any_reg(addr)],
446+
);
447+
}
448+
}
420449
}
421450
}
422451

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# run: codegen[large-abs]
2+
3+
func @zero64:f64() {
4+
# check: function `zero64`:
5+
# nextln: 000000: 55 push rbp
6+
# nextln: 000001: 48 89 e5 mov rbp, rsp
7+
# nextln: 000004: 0f 57 c0 xorps xmm0, xmm0
8+
# nextln: 000007: 5d pop rbp
9+
# nextln: 000008: c3 ret
10+
11+
%c:ctrl = entry
12+
%0:f64 = fconst64 0x0
13+
return %c, %0
14+
}
15+
16+
func @five64:f64() {
17+
# check: function `five64`:
18+
# nextln: 000000: 55 push rbp
19+
# nextln: 000001: 48 89 e5 mov rbp, rsp
20+
# nextln: 000004: 48 b8 00 00 00 00 00 00 00 00 movabs rax, 0 # RELOC_ABS64 -> @<CP> + 0
21+
# nextln: 00000e: f2 0f 10 00 movsd xmm0, qword ptr [rax]
22+
# nextln: 000012: 5d pop rbp
23+
# nextln: 000013: c3 ret
24+
# nextln: <CP>:
25+
# nextln: 000000: 00 00 00 00 00 00 14 40
26+
27+
%c:ctrl = entry
28+
%0:f64 = fconst64 0x5
29+
return %c, %0
30+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# run: isel[large-abs]
2+
3+
func @zero64:f64() {
4+
# check: function `zero64`:
5+
# nextln: block0[]:
6+
# nextln: 0000: %0:xmm(reg)[late] = SseMovRZ
7+
# nextln: 0001: Ret %0($$xmm0)[early]
8+
9+
%c:ctrl = entry
10+
%0:f64 = fconst64 0x0
11+
return %c, %0
12+
}
13+
14+
func @five64:f64() {
15+
# check: function `five64`:
16+
# nextln: block0[]:
17+
# nextln: 0000: %1:gpr(reg)[late] = F64ConstAddrAbs(5.0)
18+
# nextln: 0001: %0:xmm(reg)[late] = MovsRM(Double, [reg + 0]) %1(reg)[early]
19+
# nextln: 0002: Ret %0($$xmm0)[early]
20+
21+
%c:ctrl = entry
22+
%0:f64 = fconst64 0x5
23+
return %c, %0
24+
}

0 commit comments

Comments
 (0)