Переглянути джерело

[analyzer] don't recurse into var origins during LocalDCE mark phase

closes #10972
Simon Krajewski 2 роки тому
батько
коміт
4990b80967
2 змінених файлів з 53 додано та 8 видалено
  1. 8 2
      src/optimization/analyzer.ml
  2. 45 6
      tests/optimization/src/TestJs.hx

+ 8 - 2
src/optimization/analyzer.ml

@@ -671,8 +671,14 @@ module LocalDce = struct
 				add_var_flag v VUsed;
 				(try expr (get_var_value ctx.graph v) with Not_found -> ());
 				begin match Ssa.get_reaching_def ctx.graph v with
-					| None -> use (get_var_origin ctx.graph v)
-					| Some v -> use v;
+					| None ->
+						(* We don't want to fully recurse for the origin variable because we don't care about its
+						   reaching definition (issue #10972). Simply marking it as being used should be sufficient. *)
+						let v' = get_var_origin ctx.graph v in
+						if not (is_used v') then
+							add_var_flag v' VUsed
+					| Some v ->
+						use v;
 				end
 			end
 		and expr e = match e.eexpr with

+ 45 - 6
tests/optimization/src/TestJs.hx

@@ -274,13 +274,26 @@ class TestJs {
 
 	@:js('
 		var x = TestJs.getInt();
-		var tmp = [x,"foo"];
-		x = TestJs.getInt();
+		TestJs.getInt();
+		TestJs.call([x,"foo"],TestJs.getInt());
+	')
+	static function testMightActuallyNotBeAffected() {
+		var x = getInt();
+		call([x, "foo"], {
+			x = getInt();
+			getInt();
+		});
+	}
+
+	@:js('
+		TestJs.getInt();
+		var tmp = TestJs.getImpureArray();
+		TestJs.getInt();
 		TestJs.call(tmp,TestJs.getInt());
 	')
 	static function testMightBeAffected2() {
 		var x = getInt();
-		call([x, "foo"], {
+		call(getImpureArray(), {
 			x = getInt();
 			getInt();
 		});
@@ -288,7 +301,7 @@ class TestJs {
 
 	@:js('
 		var x = TestJs.getInt();
-		TestJs.call(x++,TestJs.getInt());
+		TestJs.call(x,TestJs.getInt());
 	')
 	static function testMightBeAffected3() {
 		var x = getInt();
@@ -323,6 +336,29 @@ class TestJs {
 		use(b);
 	}
 
+	@:js('
+		var a = Std.random(100);
+		var b = Std.random(100);
+		var c = Std.random(100);
+		var d = Std.random(100);
+		Std.random(100);
+		a = b + c;
+		b -= d;
+		TestJs.use(a + b);
+	')
+	static function testIssue10972() {
+		var a = Std.random(100);
+		var b = Std.random(100);
+		var c = Std.random(100);
+		var d = Std.random(100);
+		var e = Std.random(100);
+		a = b + c;
+		b = b - d;
+		c = c + d;
+		e = b + c;
+		use(a + b);
+	}
+
 	@:js('
 		var a = TestJs.getInt();
 		TestJs.use(a);
@@ -336,7 +372,7 @@ class TestJs {
 	@:js('
 		var a = TestJs.getInt();
 		var b = a;
-		a = TestJs.getInt();
+		TestJs.getInt();
 		TestJs.use(b);
 	')
 	static function testCopyPropagation2() {
@@ -484,6 +520,10 @@ class TestJs {
 	@:pure(false)
 	static function getInt(?d:Dynamic) { return 1; }
 	static function getArray() { return [0, 1]; }
+
+	@:pure(false)
+	static function getImpureArray() { return [0, 1]; }
+
 	@:pure(false)
 	static function call(d1:Dynamic, d2:Dynamic) { return d1; }
 	@:pure(false)
@@ -655,7 +695,6 @@ class TestJs {
 		var _g = c;
 		var value = 42;
 		TestJs.run(function() {_g.process(value);});
-		c = null;
 	')
 	static function testIssue10737_avoidInstanceMethodClosure() {
 		var c = new Issue10737();