diff --git a/cranelift/codegen/meta/src/cdsl/types.rs b/cranelift/codegen/meta/src/cdsl/types.rs index 53b0032803..f431bb3ed7 100644 --- a/cranelift/codegen/meta/src/cdsl/types.rs +++ b/cranelift/codegen/meta/src/cdsl/types.rs @@ -215,13 +215,14 @@ impl LaneType { LaneType::BoolType(shared_types::Bool::B16) => 2, LaneType::BoolType(shared_types::Bool::B32) => 3, LaneType::BoolType(shared_types::Bool::B64) => 4, - LaneType::IntType(shared_types::Int::I8) => 5, - LaneType::IntType(shared_types::Int::I16) => 6, - LaneType::IntType(shared_types::Int::I32) => 7, - LaneType::IntType(shared_types::Int::I64) => 8, - LaneType::IntType(shared_types::Int::I128) => 9, - LaneType::FloatType(shared_types::Float::F32) => 10, - LaneType::FloatType(shared_types::Float::F64) => 11, + LaneType::BoolType(shared_types::Bool::B128) => 5, + LaneType::IntType(shared_types::Int::I8) => 6, + LaneType::IntType(shared_types::Int::I16) => 7, + LaneType::IntType(shared_types::Int::I32) => 8, + LaneType::IntType(shared_types::Int::I64) => 9, + LaneType::IntType(shared_types::Int::I128) => 10, + LaneType::FloatType(shared_types::Float::F32) => 11, + LaneType::FloatType(shared_types::Float::F64) => 12, } } @@ -232,6 +233,7 @@ impl LaneType { 16 => shared_types::Bool::B16, 32 => shared_types::Bool::B32, 64 => shared_types::Bool::B64, + 128 => shared_types::Bool::B128, _ => unreachable!("unxpected num bits for bool"), }) } diff --git a/cranelift/codegen/meta/src/cdsl/typevar.rs b/cranelift/codegen/meta/src/cdsl/typevar.rs index 27ec365227..71c2fd2e29 100644 --- a/cranelift/codegen/meta/src/cdsl/typevar.rs +++ b/cranelift/codegen/meta/src/cdsl/typevar.rs @@ -10,6 +10,7 @@ use crate::cdsl::types::{BVType, LaneType, ReferenceType, SpecialType, ValueType const MAX_LANES: u16 = 256; const MAX_BITS: u16 = 128; +const MAX_FLOAT_BITS: u16 = 64; const MAX_BITVEC: u16 = MAX_BITS * MAX_LANES; /// Type variables can be used in place of concrete types when defining @@ -177,7 +178,7 @@ impl TypeVar { "can't double all integer types" ); assert!( - ts.floats.len() == 0 || *ts.floats.iter().max().unwrap() < MAX_BITS, + ts.floats.len() == 0 || *ts.floats.iter().max().unwrap() < MAX_FLOAT_BITS, "can't double all float types" ); assert!( @@ -503,7 +504,7 @@ impl TypeSet { copy.floats = NumSet::from_iter( self.floats .iter() - .filter(|&&x| x < MAX_BITS) + .filter(|&&x| x < MAX_FLOAT_BITS) .map(|&x| x * 2), ); copy.bools = NumSet::from_iter( @@ -621,7 +622,7 @@ impl TypeSet { let mut copy = self.clone(); copy.bitvecs = NumSet::new(); if self.bools.contains(&1) { - copy.ints = NumSet::from_iter(vec![8, 16, 32, 64]); + copy.ints = NumSet::from_iter(vec![8, 16, 32, 64, 128]); copy.floats = NumSet::from_iter(vec![32, 64]); } else { copy.ints = &self.bools - &NumSet::from_iter(vec![1]); @@ -950,7 +951,7 @@ fn test_typevar_builder() { let type_set = TypeSetBuilder::new().ints(Interval::All).build(); assert_eq!(type_set.lanes, num_set![1]); assert!(type_set.floats.is_empty()); - assert_eq!(type_set.ints, num_set![8, 16, 32, 64]); + assert_eq!(type_set.ints, num_set![8, 16, 32, 64, 128]); assert!(type_set.bools.is_empty()); assert!(type_set.bitvecs.is_empty()); assert!(type_set.specials.is_empty()); @@ -959,7 +960,7 @@ fn test_typevar_builder() { assert_eq!(type_set.lanes, num_set![1]); assert!(type_set.floats.is_empty()); assert!(type_set.ints.is_empty()); - assert_eq!(type_set.bools, num_set![1, 8, 16, 32, 64]); + assert_eq!(type_set.bools, num_set![1, 8, 16, 32, 64, 128]); assert!(type_set.bitvecs.is_empty()); assert!(type_set.specials.is_empty()); @@ -1101,7 +1102,7 @@ fn test_forward_images() { ); assert_eq!( TypeSetBuilder::new().ints(32..64).build().double_width(), - TypeSetBuilder::new().ints(64..64).build() + TypeSetBuilder::new().ints(64..128).build() ); assert_eq!( TypeSetBuilder::new().floats(32..32).build().double_width(), @@ -1117,7 +1118,7 @@ fn test_forward_images() { ); assert_eq!( TypeSetBuilder::new().bools(32..64).build().double_width(), - TypeSetBuilder::new().bools(64..64).build() + TypeSetBuilder::new().bools(64..128).build() ); } @@ -1145,7 +1146,7 @@ fn test_backward_images() { assert_eq!( TypeSetBuilder::new() .simd_lanes(1..4) - .bools(1..64) + .bools(1..128) .build() .preimage(DerivedFunc::AsBool), TypeSetBuilder::new() @@ -1205,9 +1206,9 @@ fn test_backward_images() { // Half width. assert_eq!( TypeSetBuilder::new() - .ints(64..64) + .ints(128..128) .floats(64..64) - .bools(64..64) + .bools(128..128) .build() .preimage(DerivedFunc::HalfWidth) .size(), @@ -1221,7 +1222,7 @@ fn test_backward_images() { .preimage(DerivedFunc::HalfWidth), TypeSetBuilder::new() .simd_lanes(64..256) - .bools(16..64) + .bools(16..128) .build(), ); diff --git a/cranelift/codegen/meta/src/shared/types.rs b/cranelift/codegen/meta/src/shared/types.rs index 60c546657e..52fa9545c6 100644 --- a/cranelift/codegen/meta/src/shared/types.rs +++ b/cranelift/codegen/meta/src/shared/types.rs @@ -12,6 +12,8 @@ pub enum Bool { B32 = 32, /// 64-bit bool. B64 = 64, + /// 128-bit bool. + B128 = 128, } /// This provides an iterator through all of the supported bool variants. @@ -34,6 +36,7 @@ impl Iterator for BoolIterator { 2 => Some(Bool::B16), 3 => Some(Bool::B32), 4 => Some(Bool::B64), + 5 => Some(Bool::B128), _ => return None, }; self.index += 1; @@ -192,6 +195,7 @@ mod iter_tests { assert_eq!(bool_iter.next(), Some(Bool::B16)); assert_eq!(bool_iter.next(), Some(Bool::B32)); assert_eq!(bool_iter.next(), Some(Bool::B64)); + assert_eq!(bool_iter.next(), Some(Bool::B128)); assert_eq!(bool_iter.next(), None); } diff --git a/cranelift/codegen/src/ir/types.rs b/cranelift/codegen/src/ir/types.rs index 394ec8e024..10fca8aaa8 100644 --- a/cranelift/codegen/src/ir/types.rs +++ b/cranelift/codegen/src/ir/types.rs @@ -14,7 +14,7 @@ use target_lexicon::{PointerWidth, Triple}; /// /// Basic floating point types: `F32` and `F64`. IEEE single and double precision. /// -/// Boolean types: `B1`, `B8`, `B16`, `B32`, and `B64`. These all encode 'true' or 'false'. The +/// Boolean types: `B1`, `B8`, `B16`, `B32`, `B64`, and `B128`. These all encode 'true' or 'false'. The /// larger types use redundant bits. /// /// SIMD vector types have power-of-two lanes, up to 256. Lanes can be any int/float/bool type. @@ -63,7 +63,7 @@ impl Type { B16 | I16 => 4, B32 | I32 | F32 | R32 => 5, B64 | I64 | F64 | R64 => 6, - I128 => 7, + B128 | I128 => 7, _ => 0, } } @@ -76,7 +76,7 @@ impl Type { B16 | I16 => 16, B32 | I32 | F32 | R32 => 32, B64 | I64 | F64 | R64 => 64, - I128 => 128, + B128 | I128 => 128, _ => 0, } } @@ -112,6 +112,7 @@ impl Type { B32 | I32 | F32 => B32, B64 | I64 | F64 => B64, R32 | R64 => panic!("Reference types should not convert to bool"), + B128 | I128 => B128, _ => B1, }) } @@ -140,6 +141,7 @@ impl Type { B16 => B8, B32 => B16, B64 => B32, + B128 => B64, _ => return None, })) } @@ -156,6 +158,7 @@ impl Type { B8 => B16, B16 => B32, B32 => B64, + B64 => B128, _ => return None, })) } @@ -187,7 +190,7 @@ impl Type { /// Is this a scalar boolean type? pub fn is_bool(self) -> bool { match self { - B1 | B8 | B16 | B32 | B64 => true, + B1 | B8 | B16 | B32 | B64 | B128 => true, _ => false, } } @@ -375,6 +378,7 @@ mod tests { assert_eq!(B16, B16.lane_type()); assert_eq!(B32, B32.lane_type()); assert_eq!(B64, B64.lane_type()); + assert_eq!(B128, B128.lane_type()); assert_eq!(I8, I8.lane_type()); assert_eq!(I16, I16.lane_type()); assert_eq!(I32, I32.lane_type()); @@ -396,6 +400,7 @@ mod tests { assert_eq!(B16.lane_bits(), 16); assert_eq!(B32.lane_bits(), 32); assert_eq!(B64.lane_bits(), 64); + assert_eq!(B128.lane_bits(), 128); assert_eq!(I8.lane_bits(), 8); assert_eq!(I16.lane_bits(), 16); assert_eq!(I32.lane_bits(), 32); @@ -417,6 +422,7 @@ mod tests { assert_eq!(B16.half_width(), Some(B8)); assert_eq!(B32.half_width(), Some(B16)); assert_eq!(B64.half_width(), Some(B32)); + assert_eq!(B128.half_width(), Some(B64)); assert_eq!(I8.half_width(), None); assert_eq!(I16.half_width(), Some(I8)); assert_eq!(I32.half_width(), Some(I16)); @@ -433,7 +439,8 @@ mod tests { assert_eq!(B8.double_width(), Some(B16)); assert_eq!(B16.double_width(), Some(B32)); assert_eq!(B32.double_width(), Some(B64)); - assert_eq!(B64.double_width(), None); + assert_eq!(B64.double_width(), Some(B128)); + assert_eq!(B128.double_width(), None); assert_eq!(I8.double_width(), Some(I16)); assert_eq!(I16.double_width(), Some(I32)); assert_eq!(I32.double_width(), Some(I64)); @@ -470,6 +477,7 @@ mod tests { assert_eq!(B16.to_string(), "b16"); assert_eq!(B32.to_string(), "b32"); assert_eq!(B64.to_string(), "b64"); + assert_eq!(B128.to_string(), "b128"); assert_eq!(I8.to_string(), "i8"); assert_eq!(I16.to_string(), "i16"); assert_eq!(I32.to_string(), "i32"); diff --git a/cranelift/filetests/filetests/isa/x86/i128.clif b/cranelift/filetests/filetests/isa/x86/i128.clif index 044b01e58f..41b2a80fce 100644 --- a/cranelift/filetests/filetests/isa/x86/i128.clif +++ b/cranelift/filetests/filetests/isa/x86/i128.clif @@ -27,7 +27,7 @@ ebb0(v0: i128): ; check: return v3, v4, v6 } -function u0:1(i64, i128) fast { +function u0:2(i64, i128) fast { ; check: ebb0(v0: i64 [%rdi], v2: i64 [%rsi], v3: i64 [%rdx], v4: i64 [%rbp]): ebb0(v0: i64, v1: i128): ; check: store v2, v0 @@ -36,7 +36,7 @@ ebb0(v0: i64, v1: i128): return } -function u0:1(i64) -> i128 fast { +function u0:3(i64) -> i128 fast { ebb0(v0: i64): ; check: v2 = load.i64 v0 ; check: v3 = load.i64 v0+8 diff --git a/cranelift/reader/src/lexer.rs b/cranelift/reader/src/lexer.rs index 151fbd7af5..2432ab0551 100644 --- a/cranelift/reader/src/lexer.rs +++ b/cranelift/reader/src/lexer.rs @@ -373,6 +373,7 @@ impl<'a> Lexer<'a> { "b16" => types::B16, "b32" => types::B32, "b64" => types::B64, + "b128" => types::B128, "r32" => types::R32, "r64" => types::R64, _ => return None,