Skip to content

Commit cf6d095

Browse files
shumboalexcrichton
authored andcommitted
Fix type confusion in AArch64 amode RegScaled folding
1 parent d06fd9e commit cf6d095

2 files changed

Lines changed: 99 additions & 4 deletions

File tree

cranelift/codegen/src/isa/aarch64/inst.isle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3954,11 +3954,11 @@
39543954
;; Note that this can additionally bundle an extending operation but the
39553955
;; extension must happen before the shift. This will pattern-match the shift
39563956
;; first and then if that succeeds afterwards try to find an extend.
3957-
(rule 6 (amode_no_more_iconst ty (iadd _ x (ishl _ y (iconst _ (u64_from_imm64 n)))) offset)
3958-
(if-let true (u64_eq (ty_bytes ty) (u64_wrapping_shl 1 (shift_masked_imm ty n))))
3957+
(rule 6 (amode_no_more_iconst ty (iadd _ x (ishl shift_ty y (iconst _ (u64_from_imm64 n)))) offset)
3958+
(if-let true (u64_eq (ty_bytes ty) (u64_wrapping_shl 1 (shift_masked_imm shift_ty n))))
39593959
(amode_reg_scaled (amode_add x offset) y))
3960-
(rule 7 (amode_no_more_iconst ty (iadd _ (ishl _ y (iconst _ (u64_from_imm64 n))) x) offset)
3961-
(if-let true (u64_eq (ty_bytes ty) (u64_wrapping_shl 1 (shift_masked_imm ty n))))
3960+
(rule 7 (amode_no_more_iconst ty (iadd _ (ishl shift_ty y (iconst _ (u64_from_imm64 n))) x) offset)
3961+
(if-let true (u64_eq (ty_bytes ty) (u64_wrapping_shl 1 (shift_masked_imm shift_ty n))))
39623962
(amode_reg_scaled (amode_add x offset) y))
39633963

39643964
(decl amode_reg_scaled (Reg Value) AMode)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
test compile precise-output
2+
set unwind_info=false
3+
target aarch64
4+
5+
;; Regression test: shift_masked_imm in amode_no_more_iconst must use the ishl
6+
;; type, not the load access type. When load.i8 has ishl.i64 by 56, the old code
7+
;; computed shift_masked_imm(I8, 56) = 56 & 7 = 0, incorrectly folding the
8+
;; shift into a RegScaled amode with LSL #0. The correct masking is
9+
;; shift_masked_imm(I64, 56) = 56 & 63 = 56, which does not match ty_bytes(I8)
10+
;; and prevents the fold.
11+
12+
function %load_i8_ishl56_should_not_fold(i64, i64) -> i8 {
13+
block0(v0: i64, v1: i64):
14+
v2 = iconst.i64 56
15+
v3 = ishl v1, v2
16+
v4 = iadd v0, v3
17+
v5 = load.i8 v4
18+
return v5
19+
}
20+
21+
; VCode:
22+
; block0:
23+
; lsl x4, x1, #56
24+
; ldrb w0, [x0, x4]
25+
; ret
26+
;
27+
; Disassembled:
28+
; block0: ; offset 0x0
29+
; lsl x4, x1, #0x38
30+
; ldrb w0, [x0, x4] ; trap: heap_oob
31+
; ret
32+
33+
function %load_i16_ishl17_should_not_fold(i64, i64) -> i16 {
34+
block0(v0: i64, v1: i64):
35+
v2 = iconst.i64 17
36+
v3 = ishl v1, v2
37+
v4 = iadd v0, v3
38+
v5 = load.i16 v4
39+
return v5
40+
}
41+
42+
; VCode:
43+
; block0:
44+
; lsl x4, x1, #17
45+
; ldrh w0, [x0, x4]
46+
; ret
47+
;
48+
; Disassembled:
49+
; block0: ; offset 0x0
50+
; lsl x4, x1, #0x11
51+
; ldrh w0, [x0, x4] ; trap: heap_oob
52+
; ret
53+
54+
function %load_i32_ishl34_should_not_fold(i64, i64) -> i32 {
55+
block0(v0: i64, v1: i64):
56+
v2 = iconst.i64 34
57+
v3 = ishl v1, v2
58+
v4 = iadd v0, v3
59+
v5 = load.i32 v4
60+
return v5
61+
}
62+
63+
; VCode:
64+
; block0:
65+
; lsl x4, x1, #34
66+
; ldr w0, [x0, x4]
67+
; ret
68+
;
69+
; Disassembled:
70+
; block0: ; offset 0x0
71+
; lsl x4, x1, #0x22
72+
; ldr w0, [x0, x4] ; trap: heap_oob
73+
; ret
74+
75+
;; Same as the i8 case but with iadd operands swapped
76+
function %load_i8_ishl56_swapped_should_not_fold(i64, i64) -> i8 {
77+
block0(v0: i64, v1: i64):
78+
v2 = iconst.i64 56
79+
v3 = ishl v1, v2
80+
v4 = iadd v3, v0
81+
v5 = load.i8 v4
82+
return v5
83+
}
84+
85+
; VCode:
86+
; block0:
87+
; lsl x4, x1, #56
88+
; ldrb w0, [x4, x0]
89+
; ret
90+
;
91+
; Disassembled:
92+
; block0: ; offset 0x0
93+
; lsl x4, x1, #0x38
94+
; ldrb w0, [x4, x0] ; trap: heap_oob
95+
; ret

0 commit comments

Comments
 (0)