فهرست منبع

make dominators for if and switch more accurate

Simon Krajewski 9 سال پیش
والد
کامیت
210677921b
1فایلهای تغییر یافته به همراه22 افزوده شده و 4 حذف شده
  1. 22 4
      analyzer.ml

+ 22 - 4
analyzer.ml

@@ -1113,7 +1113,15 @@ module TexprTransformer = struct
 				let bb_then_next = block bb_then e2 in
 				let bb_else_next = block bb_else e3 in
 				scope();
-				let bb_next = create_node BKNormal bb bb.bb_type bb.bb_pos in (* TODO: dominator might be wrong if either branch is unreachable *)
+				let dead_then = bb_then_next == g.g_unreachable in
+				let dead_else = bb_else_next == g.g_unreachable in
+				let dom = match dead_then,dead_else with
+					| false,false -> bb
+					| true,true -> g.g_unreachable
+					| true,false -> bb_else_next
+					| false,true -> bb_then_next
+				in
+				let bb_next = create_node BKNormal dom bb.bb_type bb.bb_pos in
 				set_syntax_edge g bb (SEIfThenElse(bb_then,bb_else,bb_next,e.etype));
 				add_cfg_edge g bb_then_next bb_next CFGGoto;
 				add_cfg_edge g bb_else_next bb_next CFGGoto;
@@ -1124,14 +1132,14 @@ module TexprTransformer = struct
 				let is_exhaustive = edef <> None || Optimizer.is_exhaustive e1 in
 				let bb,e1 = bind_to_temp bb false e1 in
 				add_texpr g bb (wrap_meta ":cond-branch" e1);
-				let bb_next = create_node BKNormal bb bb.bb_type bb.bb_pos in
-				if not is_exhaustive then add_cfg_edge g bb bb_next CFGGoto;
+				let reachable = ref [] in
 				let make_case e =
 					let scope = increase_scope() in
 					let bb_case = create_node BKConditional bb e.etype e.epos in
 					let bb_case_next = block bb_case e in
 					scope();
-					add_cfg_edge g bb_case_next bb_next CFGGoto;
+					if bb_case_next != g.g_unreachable then
+						reachable := bb_case_next :: !reachable;
 					close_node g bb_case_next;
 					bb_case
 				in
@@ -1148,6 +1156,16 @@ module TexprTransformer = struct
 						add_cfg_edge g bb bb_case (CFGCondElse);
 						Some (bb_case)
 				in
+				let bb_next = if not is_exhaustive then begin
+					let bb_next = create_node BKNormal bb bb.bb_type bb.bb_pos in
+					add_cfg_edge g bb bb_next CFGGoto;
+					bb_next
+				end else match !reachable with
+					| [] -> g.g_unreachable
+					| [bb_case] -> create_node BKNormal bb_case bb.bb_type bb.bb_pos
+					| _ -> create_node BKNormal bb bb.bb_type bb.bb_pos
+				in
+				List.iter (fun bb -> add_cfg_edge g bb bb_next CFGGoto) !reachable;
 				set_syntax_edge g bb (SESwitch(cases,def,bb_next));
 				close_node g bb;
 				bb_next