private JExpression maybeAsArrayRef(JExpression arg, int offset) { if (arg instanceof JLiteral) { return arg; } else { return CVectorType.asArrayRef(arg,offset); } }
    static JStatement fixTypesPeeksPopsPushes(JStatement methodBody,            final int inputStride,            final boolean vectorizePush, final int outputStride,            final JExpression pokeBufRef,            final JExpression pokeBufOffset,            final Map<String,CType> vectorIds) {            class fixTypesPeeksPopsPushesVisitor extends StatementQueueVisitor {                JExpression lastLhs = null;   // left hand side of assignment being processed or null if not processing rhs of assignment//                JExpression lastOldLhs = null; // value before converting.                boolean suppressSelector = false; // true to not refer to as vector                boolean replaceStatement = false; // true to discard current statement                boolean constantsToVector = false; // rhs should have vector type, so turn constants in rhs into                                                   // vector constants.                @Override                public Object visitVariableDefinition(JVariableDefinition self,                        int modifiers,                        CType type,                        String ident,                        JExpression expr) {                    if (vectorIds.containsKey(ident)) {//                        System.err.println("VisitVariableDefinition: " //                                + self.getIdent() + " " + self.getType().toString() //                                + " " + self.hashCode());                        if (!(type instanceof CVectorType ||                                 (type instanceof CArrayType  &&                                        ((CArrayType)type).getBaseType() instanceof CVectorType))) {                            CType newType = CVectorType.makeVectortype(type);                            self.setType(newType);//                            System.err.println("                becomes: " //                                    + self.getIdent() + " " + self.getType().toString() //                                    + " " + self.hashCode());                        }                    }                    return self;                }                @Override                public Object visitPopExpression(SIRPopExpression self,                        CType tapeType) {                    if (lastLhs == null) {                        // just a pop not returning a value.                        return self;                    }                    // e = pop();    =>                    // (e).a[0] = pop();                    // (e).a[1] = peek(1 * inputStride);                    // (e).a[2] = peek(2 * inputStride);                    // (e).a[3] = peek(3 * inputStride);                    // lastLhs non-null here.                                        JExpression lhs = lastLhs;                    // left hand side L converted to L.v, but we want just L                     // so as to convert to L.a[0] .. L.a[n] below                    assert lhs instanceof JFieldAccessExpression;                    lhs = ((JFieldAccessExpression)lhs).getPrefix();                                        this.addPendingStatement(                            new JExpressionStatement(                                    new JAssignmentExpression(                                            CVectorType.asArrayRef(lhs,0),                                            new SIRPopExpression(tapeType))));                    for (int i = 1; i < KjcOptions.vectorize / 4; i++) {                        this.addPendingStatement(                                new JExpressionStatement(                                        new JAssignmentExpression(                                                CVectorType.asArrayRef(lhs,i),                                                new SIRPeekExpression(                                                        new JIntLiteral(i * inputStride),                                                        tapeType))));                    }                    replaceStatement = true; // throw out statement built with this return value                    return self;                }                @Override                public Object visitPeekExpression(SIRPeekExpression self,                        CType tapeType, JExpression arg) {                    // e1 = peek(e2);  =>                    // (e1).a[0] = peek((e2) + 0 * inputStride);                    // ...                    // (e1).a[3] = peek((e2) + 3 * inputStride);                    JExpression lhs = lastLhs;                    // left hand side L converted to L.v, but we want just L                     // so as to convert to L.a[0] .. L.a[n] below                    assert lhs instanceof JFieldAccessExpression;                    lhs = ((JFieldAccessExpression)lhs).getPrefix();                                        for (int i = 0; i < KjcOptions.vectorize / 4; i++) {                        this.addPendingStatement(                                new JExpressionStatement(                                        new JAssignmentExpression(                                                CVectorType.asArrayRef(lhs,i),                                                new SIRPeekExpression(                                                        new JAddExpression(arg,                                                                new JIntLiteral(i * inputStride)),                                                        tapeType))));                    }                    replaceStatement = true; // throw out statement built with this return value                    return self;                 }                @Override                public Object visitPushExpression(SIRPushExpression self,                        CType tapeType,                        JExpression arg) {                    if (! vectorizePush) {                        // vector type does not reach push expression.                        return self;                    }                    // push(e)  =>                    // poke((e).a[0], 0 * outputStride);                    // poke((e).a[1], 1 * outputStride);                    // ...                    // poke((e).a[3], 3 * outputStride);                    // (assuming vector length of 4  4-byte words).                    //                    // Variants: at least on Pentiuum + SSE, storing a SSE register                    // seems no faster than storing individual 4-byte fields, so                    // push(e)  =>                    // push((e).a[0]);                    // poke((e).a[1], 1 * outputStride);                    // ...                    // poke((e).a[3], 3 * outputStride);                    //                    // If we know that pushes were to a buffer with sufficient space                    // (rather than to a communication register or to a variable-                    // length buffer) we could write out-of order to the output buffer.                    // For now, just keep a separate buffer for pokes.                    // since pushing the first element of the vector, the poke buffer                    // is of size ((KjcOptions.vectorize / 4) - 1) * outputStride)                    // and the converted code is:                    // push(e)  =>                    // push((e).a[0]);                    // pokeBuf[head + 0 * outputStride] = (e).a[1];                    // ...                    // pokeBuf[head + 2 * outputStride] = (e).a[3];                    // head++;                    //                    // Important case: if work is "push 1" then                     // we do not need to buffer "pokes"                    // We still write as 4-byte fields since                    // a nuisance to do otherwise: would require casting (supported)                    // and pointer dereference (not supported) to use a single vector                    // store.                    for (int i = 1; i < KjcOptions.vectorize / 4; i++) {                        if (outputStride == 1) {                            this.addPendingStatement(                                new JExpressionStatement(                                        new SIRPushExpression(                                                CVectorType.asArrayRef(arg,i),                                                tapeType)));                        } else {//                         if (canPokeToPushTape)                           //                            this.addPendingStatement(//                                    new JExpressionStatement(//                                            new SIRPokeExpression(//                                                    CVectorType.asArrayRef(arg,i),//                                                    i * outputStride,//                                                    tapeType)));                            this.addPendingStatement(                                new JExpressionStatement(                                    new JAssignmentExpression (                                        new JArrayAccessExpression(                                            pokeBufRef,                                            new JAddExpression(                                                pokeBufOffset,                                                new JIntLiteral((i - 1) * (outputStride - 1)))),                                       CVectorType.asArrayRef(arg,i)                                    )));                        }                    }                    if (outputStride != 1) {                        this.addPendingStatement(                            new JExpressionStatement(                                new JPostfixExpression(                                    at.dms.kjc.Constants.OPE_POSTINC,                                    pokeBufOffset)));                    }                    return new SIRPushExpression(                            CVectorType.asArrayRef(arg,0),                            tapeType);                }                @Override                public Object visitAssignmentExpression(JAssignmentExpression self,                    JExpression left, JExpression right) {                // assignment has 4 cases                // (1) vector_value = constant;                // (2) vector_value = complex expression not containing vector                // values;                // (2b) array of vector values = array of scalar values.                // (3) vector_value = expression containing vector value(s);                // (4) non_vector = expression;                boolean leftHasVectorType = hasVectorType(left, vectorIds);                boolean rightHasVectorType = hasVectorType(right, vectorIds);                if (leftHasVectorType && !rightHasVectorType) {                    // setting a vector value from non-vector.                    // _v4F b[N];                    // float j, k;                    // ...                    // b[i] = j + k;                    //                     // ==>                    //                     // _v4F b[N];                    // float j, k;                    // ...                    // tmp = j + k;                    // b[i].a[0] = tmp;                    // ...                    // b[i].a[3] = tmp;                    //                    CType oldType = left.getType();                    if (oldType instanceof CVectorType) {                        // if not first reference to a variable on left, then                        // the JVariableDefinition has probably been updated                        // with the vector type -- since JVariableDefinition's                         // are shared.                        oldType = ((CVectorType) oldType).getBaseType();                    }                    suppressSelector = true;                    JExpression newLeft = (JExpression) left.accept(this);                    // JExpression newLeftArray =                    // CVectorType.asArrayRef(newLeft, i);                    suppressSelector = false;                    if (right instanceof JLiteral) {                        // odd case:                        // x = 2.0f;                        // ==>                        // static const tmp = {2.0f,2.0f,2.0f,2.0f};                        // x.v = tmp;                        // by setting rhs to be a "vector constant"                        newLeft = CVectorType.asVectorRef(newLeft);                        constantsToVector = true;                        JExpression newRight = (JExpression) right.accept(this);                        constantsToVector = false;                        self.setLeft(newLeft);                        self.setRight(newRight);                        return self;                    } else if (oldType instanceof CArrayType) {                        throw new AssertionError("Unimplemented: assign array of vectors from array of scalars");                    } else {                        JVariableDefinition defn = new JVariableDefinition(                                oldType, ThreeAddressCode.nextTemp());                        JStatement decl = new JVariableDeclarationStatement(                                defn);                        JLocalVariableExpression tmp = new JLocalVariableExpression(                                defn);                        addPendingStatement(decl);                        addPendingStatement(new JExpressionStatement(                                new JAssignmentExpression(tmp, right)));                        for (int i = 0; i < KjcOptions.vectorize / 4; i++) {                            addPendingStatement(new JExpressionStatement(                                    new JAssignmentExpression(CVectorType                                            .asArrayRef(newLeft, i), tmp)));                        }                        replaceStatement = true;                        return self;                    }                }                // cases (3) or (4)                JExpression newLeft = (JExpression) left.accept(this);                lastLhs = newLeft;                if (leftHasVectorType) {                    constantsToVector = true;                }                JExpression newRight = (JExpression) right.accept(this);                constantsToVector = false;                lastLhs = null;                self.setLeft(newLeft);                self.setRight(newRight);                return self;            }                @Override                 public Object visitExpressionStatement(JExpressionStatement self, JExpression expr) {                    // Some expressions need to return an expression, but have the statement                    // they are in removed.  Such expressions are all expected to be inside                    // a JExpressionStatement                    replaceStatement = false;                    Object retval = super.visitExpressionStatement(self, expr);                    if (replaceStatement) {                        assert retval instanceof JBlock;                        JBlock b = (JBlock)retval;                        b.removeStatement(0);                        return b;                    } else {                        return retval;                    }                }                /**                 * visits a float literal  (what about double if accepted by parser?)                 */                @Override                public Object visitFloatLiteral(JFloatLiteral self,                                                float value)                {                    if (constantsToVector) {                        return new JVectorLiteral(self);                    }                    return self;                }                /**                 * visits a int literal (what about other int types accepted by parser?)                 */                @Override                public Object visitIntLiteral(JIntLiteral self,                                              int value)                {                    if (constantsToVector) {                        return new JVectorLiteral(self);                    }                   return self;                }                                @Override                public Object visitFieldExpression(JFieldAccessExpression self,                        JExpression left,                        String ident) {                    if (vectorIds.containsKey(getIdent(self)) && ! suppressSelector) {                        return CVectorType.asVectorRef(self);                    } else {                        return self;                    }                }                @Override                public Object visitLocalVariableExpression(JLocalVariableExpression self, String ident) {                    if (vectorIds.containsKey(getIdent(self)) && ! suppressSelector) {                        if (! (self.getType() instanceof CVectorType)) {                            assert self.getVariable() instanceof JVariableDefinition;                            JVariableDefinition newDefn = (JVariableDefinition)self.getVariable().accept(this);                            self = new JLocalVariableExpression(self.getTokenReference(),newDefn);                        }                        return CVectorType.asVectorRef(self);                    } else {                        return self;                    }                }                @Override                public Object visitArrayAccessExpression(JArrayAccessExpression self,                        JExpression prefix,                        JExpression accessor) {                    prefix.accept(this);                    // note if recurr into accessor, need to set constantsToVector temporarily to false                    if (vectorIds.containsKey(getIdent(self)) && ! suppressSelector) {                        // XXX does not currently work for array slices                        return CVectorType.asVectorRef(self);                    } else {                        return self;                    }                }                @Override                public Object visitShiftExpression(JShiftExpression self,                        int oper,                            JExpression left,                        JExpression right) {                        // do not visit right on a shift expression: always int!                        JExpression newLeft = (JExpression)left.accept(this);                        self.setLeft(newLeft);                        return self;                }            }                       return (JStatement)methodBody.accept(new fixTypesPeeksPopsPushesVisitor());            }