| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 import 'sexpr_unstringifier.dart'; | |
| 6 import "package:expect/expect.dart"; | |
| 7 import 'package:compiler/src/cps_ir/cps_ir_nodes.dart'; | |
| 8 import 'package:compiler/src/cps_ir/cps_ir_nodes_sexpr.dart'; | |
| 9 import 'package:compiler/src/cps_ir/optimizers.dart'; | |
| 10 | |
| 11 // The 'read in loop' IR tests the most basic case of redundant phi removal | |
| 12 // and represents the following source code: | |
| 13 // | |
| 14 // void main() { | |
| 15 // int j = 42; | |
| 16 // for (int i = 0; i < 2; i++) { | |
| 17 // print(j.toString()); | |
| 18 // } | |
| 19 // } | |
| 20 | |
| 21 String READ_IN_LOOP_IN = """ | |
| 22 (FunctionDefinition main () () return | |
| 23 (LetPrim (v0 (Constant (Int 42))) | |
| 24 (LetPrim (v1 (Constant (Int 0))) | |
| 25 (LetCont | |
| 26 ((rec k0 (v2 v3) | |
| 27 (LetCont | |
| 28 ((k1 () | |
| 29 (LetPrim (v4 (Constant (Null))) | |
| 30 (InvokeContinuation return (v4)))) | |
| 31 (k2 () | |
| 32 (LetCont | |
| 33 ((k3 (v5) | |
| 34 (LetCont | |
| 35 ((k4 (v6) | |
| 36 (LetPrim (v7 (Constant (Int 1))) | |
| 37 (LetCont | |
| 38 ((k5 (v8) | |
| 39 (InvokeContinuation rec k0 (v2 v8)))) | |
| 40 (InvokeMethod v3 + (v7) k5))))) | |
| 41 (InvokeStatic print (v5) k4)))) | |
| 42 (InvokeMethod v2 toString () k3)))) | |
| 43 (LetPrim (v9 (Constant (Int 2))) | |
| 44 (LetCont | |
| 45 ((k6 (v10) | |
| 46 (Branch (IsTrue v10) k2 k1))) | |
| 47 (InvokeMethod v3 < (v9) k6)))))) | |
| 48 (InvokeContinuation k0 (v0 v1)))))) | |
| 49 """; | |
| 50 | |
| 51 String READ_IN_LOOP_OUT = """ | |
| 52 (FunctionDefinition main () () return | |
| 53 (LetPrim (v0 (Constant (Int 42))) | |
| 54 (LetPrim (v1 (Constant (Int 0))) | |
| 55 (LetCont | |
| 56 ((rec k0 (v2) | |
| 57 (LetCont | |
| 58 ((k1 () | |
| 59 (LetPrim (v3 (Constant (Null))) | |
| 60 (InvokeContinuation return (v3)))) | |
| 61 (k2 () | |
| 62 (LetCont | |
| 63 ((k3 (v4) | |
| 64 (LetCont | |
| 65 ((k4 (v5) | |
| 66 (LetPrim (v6 (Constant (Int 1))) | |
| 67 (LetCont | |
| 68 ((k5 (v7) | |
| 69 (InvokeContinuation rec k0 (v7)))) | |
| 70 (InvokeMethod v2 + (v6) k5))))) | |
| 71 (InvokeStatic print (v4) k4)))) | |
| 72 (InvokeMethod v0 toString () k3)))) | |
| 73 (LetPrim (v8 (Constant (Int 2))) | |
| 74 (LetCont | |
| 75 ((k6 (v9) | |
| 76 (Branch (IsTrue v9) k2 k1))) | |
| 77 (InvokeMethod v2 < (v8) k6)))))) | |
| 78 (InvokeContinuation k0 (v1)))))) | |
| 79 """; | |
| 80 | |
| 81 // The 'inner loop' IR represents the following source code: | |
| 82 // | |
| 83 // void main() { | |
| 84 // int j = 42; | |
| 85 // for (int i = 0; i < 2; i++) { | |
| 86 // for (int k = 0; k < 2; k++) { | |
| 87 // print(i.toString()); | |
| 88 // } | |
| 89 // } | |
| 90 // print(j.toString()); | |
| 91 // } | |
| 92 // | |
| 93 // This test case ensures that iterative optimization works: first, v8 and v9 | |
| 94 // are removed from k5, and only then can k0 be optimized as well. | |
| 95 | |
| 96 const String INNER_LOOP_IN = """ | |
| 97 (FunctionDefinition main () () return | |
| 98 (LetPrim (v0 (Constant (Int 42))) | |
| 99 (LetPrim (v1 (Constant (Int 0))) | |
| 100 (LetCont | |
| 101 ((rec k0 (v2 v3) | |
| 102 (LetCont | |
| 103 ((k1 () | |
| 104 (LetCont | |
| 105 ((k2 (v4) | |
| 106 (LetCont | |
| 107 ((k3 (v5) | |
| 108 (LetPrim (v6 (Constant (Null))) | |
| 109 (InvokeContinuation return (v6))))) | |
| 110 (InvokeStatic print (v4) k3)))) | |
| 111 (InvokeMethod v2 toString () k2))) | |
| 112 (k4 () | |
| 113 (LetPrim (v7 (Constant (Int 0))) | |
| 114 (LetCont | |
| 115 ((rec k5 (v8 v9 v10) | |
| 116 (LetCont | |
| 117 ((k6 () | |
| 118 (LetPrim (v11 (Constant (Int 1))) | |
| 119 (LetCont | |
| 120 ((k7 (v12) | |
| 121 (InvokeContinuation rec k0 (v8 v12)
))) | |
| 122 (InvokeMethod v9 + (v11) k7)))) | |
| 123 (k8 () | |
| 124 (LetCont | |
| 125 ((k9 (v13) | |
| 126 (LetCont | |
| 127 ((k10 (v14) | |
| 128 (LetPrim (v15 (Constant (Int 1
))) | |
| 129 (LetCont | |
| 130 ((k11 (v16) | |
| 131 (InvokeContinuation r
ec k5 (v8 v9 v16)))) | |
| 132 (InvokeMethod v10 + (v15)
k11))))) | |
| 133 (InvokeStatic print (v13) k10)))) | |
| 134 (InvokeMethod v9 toString () k9)))) | |
| 135 (LetPrim (v17 (Constant (Int 2))) | |
| 136 (LetCont | |
| 137 ((k12 (v18) | |
| 138 (Branch (IsTrue v18) k8 k6))) | |
| 139 (InvokeMethod v10 < (v17) k12)))))) | |
| 140 (InvokeContinuation k5 (v2 v3 v7)))))) | |
| 141 (LetPrim (v19 (Constant (Int 2))) | |
| 142 (LetCont | |
| 143 ((k13 (v20) | |
| 144 (Branch (IsTrue v20) k4 k1))) | |
| 145 (InvokeMethod v3 < (v19) k13)))))) | |
| 146 (InvokeContinuation k0 (v0 v1)))))) | |
| 147 """; | |
| 148 | |
| 149 const String INNER_LOOP_OUT = """ | |
| 150 (FunctionDefinition main () () return | |
| 151 (LetPrim (v0 (Constant (Int 42))) | |
| 152 (LetPrim (v1 (Constant (Int 0))) | |
| 153 (LetCont | |
| 154 ((rec k0 (v2) | |
| 155 (LetCont | |
| 156 ((k1 () | |
| 157 (LetCont | |
| 158 ((k2 (v3) | |
| 159 (LetCont | |
| 160 ((k3 (v4) | |
| 161 (LetPrim (v5 (Constant (Null))) | |
| 162 (InvokeContinuation return (v5))))) | |
| 163 (InvokeStatic print (v3) k3)))) | |
| 164 (InvokeMethod v0 toString () k2))) | |
| 165 (k4 () | |
| 166 (LetPrim (v6 (Constant (Int 0))) | |
| 167 (LetCont | |
| 168 ((rec k5 (v7) | |
| 169 (LetCont | |
| 170 ((k6 () | |
| 171 (LetPrim (v8 (Constant (Int 1))) | |
| 172 (LetCont | |
| 173 ((k7 (v9) | |
| 174 (InvokeContinuation rec k0 (v9)))) | |
| 175 (InvokeMethod v2 + (v8) k7)))) | |
| 176 (k8 () | |
| 177 (LetCont | |
| 178 ((k9 (v10) | |
| 179 (LetCont | |
| 180 ((k10 (v11) | |
| 181 (LetPrim (v12 (Constant (Int 1
))) | |
| 182 (LetCont | |
| 183 ((k11 (v13) | |
| 184 (InvokeContinuation r
ec k5 (v13)))) | |
| 185 (InvokeMethod v7 + (v12) k
11))))) | |
| 186 (InvokeStatic print (v10) k10)))) | |
| 187 (InvokeMethod v2 toString () k9)))) | |
| 188 (LetPrim (v14 (Constant (Int 2))) | |
| 189 (LetCont | |
| 190 ((k12 (v15) | |
| 191 (Branch (IsTrue v15) k8 k6))) | |
| 192 (InvokeMethod v7 < (v14) k12)))))) | |
| 193 (InvokeContinuation k5 (v6)))))) | |
| 194 (LetPrim (v16 (Constant (Int 2))) | |
| 195 (LetCont | |
| 196 ((k13 (v17) | |
| 197 (Branch (IsTrue v17) k4 k1))) | |
| 198 (InvokeMethod v2 < (v16) k13)))))) | |
| 199 (InvokeContinuation k0 (v1)))))) | |
| 200 """; | |
| 201 | |
| 202 // There are no redundant phis in the 'basic loop' IR, and this test ensures | |
| 203 // simply that the optimization does not alter the IR. It represents the | |
| 204 // following program: | |
| 205 // | |
| 206 // void main() { | |
| 207 // for (int i = 0; i < 2; i++) { | |
| 208 // print(i.toString()); | |
| 209 // } | |
| 210 // } | |
| 211 | |
| 212 String BASIC_LOOP_IN = """ | |
| 213 (FunctionDefinition main () () return | |
| 214 (LetPrim (v0 (Constant (Int 0))) | |
| 215 (LetCont | |
| 216 ((rec k0 (v1) | |
| 217 (LetCont | |
| 218 ((k1 () | |
| 219 (LetPrim (v2 (Constant (Null))) | |
| 220 (InvokeContinuation return (v2)))) | |
| 221 (k2 () | |
| 222 (LetCont | |
| 223 ((k3 (v3) | |
| 224 (LetCont | |
| 225 ((k4 (v4) | |
| 226 (LetPrim (v5 (Constant (Int 1))) | |
| 227 (LetCont | |
| 228 ((k5 (v6) | |
| 229 (InvokeContinuation rec k0 (v6)))) | |
| 230 (InvokeMethod v1 + (v5) k5))))) | |
| 231 (InvokeStatic print (v3) k4)))) | |
| 232 (InvokeMethod v1 toString () k3)))) | |
| 233 (LetPrim (v7 (Constant (Int 2))) | |
| 234 (LetCont | |
| 235 ((k6 (v8) | |
| 236 (Branch (IsTrue v8) k2 k1))) | |
| 237 (InvokeMethod v1 < (v7) k6)))))) | |
| 238 (InvokeContinuation k0 (v0))))) | |
| 239 """; | |
| 240 | |
| 241 String BASIC_LOOP_OUT = BASIC_LOOP_IN; | |
| 242 | |
| 243 // Ensures that proper scoping is preserved, i.e. that the optimized | |
| 244 // continuation body does reference out of scope primitives. | |
| 245 // IR written by hand since this case is currently not being generated. | |
| 246 | |
| 247 String SCOPING_IN = """ | |
| 248 (FunctionDefinition main () () return | |
| 249 (LetCont | |
| 250 ((k0 (v1) | |
| 251 (InvokeStatic print (v1) return))) | |
| 252 (LetPrim (v0 (Constant (Int 0))) | |
| 253 (LetPrim (v2 (Constant (Null))) | |
| 254 (InvokeContinuation k0 (v0)))))) | |
| 255 """; | |
| 256 | |
| 257 String SCOPING_OUT = """ | |
| 258 (FunctionDefinition main () () return | |
| 259 (LetPrim (v0 (Constant (Int 0))) | |
| 260 (LetCont | |
| 261 ((k0 () | |
| 262 (InvokeStatic print (v0) return))) | |
| 263 (LetPrim (v1 (Constant (Null))) | |
| 264 (InvokeContinuation k0 ()))))) | |
| 265 """; | |
| 266 | |
| 267 // Ensures that continuations which are never invoked are not optimized. | |
| 268 // IR written by hand. | |
| 269 | |
| 270 String NEVER_INVOKED_IN = """ | |
| 271 (FunctionDefinition main () () return | |
| 272 (LetPrim (v0 (Constant (Int 0))) | |
| 273 (LetCont | |
| 274 ((k0 (v1) | |
| 275 (InvokeStatic print (v1) return))) | |
| 276 (InvokeContinuation return (v0))))) | |
| 277 """; | |
| 278 | |
| 279 String NEVER_INVOKED_OUT = NEVER_INVOKED_IN; | |
| 280 | |
| 281 /// Normalizes whitespace by replacing all whitespace sequences by a single | |
| 282 /// space and trimming leading and trailing whitespace. | |
| 283 String normalizeSExpr(String input) { | |
| 284 return input.replaceAll(new RegExp(r'[ \n\t]+'), ' ').trim(); | |
| 285 } | |
| 286 | |
| 287 /// Parses the given input IR, runs a redundant phi pass over it, and compares | |
| 288 /// the stringification of the result against the expected output. | |
| 289 void testRedundantPhi(String input, String expectedOutput) { | |
| 290 final unstringifier = new SExpressionUnstringifier(); | |
| 291 final stringifier = new SExpressionStringifier(); | |
| 292 final optimizer = new RedundantPhiEliminator(); | |
| 293 | |
| 294 FunctionDefinition f = unstringifier.unstringify(input); | |
| 295 optimizer.rewrite(f); | |
| 296 | |
| 297 String expected = normalizeSExpr(expectedOutput); | |
| 298 String actual = normalizeSExpr(stringifier.visit(f)); | |
| 299 | |
| 300 Expect.equals(expected, actual, "Actual:\n$actual"); | |
| 301 } | |
| 302 | |
| 303 void main() { | |
| 304 testRedundantPhi(READ_IN_LOOP_IN, READ_IN_LOOP_OUT); | |
| 305 testRedundantPhi(INNER_LOOP_IN, INNER_LOOP_OUT); | |
| 306 testRedundantPhi(BASIC_LOOP_IN, BASIC_LOOP_OUT); | |
| 307 testRedundantPhi(SCOPING_IN, SCOPING_OUT); | |
| 308 testRedundantPhi(NEVER_INVOKED_IN, NEVER_INVOKED_OUT); | |
| 309 } | |
| OLD | NEW |