@@ -68,17 +68,18 @@ use serde::{Deserialize, Serialize};
68
68
/// class; i.e., they are disjoint.
69
69
///
70
70
/// For tight bit-packing throughout our data structures, we support
71
- /// only two classes, "int" and "float ". This will usually be enough
72
- /// on modern machines, as they have one class of general-purpose
71
+ /// only three classes, "int", "float" and "vector ". Usually two will
72
+ /// be enough on modern machines, as they have one class of general-purpose
73
73
/// integer registers of machine width (e.g. 64 bits), and another
74
74
/// class of float/vector registers used both for FP and for vector
75
- /// operations. If needed, we could adjust bitpacking to allow for
76
- /// more classes in the future .
75
+ /// operations. Additionally for machines with totally separate vector
76
+ /// registers a third class is provided .
77
77
#[ derive( Clone , Copy , Debug , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
78
78
#[ cfg_attr( feature = "enable-serde" , derive( Serialize , Deserialize ) ) ]
79
79
pub enum RegClass {
80
80
Int = 0 ,
81
81
Float = 1 ,
82
+ Vector = 2 ,
82
83
}
83
84
84
85
/// A physical register. Contains a physical register number and a class.
@@ -104,7 +105,7 @@ pub struct PReg {
104
105
impl PReg {
105
106
pub const MAX_BITS : usize = 6 ;
106
107
pub const MAX : usize = ( 1 << Self :: MAX_BITS ) - 1 ;
107
- pub const NUM_INDEX : usize = 1 << ( Self :: MAX_BITS + 1 ) ; // including RegClass bit
108
+ pub const NUM_INDEX : usize = 1 << ( Self :: MAX_BITS + 2 ) ; // including RegClass bits
108
109
109
110
/// Create a new PReg. The `hw_enc` range is 6 bits.
110
111
#[ inline( always) ]
@@ -124,10 +125,11 @@ impl PReg {
124
125
/// The register class.
125
126
#[ inline( always) ]
126
127
pub const fn class ( self ) -> RegClass {
127
- if self . bits & ( 1 << Self :: MAX_BITS ) == 0 {
128
- RegClass :: Int
129
- } else {
130
- RegClass :: Float
128
+ match self . bits & ( 0b11 << Self :: MAX_BITS ) {
129
+ 0 => RegClass :: Int ,
130
+ 1 => RegClass :: Float ,
131
+ 2 => RegClass :: Vector ,
132
+ _ => unreachable ! ( ) ,
131
133
}
132
134
}
133
135
@@ -172,6 +174,7 @@ impl core::fmt::Display for PReg {
172
174
let class = match self . class ( ) {
173
175
RegClass :: Int => "i" ,
174
176
RegClass :: Float => "f" ,
177
+ RegClass :: Vector => "v" ,
175
178
} ;
176
179
write ! ( f, "p{}{}" , self . hw_enc( ) , class)
177
180
}
@@ -299,21 +302,22 @@ impl VReg {
299
302
pub const fn new ( virt_reg : usize , class : RegClass ) -> Self {
300
303
debug_assert ! ( virt_reg <= VReg :: MAX ) ;
301
304
VReg {
302
- bits : ( ( virt_reg as u32 ) << 1 ) | ( class as u8 as u32 ) ,
305
+ bits : ( ( virt_reg as u32 ) << 2 ) | ( class as u8 as u32 ) ,
303
306
}
304
307
}
305
308
306
309
#[ inline( always) ]
307
310
pub const fn vreg ( self ) -> usize {
308
- let vreg = ( self . bits >> 1 ) as usize ;
311
+ let vreg = ( self . bits >> 2 ) as usize ;
309
312
vreg
310
313
}
311
314
312
315
#[ inline( always) ]
313
316
pub const fn class ( self ) -> RegClass {
314
- match self . bits & 1 {
317
+ match self . bits & 0b11 {
315
318
0 => RegClass :: Int ,
316
319
1 => RegClass :: Float ,
320
+ 2 => RegClass :: Vector ,
317
321
_ => unreachable ! ( ) ,
318
322
}
319
323
}
@@ -734,6 +738,7 @@ impl Operand {
734
738
match class_field {
735
739
0 => RegClass :: Int ,
736
740
1 => RegClass :: Float ,
741
+ 2 => RegClass :: Vector ,
737
742
_ => unreachable ! ( ) ,
738
743
}
739
744
}
@@ -832,6 +837,7 @@ impl core::fmt::Display for Operand {
832
837
match self . class( ) {
833
838
RegClass :: Int => "i" ,
834
839
RegClass :: Float => "f" ,
840
+ RegClass :: Vector => "v" ,
835
841
} ,
836
842
self . constraint( )
837
843
)
@@ -1337,7 +1343,7 @@ pub struct MachineEnv {
1337
1343
///
1338
1344
/// If an explicit scratch register is provided in `scratch_by_class` then
1339
1345
/// it must not appear in this list.
1340
- pub preferred_regs_by_class : [ Vec < PReg > ; 2 ] ,
1346
+ pub preferred_regs_by_class : [ Vec < PReg > ; 3 ] ,
1341
1347
1342
1348
/// Non-preferred physical registers for each class. These are the
1343
1349
/// registers that will be allocated if a preferred register is
@@ -1346,7 +1352,7 @@ pub struct MachineEnv {
1346
1352
///
1347
1353
/// If an explicit scratch register is provided in `scratch_by_class` then
1348
1354
/// it must not appear in this list.
1349
- pub non_preferred_regs_by_class : [ Vec < PReg > ; 2 ] ,
1355
+ pub non_preferred_regs_by_class : [ Vec < PReg > ; 3 ] ,
1350
1356
1351
1357
/// Optional dedicated scratch register per class. This is needed to perform
1352
1358
/// moves between registers when cyclic move patterns occur. The
@@ -1363,7 +1369,7 @@ pub struct MachineEnv {
1363
1369
/// If a scratch register is not provided then the register allocator will
1364
1370
/// automatically allocate one as needed, spilling a value to the stack if
1365
1371
/// necessary.
1366
- pub scratch_by_class : [ Option < PReg > ; 2 ] ,
1372
+ pub scratch_by_class : [ Option < PReg > ; 3 ] ,
1367
1373
1368
1374
/// Some `PReg`s can be designated as locations on the stack rather than
1369
1375
/// actual registers. These can be used to tell the register allocator about
0 commit comments