Module LazyCodeOracle

module LazyCodeOracle: sig .. end

LCT Oracle implementation


Detection, construction and insertion of candidates

val lhs_blk_add : LazyCodeCore.cand_t -> int -> BTLtypes.OrdIS.elt -> unit
val lhs_blk_rem : LazyCodeCore.cand_t -> int -> BTLtypes.OrdIS.elt -> unit
val insert_cand : LazyCodeCore.ckey_t ->
BTLtypes.OrdIS.elt -> Camlcoq.P.t -> bool -> Camlcoq.P.t list -> unit

If the ckey already exist, we check if the candidate was already seen in block pc, ifso, we add it to the offset set, ifnot, we create a singleton.

val erase_latest_cand : LazyCodeCore.ckey_t ->
LazyCodeCore.cand_t ->
LazyCodeCore.cand_t -> BTLtypes.OrdIS.t LazyCodeCore.IM.t -> unit

Compare both cand and old_cand according to their position, update the lhs field of the earlier, and and erase the last one by emptying lhs.

val merge_cand : LazyCodeCore.ckey_t -> LazyCodeCore.cand_t -> unit

Merge an eventually existing candidate at ckey with cand, and erase the latest one.

val make_op_ckey : BTLtypes.OrdIS.elt ->
Camlcoq.P.t ->
AST.trapping_mode -> Op.operation -> Camlcoq.P.t list -> Camlcoq.P.t -> unit

Build a candidate from a btl operation.

val make_load_ckey : BTLtypes.OrdIS.elt ->
Camlcoq.P.t ->
AST.trapping_mode ->
AST.memory_chunk ->
Op.addressing -> Camlcoq.P.t list -> ValueDomain.aval option -> unit
val detect_constants : (Camlcoq.P.t * BTL.iblock_info) list -> unit

Detect constants over the whole function (never erased) A constant that is defined multiple times is still a constant, and in this case we keep the oldest (former) one.

val detect_candidates : Camlcoq.P.t -> BTL.iblock_info -> unit

Detect candidates (transfer function to be used with apply_over_function).

Match and extraction functions for candidates

val match_op_ckey : Op.operation -> Camlcoq.P.t list -> LazyCodeCore.ckey_t -> bool
val match_load_ckey : AST.trapping_mode ->
AST.memory_chunk ->
Op.addressing ->
Camlcoq.P.t list -> ValueDomain.aval option -> LazyCodeCore.ckey_t -> bool
val extract_ckey_args : LazyCodeCore.ckey_t -> Camlcoq.P.t list
val extract_ckey_chk_aaddr : LazyCodeCore.ckey_t -> AST.memory_chunk * ValueDomain.aval option

Local analysis part

val initialize_nonrec_predicates : int -> LazyCodeCore.ckey_t -> LazyCodeCore.cand_t -> unit

Initialize local and non-recursive predicates.

type bb_tf_event_t = 
| E_matchN
| E_matchX
| E_smash
| E_injure
| E_end
val bb_analysis : LazyCodeCore.ckey_t ->
LazyCodeCore.cand_t ->
(int -> int -> int -> bb_tf_event_t -> unit) ->
BTL.iblock -> unit

This function performs an analysis over a single basic-block ib. It has currently two main purposes:

val local_predicates_for_cand : int Maps.PTree.t ->
LazyCodeCore.ckey_t ->
LazyCodeCore.cand_t -> Camlcoq.P.t -> BTL.iblock -> unit

Computes transp, injure, ncomp and xcomp predicates.

val init_and_local_analysis : BTL.code ->
LazyCodeCore.blk_tools_t ->
LazyCodeCore.ckey_t -> LazyCodeCore.cand_t -> unit

Init non-recursive predicates and computes local ones for a whole function.

Predicates transfer functions (to be used with round-robin algorithm)

val d_safe_tf : int Maps.PTree.t ->
Camlcoq.P.t list ->
LazyCodeCore.cand_t -> Camlcoq.P.t -> int -> Bitv.t array -> bool array

D_Safe transfer function sols.(0) should be xdsafe and sols.(1) should be ndsafe.

val u_safe_tf : int Maps.PTree.t ->
Camlcoq.P.t list ->
LazyCodeCore.cand_t -> Camlcoq.P.t -> int -> Bitv.t array -> bool array

U_Safe transfer function sols.(0) should be nusafe and sols.(1) should be xusafe.

val delayed_tf : int Maps.PTree.t ->
Camlcoq.P.t list ->
LazyCodeCore.cand_t -> Camlcoq.P.t -> int -> Bitv.t array -> bool array

Delayed transfer function sols.(0) should be ndelayed and sols.(1) should be xdelayed.

val isolated_tf : int Maps.PTree.t ->
Camlcoq.P.t list ->
LazyCodeCore.cand_t -> Camlcoq.P.t -> int -> Bitv.t array -> bool array

Isolated transfer function sols.(0) should be xisolated and sols.(1) should be nisolated.

val critical_tf : int Maps.PTree.t ->
Camlcoq.P.t list ->
LazyCodeCore.cand_t -> Camlcoq.P.t -> int -> Bitv.t array -> bool array

Critical transfer function sols.(0) should be xcritical and sols.(1) should be ncritical.

val substcrit_tf : int Maps.PTree.t ->
Camlcoq.P.t list ->
LazyCodeCore.cand_t -> Camlcoq.P.t -> int -> Bitv.t array -> bool array

Subst-Crit transfer function sols.(0) should be nsubstcrit and sols.(1) should be xsubstcrit.

Update transfer function with two equations sols.(0) should be xupdate and sols.(1) should be nupdate let update_tf (blk2id: int PTree.t) (succs_list : P.t list) (cand : cand_t) (pc : P.t) (bitvi : int) (sols : Bitv.t array) : bool array = llog 3 "Update analyzing %d\n" (p2i pc); let xupdate = let xcomp = get_predicate_value cand bitvi P_xcomp in if xcomp then xcomp else List.exists (fun succ -> let succi = pget succ blk2id in let ninsert = get_predicate_value cand succi P_ninsert in let nupdate = Bitv.get sols.(1) succi in llog 3 "ninsert is %b and nupdate is %b\n" ninsert nupdate; (not ninsert) && nupdate) succs_list in llog 3 "xupdate is %b\n" xupdate; let nupdate = let ncomp = get_predicate_value cand bitvi P_ncomp in if ncomp then ncomp else let xinsert = get_predicate_value cand bitvi P_xinsert in if xinsert then not xinsert else xupdate in llog 3 "nupdate is %b\n" nupdate; | xupdate; nupdate |

val update_tf : int Maps.PTree.t ->
Camlcoq.P.t list ->
LazyCodeCore.cand_t -> Camlcoq.P.t -> int -> Bitv.t array -> bool array

Update transfer function sols contains the single equation.

Dataflow analysis part

val round_robin : BTL.code ->
LazyCodeCore.blk_tools_t ->
(int Maps.PTree.t ->
Camlcoq.P.t list ->
LazyCodeCore.cand_t -> Camlcoq.P.t -> int -> Bitv.t array -> bool array) ->
LazyCodeCore.lct_predicate_t array -> LazyCodeCore.cand_t -> Bitv.t array

Main dataflow function: a unidirectionnal round-robin worklist (in wl) based dataflow algorithm taking a transfer function tf as parameter, and working on a single candidate cand at a time. The predicates parameter is an array containing the system of equations to evaluate.

Computation of predicates from dataflow equations

val compute_earliestness : BTL.code -> LazyCodeCore.blk_tools_t -> LazyCodeCore.cand_t -> unit
val compute_latestness : BTL.code -> LazyCodeCore.blk_tools_t -> LazyCodeCore.cand_t -> unit

Insertion points predicates and related functions

val compute_critical_insertion : LazyCodeCore.cand_t -> unit
val set_lct_targets : LazyCodeCore.cand_t -> Bitv.t -> Bitv.t -> Bitv.t -> Bitv.t -> unit

Set insertion and replacement points in the candidate record.

val find_substcrit_targets : BTL.code -> LazyCodeCore.blk_tools_t -> LazyCodeCore.cand_t -> unit

Push critical insertion points forward to the first non critical but substitution critical point, in the direction of the control-flow.

val compute_lcm_targets_notrap : LazyCodeCore.cand_t -> unit

Non-trapping insertion points: Insert(n) = Latest(n) /\ not Isolated(n)

val compute_lcm_targets_trap : BTL.code ->
Camlcoq.P.t -> LazyCodeCore.blk_tools_t -> LazyCodeCore.cand_t -> unit

Trapping insertion points:

val dataflow_analysis : BTL.code ->
Camlcoq.P.t ->
LazyCodeCore.blk_tools_t ->
LazyCodeCore.ckey_t -> LazyCodeCore.cand_t -> unit

Main dataflow analysis.

Rewriting part (modifying the CFG once analysis is done)

val insert_node : BTL.iblock -> int -> BTL.iblock -> BTL.iblock

Insert inst in ib at offset_target, using offset as iterator.

val commit_new_block : BTL.code Stdlib.ref -> Camlcoq.P.t -> BTL.iblock -> BTL.iblock_info -> unit
val update_args_ckey : LazyCodeCore.ckey_t -> Camlcoq.P.t list -> LazyCodeCore.ckey_t
val mark_updated_ckey : LazyCodeCore.ckey_t -> Camlcoq.P.t list -> unit
val mark_updated_op : Op.operation -> Camlcoq.P.t list -> Camlcoq.P.t list -> Camlcoq.P.t -> unit
val mark_updated_load : AST.trapping_mode ->
AST.memory_chunk ->
Op.addressing ->
Camlcoq.P.t list -> Camlcoq.P.t list -> ValueDomain.aval option -> unit
val subst_arg : Camlcoq.P.t -> Camlcoq.P.t -> Camlcoq.P.t -> Camlcoq.P.t
val subst_arg_list : Camlcoq.P.t -> Camlcoq.P.t -> Camlcoq.P.t list -> Camlcoq.P.t list
val forward_replace : Camlcoq.P.t ->
int -> LazyCodeCore.ckey_t -> Camlcoq.P.t -> BTL.iblock -> BTL.iblock

Forward substitution of auxiliary variables, and candidate replacement procedure. This function takes the target block pc, the target offset offset_target, and recurses through the basic-block ib. It bases its behavior on the comparison between the current offset offset and offset_target:

val compute_insertion_point : LazyCodeCore.ckey_t -> LazyCodeCore.cand_t -> BTL.iblock -> bool -> int

Compute the insertion point for a given basic-block and candidate.

val build_inst_from_ckey : Camlcoq.P.t -> LazyCodeCore.ckey_t -> BTL.iblock

Translate a virtual candidate to a concrete BTL instruction.

val sr_update_mul : Camlcoq.P.t list -> Camlcoq.P.t -> Camlcoq.P.t -> BTL.iblock -> BTL.iblock
val sr_update_add : Camlcoq.P.t list ->
Camlcoq.P.t list -> Camlcoq.P.t -> Camlcoq.P.t -> BTL.iblock -> BTL.iblock
val strength_reduce_update : LazyCodeCore.blk_tools_t ->
Camlcoq.P.t list ->
Camlcoq.P.t ->
LazyCodeCore.ckey_t -> LazyCodeCore.cand_t -> BTL.iblock -> BTL.iblock

Insert update assignments for strength reduction candidates

val code_motion : BTL.code Stdlib.ref ->
Camlcoq.P.t LazyCodeCore.IM.t ->
LazyCodeCore.ckey_t ->
LazyCodeCore.cand_t -> Bitv.t -> Bitv.t -> bool -> unit

Applies code motion using the information in insert_pred and replace_pred.

val strength_reduction : BTL.code Stdlib.ref ->
LazyCodeCore.blk_tools_t ->
Camlcoq.P.t list -> LazyCodeCore.ckey_t -> LazyCodeCore.cand_t -> unit
val rewrite_graph : BTL.code Stdlib.ref ->
LazyCodeCore.blk_tools_t ->
LazyCodeCore.ckey_t -> LazyCodeCore.cand_t -> unit

Invariant construction part

val build_ival_from_ckey : bool -> LazyCodeCore.ckey_t -> BTL_Invariants.ival
val build_invariants : BTL.code ->
BTL_Invariants.gluemap ->
Camlcoq.P.t ->
LazyCodeCore.blk_tools_t ->
(LazyCodeCore.ckey_t * LazyCodeCore.cand_t) list -> BTL_Invariants.gluemap

Build all the needed invariants for LCT: for each candidate in the list, with a defined vaux: g1 = (N-REPLACE /\ not N-INSERT) \/ (X-REPLACE /\ not X-INSERT) g2 = (not N-ISOLATED /\ not X-ISOLATED) g3 = (not N-DELAYED /\ not X-DELAYED) pp = g1 \/ (g2 /\ g3) if the candidate is trapping: pp = pp /\ N-U-SAFE for blk_pc in CFG if blk_pc <> entry: if candidate is a SRmul && candidate is not immediate SR op && candidate was reduced: r = constant_reg of candidate cop, cpc = obtain the constant operation and first appearance block pc if blk_pc < cpc && r <= last_reg (ie is not a fresh variable) && (blk_pc in pp || r live in blk_pc) add an history invariant based on the constant operation, along with a corresponding liveness entry. if blk_pc in pp: add a gluing invariant based on the candidate operation in ckey

Main part

val identify_blocks : BTL.code -> int Maps.PTree.t * Camlcoq.P.t LazyCodeCore.IM.t

This function builds two mappings from block ids to bitvector ids and its reverse, to facilitate bitvector manipulation.

val initialize : unit -> unit
val prepare_data : BTL.code ->
Camlcoq.P.t ->
BTL.code * BTL_Invariants.gluemap * LazyCodeCore.blk_tools_t *
(LazyCodeCore.ckey_t * LazyCodeCore.cand_t) list
val may_downgrade_ckey : BTL.code ->
LazyCodeCore.blk_tools_t ->
LazyCodeCore.ckey_t -> LazyCodeCore.cand_t -> LazyCodeCore.ckey_t

Downgrading an SRadd candidate to a LCM one. The candidate is downgraded if none of the arguments are strength-reduction auxiliary variables.

val update_ckey : BTL.code ->
LazyCodeCore.blk_tools_t ->
LazyCodeCore.ckey_t -> LazyCodeCore.cand_t -> LazyCodeCore.ckey_t
val lazy_optim : BTL.code Stdlib.ref ->
Camlcoq.P.t ->
LazyCodeCore.blk_tools_t ->
(LazyCodeCore.ckey_t * LazyCodeCore.cand_t) list ->
(LazyCodeCore.ckey_t * LazyCodeCore.cand_t) list
val liveness_and_dce : BTL.code -> BTL.code
val lazy_code_oracle : BTL.code -> Camlcoq.P.t -> BTL.code * BTL_Invariants.gluemap

Launch according to cli args.