@Override public void visit(SubscriptExpr expr) { expr.getIndex().acceptVisitor(this); Expr index = resultExpr; expr.getArray().acceptVisitor(this); Expr array = resultExpr; expr.setArray(array); expr.setIndex(index); resultExpr = expr; }
public Cost computeRefCost(LoopHeaderChord loop, SubscriptExpr se) { Cost tripL = loop.getTripCount(); InductionVar ivar = loop.getPrimaryInductionVar(); if (ivar == null) return tripL; // Compute // tripL = (ubL - lbL + stepL) / stepL int nsubs = se.numSubscripts(); // number of subscripts in the subscript LoopHeaderChord tloop = loop.getTopLoop(); VariableDecl iv = ivar.getVar(); for (int i = 0; i < nsubs - 1; i++) { // for c code // If the loop index variable of this loop appears in any of the // subscripts other then the last, then return tripL. Expr sI = se.getSubscript(i); AffineExpr ae = tloop.isAffine(sI); if (ae == null) return null; if (ae.hasTerm(iv)) return tripL; } int fs = nsubs - 1; Expr s0 = se.getSubscript(fs); AffineExpr ae = tloop.isAffine(s0); if (ae == null) return null; int at = ae.getTermIndexOrig(iv); long coeff = 0; if (at >= 0) coeff = ae.getCoefficient(at); if (coeff == 0) // Invariant Reuse. return new Cost(1.0, 0); long stepL = loop.getStepValue(); long stride = stepL * coeff; if (stride < 0) stride = -stride; // Unit Reuse. Type et = se.getCoreType().getPointedTo(); int bs = et.memorySizeAsInt(Machine.currentMachine); int cs = Machine.currentMachine.getCacheSize(bs); if (stride <= cs) { // cache line or block size tripL.multiply(stride); tripL.divide(cs); return tripL; } // No Reuse. return tripL; }
@Override public Node forSubscriptExpr(SubscriptExpr that) { if (!Shell.getAssignmentPreDesugaring()) { return super.forSubscriptExpr(that); } else { // Rewrite a subscript expression into a method call (pretty straightforward) Expr obj = that.getObj(); List<Expr> subs = that.getSubs(); Option<Op> op = that.getOp(); List<StaticArg> staticArgs = that.getStaticArgs(); if (!op.isSome()) bug(that, "Subscript operator expected"); Op knownOp = op.unwrap(); Expr result = ExprFactory.makeMethodInvocation( that, obj, knownOp, staticArgs, ExprFactory.makeTupleExpr(NodeUtil.getSpan(knownOp), subs)); return (Expr) recur(result); } }
@Override public Node forAssignment(Assignment that) { // System.out.println("PreDesugar entry"); // Here there are three sorts of rewrite to consider: // (a) If this is a compound assignment, rewrite to use ordinary assignment. // (b) If the lhs is a tuple, rewrite into a set of individual assignments. // (c) If the lhs is a subscript expression, rewrite to a method call. List<Lhs> lhs = that.getLhs(); Option<FunctionalRef> assignOp = that.getAssignOp(); Expr rhs = that.getRhs(); List<CompoundAssignmentInfo> assignmentInfos = that.getAssignmentInfos(); if (!Shell.getAssignmentPreDesugaring()) { // System.out.println("Did not PreDesugar"); return super.forAssignment(that); } else if (assignOp.isSome() || lhs.size() > 1) { // System.out.println("Compound/tuple PreDesugar"); // Compound and/or tuple assignment // The basic idea is to transform `(a, b.field, c[sub1,sub2]) := e` into // `do (ta, tb, tc, tsub1, tsub2, (t1, t2, t3)) = (a, b, c, sub1, sub2, e) // a := t1; tb.field := t2; tc[tsub1, tsub2] := t3 end` // (TODO) Unfortunately, currently we don't handle nested binding tuples. // For now, we'll just transform it into // `do (ta, tb, tc, tsub1, tsub2) = (a, b, c, sub1, sub2) // (t1, t2, t3) = e // a := t1; tb.field := t2; tc[tsub1, tsub2] := t3 end` // which merely loses a bit of potential parallelism. // We omit the first tuple binding if the tuple is empty. // If it is a compound assignment `(a, b.field, c[sub1,sub2]) OP= e`, it becomes // `do (ta, tb, tc, tsub1, tsub2) = (a, b, c, sub1, sub2) // (t1, t2, t3) = (ta, tb, tc[tsub1, tsub2]) OP e // a := t1; tb.field := t2; tc[tsub1, tsub2] := t3 end` List<LValue> exprLValues = Useful.list(); List<LValue> otherLValues = Useful.list(); List<Expr> otherExprs = Useful.list(); List<Expr> assignments = Useful.list(); boolean isCompound = assignOp.isSome(); List<Expr> accesses = Useful.list(); Span thatSpan = NodeUtil.getSpan(that); for (Lhs lh : lhs) { Span lhSpan = NodeUtil.getSpan((Expr) lh); Id tempId = DesugarerUtil.gensymId(lhSpan, "e"); VarRef tempVar = ExprFactory.makeVarRef(lhSpan, tempId); exprLValues = Useful.snoc(exprLValues, NodeFactory.makeLValue(lhSpan, tempId)); if (lh instanceof SubscriptExpr) { SubscriptExpr lhsub = (SubscriptExpr) lh; Expr obj = lhsub.getObj(); Span objSpan = NodeUtil.getSpan(obj); List<Expr> subs = lhsub.getSubs(); Id baseTempId = DesugarerUtil.gensymId(objSpan, "b"); VarRef baseTempVar = ExprFactory.makeVarRef(objSpan, baseTempId); otherLValues = Useful.snoc(otherLValues, NodeFactory.makeLValue(objSpan, baseTempId)); otherExprs = Useful.snoc(otherExprs, obj); List<Expr> subTempVars = Useful.list(); for (Expr sub : lhsub.getSubs()) { Span subSpan = NodeUtil.getSpan(sub); Id subTempId = DesugarerUtil.gensymId(subSpan, "s"); subTempVars = Useful.snoc(subTempVars, ExprFactory.makeVarRef(subSpan, subTempId)); otherLValues = Useful.snoc(otherLValues, NodeFactory.makeLValue(subSpan, subTempId)); } otherExprs = Useful.concat(otherExprs, subs); SubscriptExpr newLhs = ExprFactory.makeSubscriptExpr( NodeUtil.getSpan(lhsub), baseTempVar, subTempVars, lhsub.getOp(), lhsub.getStaticArgs()); if (isCompound) accesses = Useful.snoc(accesses, newLhs); assignments = Useful.snoc(assignments, ExprFactory.makeAssignment(thatSpan, newLhs, tempVar)); } else if (lh instanceof FieldRef) { FieldRef lhref = (FieldRef) lh; Expr obj = lhref.getObj(); Span objSpan = NodeUtil.getSpan(obj); Id objTempId = DesugarerUtil.gensymId(objSpan, "o"); VarRef objTempVar = ExprFactory.makeVarRef(objSpan, objTempId); otherLValues = Useful.snoc(otherLValues, NodeFactory.makeLValue(objSpan, objTempId)); otherExprs = Useful.snoc(otherExprs, obj); FieldRef newLhs = ExprFactory.makeFieldRef(NodeUtil.getSpan(lhref), objTempVar, lhref.getField()); if (isCompound) accesses = Useful.snoc(accesses, newLhs); assignments = Useful.snoc(assignments, ExprFactory.makeAssignment(thatSpan, newLhs, tempVar)); } else if (lh instanceof VarRef) { VarRef lhvar = (VarRef) lh; Span varSpan = NodeUtil.getSpan(lhvar); Id varTempId = DesugarerUtil.gensymId(varSpan, "v"); VarRef varTempVar = ExprFactory.makeVarRef(varSpan, varTempId); otherLValues = Useful.snoc(otherLValues, NodeFactory.makeLValue(varSpan, varTempId)); otherExprs = Useful.snoc(otherExprs, lhvar); if (isCompound) accesses = Useful.snoc(accesses, varTempVar); assignments = Useful.snoc(assignments, ExprFactory.makeAssignment(thatSpan, lhvar, tempVar)); } else { bug(that, "Malformed assignment LHS"); } } Expr result = ExprFactory.makeBlock(thatSpan, assignments); if (otherExprs.size() > 0) { Expr otherRhs = ExprFactory.makeMaybeTupleExpr(thatSpan, otherExprs); result = ExprFactory.makeLocalVarDecl(thatSpan, otherLValues, otherRhs, result); } Expr newRhs = isCompound ? ExprFactory.makeOpExpr( NodeUtil.spanTwo(assignOp.unwrap(), rhs), assignOp.unwrap(), ExprFactory.makeMaybeTupleExpr(thatSpan, accesses), rhs) : rhs; result = ExprFactory.makeLocalVarDecl(thatSpan, exprLValues, newRhs, result); return (Expr) recur(result); } else if (lhs.get(0) instanceof SubscriptExpr) { // System.out.println("PreDesugar single subscript expr"); // Subscripted assignment SubscriptExpr lhExpr = (SubscriptExpr) lhs.get(0); Expr obj = lhExpr.getObj(); List<Expr> subs = lhExpr.getSubs(); Option<Op> op = lhExpr.getOp(); List<StaticArg> staticArgs = lhExpr.getStaticArgs(); if (!op.isSome()) bug(lhExpr, "Subscript operator expected"); Op knownOp = op.unwrap(); Expr result = ExprFactory.makeMethodInvocation( that, obj, NodeFactory.makeOp(knownOp, knownOp.getText() + ":="), staticArgs, ExprFactory.makeTupleExpr(NodeUtil.spanTwo(knownOp, rhs), Useful.cons(rhs, subs))); return (Expr) recur(result); } else { // System.out.println("PreDesugar single expr of class " + lhs.get(0).getClass().getName()); return super.forAssignment(that); } }
/** * Compute the reference groups for this loop. Two array references are in the same group with * respect to this loop if - there is a loop-independent dependence between them, or - the * dependence distance(dependence vector entry dl) for this loop is less than some constant * *dist*, and all other dependence vector entries are 0. - the two array refer to the same array * and differ by at most *dist2* in the first subscript dimension, where d is less than or equal * to the cache line size in terms of array elements. All other subscripts must be identical. * Notes: Here we assume dist1 = dist2 = 2 */ private void computeRefGroups( int level, int dist1, int dist2, Table<Declaration, SubscriptExpr> arrayRefs, Vector<RefGroup> refGroups) { if (arrayRefs == null) return; Enumeration<Declaration> ek = arrayRefs.keys(); while (ek.hasMoreElements()) { VariableDecl vd = (VariableDecl) ek.nextElement(); String s = vd.getName(); // array name Object[] v = arrayRefs.getRowArray(vd); // vector of SubscriptExpr's int vi = v.length; for (int j = vi - 1; j >= 0; j--) { SubscriptExpr sr = (SubscriptExpr) v[j]; Vector<LoopHeaderChord> allRelatedLoops = sr.allRelatedLoops(); // ** Incorrect when something like a[(j+i][j] int arls = allRelatedLoops.size(); int firstsub = arls - 1; // ** Making an invalid assumption here // Process the list of references r' with which r has a data // dependence, and r is the source(data flows from r to r'). RefGroup rg = new RefGroup(s, sr); Object[] edges = graph.getEdges(sr); int len = edges.length; for (int i = 0; i < len; i++) { DDEdge edge = (DDEdge) edges[i]; if (edge.isSpatial()) continue; // Condition(1)-(a) in McKinley's paper if (edge.isLoopIndependentDependency()) { // add rP to the RefGroup of r: rg.add(edge); continue; } // Condition(1)-(b) in McKinley's paper computeEdgeRefs(edge, rg, level, dist1); if (arls <= 0) continue; // Condition(2) in McKinley's paper // rlevel is the level of the loop related to the first subscript. int rlevel = allRelatedLoops.elementAt(firstsub).getNestedLevel(); computeEdgeRefs(edge, rg, rlevel, dist2); } boolean isInExistingRefGroups = false; int rgl = refGroups.size(); for (int i = 0; i < rgl; i++) { RefGroup rg2 = refGroups.elementAt(i); if (!rg2.getName().equals(s)) continue; isInExistingRefGroups = rg2.contains(rg); if (isInExistingRefGroups) { rg2.add(rg); break; } } if (!isInExistingRefGroups) refGroups.addElement(rg); } } }