SLIDE 1 Array Code Generation
- 1. Array code generation
- 2. Surprises in memory access
- 3. Lessons learned
SLIDE 2 Array Code Gen – Model-Driven
VAR i, k, x : INTEGER; A : ARRAY 17 OF INTEGER; ... BEGIN x := A[i A[i]; ]; ... A[k A[k] ] := 2 * x; Des ::= ID | Des ‘[‘ E ‘]’ E ::= Des S ::= Des ‘:=‘ E
- Arrays – don’t know offset at compile time
- what is the value of i or k?
- Is there a base + offset formulation?
- Arrays – don’t know offset at compile time
- what is the value of i
i or k k?
- Is there a base + offset formulation?
SLIDE 3 Base + Offset for Arrays
Array A has its own base and offset
&A = base(A) + offset(A)
But k dictates an offset inside A
&(A[k]) = base(A) + offset(A) + ((k - lowerbound(A lowerbound(A) )) * size(elemtype(A))) &(A[k]) = base(A) + offset(A) + ((k - 0 0) * size(elemtype(A))) &(A[k]) = base(A) + offset(A) + (k * size(elemtype(A)))
Base+offset method motivated by assembler syntax
arraybase = base(A) + offset(A) &(A[k]) = arraybase + (k * size(elemtype(A)))
Two-stage base + offset! Multi-dimensional case is really nasty
SLIDE 4 Assembly – Store Case: A[k] := 2 * x;
ld [gp+4], r1 ! k ; D ::= D [E1] mul r1, 4, r2 ! k * intSize st r2, [gp+80] ! T2 <T3 := 2 * x> ! gp+88 ; E2 ::= E * E add gp, 12, r3 ! addr of A ; S ::= D := E2 ld [gp+80], r2 ! T2 add r3, r2, r4 ! &A[k] r4 ld [gp+84], r0 ! T3 st r0, [r4] ! A[k] := T3
Des ::= ID | Des ‘[‘ E1 ‘]’ E ::= Des S ::= Des ‘:=‘ E2 Des ::= ID | Des ‘[‘ E1 ‘]’ E ::= Des S ::= Des ‘:=‘ E2
SLIDE 5 Assembly – Store Case: A[k] := 2 * x;
ld [gp+4], r1 ! k ; D ::= D [E1] mul r1, 4, r2 ! k * intSize st r2, [gp+80] ! T2 <T3 := 2 * x> ! gp+88 ; E2 ::= E * E add gp, 12, r3 ! addr of A ; S ::= D := E2 ld [gp+80], r2 ! T2 add r3, r2, r4 ! &A[k] r4 ld [gp+84], r0 ! T3 st r0, [r4] ! A[k] := T3
Des ::= ID | Des ‘[‘ E1 ‘]’ E ::= Des S ::= Des ‘:=‘ E2 Des ::= ID | Des ‘[‘ E1 ‘]’ E ::= Des S ::= Des ‘:=‘ E2
SLIDE 6
Assembly – Store Case: A[k] := 2 * x;
ld [gp+4] r1 ! D ::= D [ E1 ] mul r1, 4, r2 add gp, 12, r3 add gp, 12, r3 add r3, r2, r4 add r3, r2, r4 st r4, [gp+80] <T3 = 2 * x> ! E2 ::= E * E ld [gp+84], r0 ! S ::= D := E2 ld [gp+80], r4 ! r4 holds an address! st r0, [r4]
SLIDE 7 Array Code Gen
void emit(VarSTO t, STO a, STO e) { // ArrayRef String indexReg = Machine.getReg(); String addrReg = Machine.getReg(); String resReg = Machine.getReg(); Machine.emitLoad(e, indexReg); // see next section eprint("mul %R, %D, %R", indexReg, a.elemSize(), indexReg); Machine.emitLoadAddress(a, addrReg); // ld addr, not 1st val eprint("add %R, %R, %R", addrReg, indexReg, resReg); Machine.emitStore(resReg, t); // see next section // free registers }
ld [gp+4] r1 ! load index mul r1, 4, r2 add gp, 12, r3 ! “load” &A add r3, r2, r4 st r4, [fp+80] ld [gp+4] r1 ! load index mul r1, 4, r2 add gp, 12, r3 ! “load” &A add r3, r2, r4 st r4, [fp+80]
SLIDE 8
Two “Strange” Memory Manipulations
ld [gp+4] r1 mul r1, 4, r2 add gp, 12, r3 add gp, 12, r3 ! ! load isn load isn’ ’t a load, var addr t a load, var addr add r3, r2, r4 st r4, [gp+80] ! ! stores an stores an address address <T3 = 2 * x> ld [gp+84], r0 ld [gp+80], r1 ld [gp+80], r1 ! r1 holds a var r1 holds a var address! address! st r0, [r1] [r1] ! double indirection ! double indirection ! emitStore doesn ! emitStore doesn’ ’t work t work ! this way ! this way
SLIDE 9 Two “Strange” Memory Manipulations
ld [gp+4] r1 mul r1, 4, r2 add gp, 12, r3 add gp, 12, r3 ! ! load isn load isn’ ’t a load, var addr t a load, var addr add r3, r2, r4 st r4, [gp+80] ! ! stores an stores an address address <T3 = 2 * x> ld [gp+84], r0 ld [gp+80], r1 ld [gp+80], r1 ! r1 holds a var r1 holds a var address! address! st r0, [r1] [r1] ! double indirection ! double indirection ! emitStore doesn ! emitStore doesn’ ’t work t work ! this way ! this way
void emitLoadAddress(VarSTO var, Register reg) { if (var.isReference()) // array elem, class field ref emitLoad(var, reg); // get addr out of memory else if (var.isVariable()) // for arrays & VAR args eprint("add %R, %D, %R", var.base(), var.offset(), reg); else /* error */ } // Have to rewrite emitStore to store // to reg, b+o already done
SLIDE 10 Extended emitLoad (EmitLoadValue)
void emitLoadValue(STO var, Register reg) { // was emitLoad if (var.isConstant()) // Constants are a "mode", too. eprint("set %D, %R", var.value(), reg); // value() has toString() else if (var.isReference()) { String r = getReg(); emitLoad(var, r); // load addr eprint("ld [%R], %R", r, reg); // deref freeReg(r); } else if (var.isVariable()) emitLoad(var, reg); else /* error */ }
Requires replacing existing emitLoad calls with emitLoadValue Requires replacing existing emitLoad calls with emitLoadValue
SLIDE 11 Lessons Learned
- Several problems with our “rules”
- base + offset challenged
- single-STO per-rule challenged
- load/store storage model challenged
- Generalized rules from new domain insights
- double base + offset
- introduced notion of “address” STO
- generalized value load/store for addresses and
constants
- Kept our rules by generalizing them to
conform to realities of domain
- “bend but don’t break”, refactor code