/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ //OPT_OperatorClass.java package org.jikesrvm.compilers.opt; import org.jikesrvm.*; import org.jikesrvm.compilers.opt.ir.*; import java.util.ArrayList; /** * Generated from a template. * Consists of an operator class and information about resource usage * There is only one instance of each OPT_OperatorClass, which is stored * as a static final field in OPT_OperatorClass. You can compare * OPT_OperatorClasses using ==. * Every OPT_Operator contains one of these. * * @see OPT_Operator * @see OPT_Operators */ public final class OPT_OperatorClass implements OPT_Operators { // debug level (0 = no debug) private static final int verbose = 0; private static void debug(String s) { System.err.println(s); } private static String SPACES = null; private static void debug(int depth, String s) { if (SPACES == null) SPACES = dup(7200, ' '); debug(SPACES.substring(0,depth*2)+s); } // Padding // For internal use only. private static final String ZEROS = dup(32, '0'); private static String toBinaryPad32(int value) { String s = Integer.toBinaryString(value); return ZEROS.substring(s.length())+s; } // Returns a special resource type embodying all resources of a given class. // For internal use only. private static int all_units(int rclass) { return rclass | 0x80000000; } /** * Empty Resources Mask */ static int NONE = 0; /** * All Resources Mask */ static int ALL = 0; // will be filled in // Generates an array of resource masks, and updating the static field // ALL to contain all of the masks. // For internal use only. private static int M = 1; // current mask private static int[] genMasks(int number) { int[] rs = new int[number + 1]; int rall = 0; for (int i = 0; i < number; i++) { if (VM.VerifyAssertions && M == 0) throw new InternalError("Exceeded 32 resources"); //System.err.println("Scheduler: Resource "+M); rs[i] = M; ALL |= M; rall |= M; M <<= 1; } rs[number] = rall; return rs; } /** * Resource Masks */ private static final int[][] resources = { null }; /** * Total number of resources */ static final int N = resources.length - 1; /** * Resource Names */ private static final String[] resource_names = { null }; /** * Resources */ /** * Id of the operator class */ private int id = 0; /** * Maximum Latency of any instruction */ private int maxlat = 0; /** * Returns the maximum latency of any instruction in the class. * Note: it is faster to simply check the field directly, if possible. */ public int maxLatency() { return maxlat; } /** * Latencies to other classes */ private final ArrayList<Integer> latencies; // Returns latency lookup in the hashtable for a given operator class. // For internal use only. private Object latObj(OPT_OperatorClass opclass) { int latsize = latencies.size(); Object latObj = null; if (latsize > opclass.id) latObj = latencies.get(opclass.id); // walk through backwards, since any_insn (most general) is first ArrayList<OPT_OperatorClass> opcrc = opclass.rclasses; for (int i = opcrc.size(); latObj == null && i > 0; i--) { OPT_OperatorClass rc = opcrc.get(i - 1); if (latsize > rc.id) latObj = latencies.get(rc.id); } for (int i = rclasses.size(); latObj == null && i > 0; i--) { OPT_OperatorClass rc = rclasses.get(i - 1); latObj = rc.latObj(opclass); } return latObj; } /** * Sets the operator class (for hierarchy) * * @param opClass operator class */ public void setOpClass(OPT_OperatorClass opClass) { rclasses.add(opClass); } /** * Returns the latency between instructions in this class and given class * * @param opclass destination operator class * @return latency to given operator class */ public int latency(OPT_OperatorClass opclass) { return (Integer) latObj(opclass); } /** * Sets the latency between instructions in this class and given class * * @param opclass destination operator class * @param latency desired latency */ public void setLatency(OPT_OperatorClass opclass, int latency) { int latencies_size = latencies.size(); if (opclass.id < latencies_size) { latencies.set(opclass.id, latency); } else { for(; latencies_size < opclass.id; latencies_size++) { latencies.add(null); } latencies.add(latency); } } /** * Sets the latency between instructions in given class and this class * * @param opclass source operator class * @param latency desired latency */ public void setRevLatency(OPT_OperatorClass opclass, int latency) { opclass.setLatency(this, latency); } /* * Operator Classes */ // Global class embodying all operator classes. For internal use only. private static final OPT_OperatorClass any_insn = new OPT_OperatorClass(0); /** * Map from resource to operator class representing that resource */ private static OPT_OperatorClass[] res2class = { null }; private static final OPT_OperatorClass pseudo_ops = new OPT_OperatorClass( 0+N+1, new OPT_ResourceReservation[] { } ); static { LABEL.setOpClass(pseudo_ops); BBEND.setOpClass(pseudo_ops); UNINT_BEGIN.setOpClass(pseudo_ops); UNINT_END.setOpClass(pseudo_ops); pseudo_ops.setLatency(any_insn, 0); } /** * Resource Classes used by this Operator Class */ final ArrayList<OPT_OperatorClass> rclasses; /** * Resource Usage Masks */ int[][] masks; // For internal use only. private OPT_OperatorClass(int _id) { id = _id; rclasses = new ArrayList<OPT_OperatorClass>(); latencies = new ArrayList<Integer>(); } // For internal use only. private OPT_OperatorClass(int _id, OPT_ResourceReservation[] pat) { this(_id); allocateMasks(pat); if (verbose >= 2) debug(masks.length+" masks allocated for "+pat.length+ " requests"); int[] assign = new int[pat.length]; int comb = fillMasks(pat, assign, 0, 0, 0); if (false && comb != masks.length) throw new InternalError("Insufficient Resources"); } /** * Returns the string representation of this operator class. */ public String toString() { StringBuffer sb = new StringBuffer("Size="); sb.append(masks.length).append('\n'); for (int[] mask : masks) { for (int v : mask) sb.append(toBinaryPad32(v)).append('\n'); sb.append('\n'); } return sb.toString(); } // For internal use only. private void allocateMasks(OPT_ResourceReservation[] pat) { OPT_ResourceReservation.sort(pat); int maxlen = 0; int size = 1; OPT_ResourceReservation r = new OPT_ResourceReservation(-1, -1, -1000); int len = -1; OPT_OperatorClass[] rss = new OPT_OperatorClass[N]; for (OPT_ResourceReservation p : pat) { rss[p.rclass()] = res2class[p.rclass()]; boolean same = p.equals(r); if (!p.conflicts(r)) { r = p; if (r.isGlobal()) len = 1; else len = resources[r.rclass()].length - 1; } else if (r.isGlobal()) { throw new InternalError("Insufficient Resources"); } else { len--; } size *= len; if (same) size /= 2; if (p.start + p.duration > maxlen) maxlen = p.start + p.duration; } rclasses.add(any_insn); for (int i = 0; i < N; i++) if (rss[i] != null) rclasses.add(rss[i]); masks = new int[size][]; for (int i = 0; i < size; i++) masks[i] = new int[maxlen]; } // For internal debug use only. static int depth = 0; // For internal use only. private int fillMasks(OPT_ResourceReservation[] pat, int[] assign, int all, int rrq, int comb) { if (rrq == pat.length) { for (int i = 0; i < masks[comb].length; i++) masks[comb][i] = 0; StringBuffer dbSB; if (verbose >= 1) dbSB = new StringBuffer(); for (int i = 0; i < pat.length; i++) { OPT_ResourceReservation pi = pat[i]; int rc = pi.rclass(); int mask = resources[rc][assign[i]]; if (verbose >= 1) dbSB.append(toBinaryPad32(mask)).append(" "); for (int j = 0; j < pi.duration; j++) masks[comb][pi.start + j] |= mask; if (maxlat < pi.duration) maxlat = pi.duration; } if (verbose >= 1) debug(dbSB.toString()); return comb + 1; } int rc = pat[rrq].rclass(); int start = 0; int end = resources[rc].length - 1; if (rrq != 0 && pat[rrq].equals(pat[rrq-1])) start = assign[rrq-1] + 1; boolean ignore = ((rrq != 0 && !pat[rrq].conflicts(pat[rrq-1])) || pat[rrq].isGlobal()); if (pat[rrq].isGlobal()) { start = end; end++; } for (int i = start; i < end; i++) if (ignore || (resources[rc][i] & all) == 0) { if (verbose >= 2) debug(depth, rrq+": Res#"+rc+"; Trying "+i+ "; reserved='"+toBinaryPad32(all)+"'"); depth++; assign[rrq] = i; comb = fillMasks(pat, assign, all | resources[rc][i], rrq+1, comb); depth--; } return comb; } // Generates a string of a given length filled by a given character. // For internal use only. private static String dup(int len, char c) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < len; i++) sb.append(c); return sb.toString(); } }