Title: Deriving Preconditions for Array Bound Check Elimination
1 Deriving Preconditions for Array Bound Check
Elimination
Dana N. XU Joint work with W.N. CHIN and S.C.
KHOO Dept of Computer Science School of
Computing National University of Singapore
2Array Bound Checks
0
1
2
3
n-3
n-2
n-1
i
arr
sub arr i if (0 ? i lt n) then primeSub (arr,
i) else error out of bound
3Array Bound Checks Elimination
0
1
2
3
n-3
n-2
n-1
i
arr
sub arr i if (0 ? i lt n) then primeSub(A,
i) else error out of bound
4 Motivation
- Checks are expensive.
- Precise Exception Unsafe Checks gt Less
Optimisation - Main difficulties
- recursive procedures
- partial redundancy
5 Our Solutions
- Base on Sized Typing
- Presburger Constraint Solving
- Partial Redundancy via Pre-conditions
Derivation - Utilize Recursive Invariants
6 Outline of Talk
- Motivation
- Language, Sized Types Presburger Solver
- Key Idea
- Bound Checks Elimination Procedure
- Context Synthesis
- Deriving Weakest Pre-Condition
- Converting Preconditions to Checks
- Bound Check Specialisation
7 Language
8 Sized Type and Presburger Arithmetic
9 Binary Search Example
10 Example
getmid(arr,lo,hi) let m(lohi)/2 in let
xL_at_H_at_sub(arr,m) in (m,x)
Polymorphic type getmid (Arr ?,Int,Int) ?
(Int,?) sub (Arr ?,Int) ? ?
11 Example
getmid(arr,lo,hi) let m(lohi)/2 in let
xL_at_H_at_sub(arr,m) in (m,x)
Sized type sub (Arra ?,Inti) ? (?) Size
(agt0)
getmid (Arra ?,Intl,Inth) ? (Intm,?) Size
(agt0) ? (2mltlh) ? (12mgtlh)
12 Key Idea
f(v1,..,vn) L_at_e
ctx(L)
chk(L)
13 pre ? ctx ? chk
- f a x if (xgt5) then a!x
- else 0
- It is safe to remove lower bound check under the
condition - (xgt5) Ç x0
- It is safe to remove higher bound check under the
condition - (xgt5) Ç xlt(length a -1)
14 Example
newsub (Arra ?,Inti,Intj) ? Intr
newsub(arr,i,j) if (0ltiltj) then
L1_at_H1_at_sub(arr,i) else -1
We have ctx(L1) (agt0) ? (0ltiltj)
chk(L1) (igt0)
pre(L1) ? ctx(L1) ? chk(L1) ?(agt0 ?
0ltiltj) ? (igt0) True
15 Example
newsub (Arra ?,Inti,Intj) ? Intr
newsub(arr,i,j) if (0ltiltj) then
L1_at_H1_at_sub(arr,i) else -1
We have ctx(H1) (agt0 ? 0ltiltj)
chk(H1) (ilta)
pre(H1) ? ctx(H1) ? chk(H1) ?(agt0 ?
0ltiltj) ? (ilta) (ilt-1) ? (jlti ? 0lti) ?
(ilta)
16 Check Classification
- Totally redundant
- Unsafe/unknown
- Partially redundant
pre(L) True
pre(L) False
pre(L) ? ctx(L) ? chk(L)
17 Example
getmid(arr,lo,hi) let m(lohi)/2 in let
xL_at_H_at_sub(arr,m) in (m,x)
Sized type sub (Arra ?,Inti) ? ? Size
(agt0)
getmid (Arra ?,Intl,Inth) ? (Intm,?)
Size (agt0) ? (2mltlh) ? (12mgtlh)
18Check Elimination Steps
- Context Synthesis
- Pre-condition Derivation
- From Pre-condition to Check
- Bound Check Specialisation
19Context Synthesis Algorithm
20Check Elimination Steps
- Context Synthesis
- Pre-condition Derivation
- From Pre-condition to Check
- Bound Check Specialisation
21Precondition of Recursion
-
- Make use of size invariant
- Separate analyses for
- first recursive call
- other recursive calls
22 Sized Invariant
look(arr,lo,hi,key) if (lolthi) then let
(m,x)L4_at_H4_at_getmid(arr,lo,hi) in let
tcmp(key,x0) in if (tlt0) then
look(arr,lo,m-1,key) else if (t0) then
m else look(arr,m1,hi,key) else -1
sized type look (Arra Int,Intl,Inth ,Int) ?
Intr size (agt0) ? ( (llth) ? ((lgth) ? (r
-1)) )
(a a) ? (l lt h,l) ? (h lth) ? (22h2h
lt l3l) ? (l2h lt h2l)
inv
23Recursive Procedure
Two Checks chkFst(L4) 0ltlh chkRec(L4)
0ltlh
Two Contexts ctxFst(L4)
(llth) ctxRec(L4) (llth) ? (aa) ?
(llth,l) ? (hlth) ? (22h2hltl3l) ?
(l2hlth2l)
Two Preconditions preFst(L4)
?ctxFst(L4) ? chkFst(L4) (hltl) ? (0ltlh)
preRec(L4) ?ctxRec(L4) ? chkRec(L4) (hltl)
? (0ltllth) ? (l-1 ? h0)
Combined Precondition
pre(L4) preFst(L4) ? preRec(L4)
(hltl) ? (0ltlh ? 0ltl)
24Check Elimination Steps
- Context Synthesis
- Pre-condition Derivation
- From Pre-condition to Check
- Bound Check Specialisation
25Converting Preconditions to Checks
- Interprocedural propagation of safety
pre-condition to become check. - Conversion Formulae used
- chk(C) ? X. pre(L) ? subs(C)
26Converting Preconditions to Checks
look(arr,lo,hi,k) L4_at_H4_at_getmid(arr,lo,hi)
pre(L4) (hltl) ? (0ltlh ? 0ltl) pre(H4)
(hltl) ? (hlta ? lhlt2a)
subs(L5) subs(H5) (l0) ? (hv-1)
bsearch(arr,key) let vlength(arr) in
L5_at_H5_at_look(arr,0,v-1,key)
chk(L5) ? l,h. pre(L4) ? subs(L5) (vlt0)
? (1ltv) chk(H5) ? l,h. pre(H4) ? subs(H5)
(vlt0) ? (vlta,2a)
27Interprocedural Propagation
ctx(L5) ctx(H5) (agt0 ? va)
bsearch(arr,key) let vlength(arr) in
L5_at_H5_at_look(arr,0,v-1,key)
chk(L5) (vlt0 ? 1ltv) chk(H5) (vlt0 ? vlta,2a)
pre(L5) ?ctx(L5) ? chk(L5) ?v ?(agt0
? va) ? (vlt0 ? 1ltv) True pre(H5)
?ctx(H5) ? chk(H5) ?v ?(agt0 ? va) ? (vlt0 ?
vlta,2a) True
28Check Elimination Steps
- Context Synthesis
- Pre-condition Derivation
- From Pre-condition to Check
- Bound Check Specialisation
29Bound Check Specialisation
Guided by each set of Satisfiable Pre-Conditions
getmid(arr,l,h) L_at_H_at_sub(arr,m)
look(arr,lo,hi,k) L4_at_H4_at_getmid(arr,lo,hi)
bsearch(arr,key) let vlength(arr) in
L5_at_H5_at_look(arr,0,v-1,key)
pre(L5) True pre(H5) True
lookL4H4(arr,l,h,k) look(arr,l,h,k) st pre(L4)
? pre(H4) getmidLH(arr,lo,hi)
getmidLH(arr,l,h) getmid(arr,l,h) st pre(L) ?
pre(H) subLH(arr,m)
30 Bound Check Specialization
- Space-Time Trade-Off
- Polyvariant (a version for each context of
use) - Monovariant (a common minimal version)
- Duovariant (a minimal and a maximal version)
31 Cost of Analysis (Constraint Solving)
32 Contributions
- Combined Analysis
- Forward Analysis for Context
- Backward Analysis for Pre-condition
- Recursive Procedures
- Partial Redundancy without Code Motion.
- Guided Bound Check Specialisation.
33Future Work
- Higher-order and polymorphic extension
- Other Safety Checks.
- Component Analysis.
- Imperative Languages
34 Previous Approaches
- Dataflow Analysis
- fast but inaccurate
- Verification Method
- requires theorem proving or checker
- Abstract Interpretation
- focused on total redundancy