package com.seaofnodes.simple.codegen; import com.seaofnodes.simple.util.SB; import com.seaofnodes.simple.util.Utils; /** RegMask * A "register mask" - 1 bit set for each allowed register. In addition, * "stack slot" registers may be allowed, effectively making the set infinite. *

* For smaller and simpler machines it suffices to make such masks an i64 or * i128 (64- or 128-bit integers), and this presentation is by far the better * way to go... if all register allocations can fit in this bit limitation. * The allocator will need bits for stack-based parameters and for splits * which cannot get a register. For a 32-register machine like the X86, add 1 * for flags - gives 33 registers. Using a Java `long` has 64 bits, leaving * 31 for spills and stack passing. This is adequate for nearly all * allocations; only the largest allocations will run this out. However, if * we move to a chip with 64 registers we'll immediately run out, and need at * least a 128 bit mask. Since you cannot *return* a 128 bit value directly * in Java, Simple will pick up a `RegMask` class object. */ public class RegMask { long _bits0, _bits1; private static final RegMask EMPTY = new RegMask(0L); public static final RegMask FULL = new RegMask(-1L); public RegMask(int bit) { if( bit < 64 ) _bits0 = 1L<> reg)&1)==0; if( reg < 128 ) return ((_bits1 >> reg)&1)==0; return true; } public short firstReg() { if( isEmpty() ) return -1; return (short)(_bits0 != 0 ? Long.numberOfTrailingZeros(_bits0) : Long.numberOfTrailingZeros(_bits1)+64); } public short nextReg(short reg) { if( reg < 63 ) { long bits0 = _bits0 & (-1L << (reg+1)); if( bits0!=0 ) return (short)Long.numberOfTrailingZeros(bits0); } long bits1 = reg < 64 ? _bits1 : reg < 127 ? _bits1 & (-1L << (reg-63)) : 0; return bits1==0 ? -1 : (short)(64+Long.numberOfTrailingZeros(bits1)); } boolean isEmpty() { return _bits0==0 && _bits1==0; } public boolean test( int reg ) { return ((reg<64 ? (_bits0 >> reg) : (_bits1 >> (reg-64))) & 1) != 0; } // checks if the 2 masks have at least 1 bit in common public boolean overlap( RegMask mask ) { return (_bits0 & mask._bits0)!=0 || (_bits1 & mask._bits1)!=0; } // Defensive writable copy public RegMaskRW copy() { return new RegMaskRW( _bits0, _bits1 ); } // Has exactly 1 bit set public boolean size1() { return !isEmpty() && (((_bits0 & -_bits0)==_bits0 && _bits1==0) || ((_bits1 & -_bits1)==_bits1 && _bits0==0)); } // Cardinality public short size() { return (short)(Long.bitCount(_bits0)+Long.bitCount(_bits1)); } @Override public String toString() { return toString(new SB()).toString(); } public SB toString(SB sb) { Machine mach = CodeGen.CODE._mach; if( _bits0==0 && _bits1==0 ) return sb.p("[]"); sb.p("["); String[] regs = mach.regs(); for( int i=0; i<64; i++ ) if( ((_bits0 >> i)&1) != 0 ) sb.p(reg(regs,i)).p(","); for( int i=0; i<64; i++ ) if( ((_bits1 >> i)&1) != 0 ) sb.p(reg(regs,i+64)).p(","); return sb.unchar().p("]"); } public static String reg(String[] regs, int i) { return i