Use u32 in Type API (#4280)
Move from passing and returning u8 and u16 values to u32 in many of the functions. This removes a number of type conversions and gives a small compilation time speedup, around ~0.7% on my aarch64 machine. Copyright (c) 2022, Arm Limited.
This commit is contained in:
@@ -99,8 +99,8 @@ impl StackMap {
|
|||||||
pub fn get_bit(&self, bit_index: usize) -> bool {
|
pub fn get_bit(&self, bit_index: usize) -> bool {
|
||||||
assert!(bit_index < NUM_BITS * self.bitmap.len());
|
assert!(bit_index < NUM_BITS * self.bitmap.len());
|
||||||
let word_index = bit_index / NUM_BITS;
|
let word_index = bit_index / NUM_BITS;
|
||||||
let word_offset = (bit_index % NUM_BITS) as u8;
|
let word_offset = bit_index % NUM_BITS;
|
||||||
self.bitmap[word_index].contains(word_offset)
|
self.bitmap[word_index].contains(word_offset as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the raw bitmap that represents this stack map.
|
/// Returns the raw bitmap that represents this stack map.
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if this BitSet contains the number num
|
/// Check if this BitSet contains the number num
|
||||||
pub fn contains(&self, num: u8) -> bool {
|
pub fn contains(&self, num: u32) -> bool {
|
||||||
debug_assert!((num as usize) < Self::bits());
|
debug_assert!((num as usize) < Self::bits());
|
||||||
debug_assert!((num as usize) < Self::max_bits());
|
debug_assert!((num as usize) < Self::max_bits());
|
||||||
self.0.into() & (1 << num) != 0
|
self.0.into() & (1 << num) != 0
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ impl Imm64 {
|
|||||||
|
|
||||||
/// Sign extend this immediate as if it were a signed integer of the given
|
/// Sign extend this immediate as if it were a signed integer of the given
|
||||||
/// power-of-two width.
|
/// power-of-two width.
|
||||||
pub fn sign_extend_from_width(&mut self, bit_width: u16) {
|
pub fn sign_extend_from_width(&mut self, bit_width: u32) {
|
||||||
debug_assert!(bit_width.is_power_of_two());
|
debug_assert!(bit_width.is_power_of_two());
|
||||||
|
|
||||||
if bit_width >= 64 {
|
if bit_width >= 64 {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ impl Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get log_2 of the number of bits in a lane.
|
/// Get log_2 of the number of bits in a lane.
|
||||||
pub fn log2_lane_bits(self) -> u8 {
|
pub fn log2_lane_bits(self) -> u32 {
|
||||||
match self.lane_type() {
|
match self.lane_type() {
|
||||||
B1 => 0,
|
B1 => 0,
|
||||||
B8 | I8 => 3,
|
B8 | I8 => 3,
|
||||||
@@ -67,7 +67,7 @@ impl Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the number of bits in a lane.
|
/// Get the number of bits in a lane.
|
||||||
pub fn lane_bits(self) -> u8 {
|
pub fn lane_bits(self) -> u32 {
|
||||||
match self.lane_type() {
|
match self.lane_type() {
|
||||||
B1 => 1,
|
B1 => 1,
|
||||||
B8 | I8 => 8,
|
B8 | I8 => 8,
|
||||||
@@ -284,25 +284,25 @@ impl Type {
|
|||||||
/// will be a number in the range 0-8.
|
/// will be a number in the range 0-8.
|
||||||
///
|
///
|
||||||
/// A scalar type is the same as a SIMD vector type with one lane, so it returns 0.
|
/// A scalar type is the same as a SIMD vector type with one lane, so it returns 0.
|
||||||
pub fn log2_lane_count(self) -> u8 {
|
pub fn log2_lane_count(self) -> u32 {
|
||||||
self.0.saturating_sub(constants::LANE_BASE) >> 4
|
(self.0.saturating_sub(constants::LANE_BASE) >> 4) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the number of lanes in this SIMD vector type.
|
/// Get the number of lanes in this SIMD vector type.
|
||||||
///
|
///
|
||||||
/// A scalar type is the same as a SIMD vector type with one lane, so it returns 1.
|
/// A scalar type is the same as a SIMD vector type with one lane, so it returns 1.
|
||||||
pub fn lane_count(self) -> u16 {
|
pub fn lane_count(self) -> u32 {
|
||||||
1 << self.log2_lane_count()
|
1 << self.log2_lane_count()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the total number of bits used to represent this type.
|
/// Get the total number of bits used to represent this type.
|
||||||
pub fn bits(self) -> u16 {
|
pub fn bits(self) -> u32 {
|
||||||
u16::from(self.lane_bits()) * self.lane_count()
|
self.lane_bits() * self.lane_count()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the number of bytes used to store this type in memory.
|
/// Get the number of bytes used to store this type in memory.
|
||||||
pub fn bytes(self) -> u32 {
|
pub fn bytes(self) -> u32 {
|
||||||
(u32::from(self.bits()) + 7) / 8
|
(self.bits() + 7) / 8
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a SIMD vector type with `n` times more lanes than this one.
|
/// Get a SIMD vector type with `n` times more lanes than this one.
|
||||||
@@ -311,7 +311,7 @@ impl Type {
|
|||||||
///
|
///
|
||||||
/// If this is already a SIMD vector type, this produces a SIMD vector type with `n *
|
/// If this is already a SIMD vector type, this produces a SIMD vector type with `n *
|
||||||
/// self.lane_count()` lanes.
|
/// self.lane_count()` lanes.
|
||||||
pub fn by(self, n: u16) -> Option<Self> {
|
pub fn by(self, n: u32) -> Option<Self> {
|
||||||
if self.lane_bits() == 0 || !n.is_power_of_two() {
|
if self.lane_bits() == 0 || !n.is_power_of_two() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,7 +219,8 @@ fn extend_input_to_reg<C: LowerCtx<I = Inst>>(
|
|||||||
let ext_mode = match (input_size, requested_size) {
|
let ext_mode = match (input_size, requested_size) {
|
||||||
(a, b) if a == b => return put_input_in_reg(ctx, spec),
|
(a, b) if a == b => return put_input_in_reg(ctx, spec),
|
||||||
(1, 8) => return put_input_in_reg(ctx, spec),
|
(1, 8) => return put_input_in_reg(ctx, spec),
|
||||||
(a, b) => ExtMode::new(a, b).unwrap_or_else(|| panic!("invalid extension: {} -> {}", a, b)),
|
(a, b) => ExtMode::new(a.try_into().unwrap(), b.try_into().unwrap())
|
||||||
|
.unwrap_or_else(|| panic!("invalid extension: {} -> {}", a, b)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let src = input_to_reg_mem(ctx, spec);
|
let src = input_to_reg_mem(ctx, spec);
|
||||||
|
|||||||
@@ -125,9 +125,7 @@ where
|
|||||||
let inputs = self.lower_ctx.get_value_as_source_or_const(val);
|
let inputs = self.lower_ctx.get_value_as_source_or_const(val);
|
||||||
|
|
||||||
if let Some(c) = inputs.constant {
|
if let Some(c) = inputs.constant {
|
||||||
let mask = 1_u64
|
let mask = 1_u64.checked_shl(ty.bits()).map_or(u64::MAX, |x| x - 1);
|
||||||
.checked_shl(ty.bits() as u32)
|
|
||||||
.map_or(u64::MAX, |x| x - 1);
|
|
||||||
return Imm8Gpr::new(Imm8Reg::Imm8 {
|
return Imm8Gpr::new(Imm8Reg::Imm8 {
|
||||||
imm: (c & mask) as u8,
|
imm: (c & mask) as u8,
|
||||||
})
|
})
|
||||||
@@ -218,9 +216,7 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn const_to_type_masked_imm8(&mut self, c: u64, ty: Type) -> Imm8Gpr {
|
fn const_to_type_masked_imm8(&mut self, c: u64, ty: Type) -> Imm8Gpr {
|
||||||
let mask = 1_u64
|
let mask = 1_u64.checked_shl(ty.bits()).map_or(u64::MAX, |x| x - 1);
|
||||||
.checked_shl(ty.bits() as u32)
|
|
||||||
.map_or(u64::MAX, |x| x - 1);
|
|
||||||
Imm8Gpr::new(Imm8Reg::Imm8 {
|
Imm8Gpr::new(Imm8Reg::Imm8 {
|
||||||
imm: (c & mask) as u8,
|
imm: (c & mask) as u8,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::ops::{Add, BitAnd, Not, Sub};
|
|||||||
|
|
||||||
/// Returns the size (in bits) of a given type.
|
/// Returns the size (in bits) of a given type.
|
||||||
pub fn ty_bits(ty: Type) -> usize {
|
pub fn ty_bits(ty: Type) -> usize {
|
||||||
usize::from(ty.bits())
|
ty.bits() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the type represented by an integer (not float) at the machine level?
|
/// Is the type represented by an integer (not float) at the machine level?
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ macro_rules! isle_prelude_methods {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ty_bits_u16(&mut self, ty: Type) -> u16 {
|
fn ty_bits_u16(&mut self, ty: Type) -> u16 {
|
||||||
ty.bits()
|
ty.bits().try_into().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -410,7 +410,7 @@ macro_rules! isle_prelude_methods {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn multi_lane(&mut self, ty: Type) -> Option<(u8, u16)> {
|
fn multi_lane(&mut self, ty: Type) -> Option<(u32, u32)> {
|
||||||
if ty.lane_count() > 1 {
|
if ty.lane_count() > 1 {
|
||||||
Some((ty.lane_bits(), ty.lane_count()))
|
Some((ty.lane_bits(), ty.lane_count()))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -430,7 +430,7 @@
|
|||||||
|
|
||||||
;; Match a multi-lane type, extracting (# bits per lane, # lanes) from the given
|
;; Match a multi-lane type, extracting (# bits per lane, # lanes) from the given
|
||||||
;; type. Will only match when there is more than one lane.
|
;; type. Will only match when there is more than one lane.
|
||||||
(decl multi_lane (u8 u16) Type)
|
(decl multi_lane (u32 u32) Type)
|
||||||
(extern extractor multi_lane multi_lane)
|
(extern extractor multi_lane multi_lane)
|
||||||
|
|
||||||
;; Match the instruction that defines the given value, if any.
|
;; Match the instruction that defines the given value, if any.
|
||||||
|
|||||||
@@ -922,7 +922,7 @@ mod simplify {
|
|||||||
if !const_data.iter().all(|&b| b == 0 || b == 0xFF) {
|
if !const_data.iter().all(|&b| b == 0 || b == 0xFF) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let new_type = B8.by(old_cond_type.bytes() as u16).unwrap();
|
let new_type = B8.by(old_cond_type.bytes()).unwrap();
|
||||||
(pos.ins().raw_bitcast(new_type, args[0]), new_type)
|
(pos.ins().raw_bitcast(new_type, args[0]), new_type)
|
||||||
}
|
}
|
||||||
_ => return,
|
_ => return,
|
||||||
|
|||||||
@@ -535,7 +535,9 @@ fn souper_type_of(dfg: &ir::DataFlowGraph, val: ir::Value) -> Option<ast::Type>
|
|||||||
let ty = dfg.value_type(val);
|
let ty = dfg.value_type(val);
|
||||||
assert!(ty.is_int() || ty.is_bool());
|
assert!(ty.is_int() || ty.is_bool());
|
||||||
assert_eq!(ty.lane_count(), 1);
|
assert_eq!(ty.lane_count(), 1);
|
||||||
Some(ast::Type { width: ty.bits() })
|
Some(ast::Type {
|
||||||
|
width: ty.bits().try_into().unwrap(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -1646,7 +1646,7 @@ impl<'a> Verifier<'a> {
|
|||||||
// We must be specific about the opcodes above because other instructions are using
|
// We must be specific about the opcodes above because other instructions are using
|
||||||
// the same formats.
|
// the same formats.
|
||||||
let ty = self.func.dfg.value_type(arg);
|
let ty = self.func.dfg.value_type(arg);
|
||||||
if u16::from(lane) >= ty.lane_count() {
|
if lane as u32 >= ty.lane_count() {
|
||||||
errors.fatal((
|
errors.fatal((
|
||||||
inst,
|
inst,
|
||||||
self.context(inst),
|
self.context(inst),
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ impl<'a> Lexer<'a> {
|
|||||||
};
|
};
|
||||||
if is_vector {
|
if is_vector {
|
||||||
if number <= u32::from(u16::MAX) {
|
if number <= u32::from(u16::MAX) {
|
||||||
base_type.by(number as u16).map(Token::Type)
|
base_type.by(number).map(Token::Type)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user