Browse Source

[analyzer] invert local DCE traversal

also don't generate dead blocks
Simon Krajewski 4 năm trước cách đây
mục cha
commit
7d6bb81a46

+ 12 - 9
src/optimization/analyzer.ml

@@ -684,9 +684,8 @@ module LocalDce = struct
 			| _ ->
 				Type.iter expr e
 		in
-		let bb_marked = ref [] in
 		let rec mark bb =
-			bb_marked := bb :: !bb_marked;
+			add_block_flag bb BlockDce;
 			DynArray.iter expr bb.bb_el;
 			DynArray.iter expr bb.bb_phi;
 			terminator_iter expr bb.bb_terminator;
@@ -694,11 +693,11 @@ module LocalDce = struct
 				if not (has_flag edge FlagDce) then begin
 					edge.cfg_flags <- FlagDce :: edge.cfg_flags;
 					if not ctx.config.const_propagation || has_flag edge FlagExecutable then
-						mark edge.cfg_from;
+						mark edge.cfg_to;
 				end
-			) bb.bb_incoming
+			) bb.bb_outgoing
 		in
-		mark ctx.graph.g_exit;
+		mark ctx.graph.g_root;
 		let rec sweep e = match e.eexpr with
 			| TBinop(OpAssign,{eexpr = TLocal v},e2) | TVar(v,Some e2) when not (keep v) ->
 				if has_side_effect e2 then
@@ -710,10 +709,12 @@ module LocalDce = struct
 			| _ ->
 				Type.map_expr sweep e
 		in
-		List.iter (fun bb ->
-			dynarray_map sweep bb.bb_el;
-			bb.bb_terminator <- terminator_map sweep bb.bb_terminator;
-		) !bb_marked;
+		Graph.iter_dom_tree ctx.graph (fun bb ->
+			if has_block_flag bb BlockDce then begin
+				dynarray_map sweep bb.bb_el;
+				bb.bb_terminator <- terminator_map sweep bb.bb_terminator;
+			end
+		)
 end
 
 module Debug = struct
@@ -952,6 +953,7 @@ module Run = struct
 			loop_stack = [];
 			debug_exprs = [];
 			name_stack = [];
+			did_optimize = false;
 		} in
 		ctx
 
@@ -1042,6 +1044,7 @@ module Run = struct
 		with_timer actx.config.detail_times ["->";"var writes"] (fun () -> Graph.infer_var_writes actx.graph);
 		if actx.com.debug then Graph.check_integrity actx.graph;
 		if actx.config.optimize && not actx.has_unbound then begin
+			actx.did_optimize <- true;
 			with_timer actx.config.detail_times ["optimize";"ssa-apply"] (fun () -> Ssa.apply actx);
 			if actx.config.const_propagation then with_timer actx.config.detail_times ["optimize";"const-propagation"] (fun () -> ConstPropagation.apply actx);
 			if actx.config.copy_propagation then with_timer actx.config.detail_times ["optimize";"copy-propagation"] (fun () -> CopyPropagation.apply actx);

+ 16 - 16
src/optimization/analyzerTexprTransformer.ml

@@ -679,7 +679,13 @@ let rec block_to_texpr_el ctx bb =
 		[]
 	else begin
 		let block bb = block_to_texpr ctx bb in
+		let live bb = not ctx.did_optimize || not ctx.config.local_dce || has_block_flag bb BlockDce in
+		let if_live bb = if live bb then Some bb else None in
 		let rec loop bb se =
+			let get_terminator() = match bb.bb_terminator with
+				| TermCondBranch e1 -> e1
+				| _ -> die "" __LOC__
+			in
 			match se with
 			| SESubBlock(bb_sub,bb_next) ->
 				Some bb_next,Some (block bb_sub)
@@ -688,22 +694,16 @@ let rec block_to_texpr_el ctx bb =
 			| SENone ->
 				None,terminator_to_texpr_maybe bb.bb_terminator
 			| SETry(bb_try,_,bbl,bb_next,p) ->
-				Some bb_next,Some (mk (TTry(block bb_try,List.map (fun (v,bb) -> v,block bb) bbl)) ctx.com.basic.tvoid p)
-			| se ->
-				let e1 = match bb.bb_terminator with
-					| TermCondBranch e1 -> e1
-					| _ -> die "" __LOC__
-				in
-				let bb_next,e1_def,t,p = match se with
-					| SEIfThen(bb_then,bb_next,p) -> Some bb_next,TIf(e1,block bb_then,None),ctx.com.basic.tvoid,p
-					| SEIfThenElse(bb_then,bb_else,bb_next,t,p) -> Some bb_next,TIf(e1,block bb_then,Some (block bb_else)),t,p
-					| SESwitch(bbl,bo,bb_next,p) -> Some bb_next,TSwitch(e1,List.map (fun (el,bb) -> el,block bb) bbl,Option.map block bo),ctx.com.basic.tvoid,p
-					| SEWhile(_,bb_body,bb_next,p) ->
-						let e2 = block bb_body in
-						Some bb_next,TWhile(e1,e2,NormalWhile),ctx.com.basic.tvoid,p
-					| _ -> abort (Printf.sprintf "Invalid node exit: %s" (s_expr_pretty e1)) bb.bb_pos
-				in
-				bb_next,Some (mk e1_def t p)
+				if_live bb_next,Some (mk (TTry(block bb_try,List.map (fun (v,bb) -> v,block bb) bbl)) ctx.com.basic.tvoid p)
+			| SEIfThen(bb_then,bb_next,p) ->
+				if_live bb_next,Some (mk (TIf(get_terminator(),block bb_then,None)) ctx.com.basic.tvoid p)
+			| SEIfThenElse(bb_then,bb_else,bb_next,t,p) ->
+				if_live bb_next,Some (mk (TIf(get_terminator(),block bb_then,Some (block bb_else))) t p)
+			| SEWhile(_,bb_body,bb_next,p) ->
+				let e2 = block bb_body in
+				if_live bb_next,Some (mk (TWhile(get_terminator(),e2,NormalWhile)) ctx.com.basic.tvoid p)
+			| SESwitch(bbl,bo,bb_next,p) ->
+				Some bb_next,Some (mk (TSwitch(get_terminator(),List.map (fun (el,bb) -> el,block bb) bbl,Option.map block bo)) ctx.com.basic.tvoid p)
 		in
 		let bb_next,e_term = loop bb bb.bb_syntax_edge in
 		let el = DynArray.to_list bb.bb_el in

+ 18 - 0
src/optimization/analyzerTypes.ml

@@ -43,6 +43,9 @@ module BasicBlock = struct
 		| BKUnreachable             (* The unique unreachable block *)
 		| BKCatch of tvar           (* A catch block *)
 
+	type flag_block =
+		| BlockDce
+
 	type cfg_edge_Flag =
 		| FlagExecutable      (* Used by constant propagation to handle live edges *)
 		| FlagDce             (* Used by DCE to keep track of handled edges *)
@@ -93,6 +96,7 @@ module BasicBlock = struct
 		bb_pos : pos;                         (* The block position *)
 		bb_kind : block_kind;                 (* The block kind *)
 		mutable bb_closed : bool;             (* Whether or not the block has been closed *)
+		mutable bb_flags : int;
 		(* elements *)
 		bb_el : texpr DynArray.t;             (* The block expressions *)
 		bb_phi : texpr DynArray.t;            (* SSA-phi expressions *)
@@ -115,6 +119,18 @@ module BasicBlock = struct
 		| LUEl of int
 		| LUTerm
 
+	let int_of_block_flag (flag : flag_block) =
+		Obj.magic flag
+
+	let add_block_flag bb (flag : flag_block) =
+		bb.bb_flags <- set_flag bb.bb_flags (int_of_block_flag flag)
+
+	let remove_block_flag bb (flag : flag_block) =
+		bb.bb_flags <- unset_flag bb.bb_flags (int_of_block_flag flag)
+
+	let has_block_flag bb (flag : flag_block) =
+		has_flag bb.bb_flags (int_of_block_flag flag)
+
 	let s_block_kind = function
 		| BKRoot -> "BKRoot"
 		| BKNormal -> "BKNormal"
@@ -177,6 +193,7 @@ module BasicBlock = struct
 			bb_type = t;
 			bb_pos = p;
 			bb_closed = false;
+			bb_flags = 0;
 			bb_el = DynArray.create();
 			bb_phi = DynArray.create();
 			bb_terminator = TermNone;
@@ -584,4 +601,5 @@ type analyzer_context = {
 	mutable loop_stack : int list;
 	mutable debug_exprs : (string * texpr) list;
 	mutable name_stack : string list;
+	mutable did_optimize : bool;
 }