Skip to content

Commit 5ec7318

Browse files
authored
riscv64: Use PCRelLo12I relocation on Loads (#6938)
* riscv64: Use `PCRelLo12I` relocation on Loads * riscv64: Strenghten pattern matching when emitting Load's * riscv64: Clarify some of the load address logic * riscv64: Even stronger matching
1 parent df8d369 commit 5ec7318

File tree

14 files changed

+163
-164
lines changed

14 files changed

+163
-164
lines changed

cranelift/codegen/src/isa/riscv64/inst/args.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,18 @@ impl AMode {
161161
}
162162
}
163163

164+
/// Retrieve a MachLabel that corresponds to this addressing mode, if it exists.
165+
pub(crate) fn get_label_with_sink(&self, sink: &mut MachBuffer<Inst>) -> Option<MachLabel> {
166+
match self {
167+
&AMode::Const(addr) => Some(sink.get_label_for_constant(addr)),
168+
&AMode::Label(label) => Some(label),
169+
&AMode::RegOffset(..)
170+
| &AMode::SPOffset(..)
171+
| &AMode::FPOffset(..)
172+
| &AMode::NominalSPOffset(..) => None,
173+
}
174+
}
175+
164176
pub(crate) fn to_string_with_alloc(&self, allocs: &mut AllocationConsumer<'_>) -> String {
165177
format!("{}", self.clone().with_allocs(allocs))
166178
}

cranelift/codegen/src/isa/riscv64/inst/emit.rs

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -620,18 +620,49 @@ impl MachInstEmit for Inst {
620620
let base = from.get_base_register();
621621
let offset = from.get_offset_with_state(state);
622622
let offset_imm12 = Imm12::maybe_from_i64(offset);
623+
let label = from.get_label_with_sink(sink);
623624

624-
// TODO: We shouldn't just fall back to `LoadAddr` immediately. For `MachLabel`s
625-
// we should try to emit the `auipc` and add a relocation on this load.
626-
let (addr, imm12) = match (base, offset_imm12) {
627-
// If the offset fits into an imm12 we can directly encode it.
628-
(Some(base), Some(imm12)) => (base, imm12),
629-
// Otherwise load the address it into a reg and load from it.
630-
_ => {
625+
let (addr, imm12) = match (base, offset_imm12, label) {
626+
// When loading from a Reg+Offset, if the offset fits into an imm12 we can directly encode it.
627+
(Some(base), Some(imm12), None) => (base, imm12),
628+
629+
// Otherwise, if the offset does not fit into a imm12, we need to materialize it into a
630+
// register and load from that.
631+
(Some(_), None, None) => {
631632
let tmp = writable_spilltmp_reg();
632633
Inst::LoadAddr { rd: tmp, mem: from }.emit(&[], sink, emit_info, state);
633634
(tmp.to_reg(), Imm12::zero())
634635
}
636+
637+
// If the AMode contains a label we can emit an internal relocation that gets
638+
// resolved with the correct address later.
639+
(None, Some(imm), Some(label)) => {
640+
debug_assert_eq!(imm.as_i16(), 0);
641+
642+
// Get the current PC.
643+
sink.use_label_at_offset(sink.cur_offset(), label, LabelUse::PCRelHi20);
644+
Inst::Auipc {
645+
rd,
646+
imm: Imm20::from_bits(0),
647+
}
648+
.emit(&[], sink, emit_info, state);
649+
650+
// Emit a relocation for the load. This patches the offset into the instruction.
651+
sink.use_label_at_offset(sink.cur_offset(), label, LabelUse::PCRelLo12I);
652+
653+
// Imm12 here is meaningless since it's going to get replaced.
654+
(rd.to_reg(), Imm12::zero())
655+
}
656+
657+
// These cases are impossible with the current AModes that we have. We either
658+
// always have a register, or always have a label. Never both, and never neither.
659+
(None, None, None)
660+
| (None, Some(_), None)
661+
| (Some(_), None, Some(_))
662+
| (Some(_), Some(_), Some(_))
663+
| (None, None, Some(_)) => {
664+
unreachable!("Invalid load address")
665+
}
635666
};
636667

637668
let srcloc = state.cur_srcloc();
@@ -650,8 +681,6 @@ impl MachInstEmit for Inst {
650681
let offset = to.get_offset_with_state(state);
651682
let offset_imm12 = Imm12::maybe_from_i64(offset);
652683

653-
// TODO: We shouldn't just fall back to `LoadAddr` immediately. For `MachLabel`s
654-
// we should try to emit the `auipc` and add a relocation on this store.
655684
let (addr, imm12) = match (base, offset_imm12) {
656685
// If the offset fits into an imm12 we can directly encode it.
657686
(Some(base), Some(imm12)) => (base, imm12),

cranelift/filetests/filetests/isa/riscv64/constants.clif

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ block0:
8181
;
8282
; Disassembled:
8383
; block0: ; offset 0x0
84-
; auipc t6, 0
85-
; addi t6, t6, 0x10
86-
; ld a0, 0(t6)
84+
; auipc a0, 0
85+
; ld a0, 0x10(a0)
8786
; ret
87+
; .byte 0x00, 0x00, 0x00, 0x00
8888
; .byte 0x00, 0x00, 0xff, 0xff
8989
; .byte 0x00, 0x00, 0x00, 0x00
9090

@@ -101,11 +101,11 @@ block0:
101101
;
102102
; Disassembled:
103103
; block0: ; offset 0x0
104-
; auipc t6, 0
105-
; addi t6, t6, 0x10
106-
; ld a0, 0(t6)
104+
; auipc a0, 0
105+
; ld a0, 0x10(a0)
107106
; ret
108107
; .byte 0x00, 0x00, 0x00, 0x00
108+
; .byte 0x00, 0x00, 0x00, 0x00
109109
; .byte 0xff, 0xff, 0x00, 0x00
110110

111111
function %f() -> i64 {
@@ -121,11 +121,11 @@ block0:
121121
;
122122
; Disassembled:
123123
; block0: ; offset 0x0
124-
; auipc t6, 0
125-
; addi t6, t6, 0x10
126-
; ld a0, 0(t6)
124+
; auipc a0, 0
125+
; ld a0, 0x10(a0)
127126
; ret
128127
; .byte 0x00, 0x00, 0x00, 0x00
128+
; .byte 0x00, 0x00, 0x00, 0x00
129129
; .byte 0x00, 0x00, 0xff, 0xff
130130

131131
function %f() -> i64 {
@@ -173,10 +173,10 @@ block0:
173173
;
174174
; Disassembled:
175175
; block0: ; offset 0x0
176-
; auipc t6, 0
177-
; addi t6, t6, 0x10
178-
; ld a0, 0(t6)
176+
; auipc a0, 0
177+
; ld a0, 0x10(a0)
179178
; ret
179+
; .byte 0x00, 0x00, 0x00, 0x00
180180
; .byte 0xff, 0xff, 0x00, 0x00
181181
; .byte 0xff, 0xff, 0xff, 0xff
182182

@@ -193,10 +193,10 @@ block0:
193193
;
194194
; Disassembled:
195195
; block0: ; offset 0x0
196-
; auipc t6, 0
197-
; addi t6, t6, 0x10
198-
; ld a0, 0(t6)
196+
; auipc a0, 0
197+
; ld a0, 0x10(a0)
199198
; ret
199+
; .byte 0x00, 0x00, 0x00, 0x00
200200
; .byte 0xff, 0xff, 0xff, 0xff
201201
; .byte 0x00, 0x00, 0xff, 0xff
202202

@@ -213,10 +213,10 @@ block0:
213213
;
214214
; Disassembled:
215215
; block0: ; offset 0x0
216-
; auipc t6, 0
217-
; addi t6, t6, 0x10
218-
; ld a0, 0(t6)
216+
; auipc a0, 0
217+
; ld a0, 0x10(a0)
219218
; ret
219+
; .byte 0x00, 0x00, 0x00, 0x00
220220
; .byte 0xff, 0xff, 0xff, 0xff
221221
; .byte 0xff, 0xff, 0x00, 0x00
222222

@@ -233,10 +233,10 @@ block0:
233233
;
234234
; Disassembled:
235235
; block0: ; offset 0x0
236-
; auipc t6, 0
237-
; addi t6, t6, 0x10
238-
; ld a0, 0(t6)
236+
; auipc a0, 0
237+
; ld a0, 0x10(a0)
239238
; ret
239+
; .byte 0x00, 0x00, 0x00, 0x00
240240
; .byte 0x3a, 0x00, 0x12, 0x12
241241
; .byte 0xa3, 0xf0, 0x4b, 0xf3
242242

@@ -253,10 +253,10 @@ block0:
253253
;
254254
; Disassembled:
255255
; block0: ; offset 0x0
256-
; auipc t6, 0
257-
; addi t6, t6, 0x10
258-
; ld a0, 0(t6)
256+
; auipc a0, 0
257+
; ld a0, 0x10(a0)
259258
; ret
259+
; .byte 0x00, 0x00, 0x00, 0x00
260260
; .byte 0x00, 0x00, 0xf4, 0x1e
261261
; .byte 0x00, 0x00, 0xe9, 0x12
262262

@@ -273,10 +273,10 @@ block0:
273273
;
274274
; Disassembled:
275275
; block0: ; offset 0x0
276-
; auipc t6, 0
277-
; addi t6, t6, 0x10
278-
; ld a0, 0(t6)
276+
; auipc a0, 0
277+
; ld a0, 0x10(a0)
279278
; ret
279+
; .byte 0x00, 0x00, 0x00, 0x00
280280
; .byte 0xff, 0xff, 0xf4, 0x1e
281281
; .byte 0xff, 0xff, 0xe9, 0x12
282282

@@ -325,10 +325,10 @@ block0:
325325
;
326326
; Disassembled:
327327
; block0: ; offset 0x0
328-
; auipc t6, 0
329-
; addi t6, t6, 0x10
330-
; ld a0, 0(t6)
328+
; auipc a0, 0
329+
; ld a0, 0x10(a0)
331330
; ret
331+
; .byte 0x00, 0x00, 0x00, 0x00
332332
; .byte 0xf7, 0xff, 0xff, 0xff
333333
; .byte 0x00, 0x00, 0x00, 0x00
334334

@@ -362,13 +362,11 @@ block0:
362362
;
363363
; Disassembled:
364364
; block0: ; offset 0x0
365-
; auipc t6, 0
366-
; addi t6, t6, 0x18
367-
; ld t0, 0(t6)
365+
; auipc t0, 0
366+
; ld t0, 0x10(t0)
368367
; fmv.d.x fa0, t0
369368
; ret
370369
; .byte 0x00, 0x00, 0x00, 0x00
371-
; .byte 0x00, 0x00, 0x00, 0x00
372370
; .byte 0x00, 0x00, 0xf0, 0x3f
373371

374372
function %f() -> f32 {
@@ -403,13 +401,11 @@ block0:
403401
;
404402
; Disassembled:
405403
; block0: ; offset 0x0
406-
; auipc t6, 0
407-
; addi t6, t6, 0x18
408-
; ld t0, 0(t6)
404+
; auipc t0, 0
405+
; ld t0, 0x10(t0)
409406
; fmv.d.x fa0, t0
410407
; ret
411408
; .byte 0x00, 0x00, 0x00, 0x00
412-
; .byte 0x00, 0x00, 0x00, 0x00
413409
; .byte 0x00, 0x00, 0x49, 0x40
414410

415411
function %f() -> f32 {
@@ -480,13 +476,11 @@ block0:
480476
;
481477
; Disassembled:
482478
; block0: ; offset 0x0
483-
; auipc t6, 0
484-
; addi t6, t6, 0x18
485-
; ld t0, 0(t6)
479+
; auipc t0, 0
480+
; ld t0, 0x10(t0)
486481
; fmv.d.x fa0, t0
487482
; ret
488483
; .byte 0x00, 0x00, 0x00, 0x00
489-
; .byte 0x00, 0x00, 0x00, 0x00
490484
; .byte 0x00, 0x00, 0x30, 0xc0
491485

492486
function %f() -> f32 {

cranelift/filetests/filetests/isa/riscv64/fcvt-small.clif

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,9 @@ block0(v0: f32):
9292
; Disassembled:
9393
; block0: ; offset 0x0
9494
; feq.s a0, fa0, fa0
95-
; beqz a0, 0x44
95+
; beqz a0, 0x40
9696
; auipc t6, 0
97-
; addi t6, t6, 0x10
98-
; lw t6, 0(t6)
97+
; lw t6, 0xc(t6)
9998
; j 8
10099
; .byte 0x00, 0x00, 0x80, 0xbf
101100
; fmv.w.x ft3, t6
@@ -126,10 +125,9 @@ block0(v0: f64):
126125
; Disassembled:
127126
; block0: ; offset 0x0
128127
; feq.d a0, fa0, fa0
129-
; beqz a0, 0x5c
128+
; beqz a0, 0x54
130129
; auipc t6, 0
131-
; addi t6, t6, 0x10
132-
; ld t6, 0(t6)
130+
; ld t6, 0xc(t6)
133131
; j 0xc
134132
; .byte 0x00, 0x00, 0x00, 0x00
135133
; .byte 0x00, 0x00, 0xf0, 0xbf
@@ -138,8 +136,7 @@ block0(v0: f64):
138136
; beqz a0, 8
139137
; .byte 0x00, 0x00, 0x00, 0x00 ; trap: int_ovf
140138
; auipc t6, 0
141-
; addi t6, t6, 0x10
142-
; ld t6, 0(t6)
139+
; ld t6, 0xc(t6)
143140
; j 0xc
144141
; .byte 0x00, 0x00, 0x00, 0x00
145142
; .byte 0x00, 0x00, 0x70, 0x40
@@ -166,10 +163,9 @@ block0(v0: f32):
166163
; Disassembled:
167164
; block0: ; offset 0x0
168165
; feq.s a0, fa0, fa0
169-
; beqz a0, 0x44
166+
; beqz a0, 0x40
170167
; auipc t6, 0
171-
; addi t6, t6, 0x10
172-
; lw t6, 0(t6)
168+
; lw t6, 0xc(t6)
173169
; j 8
174170
; .byte 0x00, 0x00, 0x80, 0xbf
175171
; fmv.w.x ft3, t6
@@ -200,10 +196,9 @@ block0(v0: f64):
200196
; Disassembled:
201197
; block0: ; offset 0x0
202198
; feq.d a0, fa0, fa0
203-
; beqz a0, 0x5c
199+
; beqz a0, 0x54
204200
; auipc t6, 0
205-
; addi t6, t6, 0x10
206-
; ld t6, 0(t6)
201+
; ld t6, 0xc(t6)
207202
; j 0xc
208203
; .byte 0x00, 0x00, 0x00, 0x00
209204
; .byte 0x00, 0x00, 0xf0, 0xbf
@@ -212,8 +207,7 @@ block0(v0: f64):
212207
; beqz a0, 8
213208
; .byte 0x00, 0x00, 0x00, 0x00 ; trap: int_ovf
214209
; auipc t6, 0
215-
; addi t6, t6, 0x10
216-
; ld t6, 0(t6)
210+
; ld t6, 0xc(t6)
217211
; j 0xc
218212
; .byte 0x00, 0x00, 0x00, 0x00
219213
; .byte 0x00, 0x00, 0xf0, 0x40

0 commit comments

Comments
 (0)