Skip to content

Commit 2ba4bce

Browse files
authored
Merge pull request from GHSA-7f6x-jwh5-m9r4
Copyright (c) 2022, Arm Limited.
1 parent 2154c63 commit 2ba4bce

File tree

6 files changed

+170
-56
lines changed

6 files changed

+170
-56
lines changed

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

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,12 +1325,6 @@
13251325

13261326
;; Extractor helpers for various immmediate constants ;;;;;;;;;;;;;;;;;;;;;;;;;;
13271327

1328-
(decl move_wide_const_from_u64 (MoveWideConst) u64)
1329-
(extern extractor move_wide_const_from_u64 move_wide_const_from_u64)
1330-
1331-
(decl move_wide_const_from_negated_u64 (MoveWideConst) u64)
1332-
(extern extractor move_wide_const_from_negated_u64 move_wide_const_from_negated_u64)
1333-
13341328
(decl pure imm_logic_from_u64 (Type u64) ImmLogic)
13351329
(extern constructor imm_logic_from_u64 imm_logic_from_u64)
13361330

@@ -2025,27 +2019,36 @@
20252019

20262020
;; Immediate value helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20272021

2028-
(decl imm (Type u64) Reg)
2029-
2030-
;; 16-bit immediate (shifted by 0, 16, 32 or 48 bits) in MOVZ
2031-
(rule (imm (integral_ty _ty) (move_wide_const_from_u64 n))
2032-
(movz n (OperandSize.Size64)))
2033-
2034-
;; 16-bit immediate (shifted by 0, 16, 32 or 48 bits) in MOVN
2035-
(rule (imm (integral_ty _ty) (move_wide_const_from_negated_u64 n))
2036-
(movn n (OperandSize.Size64)))
2037-
2038-
;; Weird logical-instruction immediate in ORI using zero register
2039-
(rule (imm (integral_ty _ty) k)
2040-
(if-let n (imm_logic_from_u64 $I64 k))
2041-
(orr_imm $I64 (zero_reg) n))
2042-
2043-
(decl load_constant64_full (u64) Reg)
2022+
;; Type of extension performed by an immediate helper
2023+
(type ImmExtend
2024+
(enum
2025+
(Sign)
2026+
(Zero)))
2027+
2028+
;; Arguments:
2029+
;; * Immediate type
2030+
;; * Way to extend the immediate value to the full width of the destination
2031+
;; register
2032+
;; * Immediate value - only the bits that fit within the type are used and
2033+
;; extended, while the rest are ignored
2034+
;;
2035+
;; Note that, unlike the convention in the AArch64 backend, this helper leaves
2036+
;; all bits in the destination register in a defined state, i.e. smaller types
2037+
;; such as `I8` are either sign- or zero-extended.
2038+
(decl imm (Type ImmExtend u64) Reg)
2039+
2040+
;; Weird logical-instruction immediate in ORI using zero register; to simplify,
2041+
;; we only match when we are zero-extending the value.
2042+
(rule (imm (integral_ty ty) (ImmExtend.Zero) k)
2043+
(if-let n (imm_logic_from_u64 ty k))
2044+
(orr_imm ty (zero_reg) n))
2045+
2046+
(decl load_constant64_full (Type ImmExtend u64) Reg)
20442047
(extern constructor load_constant64_full load_constant64_full)
20452048

2046-
;; Fallback for integral 64-bit constants that uses lots of `movk`
2047-
(rule (imm (integral_ty _ty) n)
2048-
(load_constant64_full n))
2049+
;; Fallback for integral 64-bit constants
2050+
(rule (imm (integral_ty ty) extend n)
2051+
(load_constant64_full ty extend n))
20492052

20502053
;; Sign extension helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20512054

cranelift/codegen/src/isa/aarch64/inst/imms.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,10 @@ impl MoveWideConst {
618618
})
619619
}
620620
}
621+
622+
pub fn zero() -> MoveWideConst {
623+
MoveWideConst { bits: 0, shift: 0 }
624+
}
621625
}
622626

623627
/// Advanced SIMD modified immediate as used by MOVI/MVNI.

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@
77
;;;; Rules for `iconst` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
88

99
(rule (lower (has_type ty (iconst (u64_from_imm64 n))))
10-
(imm ty n))
10+
(imm ty (ImmExtend.Zero) n))
1111

1212
;;;; Rules for `bconst` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1313

1414
(rule (lower (has_type ty (bconst $false)))
15-
(imm ty 0))
15+
(imm ty (ImmExtend.Zero) 0))
1616

1717
(rule (lower (has_type ty (bconst $true)))
18-
(imm ty 1))
18+
(imm ty (ImmExtend.Zero) 1))
1919

2020
;;;; Rules for `null` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2121

2222
(rule (lower (has_type ty (null)))
23-
(imm ty 0))
23+
(imm ty (ImmExtend.Zero) 0))
2424

2525
;;;; Rules for `iadd` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2626

@@ -533,7 +533,7 @@
533533
;; move it into a register.
534534
(rule (put_nonzero_in_reg_zext64 (and (value_type ty)
535535
(iconst (nonzero_u64_from_imm64 n))))
536-
(imm ty n))
536+
(imm ty (ImmExtend.Zero) n))
537537

538538
;;;; Rules for `sdiv` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
539539

@@ -568,7 +568,7 @@
568568
;; Special case for `sdiv` where no checks are needed due to division by a
569569
;; constant meaning the checks are always passed.
570570
(rule (lower (has_type (fits_in_64 ty) (sdiv x (iconst (safe_divisor_from_imm64 y)))))
571-
(a64_sdiv $I64 (put_in_reg_sext64 x) (imm ty y)))
571+
(a64_sdiv $I64 (put_in_reg_sext64 x) (imm ty (ImmExtend.Sign) y)))
572572

573573
;; Helper for placing a `Value` into a `Reg` and validating that it's nonzero.
574574
(decl put_nonzero_in_reg_sext64 (Value) Reg)
@@ -579,7 +579,7 @@
579579
;; not zero we can skip the zero check.
580580
(rule (put_nonzero_in_reg_sext64 (and (value_type ty)
581581
(iconst (nonzero_u64_from_imm64 n))))
582-
(imm ty n))
582+
(imm ty (ImmExtend.Sign) n))
583583

584584
;;;; Rules for `urem` and `srem` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
585585

@@ -646,14 +646,14 @@
646646
;; Conversion to 128-bit needs a zero-extension of the lower bits and the upper
647647
;; bits are all zero.
648648
(rule (lower (has_type $I128 (uextend x)))
649-
(value_regs (put_in_reg_zext64 x) (imm $I64 0)))
649+
(value_regs (put_in_reg_zext64 x) (imm $I64 (ImmExtend.Zero) 0)))
650650

651651
;; Like above where vector extraction automatically zero-extends extending to
652652
;; i128 only requires generating a 0 constant for the upper bits.
653653
(rule (lower (has_type $I128
654654
(uextend (extractlane vec @ (value_type in)
655655
(u8_from_uimm8 lane)))))
656-
(value_regs (mov_from_vec (put_in_reg vec) lane (vector_size in)) (imm $I64 0)))
656+
(value_regs (mov_from_vec (put_in_reg vec) lane (vector_size in)) (imm $I64 (ImmExtend.Zero) 0)))
657657

658658
;;;; Rules for `sextend` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
659659

@@ -1037,7 +1037,7 @@
10371037
(rule (lower (has_type $I128 (rotl x y)))
10381038
(let ((val ValueRegs x)
10391039
(amt Reg (value_regs_get y 0))
1040-
(neg_amt Reg (sub $I64 (imm $I64 128) amt))
1040+
(neg_amt Reg (sub $I64 (imm $I64 (ImmExtend.Zero) 128) amt))
10411041
(lshift ValueRegs (lower_shl128 val amt))
10421042
(rshift ValueRegs (lower_ushr128 val neg_amt)))
10431043
(value_regs
@@ -1121,7 +1121,7 @@
11211121
(rule (lower (has_type $I128 (rotr x y)))
11221122
(let ((val ValueRegs x)
11231123
(amt Reg (value_regs_get y 0))
1124-
(neg_amt Reg (sub $I64 (imm $I64 128) amt))
1124+
(neg_amt Reg (sub $I64 (imm $I64 (ImmExtend.Zero) 128) amt))
11251125
(rshift ValueRegs (lower_ushr128 val amt))
11261126
(lshift ValueRegs (lower_shl128 val neg_amt))
11271127
(hi Reg (orr $I64 (value_regs_get rshift 1) (value_regs_get lshift 1)))
@@ -1176,7 +1176,7 @@
11761176
(let ((hi_clz Reg (a64_clz $I64 (value_regs_get val 1)))
11771177
(lo_clz Reg (a64_clz $I64 (value_regs_get val 0)))
11781178
(tmp Reg (lsr_imm $I64 hi_clz (imm_shift_from_u8 6))))
1179-
(value_regs (madd $I64 lo_clz tmp hi_clz) (imm $I64 0))))
1179+
(value_regs (madd $I64 lo_clz tmp hi_clz) (imm $I64 (ImmExtend.Zero) 0))))
11801180

11811181
;;;; Rules for `ctz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11821182

@@ -1228,7 +1228,7 @@
12281228
(maybe_lo Reg (with_flags_reg
12291229
(cmp64_imm hi_cls (u8_into_imm12 63))
12301230
(csel (Cond.Eq) lo_sign_bits (zero_reg)))))
1231-
(value_regs (add $I64 maybe_lo hi_cls) (imm $I64 0))))
1231+
(value_regs (add $I64 maybe_lo hi_cls) (imm $I64 (ImmExtend.Zero) 0))))
12321232

12331233
(rule (lower (has_type ty (cls x)))
12341234
(a64_cls ty x))
@@ -1242,7 +1242,7 @@
12421242
(let ((val ValueRegs x)
12431243
(in_lo Reg (value_regs_get val 0))
12441244
(dst_lo Reg (and_imm $I32 in_lo (u64_into_imm_logic $I32 1)))
1245-
(dst_hi Reg (imm $I64 0)))
1245+
(dst_hi Reg (imm $I64 (ImmExtend.Zero) 0)))
12461246
(value_regs dst_lo dst_hi)))
12471247

12481248
(rule (lower (bint x))
@@ -1337,7 +1337,7 @@
13371337
(tmp Reg (mov_to_vec tmp_half (value_regs_get val 1) 1 (VectorSize.Size64x2)))
13381338
(nbits Reg (vec_cnt tmp (VectorSize.Size8x16)))
13391339
(added Reg (addv nbits (VectorSize.Size8x16))))
1340-
(value_regs (mov_from_vec added 0 (VectorSize.Size8x16)) (imm $I64 0))))
1340+
(value_regs (mov_from_vec added 0 (VectorSize.Size8x16)) (imm $I64 (ImmExtend.Zero) 0))))
13411341

13421342
(rule (lower (has_type $I8X16 (popcnt x)))
13431343
(vec_cnt x (VectorSize.Size8x16)))

cranelift/codegen/src/isa/aarch64/lower/isle.rs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,20 +75,12 @@ where
7575
}
7676
}
7777

78-
fn move_wide_const_from_u64(&mut self, n: u64) -> Option<MoveWideConst> {
79-
MoveWideConst::maybe_from_u64(n)
80-
}
81-
82-
fn move_wide_const_from_negated_u64(&mut self, n: u64) -> Option<MoveWideConst> {
83-
MoveWideConst::maybe_from_u64(!n)
84-
}
85-
8678
fn imm_logic_from_u64(&mut self, ty: Type, n: u64) -> Option<ImmLogic> {
87-
let ty = if ty.bits() < 32 { I32 } else { ty };
8879
ImmLogic::maybe_from_u64(n, ty)
8980
}
9081

9182
fn imm_logic_from_imm64(&mut self, ty: Type, n: Imm64) -> Option<ImmLogic> {
83+
let ty = if ty.bits() < 32 { I32 } else { ty };
9284
self.imm_logic_from_u64(ty, n.bits() as u64)
9385
}
9486

@@ -136,7 +128,45 @@ where
136128
///
137129
/// The logic here is nontrivial enough that it's not really worth porting
138130
/// this over to ISLE.
139-
fn load_constant64_full(&mut self, value: u64) -> Reg {
131+
fn load_constant64_full(
132+
&mut self,
133+
ty: Type,
134+
extend: &generated_code::ImmExtend,
135+
value: u64,
136+
) -> Reg {
137+
let bits = ty.bits();
138+
let value = if bits < 64 {
139+
if *extend == generated_code::ImmExtend::Sign {
140+
let shift = 64 - bits;
141+
let value = value as i64;
142+
143+
((value << shift) >> shift) as u64
144+
} else {
145+
value & !(u64::MAX << bits)
146+
}
147+
} else {
148+
value
149+
};
150+
let rd = self.temp_writable_reg(I64);
151+
152+
if value == 0 {
153+
self.emit(&MInst::MovWide {
154+
op: MoveWideOp::MovZ,
155+
rd,
156+
imm: MoveWideConst::zero(),
157+
size: OperandSize::Size64,
158+
});
159+
return rd.to_reg();
160+
} else if value == u64::MAX {
161+
self.emit(&MInst::MovWide {
162+
op: MoveWideOp::MovN,
163+
rd,
164+
imm: MoveWideConst::zero(),
165+
size: OperandSize::Size64,
166+
});
167+
return rd.to_reg();
168+
};
169+
140170
// If the top 32 bits are zero, use 32-bit `mov` operations.
141171
let (num_half_words, size, negated) = if value >> 32 == 0 {
142172
(2, OperandSize::Size32, (!value << 32) >> 32)
@@ -152,8 +182,6 @@ where
152182
let ignored_halfword = if first_is_inverted { 0xffff } else { 0 };
153183
let mut first_mov_emitted = false;
154184

155-
let rd = self.temp_writable_reg(I64);
156-
157185
for i in 0..num_half_words {
158186
let imm16 = (value >> (16 * i)) & 0xffff;
159187
if imm16 != ignored_halfword {

cranelift/filetests/filetests/isa/aarch64/arithmetic.clif

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ block0(v0: i64):
7474
}
7575

7676
; block0:
77-
; orr x3, xzr, #2
77+
; movz w3, #2
7878
; sdiv x0, x0, x3
7979
; ret
8080

@@ -150,7 +150,7 @@ block0(v0: i32):
150150

151151
; block0:
152152
; sxtw x3, w0
153-
; orr x5, xzr, #2
153+
; movz w5, #2
154154
; sdiv x0, x3, x5
155155
; ret
156156

@@ -176,7 +176,7 @@ block0(v0: i32):
176176

177177
; block0:
178178
; mov w3, w0
179-
; orr x5, xzr, #2
179+
; orr w5, wzr, #2
180180
; udiv x0, x3, x5
181181
; ret
182182

@@ -460,7 +460,7 @@ block0(v0: i64):
460460
}
461461

462462
; block0:
463-
; orr x3, xzr, #2
463+
; movz w3, #2
464464
; sdiv x5, x0, x3
465465
; msub x0, x5, x3, x0
466466
; ret

0 commit comments

Comments
 (0)