let wp_loop ((_, cfg, strategy, _, wenv)) res nloop e get_loop_head =
    let loop_with_cut_pass1 () =
      (* simply propagate both for [entry_edge] and [back_edge] *)
      debug "[wp_loop] propagate";
      let obj = get_loop_head nloop (* loop should be broken by a cut *) in
      let obj =
        if Cil2cfg.is_back_edge e then obj
        else W.tag "BeforeLoop" obj
      in obj
    in
    let loop_with_quantif () =
      if Cil2cfg.is_back_edge e then
        (* Be careful not to use get_only_succ here (infinite loop) *)
        (debug "[wp_loop] cut at back edge";
        W.empty)
      else (* edge going into the loop from outside : quantify *)
          begin
            debug "[wp_loop] quantify";
            let obj = get_loop_head nloop in
            let head = match Cil2cfg.succ_e cfg nloop with
              | [h] -> h
              | _ -> assert false (* already detected in [get_loop_head] *)
            in use_loop_assigns strategy wenv head obj
          end
    in
    if WpStrategy.new_loop_computation strategy
       && R.is_pass1 res
       && loop_with_cut cfg strategy nloop
    then
      loop_with_cut_pass1 ()
    else (* old mode or no inv or pass2 *)
      match Cil2cfg.node_type nloop with
        | Cil2cfg.Vloop (Some true, _) -> (* natural loop (has back edges) *)
            loop_with_quantif ()
        | _ -> (* TODO : print info about the loop *)
            Wp_error.unsupported
                 "non-natural loop without invariant property."