diff --git a/src/plugins/value/domains/traces/traces_domain.ml b/src/plugins/value/domains/traces/traces_domain.ml
index 08d003bee749e6f5819b17ef859c622aaa44416f..1bdad678c7ae85f30348c34cb425d55190891311 100644
--- a/src/plugins/value/domains/traces/traces_domain.ml
+++ b/src/plugins/value/domains/traces/traces_domain.ml
@@ -20,10 +20,11 @@
 (*                                                                        *)
 (**************************************************************************)
 
+module OCamlGraph = Graph
 module Frama_c_File = File
 open Cil_datatype
 
-let loop_mode_at_enter_loop = false
+let loop_mode_at_enter_loop = true
 
 [@@@ warning "-40-42"]
 
@@ -55,9 +56,30 @@ type edge =
   | Loop of Node.t * Stmt.t * Node.t (** start *) * edge list GraphShape.t
   | Msg of Node.t * string
 
+
 (* Frama-C "datatype" for type [inout] *)
 module Edge = struct
 
+  let rec pretty fmt = function
+    | Assign(n,loc,_typ,exp) -> Format.fprintf fmt "@[Assign:@ %a = %a -> %a@]"
+                                  Lval.pretty loc Exp.pretty exp Node.pretty n
+    | Assume(n,e,b) -> Format.fprintf fmt "@[Assume:@ %a %b -> %a@]" Exp.pretty e b Node.pretty n
+    | EnterScope(n,vs) -> Format.fprintf fmt "@[EnterScope:@ %a -> %a@]"
+                            (Pretty_utils.pp_list ~sep:"@ " Varinfo.pretty) vs Node.pretty n
+    | LeaveScope(n,vs) -> Format.fprintf fmt "@[LeaveScope:@ %a -> %a@]"
+                            (Pretty_utils.pp_list ~sep:"@ " Varinfo.pretty) vs Node.pretty n
+    | CallDeclared(n,kf1,exp1,lval1) ->
+      Format.fprintf fmt "@[CallDeclared:@ %a%s(%a) -> %a@]"
+        (Pretty_utils.pp_opt ~pre:"" ~suf:" =@ " Lval.pretty) lval1
+        (Kernel_function.get_name kf1)
+        (Pretty_utils.pp_list ~sep:",@ " Exp.pretty) exp1
+        Node.pretty n
+    | Msg(n,s) -> Format.fprintf fmt "@[%s -> %a@]" s Node.pretty n
+    | Loop(n,_,s,g) -> Format.fprintf fmt "@[<hv 2>@[Loop(%a)@] %a @[-> %a@]@]"
+                         Node.pretty s
+                         (GraphShape.pretty pretty_list) g Node.pretty n
+  and pretty_list fmt l = Pretty_utils.pp_list ~sep:";@ " pretty fmt l
+
   include Datatype.Make_with_collections(struct
       type nonrec t = edge
       let name = "Value.Traces_domain.Edge.t"
@@ -131,24 +153,7 @@ module Edge = struct
 
       let equal = Datatype.from_compare
 
-      let rec pretty fmt = function
-        | Assign(n,loc,_typ,exp) -> Format.fprintf fmt "@[Assign:@ %a = %a -> %a@]"
-                                      Lval.pretty loc Exp.pretty exp Node.pretty n
-        | Assume(n,e,b) -> Format.fprintf fmt "@[Assume:@ %a %b -> %a@]" Exp.pretty e b Node.pretty n
-        | EnterScope(n,vs) -> Format.fprintf fmt "@[EnterScope:@ %a -> %a@]"
-                              (Pretty_utils.pp_list ~sep:"@ " Varinfo.pretty) vs Node.pretty n
-        | LeaveScope(n,vs) -> Format.fprintf fmt "@[LeaveScope:@ %a -> %a@]"
-                              (Pretty_utils.pp_list ~sep:"@ " Varinfo.pretty) vs Node.pretty n
-        | CallDeclared(n,kf1,exp1,lval1) ->
-          Format.fprintf fmt "@[CallDeclared:@ %a%s(%a) -> %a@]"
-            (Pretty_utils.pp_opt ~pre:"" ~suf:" =@ " Lval.pretty) lval1
-            (Kernel_function.get_name kf1)
-            (Pretty_utils.pp_list ~sep:",@ " Exp.pretty) exp1
-             Node.pretty n
-        | Msg(n,s) -> Format.fprintf fmt "@[%s -> %a@]" s Node.pretty n
-        | Loop(n,_,s,g) -> Format.fprintf fmt "@[<hv 2>@[Loop(%a)@] %a @[-> %a@]@]"
-                           Node.pretty s
-                           (GraphShape.pretty (Pretty_utils.pp_list pretty)) g Node.pretty n
+      let pretty = pretty
 
       let hash = function
         | Assume(n,e,b) ->
@@ -188,6 +193,7 @@ end
 
 module EdgeList = struct
   include Datatype.List_with_collections(Edge)(struct let module_name = "Traces_domain.EdgeList" end)
+  let pretty = Edge.pretty_list
   let pretty_debug = pretty
 end
 
@@ -391,64 +397,66 @@ module Traces = struct
     | Msg (_,s) -> Msg(n,s)
     | Loop(_,stmt,s,g) -> Loop(n,stmt,s,g)
 
-  let add_edge c edge =
-    if c == top then c
-    else if c.call_declared_function then c (** forget intermediary state *)
-    else
-      let (current,graph) = get_current c in
-      let same edge' =
-        match edge, edge' with
-        | Assign (_,loc1,typ1,exp1), Assign (_,loc2,typ2,exp2) ->
-          let c = Lval.compare loc1 loc2 in
-          if c <> 0 then false else
-            let c = Typ.compare typ1 typ2 in
-            if c <> 0 then false else
-              Exp.compare exp1 exp2 = 0
-        | Assume(_,e1,b1), Assume(_,e2,b2) ->
-          let c = Exp.compare e1 e2 in
-          if c <> 0 then false else
-            Pervasives.compare b1 b2 = 0
-        | EnterScope(_,vs1),EnterScope(_,vs2) ->
-          let c = Extlib.list_compare Varinfo.compare vs1 vs2 in
+  let same_edge edge edge' =
+    match edge, edge' with
+    | Assign (_,loc1,typ1,exp1), Assign (_,loc2,typ2,exp2) ->
+      let c = Lval.compare loc1 loc2 in
+      if c <> 0 then false else
+        let c = Typ.compare typ1 typ2 in
+        if c <> 0 then false else
+          Exp.compare exp1 exp2 = 0
+    | Assume(_,e1,b1), Assume(_,e2,b2) ->
+      let c = Exp.compare e1 e2 in
+      if c <> 0 then false else
+        Pervasives.compare b1 b2 = 0
+    | EnterScope(_,vs1),EnterScope(_,vs2) ->
+      let c = Extlib.list_compare Varinfo.compare vs1 vs2 in
+      c = 0
+    | LeaveScope(_,vs1), LeaveScope(_,vs2) ->
+      let c = Extlib.list_compare Varinfo.compare vs1 vs2 in
+      c = 0
+    | CallDeclared(_,kf1,exp1,lval1), CallDeclared(_,kf2,exp2,lval2) ->
+      let c = Kernel_function.compare kf1 kf2 in
+      if c <> 0 then false else
+        let c = Extlib.list_compare Exp.compare exp1 exp2 in
+        if c <> 0 then false else
+          let c = Extlib.opt_compare Lval.compare lval1 lval2 in
           c = 0
-        | LeaveScope(_,vs1), LeaveScope(_,vs2) ->
-          let c = Extlib.list_compare Varinfo.compare vs1 vs2 in
-          c = 0
-        | CallDeclared(_,kf1,exp1,lval1), CallDeclared(_,kf2,exp2,lval2) ->
-          let c = Kernel_function.compare kf1 kf2 in
-          if c <> 0 then false else
-            let c = Extlib.list_compare Exp.compare exp1 exp2 in
-            if c <> 0 then false else
-              let c = Extlib.opt_compare Lval.compare lval1 lval2 in
-              c = 0
-        | Msg(_,s1), Msg(_,s2) ->
-          let c = String.compare s1 s2 in
-          c = 0
-        | Loop(_,stmt1,s1,g1), Loop(_,stmt2,s2,g2) ->
-          Stmt.equal stmt1 stmt2 &&
-          Node.equal s1 s2 && GraphShape.equal g1 g2
-        | _ -> false
-      in
-      let reusable = match get_last c with
-        | None -> None
-        | Some last ->
-          let succs = find_succs current last in
-          List.find_opt same succs
-      in
-      match reusable with
+    | Msg(_,s1), Msg(_,s2) ->
+      let c = String.compare s1 s2 in
+      c = 0
+    | Loop(_,stmt1,s1,g1), Loop(_,stmt2,s2,g2) ->
+      Stmt.equal stmt1 stmt2 &&
+      Node.equal s1 s2 && GraphShape.equal g1 g2
+    | _ -> false
+
+  let add_edge_aux c edge =
+    let (current,graph) = get_current c in
+    let reusable = match get_last c with
+      | None -> None
+      | Some last ->
+        let succs = find_succs current last in
+        List.find_opt (same_edge edge) succs
+    in
+    let (n,e) = match reusable with
       | Some e ->
         (** reuse an edge from last *)
         let n = get_node e in
-        let m = Graph.singleton current [e] in
-        let graph = join_graph m graph in
-        move_to n graph c
-      | None ->
-        (** create a new edge *)
-        let n = Node.next () in
-        let e = change_next n edge in
-        let m = Graph.singleton current [e] in
-        let graph = join_graph m graph in
-        move_to n graph c
+        (n,e)
+    | None ->
+      (** create a new edge *)
+      let n = Node.next () in
+      let e = change_next n edge in
+      (n,e)
+    in
+    let m = Graph.singleton current [e] in
+    let graph = join_graph m graph in
+    move_to n graph c
+
+  let add_edge c e =
+    if c == top then c
+    else if c.call_declared_function then c (** forget intermediary state *)
+      else add_edge_aux c e
 
   let copy_edges s old_current_node g state =
     let cache = Node.Hashtbl.create 10 in
@@ -553,14 +561,32 @@ module Traces = struct
     c1.globals != c2.globals ||
     c1.main_formals != c2.main_formals
 
-  let join_path graph c1 c2 =
+  let join_path ?last graph c1 c2 =
     if epsilon_path c1 c2 graph
     then (c2, graph)
     else if epsilon_path c2 c1 graph
     then (c1, graph)
     else
-      let n = Node.next () in
-      let m = Msg(n,"join") in
+      let m = Msg(Node.dumb,"join") in
+      let reusable = match last with
+        | None -> None
+        | Some last ->
+          let succs1 = find_succs c1 last in
+          let succs1 = List.filter (same_edge m) succs1 in
+          let succs2 = find_succs c2 last in
+          let find s1 = List.exists (Edge.equal s1) succs2 in
+          List.find_opt find succs1
+      in
+      let (n,m) = match reusable with
+        | None ->
+          let n = Node.next () in
+          let m = change_next n m in
+          (n,m)
+        | Some m ->
+          (** reuse an edge from last *)
+          let n = get_node m in
+          (n,m)
+      in
       let m1 = Graph.singleton c1 [m] in
       let m2 = Graph.singleton c2 [m] in
       let g = join_graph (join_graph m1 graph) m2 in
@@ -591,7 +617,7 @@ module Traces = struct
         | `Value(l) ->
           let last = join_graph last1 last2 in
           let g = join_graph g1 g2 in
-          let (n,g) = join_path g c1 c2 in
+          let (n,g) = join_path ~last g c1 c2 in
           `Value(OpenLoop(stmt,s,last,n,g,l))
       end
     | UnrollLoop(stmt,l1), UnrollLoop(_,l2) ->
@@ -607,22 +633,25 @@ module Traces = struct
       end
 
   let join c1 c2 =
-    if c1.call_declared_function || c2.call_declared_function
-    then assert false (* should not appended, since nothing append during a call to a not defined function *);
-    match view c1, view c2 with
-    | `Top, _ -> c1
-    | _, `Top -> c2
-    | `Other c1, `Other c2 when is_included c1 c2 -> c2
-    | `Other c1, `Other c2 when is_included c2 c1 -> c1
-    | `Other c1, `Other c2 ->
-      if not_same_origin c1 c2 then assert false
-      else
-        match join_loops c1.current c2.current with
-        | `Top -> top
-        | `Value(current) -> {
-            start = c1.start; current; call_declared_function = false;
-            globals = c1.globals; main_formals = c1.main_formals;
-          }
+    if c1.call_declared_function <> c2.call_declared_function
+    then
+      Value_parameters.fatal "@[<hv>@[At the same time inside and outside a function call:@]@ %a@ %a@]"
+        pretty c1 pretty c2
+    else
+      match view c1, view c2 with
+      | `Top, _ -> c1
+      | _, `Top -> c2
+      | `Other c1, `Other c2 when is_included c1 c2 -> c2
+      | `Other c1, `Other c2 when is_included c2 c1 -> c1
+      | `Other c1, `Other c2 ->
+        if not_same_origin c1 c2 then assert false
+        else
+          match join_loops c1.current c2.current with
+          | `Top -> top
+          | `Value(current) -> {
+              start = c1.start; current; call_declared_function = c1.call_declared_function;
+              globals = c1.globals; main_formals = c1.main_formals;
+            }
 
   let add_loop stmt state =
     let (n,g) = get_current state in
@@ -638,6 +667,7 @@ module Traces = struct
     { state with current }
 
   let widen _ stmt' _ c2 =
+    Format.printf "@[widen@]@.";
     if loop_mode_at_enter_loop
     then c2
     else begin
@@ -1052,6 +1082,65 @@ let project_of_cfg vreturn s =
   (*   ) () *)
 
 
+module GraphDot = OCamlGraph.Graphviz.Dot(struct
+    module V = struct type t = {node : Node.t; loops : Node.t list} end
+    module E = struct
+      open V
+      type t =
+        | Usual of Node.t * Edge.t * Node.t list
+        | Head of Node.t * Node.t list * Node.t * Node.t list
+      let src = function
+        | Usual (src,_,loops) -> {node=src;loops}
+        | Head (src,loops,_,_) -> {node=src;loops}
+      let dst = function
+        | Usual (_,edge,loops) -> {node=Traces.get_node edge;loops}
+        | Head (_,_,s,loops) -> {node=s;loops}
+    end
+    open V
+    open E
+    type t = Graph.t
+    let iter_vertex f g =
+      let rec iter_edge k (l: Node.t list) = function
+        | Loop(_,_,_,g) -> iter_vertex (k::l) g
+        | _ -> ()
+      and iter_vertex l g =
+        GraphShape.iter (fun k e -> f {node=k;loops=l}; List.iter (iter_edge k l) e) g
+      in
+      iter_vertex [] (Graph.shape g)
+    let iter_edges_e f g =
+      let rec iter_edge k l e =
+        f (Usual(k,e,l));
+        match e with
+        | Loop(_,_,s,g) ->
+          let l' = (k::l) in
+          f (Head(k,l,s,l'));
+          iter_vertex l' g
+        | _ -> ()
+      and iter_vertex l g =
+        GraphShape.iter (fun k e -> List.iter (iter_edge k l) e) g
+      in
+      iter_vertex [] (Graph.shape g)
+
+    let graph_attributes _ = []
+    let default_vertex_attributes :
+      t -> OCamlGraph.Graphviz.DotAttributes.vertex list = fun _ -> []
+    let vertex_name v = Format.asprintf "n%a%t" Node.pretty v.node
+        (fun fmt -> List.iter (fun s -> Format.fprintf fmt "L%a" Node.pretty s) v.loops)
+    let vertex_attributes :
+      V.t -> OCamlGraph.Graphviz.DotAttributes.vertex list =
+      fun n -> [`Label (Format.asprintf "%a" Node.pretty n.node)]
+    let get_subgraph :
+      V.t -> OCamlGraph.Graphviz.DotAttributes.subgraph option = fun _ -> None
+    let default_edge_attributes :
+      t -> OCamlGraph.Graphviz.DotAttributes.edge list = fun _ -> []
+    let edge_attributes : E.t -> OCamlGraph.Graphviz.DotAttributes.edge list =
+      function
+      | Usual(_,Loop _,_) -> [`Label (Format.asprintf "leave_loop")]
+      | Usual(_,e,_) -> [`Label (Format.asprintf "%a" Edge.pretty e)]
+      | Head _ -> []
+end)
+
+
 
 let finish_computation () =
   let return_stmt = Kernel_function.find_return (fst (Globals.entry_point ())) in
@@ -1067,7 +1156,11 @@ let finish_computation () =
     Value_parameters.failure "The trace is Bottom can't generate code"
   | `Value state when state == Traces.top ->
     Value_parameters.failure "The trace is TOP can't generate code"
-  | `Value state -> project_of_cfg return_exp state
+  | `Value state ->
+    let out = open_out "traces_domain.dot" in
+    GraphDot.output_graph out (snd (Traces.get_current state));
+    close_out out;
+    project_of_cfg return_exp state
 
 
 (*
diff --git a/tests/value/traces/test4.i b/tests/value/traces/test4.i
index 2e419e2fbe6677f3b5207366d26f84fd8f3a5848..523afaedbda582a3b05aba93dfabb093a4b7d7dc 100644
--- a/tests/value/traces/test4.i
+++ b/tests/value/traces/test4.i
@@ -1,11 +1,27 @@
 /* run.config
-   STDOPT: #"-eva-traces-domain -value-msg-key d-traces -slevel 10" +"-then-last -val -print"
+   STDOPT: #"-eva-traces-domain -value-msg-key d-traces -slevel 10" +"-then-last -val -slevel 10 -print -no-eva-traces-domain"
 */
 
 int main(c){
   int tmp = 0;
-  for(int i = 0; i < 3; i++){
-    tmp ++;
+  for(int i = 0; i < 100; i++){
+    if(i % 2){
+      tmp ++;
+    };
+    //@ slevel merge;
+    if(i % 3){
+      tmp ++;
+    };
+    if(i % 5){
+      tmp ++;
+    };
+    if(i % 7){
+      tmp ++;
+    };
+    if(i % 11){
+      tmp ++;
+    };
+    tmp++;
   }
   return tmp;
 }