800 likes | 947 Views
Kleene Algebra with Tests (Part 2: Applications). Dexter Kozen Cornell University Workshop on Logic & Computation Nelson, NZ, January 2004. These Lectures. Tutorial on KA and KAT model theory complexity, deductive completeness relation to Hoare logic Practical applications
E N D
Kleene Algebra with Tests(Part 2: Applications) Dexter Kozen Cornell University Workshop on Logic & Computation Nelson, NZ, January 2004
These Lectures • Tutorial on KA and KAT • model theory • complexity, deductive completeness • relation to Hoare logic • Practical applications • compiler optimization • scheme equivalence • static analysis • Theoretical applications • automata on guarded strings & BDDs • algebraic version of Parikh’s theorem • representation • dynamic model theory
def x y x + y = y Kleene Algebra (KA) • idempotent semiring under +, ·, 0, 1 • (p + q) + r = p + (q + r) (pq)r = p(qr) • p + q = q + p p1 = 1p = p • p + p = p p0 = 0p = 0 • p + 0 = p • p(q + r) = pq + pr • (p + q)r = pr + qr • linear inequalities have unique least solutions • p*q = least x such that q + px x • qp* = least x such that q + xp x
Kleene Algebra with Tests (KAT) • (K, B, +, ·, *, ¯, 0, 1) • (K, +, ·, *, 0, 1) is a Kleene algebra • (B, +, ·, ¯, 0, 1) is a Boolean algebra • B K • p,q,r, range over K • a,b,c, range over B
Schematic KAT (SKAT) x:=s;y:=t= y:=t[x/s];x:=s yFV(s) x:=s;y:=t= x:=s;y:=t[x/s] xFV(s) x:=s;x:=t = x:=t[x/s] b[x/t];x:=t = x:=t;b x:=x = 1
Levels of Reasoning • propositional • p1 = q1p2 = q2 . . . pn = qnp = q • schematic (1st order uninterpreted) • x := s ; x := t = x := t[x/s] • 1st order interpreted • i j j k i k
Reasoning with KAT • universal Horn logic • p1 = q1 p2 = q2 . . . pn = qnp = q • premises pi = qi • self-evident assumptions about local behavior • typically involve atomic instructions and tests • conclusionp = q • equivalence of original program and optimized or annotated program • use schematic and interpreted reasoning only to establish validity of premises – most reasoning done at the propositional level
Compiler Optimizations • [Kozen & Patron 00] • dead code elimination • common subexpression elimination • copy propagation • loop hoisting • loop unrolling • reducing nesting depth • induction variable elimination • instruction scheduling • algebraic simplification • elimination of redundant instructions • array bounds check elimination • introduction of sentinels
Typical Premises “two instructions that do not affect each other can be done in either order” load r1,x ; load r2,y = load r2,y ; load r1,x “after loading a value in a register, that register contains that value” load r1,x = load r1,x ; r1=x p = pb “no need to load a value if the register already contains that value” r1=x ; load r1,x = r1=x bp = b
Loop Hoisting • for (i = 0; i < n; i++) { • b[i] = x; • } • i := 0 • : test i < n • jump if false • load r,x • store r,b[i] • i := i + 1 • jump • :
Loop Hoisting • for (i = 0; i < n; i++) { • b[i] = x; • } • i := 0 • : test i < n • jump if false • load r,x • store r,b[i] • i := i + 1 • jump • :
This is of the form w(cupv)*c p = load r,xb = r=x p p b load r,x=load r,x ; r=x p = pb p b b r=x;load r,x=r=x bp = b ub = bu vb = bv
p = pb bp = b ub = bu vb = bv w(cupv)*c = w(cupv(cubv)*c + c) Suffices to show p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = (cupv)*
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cupv(cupv)* + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cupbv(cupv)* + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cupbv(cupbv)* + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cupb(vcupb)*v + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cup(bvcup)*bv + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cup(vbcup)*bv + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cup(vcbup)*bv + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cup(vcubp)*bv + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cup(vcub)*bv + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cup(vcbu)*bv + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cup(vbcu)*bv + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cup(bvcu)*bv + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cupb(vcub)*v + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cupbv(cubv)* + 1
p = pb bp = b ub = bu vb = bv (cupv)* = cupv(cubv)* + 1 (cupv)* = cupv(cubv)* + 1
Loop Unrolling while b do { while b do { p; p; } if b then p; } (bp)*b = (bp(bp + b))*b Key lemma q* = (qn)*(1 + q)n-1
Loop Denesting while b do { if b then { p; p; while c do q; while b c do } if c then q else p; } (bp(cq)*c)*b = bp((b+c)(cq+cp))*(b+c) + b Key lemma (p*q)*p* = (p + q)*
Array Bounds Check Elimination • for (i = 0; i < x.length; i++) { • x[i] := e(i); • } • i := 0 • : test i < n • jump if false • compute e(i) • if i out of bounds then error • x[i] := e(i) • i := i + 1 • jump • :
Array Bounds Check Elimination • for (i = 0; i < x.length; i++) { • x[i] := e(i); • } • i := 0 • : test i < n • jump if false • compute e(i) • if i out of bounds then error • x[i] := e(i) • i := i + 1 • jump • :
Array Bounds Check Elimination a = 0 i b = i < x.length c = ab i is in bounds We have to prove u(bp(cq + cs)v)*b = u(bpqv)*b Introduce a using u = ua, show a and b (and therefore c) hold where needed to eliminate the array bounds check
LU Decomposition with Pivoting[Mateev, Menon, Pingali 01] • Restructuring of matrix operations to take advantage of locality • Def/use analysis fails: transformations break def/use dependencies • MMP develop a new technique, fractal symbolic analysis
y = x; x = 2*x; y = 2*y; y = 2*y; x = 2*x; y = x;
Schematic KAT (SKAT) x:=s;y:=t= y:=t[x/s];x:=s yFV(s) x:=s;y:=t= x:=s;y:=t[x/s] xFV(s) x:=s;x:=t = x:=t[x/s] b[x/t];x:=t = x:=t;b x:=x = 1
y = x; x = 2*x; y = 2*y; y = 2*y; x = 2*x; y = x;
y = x; x = 2*x; y = 2*y; y = 2*y; x = 2*x; y = x; y = 2*x; x = 2*x; x:=s;x:=t =x:=t[x/s]
y = x; x = 2*x; y = 2*y; y = 2*y; x = 2*x; y = x; y = 2*x; x = 2*x; x = 2*x; y = x; x:=s;x:=t =x:=t[x/s]
y = x; x = 2*x; y = 2*y; y = 2*y; x = 2*x; y = x; y = 2*x;x = 2*x; x = 2*x; y = x; x:=s;y:=t =y:=t[x/s];x:=s yFV(s)
for (j = 0; j < n-1; j++) { tmp = a[j]; //swap a[j] = a[j+1]; a[j+1] = tmp; for (i = j+1; i < n; i++) { a[i] = a[i]/a[j]; //update } } for (j = 0; j < n-1; j++) { tmp = a[j];//swap a[j] = a[j+1]; a[j+1] = tmp; } for (j = 0; j < n-1; j++) { for (i = j+1; i < n; i++) { a[i] = a[i]/a[j];//update } }
for (j = 0; j < n-1; j++) { swap(j,j+1); for (i = j+1; i < n; i++) { update(i,j); } } for (j = 0; j < n-1; j++) { swap(j,j+1); } for (j = 0; j < n-1; j++) { for (i = j+1; i < n; i++) { update(i,j); } }
k < i < j update(i,k); swap(i,j); update(j,k); = update(i,k); swap(i,j); update(j,k);
k > j swap(k,k+1); for (i = j+1; i < n; i++) { update(i,j); } = for (i = j+1; i < n; i++) { update(i,j); } swap(k,k+1); Key Lemma pq=qp pq*=q*p
for (j = 0; j < n-1; j++) { swap(j,j+1); for (i = j+1; i < n; i++) { update(i,j); } } for (j = 0; j < n-1; j++) { swap(j,j+1); } for (j = 0; j < n-1; j++) { for (i = j+1; i < n; i++) { update(i,j); } } Key Lemma pq=qp p*q*=(pq)*(p* + q*)
The Dead Variable Paradox Two ways to show x := 1 ; x := 1 = x := 1
The Dead Variable Paradox Method 1 d = “x is a dead variable” p = “x := 1” p = dp x is dead immediately before it is assigned pd = d an assignment to a dead variable is redundant To show pp = p: pp = pdp = dp = p
The Dead Variable Paradox Method 2 c = “x = 1” p = “x := 1” p = pc x has value 1 immediately after the assignment cp= c it’s pointless to assign to x a value it already has To show pp = p: pp = pcp = pc = p
The Dead Variable Paradox c = “x = 1” d = “x is a dead variable” p = “x := 1” p = dp x is dead immediately before it is assigned pd = d an assignment to a dead variable is redundant p = pc x has value 1 immediately after the assignment cp= c it’s pointless to assign a value to x it already has pp = pcdp = pdcp = dc x := 1 ; x := 1 = x is dead ; x = 1 ???