Get all the loop instructions

Reviewed By: mbouaziz

Differential Revision: D7776833

fbshipit-source-id: fb292a4
master
Ezgi Çiçek 7 years ago committed by Facebook Github Bot
parent cbdb00a710
commit cb8e734bbb

@ -53,8 +53,6 @@ type instr =
| Declare_locals of (Pvar.t * Typ.t) list * Location.t (** declare local variables *)
[@@deriving compare]
let is_loop = function Ik_dowhile | Ik_while | Ik_for -> true | _ -> false
let equal_instr = [%compare.equal : instr]
let skip_instr = Remove_temps ([], Location.dummy)

@ -23,8 +23,6 @@ type if_kind =
| Ik_switch
[@@deriving compare]
val is_loop : if_kind -> bool
(** An instruction. *)
type instr =
(* Note for frontend writers:

@ -8,11 +8,16 @@
open! IStd
module F = Format
module L = Logging
(* forward dependency analysis for computing set of variables that affect the control flow at each program point
1. perform a control flow dependency analysis CF dependency analysis by
getting all the variables that appear in the control flow path up to that node.
(* forward dependency analysis for computing set of variables that
affect the control flow at each program point
1. perform a control flow dependency analysis by getting all the
variables that appear in the control flow path up to that node.
2. perform a data dependency analysis
3. for each control dependency per node, find its respective data dependencies *)
3. for each control dependency per node, find its respective data
dependencies *)
module VarSet = AbstractDomain.FiniteSet (Var)
module DataDepSet = VarSet
@ -71,41 +76,71 @@ module TransferFunctionsDataDeps (CFG : ProcCfg.S) = struct
end
module ControlDepSet = VarSet
module GuardNodes = AbstractDomain.FiniteSet (Procdesc.Node)
(** Map exit node -> prune nodes in the loop guard *)
module ExitNodeToGuardNodes = AbstractDomain.Map (Procdesc.Node) (GuardNodes)
(** Map loop header node -> prune nodes in the loop guard *)
module LoopHeaderToGuardNodes = AbstractDomain.Map (Procdesc.Node) (GuardNodes)
type loop_control_maps =
{exit_map: ExitNodeToGuardNodes.astate; loop_header_map: LoopHeaderToGuardNodes.astate}
(* forward transfer function for control dependencies *)
module TransferFunctionsControlDeps (CFG : ProcCfg.S) = struct
module CFG = CFG
module Domain = ControlDepSet
type extras = ProcData.no_extras
type extras = loop_control_maps
let exec_instr astate _ _ instr =
match instr with
| Sil.Prune (exp, _, true_branch, if_kind) ->
(* Only keep track of control flow variables for loop prune nodes with the true branch *)
(* For false branches, remove the var from the set for fixpoint *)
let astate' =
Exp.free_vars exp |> Sequence.map ~f:Var.of_id |> Sequence.to_list
|> ControlDepSet.of_list
|>
if (true_branch && Sil.is_loop if_kind) || Language.curr_language_is Java then
Domain.union astate
else Domain.diff astate
in
Exp.program_vars exp |> Sequence.map ~f:Var.of_pvar |> Sequence.to_list
|> ControlDepSet.of_list
|>
if (true_branch && Sil.is_loop if_kind) || Language.curr_language_is Java then
Domain.union astate'
else Domain.diff astate'
| Sil.Load _
| Sil.Store _
| Sil.Call _
| Declare_locals _
| Remove_temps _
| Abstract _
| Nullify _ ->
astate
let get_vars_in_exp exp =
let aux f_free_vars f_to_var =
f_free_vars exp |> Sequence.map ~f:f_to_var |> Sequence.to_list |> ControlDepSet.of_list
in
assert (Domain.is_empty (aux Exp.program_vars Var.of_pvar)) ;
(* We should never have program variables in prune nodes *)
aux Exp.free_vars Var.of_id
(* extract vars from the prune instructions in the node *)
let get_control_vars loop_nodes =
GuardNodes.fold
(fun loop_node acc ->
let instrs = Procdesc.Node.get_instrs loop_node in
Instrs.fold ~init:acc
~f:(fun astate instr ->
match instr with
| Sil.Prune (exp, _, _, _) ->
Domain.union (get_vars_in_exp exp) astate
| _ ->
(* prune nodes include other instructions like REMOVE_TEMPS *)
astate )
instrs )
loop_nodes Domain.empty
(* Each time we pass through
- a loop header, add control variables of its guard nodes
- a loop exit node, remove control variables of its guard nodes
This is correct because the CVs are only going to be temporaries. *)
let exec_instr astate {ProcData.extras= {exit_map; loop_header_map}} (node: CFG.Node.t) _ =
let node = CFG.Node.underlying_node node in
let astate' =
match LoopHeaderToGuardNodes.find_opt node loop_header_map with
| Some loop_nodes ->
L.(debug Analysis Medium) "@\n>>> Loop header %a \n" Procdesc.Node.pp node ;
Domain.union astate (get_control_vars loop_nodes)
| _ ->
astate
in
match ExitNodeToGuardNodes.find_opt node exit_map with
| Some loop_nodes ->
L.(debug Analysis Medium)
"@\n>>>Exit node %a loop nodes=%a @\n\n" Procdesc.Node.pp node GuardNodes.pp loop_nodes ;
get_control_vars loop_nodes |> Domain.diff astate'
| _ ->
astate'
let pp_session_name node fmt =

@ -553,6 +553,8 @@ let checker ({Callbacks.tenv; proc_desc} as callback_args) : Summary.t =
in
let proc_data = ProcData.make_default proc_desc tenv in
let node_cfg = NodeCFG.from_pdesc proc_desc in
(* collect all prune nodes that occur in loop guards, needed for ControlDepAnalyzer *)
let control_maps = Loop_control.get_control_maps node_cfg in
(* computes the data dependencies: node -> (var -> var set) *)
let data_dep_invariant_map =
Control.DataDepAnalyzer.exec_cfg node_cfg proc_data ~initial:Control.DataDepMap.empty
@ -560,6 +562,7 @@ let checker ({Callbacks.tenv; proc_desc} as callback_args) : Summary.t =
in
(* computes the control dependencies: node -> var set *)
let control_dep_invariant_map =
let proc_data = ProcData.make proc_desc tenv control_maps in
Control.ControlDepAnalyzer.exec_cfg node_cfg proc_data ~initial:Control.ControlDepSet.empty
~debug:true
in

@ -0,0 +1,130 @@
(*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module L = Logging
let nid_int n = (Procdesc.Node.get_id n :> int)
type edge_type = {source: Procdesc.Node.t; target: Procdesc.Node.t} [@@deriving compare]
(* Find back-edges by using Tarjan's DFS traversal *)
(* instead of marking, we keep track of the pred node we came from *)
let get_back_edges pdesc =
let rec aux visited back_edges wl =
match wl with
| [] ->
back_edges
| (n, pred, ancestors) :: wl' ->
if Procdesc.NodeSet.mem n visited then
if Procdesc.NodeSet.mem n ancestors then
let back_edges' =
match pred with
| Some n_parent ->
{source= n_parent; target= n} :: back_edges
| None ->
assert false
in
aux visited back_edges' wl'
else aux visited back_edges wl'
else
let ancestors = Procdesc.NodeSet.add n ancestors in
let works =
List.fold ~init:wl'
~f:(fun acc m -> (m, Some n, ancestors) :: acc)
(Procdesc.Node.get_succs n)
in
aux (Procdesc.NodeSet.add n visited) back_edges works
in
let start_wl = [(Procdesc.get_start_node pdesc, None, Procdesc.NodeSet.empty)] in
aux Procdesc.NodeSet.empty [] start_wl
(* Get a set of nodes, `exit_nodes`, that themselves are not in the loop but their predecessors are
Visually:
target
/|
/ .
/ |
. node_in_loop
. |\
. . \
. . exit_node
\ .
\ |
\|
source
Often, exit_node is a prune node. *)
let get_exit_nodes_in_loop loop_nodes =
let succs_of_loop_nodes =
Control.GuardNodes.fold
(fun n acc ->
Procdesc.Node.get_succs n |> Control.GuardNodes.of_list |> Control.GuardNodes.union acc )
loop_nodes Control.GuardNodes.empty
in
Control.GuardNodes.diff succs_of_loop_nodes loop_nodes |> Control.GuardNodes.elements
(* Starting from the start_nodes, find all the nodes upwards until the
target is reached, i.e picking up predecessors which have not been
already added to the found_nodes *)
let get_all_nodes_upwards_until target start_nodes =
let rec aux found_nodes = function
| [] ->
found_nodes
| node :: wl' ->
if Control.GuardNodes.mem node found_nodes then aux found_nodes wl'
else
let preds = Procdesc.Node.get_preds node in
aux (Control.GuardNodes.add node found_nodes) (List.append preds wl')
in
aux (Control.GuardNodes.singleton target) start_nodes
let is_prune node =
match Procdesc.Node.get_kind node with Procdesc.Node.Prune_node _ -> true | _ -> false
(* Get a pair of two maps (exit_to_guard_map, loop_header_to_guard_map) where
exit_to_guard_map : exit_node -> guard_nodes
loop_header_to_guard_map : loop_header (i.e. target of the back edge) -> guard_nodes and
guard_nodes contains the nodes that may affect the looping behavior, i.e.
occur in the guard of the loop conditional. *)
let get_control_maps cfg =
(* get back edges*)
let back_edge_set = get_back_edges cfg in
List.fold_left
~f:(fun Control.({exit_map; loop_header_map}) {source; target} ->
L.(debug Analysis Medium)
"Back-edge source: %i -> target: %i\n" (nid_int source) (nid_int target) ;
let loop_nodes = get_all_nodes_upwards_until target [source] in
let exit_nodes = get_exit_nodes_in_loop loop_nodes in
(* find all the prune nodes in the loop guard *)
let guard_prune_nodes =
get_all_nodes_upwards_until target exit_nodes |> Control.GuardNodes.filter is_prune
in
let exit_map' =
(List.fold_left ~init:exit_map ~f:(fun acc exit_node ->
(*Make sure an exit node only belongs to a single loop *)
assert (not (Control.ExitNodeToGuardNodes.mem exit_node acc)) ;
Control.ExitNodeToGuardNodes.add exit_node guard_prune_nodes acc ))
exit_nodes
in
let loop_map' =
(*Make sure a loop header only belongs to a single loop *)
assert (not (Control.LoopHeaderToGuardNodes.mem target loop_header_map)) ;
Control.LoopHeaderToGuardNodes.add target guard_prune_nodes loop_header_map
in
Control.{exit_map= exit_map'; loop_header_map= loop_map'} )
back_edge_set
~init:
Control.
{ exit_map= Control.ExitNodeToGuardNodes.empty
; loop_header_map= Control.LoopHeaderToGuardNodes.empty }

@ -28,7 +28,9 @@ let facebook = is_yes "@IS_FACEBOOK_TREE@"
let extra_cflags = if "@EXTRA_CFLAGS" = "" then [] else ["@EXTRA_CFLAGS@"]
let common_cflags =
let fatal_warnings = "+3+5+6+8+10+11+12+18+19+20+21+23+26+29+27+32+33+34+35+37+38+39+50+52+57+60" in
let fatal_warnings =
"+3+5+6+8+10+11+12+18+19+20+21+23+26+29+27+32+33+34+35+37+38+39+50+52+57+60"
in
let warnings = fatal_warnings ^ "-4-9-40-41-42-45-48" in
let common_flags =
[ "-g"

@ -0,0 +1,36 @@
/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* t is also in control variables but once we have invariant analysis, it
* shouldn't be */
int break_loop(int p, int t) {
for (int i = 0; i < p; i++) {
// do something
if (t < 0)
break;
// do something
}
return 0;
}
/* t will be in control variables but once we have invariant analysis,
* it shouldn't be. */
int break_loop_with_t(int p, int t) {
for (int i = 0; i < p; i++) {
// do something
if (t < 0) {
t++;
break;
}
// do something
}
return 0;
}
/* calling break_loop with a negative t should give constant
cost. Currently, this doesn't work since we can't do case analysis
on the domain. */
int break_constant(int p) { return break_loop(p, -1); }

@ -15,9 +15,8 @@ int compound_while(int m) {
return j;
}
/* B will be in the loop and executed ~100 times-- we get infinity due to
* control variable problem with gotos */
int simulated_while_with_and(int p) {
/* this should give Theta(100) once we have extract_post in the range */
int simplified_simulated_while_with_and(int p) {
int k = 0;
int j = 0;
B:
@ -28,6 +27,23 @@ B:
return k;
}
/* simulated goto that contains && */
int simulated_while_with_and(int p) {
int i = 0;
int k = 0;
LOOP_COND:
if (k == 0 && i < p) {
goto INCR;
} else {
goto RETURN;
}
INCR:
i++;
goto LOOP_COND;
RETURN:
return i;
}
/* shortcut in the conditional, hence we won't loop, and get constant cost */
int simulated_while_shortcut(int p) {
int k = 0;
@ -43,18 +59,17 @@ B:
/* p should be in control vars */
void while_and_or(int p) {
int i = 0;
while (p == 1 || (i < 30 && i > 0)) {
while (p == 1 || (i < 30 && i >= 0)) {
i++;
}
}
// should be constant cost, but due to p occuring in control vars, we would get
// +oo for p
// should be constant cost
int nested_while_and_or(int p) {
int i = 0;
int j = 3 * i;
while (p == 1 || (i < 30 && i > 0)) {
while (p == 1 || (j < 5 && j > 0)) {
while (p == 1 || (i < 30 && i >= 0)) {
while (p == 1 || (j < 5 && j >= 0)) {
return j;
}
@ -62,3 +77,19 @@ int nested_while_and_or(int p) {
}
return j;
}
/* k,j and i will be control variables for B */
int simulated_nested_loop_with_and(int p) {
int k = 0;
int t = 5;
int j = 0;
for (int i = 0; i < 5; i++) {
B:
t = 3;
j++;
if (k == 0 && j < 100) {
goto B; // continue;
}
}
return k;
}

@ -149,3 +149,56 @@ int simulated_nested_loop_more_expensive(int p) {
}
return k;
}
int real_while() {
int i = 0;
int j = 3 * i;
while (i < 30) {
j = j + i;
i++;
}
return j;
}
// Examples with gotos
/* The following program is the version of real_while() with gotos */
int simulated_while() {
int i = 0;
int j = 3 * i;
LOOP_COND:
if (i < 30) {
goto INCR;
} else {
goto RETURN;
}
INCR:
j = j + i;
i++;
goto LOOP_COND;
RETURN:
return j;
}
/* Conditional inside goto loop */
int simulated_nested_loop_cond_in_goto(int p) {
int k = 0;
int t = 5;
int j = 0;
for (int i = 0; i < 5; i++) {
B:
if (i > 2) {
t = 3;
} else {
t = 4;
}
j++;
if (j >= 100)
j = 0;
else {
goto B; // continue;
}
}
return k;
}

@ -1,14 +1,37 @@
codetoanalyze/c/performance/break.c, break_constant, 0, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 7 + 7 * s$1]
codetoanalyze/c/performance/break.c, break_loop, 1, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 3 + 7 * s$1]
codetoanalyze/c/performance/break.c, break_loop, 1, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 3 + 7 * s$1]
codetoanalyze/c/performance/break.c, break_loop, 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 3 + 7 * s$1]
codetoanalyze/c/performance/break.c, break_loop, 7, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 6 + 7 * s$1]
codetoanalyze/c/performance/break.c, break_loop_with_t, 1, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 3 + 7 * s$1]
codetoanalyze/c/performance/break.c, break_loop_with_t, 1, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 3 + 7 * s$1]
codetoanalyze/c/performance/break.c, break_loop_with_t, 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 3 + 7 * s$1]
codetoanalyze/c/performance/break.c, break_loop_with_t, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 7 * s$1]
codetoanalyze/c/performance/compound_loop_guard.c, compound_while, 3, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, compound_while, 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 7 + 7 * s$1]
codetoanalyze/c/performance/compound_loop_guard.c, compound_while, 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 7 + 7 * s$1]
codetoanalyze/c/performance/compound_loop_guard.c, compound_while, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 7 + 7 * s$1]
codetoanalyze/c/performance/compound_loop_guard.c, compound_while, 6, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 9 + 7 * s$1]
codetoanalyze/c/performance/compound_loop_guard.c, nested_while_and_or, 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/c/performance/compound_loop_guard.c, nested_while_and_or, 4, CONDITION_ALWAYS_FALSE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, nested_while_and_or, 3, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, nested_while_and_or, 3, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, nested_while_and_or, 4, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, nested_while_and_or, 4, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, simplified_simulated_while_with_and, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 601]
codetoanalyze/c/performance/compound_loop_guard.c, simplified_simulated_while_with_and, 5, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, simplified_simulated_while_with_and, 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 602]
codetoanalyze/c/performance/compound_loop_guard.c, simplified_simulated_while_with_and, 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 601]
codetoanalyze/c/performance/compound_loop_guard.c, simplified_simulated_while_with_and, 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 601]
codetoanalyze/c/performance/compound_loop_guard.c, simplified_simulated_while_with_and, 8, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 603]
codetoanalyze/c/performance/compound_loop_guard.c, simulated_nested_loop_with_and, 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/c/performance/compound_loop_guard.c, simulated_nested_loop_with_and, 8, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, simulated_while_shortcut, 5, CONDITION_ALWAYS_FALSE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, simulated_while_with_and, 5, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, simulated_while_with_and, 4, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/compound_loop_guard.c, simulated_while_with_and, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 6 + 7 * s$1]
codetoanalyze/c/performance/compound_loop_guard.c, simulated_while_with_and, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 6 + 7 * s$1]
codetoanalyze/c/performance/compound_loop_guard.c, simulated_while_with_and, 10, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 6 + 7 * s$1]
codetoanalyze/c/performance/compound_loop_guard.c, simulated_while_with_and, 13, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 8 + 7 * s$1]
codetoanalyze/c/performance/compound_loop_guard.c, while_and_or, 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/c/performance/compound_loop_guard.c, while_and_or, 2, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/cost_test.c, loop0_bad, 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1002]
codetoanalyze/c/performance/cost_test.c, loop0_bad, 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1002]
codetoanalyze/c/performance/cost_test.c, loop0_bad, 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1004]
@ -35,8 +58,15 @@ codetoanalyze/c/performance/cost_test_deps.c, loop_no_dep2, 3, EXPENSIVE_EXECUTI
codetoanalyze/c/performance/cost_test_deps.c, loop_no_dep2, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 609]
codetoanalyze/c/performance/cost_test_deps.c, loop_no_dep2, 6, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 611]
codetoanalyze/c/performance/cost_test_deps.c, nested_loop, 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/c/performance/cost_test_deps.c, real_while, 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 214]
codetoanalyze/c/performance/cost_test_deps.c, real_while, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 214]
codetoanalyze/c/performance/cost_test_deps.c, real_while, 7, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 216]
codetoanalyze/c/performance/cost_test_deps.c, simulated_nested_loop, 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/c/performance/cost_test_deps.c, simulated_nested_loop_cond_in_goto, 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/c/performance/cost_test_deps.c, simulated_nested_loop_more_expensive, 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/c/performance/cost_test_deps.c, simulated_while, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 214]
codetoanalyze/c/performance/cost_test_deps.c, simulated_while, 10, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 214]
codetoanalyze/c/performance/cost_test_deps.c, simulated_while, 14, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 216]
codetoanalyze/c/performance/cost_test_deps.c, two_loops, 7, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 545]
codetoanalyze/c/performance/cost_test_deps.c, two_loops, 8, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 545]
codetoanalyze/c/performance/cost_test_deps.c, two_loops, 10, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 547]
@ -52,6 +82,17 @@ codetoanalyze/c/performance/invariant.c, do_k_times, 2, EXPENSIVE_EXECUTION_TIME
codetoanalyze/c/performance/jump_inside_loop.c, jump_inside_loop, 7, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 2002]
codetoanalyze/c/performance/jump_inside_loop.c, jump_inside_loop, 9, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 2002]
codetoanalyze/c/performance/jump_inside_loop.c, jump_inside_loop, 11, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 2004]
codetoanalyze/c/performance/loops.c, if_in_loop, 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 320]
codetoanalyze/c/performance/loops.c, if_in_loop, 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 320]
codetoanalyze/c/performance/loops.c, if_in_loop, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 320]
codetoanalyze/c/performance/loops.c, if_in_loop, 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 320]
codetoanalyze/c/performance/loops.c, if_in_loop, 7, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 320]
codetoanalyze/c/performance/loops.c, if_in_loop, 8, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 320]
codetoanalyze/c/performance/loops.c, if_in_loop, 9, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 320]
codetoanalyze/c/performance/loops.c, if_in_loop, 13, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 322]
codetoanalyze/c/performance/loops.c, if_out_loop, 7, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 508]
codetoanalyze/c/performance/loops.c, if_out_loop, 8, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 508]
codetoanalyze/c/performance/loops.c, if_out_loop, 11, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 513]
codetoanalyze/c/performance/two_loops_symbolic.c, two_loops_symb, 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 4 + 6 * s$1]
codetoanalyze/c/performance/two_loops_symbolic.c, two_loops_symb, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 4 + 6 * s$1]
codetoanalyze/c/performance/two_loops_symbolic.c, two_loops_symb, 6, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 8 + 12 * s$1]

@ -1,12 +1,30 @@
/*
* Copyright (c) 2018 - present Facebook, Inc.
* All rights reserved.
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* With the dominator approach, we can't find any back-edges here
since there are two entry points to the loop and there is no single
back edge to a single loop entry point, but only to the beginning
of the Loop label. With Tarjan's DFS approach, we can identify the
back-edge to the Loop label, and we are able to detect two
exit-edges correctly.
*/
int loop_always(int p) {
int i = 0;
if (p > 0) {
goto Loop;
}
while (i < 5) {
Loop:
i++;
}
return 1;
}
int jump_inside_loop(int p) {
int i = 0;
if (p > 0) {

@ -0,0 +1,37 @@
/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// j is not a control var, so shouldn't affect the bound
int if_in_loop(int t) {
int p = 0;
int j = t + 1;
for (int i = 0; i < 5; i++) {
if (j < 2) {
p++;
} else {
p = 3;
for (int k = 0; k < 10; k++) {
int m = 0;
}
}
}
return p;
}
// j is not a control var, so shouldn't affect the bound
int if_out_loop(int t) {
int p = 10;
int j = t + 10;
if (j < 2) {
p++;
} else {
p = 3;
for (int k = 0; k < 100; k++) {
int m = 0;
}
}
return p;
}

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package codetoanalyze.java.performance;
public class Break{
/* t is also in control variables but once we have invariant analysis, it shouldn't be */
private static int break_loop(int p, int t){
for (int i = 0; i < p; i++) {
// do something
if (t < 0)
break;
// do something
}
return 0;
}
/* calling break_loop with a negative t should give constant
cost. Currently, this doesn't work because parameters are removed
when computing the env size :( */
private static int break_constant(int p)
{
return break_loop(p, -1);
}
}

@ -0,0 +1,43 @@
/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package codetoanalyze.java.performance;
public class Compound_loop{
/* while loop that contains && in the guard. It gives the correct bound */
private static int compound_while(int m) {
int i = 0;
int j = 3 * i;
while (j == 0 && i < m) {
i++;
}
return j;
}
/* p should be in control vars */
private static void while_and_or(int p) {
int i = 0;
while (p == 1 || (i < 30 && i >= 0)) {
i++;
}
}
// should be constant cost
int nested_while_and_or(int p) {
int i = 0;
int j = 3 * i;
while (p == 1 || (i < 30 && i >= 0)) {
while (p == 1 || (j < 5 && j >= 0)) {
return j;
}
i++;
}
return j;
}
}

@ -0,0 +1,122 @@
/*
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package codetoanalyze.java.performance;
public class Cost_test{
// Cost: 5
private static int foo_OK() {
int i, j;
i = 17;
j = 31;
return i + j + 3 + 7;
}
// Cost: 17
private static int bar_OK() {
int j = 0;
j++;
j++;
j++;
j = foo_OK();
j++;
return j;
}
// Cost: 25
private static int cond_OK(int i) {
int x;
if (i < 0) {
x = bar_OK();
} else {
x = 1;
}
return x;
}
// Cost: 5
private static void alias_OK() {
int i = 0, j;
j = i;
i = ++i;
}
// Cost: 7
private static void alias2_OK() {
int i = 0, j, z;
j = 1;
z = 2;
j = i;
i = z;
}
// Cost: 1101
private static int loop0_bad() {
for (int i = 0; i < 100; i++) {
alias2_OK();
}
return 0;
}
// Cost: 1203
private static int loop1_bad() {
int k = 100;
for (int i = 0; i < k; i++) {
alias2_OK();
}
return 0;
}
// Expected: Linear bound
private static int FN_loop2(int k) {
for (int i = 0; i < k; i++) {
alias2_OK();
}
return 0;
}
// Expected: constant, but the bound is a polynomial since we can't
// currently map variables to polynomial symbols
private static int FN_loop3(int k) {
for (int i = k; i < k + 15; i++) {
alias2_OK();
}
return 0;
}
// Cost: 218
// Shows that calling many times non expensive function can
// result in an expensive computation
private static int main_bad() {
int k1, k2, k3, k4;
cond_OK(2);
k1 = bar_OK() + foo_OK() + cond_OK(15) * 2;
k2 = bar_OK() + foo_OK() + cond_OK(17) * 3;
k3 = bar_OK() + foo_OK() + cond_OK(11) * 3;
k4 = bar_OK() + foo_OK() + cond_OK(19) * 3;
return 0;
}
}

@ -0,0 +1,113 @@
/*
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package codetoanalyze.java.performance;
public class Cost_test_deps{
// Loop's execution count doesn't depend on values of p,t,k
private static int loop_no_dep1(int k) {
int p = 0;
int t = 2 + k;
for (int i = 0; i < 100; i++) {
p++;
}
return p;
}
private static int foo(int i, int j) { return i + j; }
// Loop's execution count doesn't depend on values of p,t,k
private static int loop_no_dep2(int k) {
int p = 0;
int t = foo(p, k);
for (int i = 0; i < 100; i++) {
p++;
}
return p;
}
private static void if_bad(int j) {
int p = 10;
if (p < 10 + j) {
p++;
} else {
p = j + 3;
for (int k = 0; k < 100; k++) {
j += 3;
}
}
}
private static int if_bad_loop() {
int p = 10;
for (int j = 0; j < 5; j++) {
if (j < 2) {
p++;
} else {
p = 3;
for (int k = 0; k < 10; k++) {
int m = 0;
}
}
}
return p;
}
private static int two_loops() {
int p = 10;
int k = 3;
int t = 2 + k;
for (int j = 0; j < 6; j++) {
k++;
}
for (int i = 0; i < 100; i++) {
p = 3;
}
return p;
}
private static int loop_despite_inferbo(int p) {
int k = 100;
for (int i = 0; i < k; i++) {
int m = p + 3;
if (m < 14) {
p += 9;
}
}
return p;
}
private static int nested_loop() {
int k = 0;
for (int i = 0; i < 5; i++) {
A:
k = 0;
for (int j = 0; j < 100; j++) {
k = 3;
}
}
return k;
}
private static int real_while()
{
int i = 0;
int j = 3 * i;
while (i < 30){
j=j+i;
i++;
}
return j;
}
}

@ -1,16 +1,47 @@
codetoanalyze/java/performance/ArrayCost.java, boolean ArrayCost.isPowOfTwo_FP(int), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/ArrayCost.java, boolean ArrayCost.isPowOfTwo_FP(int), 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 883]
codetoanalyze/java/performance/ArrayCost.java, boolean ArrayCost.isPowOfTwo_FP(int), 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 882]
codetoanalyze/java/performance/ArrayCost.java, boolean ArrayCost.isPowOfTwo_FP(int), 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 882]
codetoanalyze/java/performance/ArrayCost.java, boolean ArrayCost.isPowOfTwo_FP(int), 12, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 889]
codetoanalyze/java/performance/ArrayCost.java, void ArrayCost.ArrayCost(int[]), 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 6 + 5 * s$7^2]
codetoanalyze/java/performance/ArrayCost.java, void ArrayCost.ArrayCost(int[]), 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 5 * s$7^2]
codetoanalyze/java/performance/JsonArray.java, void JsonArray.addStringEntry(String), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/JsonMap.java, void JsonMap.addEntry(String,JsonType), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/JsonMap.java, void JsonMap.addEntry(String,Object), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/JsonMap.java, void JsonMap.addEntry(String,String), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/JsonMap.java, void JsonMap.addEntry(String,boolean), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/JsonMap.java, void JsonMap.addEntry(String,double), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/JsonMap.java, void JsonMap.addEntry(String,long), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/JsonMap.java, void JsonMap.addKeyToMap(String), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/JsonString.java, JsonString.<init>(String), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/JsonUtils.java, StringBuilder JsonUtils.serialize(String), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/JsonUtils.java, void JsonUtils.escape(StringBuilder,String), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/Break.java, int Break.break_constant(int), 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 8 + 7 * s$1]
codetoanalyze/java/performance/Break.java, int Break.break_loop(int,int), 1, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1 + 7 * s$1]
codetoanalyze/java/performance/Break.java, int Break.break_loop(int,int), 1, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 2 + 7 * s$1]
codetoanalyze/java/performance/Compound_loop.java, int Compound_loop.compound_while(int), 3, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/java/performance/Compound_loop.java, int Compound_loop.compound_while(int), 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 7 * s$1]
codetoanalyze/java/performance/Compound_loop.java, int Compound_loop.compound_while(int), 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 7 * s$1]
codetoanalyze/java/performance/Compound_loop.java, int Compound_loop.nested_while_and_or(int), 3, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/java/performance/Compound_loop.java, int Compound_loop.nested_while_and_or(int), 3, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/java/performance/Compound_loop.java, int Compound_loop.nested_while_and_or(int), 4, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/java/performance/Compound_loop.java, int Compound_loop.nested_while_and_or(int), 4, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/java/performance/Compound_loop.java, void Compound_loop.while_and_or(int), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/Compound_loop.java, void Compound_loop.while_and_or(int), 2, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/java/performance/Cost_test.java, int Cost_test.FN_loop2(int), 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 2 + 12 * s$1]
codetoanalyze/java/performance/Cost_test.java, int Cost_test.FN_loop2(int), 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1 + 12 * s$1]
codetoanalyze/java/performance/Cost_test.java, int Cost_test.FN_loop3(int), 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 2 + 12 * (-s$0 + s$1 + 15)]
codetoanalyze/java/performance/Cost_test.java, int Cost_test.FN_loop3(int), 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 3 + 12 * (-s$0 + s$1 + 15)]
codetoanalyze/java/performance/Cost_test.java, int Cost_test.loop0_bad(), 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1101]
codetoanalyze/java/performance/Cost_test.java, int Cost_test.loop0_bad(), 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1102]
codetoanalyze/java/performance/Cost_test.java, int Cost_test.loop1_bad(), 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1203]
codetoanalyze/java/performance/Cost_test.java, int Cost_test.loop1_bad(), 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1202]
codetoanalyze/java/performance/Cost_test.java, int Cost_test.main_bad(), 8, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 237]
codetoanalyze/java/performance/Cost_test.java, int Cost_test.main_bad(), 8, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 205]
codetoanalyze/java/performance/Cost_test.java, int Cost_test.main_bad(), 9, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 243]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.if_bad_loop(), 12, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 201]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.loop_despite_inferbo(int), 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1302]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.loop_despite_inferbo(int), 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1303]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.loop_despite_inferbo(int), 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1302]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.loop_no_dep1(int), 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 604]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.loop_no_dep1(int), 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 605]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.loop_no_dep2(int), 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 608]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.loop_no_dep2(int), 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 609]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.nested_loop(), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.real_while(), 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 213]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.real_while(), 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 214]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.real_while(), 6, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 213]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.two_loops(), 7, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 544]
codetoanalyze/java/performance/Cost_test_deps.java, int Cost_test_deps.two_loops(), 7, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 545]
codetoanalyze/java/performance/Cost_test_deps.java, void Cost_test_deps.if_bad(int), 6, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 608]
codetoanalyze/java/performance/Cost_test_deps.java, void Cost_test_deps.if_bad(int), 6, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 607]
codetoanalyze/java/performance/JsonMap.java, void JsonMap.addEntry(String,String), 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 239]
codetoanalyze/java/performance/JsonUtils.java, void JsonUtils.escape(StringBuilder,String), 1, BUFFER_OVERRUN_U5, no_bucket, ERROR, [Unknown value from: char[] String.toCharArray(),Assignment,ArrayAccess: Offset: [-oo, +oo] Size: [0, +oo]]
codetoanalyze/java/performance/JsonUtils.java, void JsonUtils.serialize(StringBuilder,String), 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []

Loading…
Cancel
Save