@@ -800,6 +800,24 @@ fn inline_integer_rshift(fun: &mut hir::Function, block: hir::BlockId, recv: hir
800800
801801fn inline_integer_aref ( fun : & mut hir:: Function , block : hir:: BlockId , recv : hir:: InsnId , args : & [ hir:: InsnId ] , state : hir:: InsnId ) -> Option < hir:: InsnId > {
802802 let & [ index] = args else { return None ; } ;
803+
804+ // Optimize a compile-time constant index that fits in the Fixnum payload as a bit test.
805+ // A Fixnum payload is VALUE_BITS - 1 bits wide (one bit is the tag), so its highest
806+ // (sign) bit is at index VALUE_BITS - 2.
807+ const FIXNUM_SIGN_BIT_INDEX : i64 = VALUE_BITS as i64 - 2 ;
808+ if fun. likely_a ( recv, types:: Fixnum , state) {
809+ if let Some ( index_value) = fun. type_of ( index) . fixnum_value ( ) {
810+ if ( 0 ..=FIXNUM_SIGN_BIT_INDEX ) . contains ( & index_value) {
811+ // Optimize `recv[i]` into `(recv >> i) & 1`.
812+ let recv = fun. coerce_to ( block, recv, types:: Fixnum , state) ;
813+ let shift = fun. push_insn ( block, hir:: Insn :: Const { val : hir:: Const :: Value ( VALUE :: fixnum_from_usize ( index_value as usize ) ) } ) ;
814+ let shifted = fun. push_insn ( block, hir:: Insn :: FixnumRShift { left : recv, right : shift } ) ;
815+ let mask = fun. push_insn ( block, hir:: Insn :: Const { val : hir:: Const :: Value ( VALUE :: fixnum_from_usize ( 1 ) ) } ) ;
816+ return Some ( fun. push_insn ( block, hir:: Insn :: FixnumAnd { left : shifted, right : mask } ) ) ;
817+ }
818+ }
819+ }
820+ // Use a C call (FixnumAref) for any other (e.g. non-constant) index.
803821 if fun. likely_a ( recv, types:: Fixnum , state) && fun. likely_a ( index, types:: Fixnum , state) {
804822 let recv = fun. coerce_to ( block, recv, types:: Fixnum , state) ;
805823 let index = fun. coerce_to ( block, index, types:: Fixnum , state) ;
0 commit comments