001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.compilers.opt.regalloc;
014
015import java.util.ArrayList;
016import java.util.Enumeration;
017import java.util.HashMap;
018import java.util.HashSet;
019
020import org.jikesrvm.VM;
021import org.jikesrvm.compilers.opt.ir.BasicBlock;
022import org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet;
023import org.jikesrvm.compilers.opt.ir.IR;
024import org.jikesrvm.compilers.opt.ir.Instruction;
025
026import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_OSR;
027
028import org.jikesrvm.compilers.opt.ir.Register;
029import org.jikesrvm.compilers.opt.liveness.LiveInterval;
030import org.jikesrvm.compilers.opt.util.BitSet;
031
032/**
033 * An instance of this class provides a mapping from symbolic register to
034 * a set of restricted registers.
035 * <p>
036 * Each architecture will subclass this in a class
037 * RegisterRestrictions.
038 */
039public abstract class GenericRegisterRestrictions {
040  // for each symbolic register, the set of physical registers that are
041  // illegal for assignment
042  private final HashMap<Register, RestrictedRegisterSet> hash = new HashMap<Register, RestrictedRegisterSet>();
043
044  // a set of symbolic registers that must not be spilled.
045  private final HashSet<Register> noSpill = new HashSet<Register>();
046
047  protected final GenericPhysicalRegisterSet phys;
048
049  protected RegisterAllocatorState regAllocState;
050
051  protected GenericRegisterRestrictions(GenericPhysicalRegisterSet phys) {
052    this.phys = phys;
053  }
054
055  protected final void noteMustNotSpill(Register r) {
056    noSpill.add(r);
057  }
058
059  public final boolean mustNotSpill(Register r) {
060    return noSpill.contains(r);
061  }
062
063  /**
064   * Records all the register restrictions dictated by an IR.
065   *
066   * PRECONDITION: the instructions in each basic block are numbered in
067   * increasing order before calling this.
068   *
069   * @param ir the IR to process
070   */
071  public final void init(IR ir) {
072    LiveInterval livenessInformation = ir.getLivenessInformation();
073    this.regAllocState = ir.MIRInfo.regAllocState;
074
075    // process each basic block
076    for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) {
077      BasicBlock b = e.nextElement();
078      processBlock(b, livenessInformation);
079    }
080  }
081
082  /**
083   * Records all the register restrictions dictated by live ranges on a
084   * particular basic block.<p>
085   *
086   * PRECONDITION: the instructions in each basic block are numbered in
087   * increasing order before calling this.
088   *
089   * @param bb the bb to process
090   * @param liveness liveness information for the IR
091   */
092  private void processBlock(BasicBlock bb, LiveInterval liveness) {
093    ArrayList<LiveIntervalElement> symbolic = new ArrayList<LiveIntervalElement>(20);
094    ArrayList<LiveIntervalElement> physical = new ArrayList<LiveIntervalElement>(20);
095
096    // 1. walk through the live intervals and identify which correspond to
097    // physical and symbolic registers
098    for (Enumeration<LiveIntervalElement> e = liveness.enumerateLiveIntervals(bb); e.hasMoreElements();) {
099      LiveIntervalElement li = e.nextElement();
100      Register r = li.getRegister();
101      if (r.isPhysical()) {
102        if (r.isVolatile() || r.isNonVolatile()) {
103          physical.add(li);
104        }
105      } else {
106        symbolic.add(li);
107      }
108    }
109
110    // 2. walk through the live intervals for physical registers.  For
111    // each such interval, record the conflicts where the live range
112    // overlaps a live range for a symbolic register.
113    for (LiveIntervalElement phys : physical) {
114      for (LiveIntervalElement symb : symbolic) {
115        if (overlaps(phys, symb)) {
116          addRestriction(symb.getRegister(), phys.getRegister());
117        }
118      }
119    }
120
121    // 3. Volatile registers used by CALL instructions do not appear in
122    // the liveness information.  Handle CALL instructions as a special
123    // case.
124    for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements();) {
125      Instruction s = ie.nextElement();
126      if (s.operator().isCall() && !s.operator().isCallSaveVolatile()) {
127        for (LiveIntervalElement symb : symbolic) {
128          if (contains(symb, regAllocState.getDFN(s))) {
129            forbidAllVolatiles(symb.getRegister());
130          }
131        }
132      }
133
134      // Before OSR points, we need to save all FPRs,
135      // On OptExecStateExtractor, all GPRs have to be recovered,
136      // but not FPRS.
137      //
138      if (s.operator() == YIELDPOINT_OSR) {
139        for (LiveIntervalElement symb : symbolic) {
140          if (symb.getRegister().isFloatingPoint()) {
141            if (contains(symb, regAllocState.getDFN(s))) {
142              forbidAllVolatiles(symb.getRegister());
143            }
144          }
145        }
146      }
147    }
148
149    // 3. architecture-specific restrictions
150    addArchRestrictions(bb, symbolic);
151  }
152
153  /**
154   * Add architecture-specific register restrictions for a basic block.
155   * Override as needed.
156   *
157   * @param bb the basic block
158   * @param symbolics the live intervals for symbolic registers on this
159   * block
160   */
161  public void addArchRestrictions(BasicBlock bb, ArrayList<LiveIntervalElement> symbolics) {}
162
163  /**
164   * Does a live range R contain an instruction with number n?<p>
165   *
166   * PRECONDITION: the instructions in each basic block are numbered in
167   * increasing order before calling this.
168   *
169   * @param R the live range
170   * @param n the instruction number
171   *
172   * @return {@code true} if and only if the live range contains an instruction
173   *  with the given number
174   */
175  protected final boolean contains(LiveIntervalElement R, int n) {
176    int begin = -1;
177    int end = Integer.MAX_VALUE;
178    if (R.getBegin() != null) {
179      begin = regAllocState.getDFN(R.getBegin());
180    }
181    if (R.getEnd() != null) {
182      end = regAllocState.getDFN(R.getEnd());
183    }
184
185    return ((begin <= n) && (n <= end));
186  }
187
188  /**
189   * Do two live ranges overlap?<p>
190   *
191   * PRECONDITION: the instructions in each basic block are numbered in
192   * increasing order before calling this.
193   *
194   * @param li1 first live range
195   * @param li2 second live range
196   * @return {@code true} if and only if the live ranges overlap
197   */
198  private boolean overlaps(LiveIntervalElement li1, LiveIntervalElement li2) {
199    // Under the following conditions: the live ranges do NOT overlap:
200    // 1. begin2 >= end1 > -1
201    // 2. begin1 >= end2 > -1
202    // Under all other cases, the ranges overlap
203
204    int begin1 = -1;
205    int end1 = -1;
206    int begin2 = -1;
207    int end2 = -1;
208
209    if (li1.getBegin() != null) {
210      begin1 = regAllocState.getDFN(li1.getBegin());
211    }
212    if (li2.getEnd() != null) {
213      end2 = regAllocState.getDFN(li2.getEnd());
214    }
215    if (end2 <= begin1 && end2 > -1) return false;
216
217    if (li1.getEnd() != null) {
218      end1 = regAllocState.getDFN(li1.getEnd());
219    }
220    if (li2.getBegin() != null) {
221      begin2 = regAllocState.getDFN(li2.getBegin());
222    }
223    return end1 > begin2 || end1 <= -1;
224
225  }
226
227  /**
228   * Records that it is illegal to assign a symbolic register symb to any
229   * volatile physical registerss.
230   *
231   * @param symb the register that must not be assigned to a volatile
232   *  physical register
233   */
234  final void forbidAllVolatiles(Register symb) {
235    RestrictedRegisterSet r = hash.get(symb);
236    if (r == null) {
237      r = new RestrictedRegisterSet(phys);
238      hash.put(symb, r);
239    }
240    r.setNoVolatiles();
241  }
242
243  /**
244   * Records that it is illegal to assign a symbolic register symb to any
245   * of a set of physical registers.
246   *
247   * @param symb the symbolic register to be restricted
248   * @param set the physical registers that the symbolic register
249   *  must not be assigned to
250   */
251  protected final void addRestrictions(Register symb, BitSet set) {
252    RestrictedRegisterSet r = hash.get(symb);
253    if (r == null) {
254      r = new RestrictedRegisterSet(phys);
255      hash.put(symb, r);
256    }
257    r.addAll(set);
258  }
259
260  /**
261   * Record thats it is illegal to assign a symbolic register symb to a
262   * physical register p.
263   *
264   * @param symb the symbolic register to be restricted
265   * @param p the physical register that the symbolic register
266   *  must not be assigned to
267   */
268  protected final void addRestriction(Register symb, Register p) {
269    RestrictedRegisterSet r = hash.get(symb);
270    if (r == null) {
271      r = new RestrictedRegisterSet(phys);
272      hash.put(symb, r);
273    }
274    r.add(p);
275  }
276
277  /**
278   * @param symb the register whose restrictions where interested in
279   * @return the set of restricted physical register for a given symbolic
280   * register, {@code null} if no restrictions.
281   */
282  final RestrictedRegisterSet getRestrictions(Register symb) {
283    return hash.get(symb);
284  }
285
286  /**
287   * Is it forbidden to assign symbolic register symb to any volatile
288   * register?
289   * @param symb symbolic register to check
290   * @return {@code true}: yes, all volatiles are forbidden.
291   *         {@code false} :maybe, maybe not
292   */
293  public final boolean allVolatilesForbidden(Register symb) {
294    if (VM.VerifyAssertions) {
295      VM._assert(symb != null);
296    }
297    RestrictedRegisterSet s = getRestrictions(symb);
298    if (s == null) return false;
299    return s.getNoVolatiles();
300  }
301
302  /**
303   * Is it forbidden to assign symbolic register symb to physical register
304   * phys?
305   *
306   * @param symb a symbolic register
307   * @param phys a physical register
308   * @return {@code true} if it's forbidden, false otherwise
309   */
310  public final boolean isForbidden(Register symb, Register phys) {
311    if (VM.VerifyAssertions) {
312      VM._assert(symb != null);
313      VM._assert(phys != null);
314    }
315    RestrictedRegisterSet s = getRestrictions(symb);
316    if (s == null) return false;
317    return s.contains(phys);
318  }
319
320  /**
321   * Is it forbidden to assign symbolic register symb to physical register r
322   * in instruction s?
323   *
324   * @param symb a symbolic register
325   * @param r a physical register
326   * @param s the instruction that's the scope for the check
327   * @return {@code true} if it's forbidden, false otherwise
328   */
329  public abstract boolean isForbidden(Register symb, Register r, Instruction s);
330
331  /**
332   * An instance of this class represents restrictions on physical register
333   * assignment.
334   */
335  private static final class RestrictedRegisterSet {
336    /**
337     * The set of registers to which assignment is forbidden.
338     */
339    private final BitSet bitset;
340
341    /**
342     * additionally, are all volatile registers forbidden?
343     */
344    private boolean noVolatiles = false;
345
346    boolean getNoVolatiles() {
347      return noVolatiles;
348    }
349
350    void setNoVolatiles() {
351      noVolatiles = true;
352    }
353
354    RestrictedRegisterSet(GenericPhysicalRegisterSet phys) {
355      bitset = new BitSet(phys);
356    }
357
358    void add(Register r) {
359      bitset.add(r);
360    }
361
362    void addAll(BitSet set) {
363      bitset.addAll(set);
364    }
365
366    boolean contains(Register r) {
367      if (r.isVolatile() && noVolatiles) {
368        return true;
369      } else {
370        return bitset.contains(r);
371      }
372    }
373  }
374}