Browse Source

fuse `var x; (* ... *); x = v;` to `var x = v;`
fuse `var x = e; ++e;` to `var x = e++;`

Simon Krajewski 8 years ago
parent
commit
3860f8cc65

+ 51 - 1
src/optimization/analyzerTexpr.ml

@@ -626,6 +626,33 @@ module Fusion = struct
 				end
 				end
 			| {eexpr = TVar(v1,Some e1)} :: el when config.optimize && config.local_dce && state#get_reads v1 = 0 && state#get_writes v1 = 0 ->
 			| {eexpr = TVar(v1,Some e1)} :: el when config.optimize && config.local_dce && state#get_reads v1 = 0 && state#get_writes v1 = 0 ->
 				fuse acc (e1 :: el)
 				fuse acc (e1 :: el)
+			| ({eexpr = TVar(v1,None)} as ev) :: el when not v1.v_capture ->
+				let found = ref false in
+				let rec replace deep e = match e.eexpr with
+					| TBinop(OpAssign,{eexpr = TLocal v2},e2) when v1 == v2 ->
+						if deep then raise Exit;
+						found := true;
+						{ev with eexpr = TVar(v1,Some e2)}
+					| TLocal v2 when v1 == v2 -> raise Exit
+					| _ -> Type.map_expr (replace true) e
+				in
+				begin try
+					let rec loop acc el = match el with
+						| e :: el ->
+							let e = replace false e in
+							if !found then (List.rev (e :: acc)) @ el
+							else loop (e :: acc) el
+						| [] ->
+							List.rev acc
+					in
+					let el = loop [] el in
+					if not !found then raise Exit;
+					state#changed;
+					state#dec_writes v1;
+					fuse acc el
+				with Exit ->
+					fuse (ev :: acc) el
+				end
 			| ({eexpr = TVar(v1,Some e1)} as ev) :: el when can_be_fused v1 e1 ->
 			| ({eexpr = TVar(v1,Some e1)} as ev) :: el when can_be_fused v1 e1 ->
 				let found = ref false in
 				let found = ref false in
 				let blocked = ref false in
 				let blocked = ref false in
@@ -808,7 +835,30 @@ module Fusion = struct
 					fuse acc el
 					fuse acc el
 				with Exit ->
 				with Exit ->
 					if config.fusion_debug then print_endline (Printf.sprintf "NO: %s" (Printexc.get_backtrace()));
 					if config.fusion_debug then print_endline (Printf.sprintf "NO: %s" (Printexc.get_backtrace()));
-					fuse (ev :: acc) el
+					begin match el with
+					| ({eexpr = TUnop((Increment | Decrement) as op,Prefix,{eexpr = TLocal v1})} as e2) :: el ->
+						let found = ref false in
+						let rec replace e = match e.eexpr with
+							| TLocal v2 when v1 == v2 ->
+								if !found then raise Exit;
+								found := true;
+								{e with eexpr = TUnop(op,Postfix,e)}
+							| TIf _ | TSwitch _ | TTry _ | TWhile _ | TFor _ ->
+								raise Exit
+							| _ ->
+								Type.map_expr replace e
+						in
+						begin try
+							let ev = replace ev in
+							if not !found then raise Exit;
+							state#changed;
+							fuse acc (ev :: el)
+						with Exit ->
+							fuse (ev :: acc) (e2 :: el)
+						end
+					| _ ->
+						fuse (ev :: acc) el
+					end
 				end
 				end
 			| {eexpr = TUnop((Increment | Decrement as op,Prefix,({eexpr = TLocal v} as ev)))} as e1 :: e2 :: el ->
 			| {eexpr = TUnop((Increment | Decrement as op,Prefix,({eexpr = TLocal v} as ev)))} as e1 :: e2 :: el ->
 				begin try
 				begin try

+ 8 - 16
tests/optimization/src/Test.hx

@@ -33,9 +33,8 @@ class Test {
 	}
 	}
 
 
 	@:js('
 	@:js('
-		var c_y;
 		var c_x = 12;
 		var c_x = 12;
-		c_y = "foo";
+		var c_y = "foo";
 		var x = 12;
 		var x = 12;
 		c_x = 13;
 		c_x = 13;
 		x = 13;
 		x = 13;
@@ -51,12 +50,10 @@ class Test {
 
 
 	@:js('
 	@:js('
 		var a = 0;
 		var a = 0;
-		var c_y;
-		var c_x;
 		a = 1;
 		a = 1;
 		a = 2;
 		a = 2;
-		c_x = 12;
-		c_y = "foo";
+		var c_x = 12;
+		var c_y = "foo";
 		a = 12;
 		a = 12;
 	')
 	')
 	static function testInlineCtor2() {
 	static function testInlineCtor2() {
@@ -71,14 +68,11 @@ class Test {
 
 
 	@:js('
 	@:js('
 		var a = 0;
 		var a = 0;
-		var b_y;
-		var b_x;
-		var c_y;
 		var c_x = 1;
 		var c_x = 1;
-		c_y = "c";
+		var c_y = "c";
 		a = 1;
 		a = 1;
-		b_x = 2;
-		b_y = "b";
+		var b_x = 2;
+		var b_y = "b";
 		b_x = 1;
 		b_x = 1;
 	')
 	')
 	static function testInlineCtor3() {
 	static function testInlineCtor3() {
@@ -92,10 +86,8 @@ class Test {
 	}
 	}
 
 
 	@:js('
 	@:js('
-		var x_foo;
-		var x_bar;
-		x_foo = 1;
-		x_bar = 2;
+		var x_foo = 1;
+		var x_bar = 2;
 		var y = 1;
 		var y = 1;
 		var z = 2;
 		var z = 2;
 	')
 	')

+ 1 - 3
tests/optimization/src/TestJs.hx

@@ -277,9 +277,7 @@ class TestJs {
 
 
 	@:js('
 	@:js('
 		var x = TestJs.getInt();
 		var x = TestJs.getInt();
-		var x1 = x;
-		++x;
-		TestJs.call(x1,TestJs.getInt());
+		TestJs.call(x++,TestJs.getInt());
 	')
 	')
 	static function testMightBeAffected3() {
 	static function testMightBeAffected3() {
 		var x = getInt();
 		var x = getInt();

+ 1 - 2
tests/optimization/src/issues/Issue2236.hx

@@ -33,9 +33,8 @@ private abstract ArrayRead<T>(Array<T>) {
 
 
 class Issue2236 {
 class Issue2236 {
 	@:js('
 	@:js('
-		var _g_pos;
 		var _g_a = [0];
 		var _g_a = [0];
-		_g_pos = 0;
+		var _g_pos = 0;
 		while(_g_pos < _g_a.length) ++_g_pos;
 		while(_g_pos < _g_a.length) ++_g_pos;
 	')
 	')
 	static function test() {
 	static function test() {