Jelajahi Sumber

[analyzer] reconstruct `&&` and `||` where possible

Simon Krajewski 10 tahun lalu
induk
melakukan
4d20b05d11
1 mengubah file dengan 20 tambahan dan 5 penghapusan
  1. 20 5
      analyzer.ml

+ 20 - 5
analyzer.ml

@@ -412,8 +412,18 @@ module Simplifier = struct
 		let rec get_assignment_to v e = match e.eexpr with
 			| TBinop(OpAssign,{eexpr = TLocal v2},e2) when v == v2 -> Some e2
 			| TBlock [e] -> get_assignment_to v e
+			| TIf(e1,e2,Some e3) ->
+				begin match get_assignment_to v e2,get_assignment_to v e3 with
+				| Some e2,Some e3 -> Some ({e with eexpr = TIf(e1,e2,Some e3)})
+				| _ -> None
+				end
 			| _ -> None
 		in
+		let if_or_op e e1 e2 e3 = match e1.eexpr,e3.eexpr with
+			| TUnop(Not,Prefix,e1),TConst (TBool true) -> {e with eexpr = TBinop(OpBoolOr,e1,e2)}
+			| _,TConst (TBool false) -> {e with eexpr = TBinop(OpBoolAnd,e1,e2)}
+			| _ -> {e with eexpr = TIf(e1,e2,Some e3)}
+		in
 		let rec loop e = match e.eexpr with
 			| TBlock el ->
 				let rec loop2 el = match el with
@@ -437,7 +447,7 @@ module Simplifier = struct
 										let e3 = loop e3 in
 										begin match get_assignment_to v e2,get_assignment_to v e3 with
 											| Some e2,Some e3 ->
-												let e_if = {e_if with eexpr = TIf(e1,e2,Some e3)} in
+												let e_if = if_or_op e_if (loop e1) (loop e2) (loop e3) in
 												let e = {e with eexpr = TVar(v,Some e_if)} in
 												loop2 (e :: el)
 											| _ ->
@@ -494,6 +504,11 @@ module Simplifier = struct
 						e1,e2,flag
 				in
 				{e with eexpr = TWhile(e1,e2,flag)}
+			| TIf(e1,e2,Some e3) ->
+				let e1 = loop e1 in
+				let e2 = loop e2 in
+				let e3 = loop e3 in
+				if_or_op e e1 e2 e3
 			| _ ->
 				Type.map_expr loop e
 		in
@@ -775,7 +790,7 @@ module Ssa = struct
 		apply_cond ctx (NotEqual(v,(mk (TConst TNull) t_dynamic p))) *)
 
 	let apply com e =
-		let rec handle_if ctx e econd eif eelse =
+		let rec handle_if ctx f econd eif eelse =
 			let econd = loop ctx econd in
 			(* let cond = eval_cond ctx econd in *)
 			let join = mk_join_node() in
@@ -798,8 +813,7 @@ module Ssa = struct
 					Some eelse
 			in
 			close_join_node ctx join e.epos;
-			let e = {e with eexpr = TIf(econd,eif,eelse)} in
-			e
+			f econd eif eelse
 		and handle_loop_body ctx e =
 			let join_top = mk_join_node() in
 			let join_bottom = mk_join_node() in
@@ -861,7 +875,8 @@ module Ssa = struct
 				{e with eexpr = TLocal v}
 			(* control flow *)
 			| TIf(econd,eif,eelse) ->
-				handle_if ctx e econd eif eelse
+				let f econd eif eelse = {e with eexpr = TIf(econd,eif,eelse)} in
+				handle_if ctx f econd eif eelse
 			| TSwitch(e1,cases,edef) ->
 				let e1 = loop ctx e1 in
 				let join = mk_join_node() in