| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'sexpr_unstringifier.dart'; | 5 import 'sexpr_unstringifier.dart'; |
| 6 import "package:expect/expect.dart"; | 6 import "package:expect/expect.dart"; |
| 7 import 'package:compiler/src/cps_ir/cps_ir_nodes.dart'; | 7 import 'package:compiler/src/cps_ir/cps_ir_nodes.dart'; |
| 8 import 'package:compiler/src/cps_ir/cps_ir_nodes_sexpr.dart'; | 8 import 'package:compiler/src/cps_ir/cps_ir_nodes_sexpr.dart'; |
| 9 import 'package:compiler/src/cps_ir/optimizers.dart'; | 9 import 'package:compiler/src/cps_ir/optimizers.dart'; |
| 10 | 10 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 (InvokeContinuation return (v3))))) | 146 (InvokeContinuation return (v3))))) |
| 147 (InvokeStatic print (v0) k1)))) | 147 (InvokeStatic print (v0) k1)))) |
| 148 (InvokeStatic print (v0) k0)))) | 148 (InvokeStatic print (v0) k0)))) |
| 149 """; | 149 """; |
| 150 | 150 |
| 151 // Beta-cont-lin with recursive continuation. IR written by hand. | 151 // Beta-cont-lin with recursive continuation. IR written by hand. |
| 152 | 152 |
| 153 String RECURSIVE_BETA_CONT_LIN_IN = """ | 153 String RECURSIVE_BETA_CONT_LIN_IN = """ |
| 154 (FunctionDefinition main () return () | 154 (FunctionDefinition main () return () |
| 155 (LetCont ((rec k0 (v0) | 155 (LetCont ((rec k0 (v0) |
| 156 (InvokeContinuation* k0 (v0)))) | 156 (InvokeContinuation rec k0 (v0)))) |
| 157 (LetPrim (v1 (Constant (Int 0))) | 157 (LetPrim (v1 (Constant (Int 0))) |
| 158 (InvokeContinuation k0 (v1))))) | 158 (InvokeContinuation k0 (v1))))) |
| 159 """; | 159 """; |
| 160 String RECURSIVE_BETA_CONT_LIN_OUT = RECURSIVE_BETA_CONT_LIN_IN; | 160 String RECURSIVE_BETA_CONT_LIN_OUT = RECURSIVE_BETA_CONT_LIN_IN; |
| 161 | 161 |
| 162 // Beta-cont-lin used inside body. IR written by hand. | 162 // Beta-cont-lin used inside body. IR written by hand. |
| 163 | 163 |
| 164 String USED_BETA_CONT_LIN_IN = """ | 164 String USED_BETA_CONT_LIN_IN = """ |
| 165 (FunctionDefinition main () return () | 165 (FunctionDefinition main () return () |
| 166 (LetPrim (v0 (Constant (Int 0))) | 166 (LetPrim (v0 (Constant (Int 0))) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 183 (LetCont ((k0 (v1) | 183 (LetCont ((k0 (v1) |
| 184 (LetCont ((k1 (v2) | 184 (LetCont ((k1 (v2) |
| 185 (LetPrim (v3 (Constant (Int 0))) | 185 (LetPrim (v3 (Constant (Int 0))) |
| 186 (InvokeContinuation return (v3))))) | 186 (InvokeContinuation return (v3))))) |
| 187 (InvokeStatic print (v0) k1)))) | 187 (InvokeStatic print (v0) k1)))) |
| 188 (InvokeStatic print (v0) k0)))) | 188 (InvokeStatic print (v0) k0)))) |
| 189 """; | 189 """; |
| 190 | 190 |
| 191 // Eta-cont: letcont k x = j x in K -> K[j/k]. | 191 // Eta-cont: letcont k x = j x in K -> K[j/k]. |
| 192 // IR written by hand. | 192 // IR written by hand. |
| 193 | 193 // |
| 194 // This test is incorrectly named: with the current implementation, there is no |
| 195 // eta reduction. Instead, dead-parameter, beta-cont-lin, and dead-val |
| 196 // reductions are performed, which in turn creates a second beta-cont-lin |
| 197 // reduction. |
| 198 // |
| 199 // TODO(kmillikin): To test continuation eta reduction, use eta redexes that are |
| 200 // not overlapping beta redexes. |
| 194 String ETA_CONT_IN = """ | 201 String ETA_CONT_IN = """ |
| 195 (FunctionDefinition main () return () | 202 (FunctionDefinition main () return () |
| 196 (LetPrim (v3 (Constant (Int 0))) | 203 (LetPrim (v0 (Constant (Int 0))) |
| 197 (LetCont ((rec k1 (v1) | 204 (LetCont ((rec k0 (v1) |
| 198 (InvokeContinuation return (v3)))) | 205 (InvokeContinuation return (v0)))) |
| 199 (LetCont ((k0 (v0) | 206 (LetCont ((k1 (v2) |
| 200 (InvokeContinuation k1 (v0)))) | 207 (InvokeContinuation k0 (v2)))) |
| 201 (LetPrim (v4 | 208 (LetPrim (v3 |
| 202 (CreateFunction | 209 (CreateFunction |
| 203 (FunctionDefinition f () return () | 210 (FunctionDefinition f () return () |
| 204 (InvokeContinuation k1 (v3))))) | 211 (InvokeContinuation k0 (v0))))) |
| 205 (InvokeContinuation k0 (v3))))))) | 212 (InvokeContinuation k1 (v0))))))) |
| 206 """; | 213 """; |
| 207 String ETA_CONT_OUT = """ | 214 String ETA_CONT_OUT = """ |
| 208 (FunctionDefinition main () return () | 215 (FunctionDefinition main () return () |
| 209 (LetPrim (v0 (Constant (Int 0))) | 216 (LetPrim (v0 (Constant (Int 0))) |
| 210 (LetCont ((k0 (v1) | 217 (InvokeContinuation return (v0)))) |
| 211 (InvokeContinuation return (v0)))) | |
| 212 (InvokeContinuation k0 (v0))))) | |
| 213 """; | 218 """; |
| 214 | 219 |
| 220 // Dead-parameter: |
| 221 // letcont k x = E0 in E1 -> letcont k () = E0 in E1, |
| 222 // if x does not occur free in E0. |
| 223 |
| 224 // Parameter v1 is unused in k0. |
| 225 String DEAD_PARAMETER_IN = """ |
| 226 (FunctionDefinition main (x) return () |
| 227 (LetCont ((k0 (v0 v1 v2) |
| 228 (InvokeStatic foo (v0 v2) return))) |
| 229 (LetCont ((k1 () |
| 230 (LetPrim (v3 (Constant (Int 0))) |
| 231 (LetPrim (v4 (Constant (Int 1))) |
| 232 (LetPrim (v5 (Constant (Int 2))) |
| 233 (InvokeContinuation k0 (v3 v4 v5)))))) |
| 234 (k2 () |
| 235 (LetPrim (v6 (Constant (Int 3))) |
| 236 (LetPrim (v7 (Constant (Int 4))) |
| 237 (LetPrim (v8 (Constant (Int 5))) |
| 238 (InvokeContinuation k0 (v6 v7 v8))))))) |
| 239 (Branch (IsTrue x) k1 k2)))) |
| 240 """; |
| 241 String DEAD_PARAMETER_OUT = """ |
| 242 (FunctionDefinition main (x) return () |
| 243 (LetCont ((k0 (v0 v1) |
| 244 (InvokeStatic foo (v0 v1) return))) |
| 245 (LetCont ((k1 () |
| 246 (LetPrim (v2 (Constant (Int 0))) |
| 247 (LetPrim (v3 (Constant (Int 2))) |
| 248 (InvokeContinuation k0 (v2 v3))))) |
| 249 (k2 () |
| 250 (LetPrim (v4 (Constant (Int 3))) |
| 251 (LetPrim (v5 (Constant (Int 5))) |
| 252 (InvokeContinuation k0 (v4 v5)))))) |
| 253 (Branch (IsTrue x) k1 k2)))) |
| 254 """; |
| 255 |
| 256 // Create an eta-cont redex: |
| 257 // Dead parameter reductions can create an eta-cont redex by removing unused |
| 258 // continuation parameters and thus creating the eta redex. |
| 259 String CREATE_ETA_CONT_IN = """ |
| 260 (FunctionDefinition main (x) return () |
| 261 (LetCont ((rec loop (v0) |
| 262 (InvokeContinuation rec loop (v0)))) |
| 263 (LetCont ((created (v1 v2 v3) |
| 264 (InvokeContinuation loop (v2)))) |
| 265 (LetCont ((then () |
| 266 (LetPrim (v4 (Constant (Int 0))) |
| 267 (LetPrim (v5 (Constant (Int 1))) |
| 268 (LetPrim (v6 (Constant (Int 2))) |
| 269 (InvokeContinuation created (v4 v5 v6)))))) |
| 270 (else () |
| 271 (LetPrim (v6 (Constant (Int 3))) |
| 272 (LetPrim (v7 (Constant (Int 4))) |
| 273 (LetPrim (v8 (Constant (Int 5))) |
| 274 (InvokeContinuation created (v6 v7 v8))))))) |
| 275 (Branch (IsTrue x) then else))))) |
| 276 """; |
| 277 String CREATE_ETA_CONT_OUT = """ |
| 278 (FunctionDefinition main (x) return () |
| 279 (LetCont ((rec k0 (v0) |
| 280 (InvokeContinuation rec k0 (v0)))) |
| 281 (LetCont ((k1 () |
| 282 (LetPrim (v1 (Constant (Int 1))) |
| 283 (InvokeContinuation k0 (v1)))) |
| 284 (k2 () |
| 285 (LetPrim (v2 (Constant (Int 4))) |
| 286 (InvokeContinuation k0 (v2))))) |
| 287 (Branch (IsTrue x) k1 k2)))) |
| 288 """; |
| 289 |
| 290 |
| 291 |
| 215 // Beta-fun-lin and eta-fun might not apply to us, since | 292 // Beta-fun-lin and eta-fun might not apply to us, since |
| 216 // a. in (InvokeMethod v0 call k0), v0 might carry state, and | 293 // a. in (InvokeMethod v0 call k0), v0 might carry state, and |
| 217 // b. there is no way to generate static nested functions that we could | 294 // b. there is no way to generate static nested functions that we could |
| 218 // use InvokeStatic on. | 295 // use InvokeStatic on. |
| 219 | 296 |
| 220 /// Normalizes whitespace by replacing all whitespace sequences by a single | 297 /// Normalizes whitespace by replacing all whitespace sequences by a single |
| 221 /// space and trimming leading and trailing whitespace. | 298 /// space and trimming leading and trailing whitespace. |
| 222 String normalizeSExpr(String input) { | 299 String normalizeSExpr(String input) { |
| 223 return input.replaceAll(new RegExp(r'[ \n\t]+'), ' ').trim(); | 300 return input.replaceAll(new RegExp(r'[ \n\t]+'), ' ').trim(); |
| 224 } | 301 } |
| 225 | 302 |
| 226 /// Parses the given input IR, runs an optimization pass over it, and compares | 303 /// Parses the given input IR, runs an optimization pass over it, and compares |
| 227 /// the stringification of the result against the expected output. | 304 /// the stringification of the result against the expected output. |
| 228 void testShrinkingReducer(String input, String expectedOutput) { | 305 void testShrinkingReducer(String input, String expectedOutput) { |
| 229 final unstringifier = new SExpressionUnstringifier(); | 306 final unstringifier = new SExpressionUnstringifier(); |
| 230 final stringifier = new SExpressionStringifier(); | 307 final stringifier = new SExpressionStringifier(); |
| 231 final optimizer = new ShrinkingReducer(); | 308 final optimizer = new ShrinkingReducer(); |
| 232 | 309 |
| 233 FunctionDefinition f = unstringifier.unstringify(input); | 310 FunctionDefinition f = unstringifier.unstringify(input); |
| 234 optimizer.rewrite(f); | 311 optimizer.rewrite(f); |
| 235 | 312 |
| 236 String expected = normalizeSExpr(expectedOutput); | 313 String expected = normalizeSExpr(expectedOutput); |
| 237 String actual = normalizeSExpr(stringifier.visit(f)); | 314 String actual = normalizeSExpr(stringifier.visit(f)); |
| 238 | 315 |
| 239 Expect.equals(expected, actual); | 316 Expect.equals(expected, actual); |
| 240 } | 317 } |
| 241 | 318 |
| 242 void main() { | 319 void main() { |
| 243 testShrinkingReducer(DEAD_VAL_IN, DEAD_VAL_OUT); | 320 testShrinkingReducer(DEAD_VAL_IN, DEAD_VAL_OUT); |
| 244 testShrinkingReducer(ITERATIVE_DEAD_VAL1_IN, ITERATIVE_DEAD_VAL1_OUT); | 321 testShrinkingReducer(ITERATIVE_DEAD_VAL1_IN, ITERATIVE_DEAD_VAL1_OUT); |
| 245 testShrinkingReducer(ITERATIVE_DEAD_VAL2_IN, ITERATIVE_DEAD_VAL2_OUT); | 322 testShrinkingReducer(ITERATIVE_DEAD_VAL2_IN, ITERATIVE_DEAD_VAL2_OUT); |
| 246 testShrinkingReducer(DEAD_CONT_IN, DEAD_CONT_OUT); | 323 testShrinkingReducer(DEAD_CONT_IN, DEAD_CONT_OUT); |
| 247 testShrinkingReducer(ITERATIVE_DEAD_CONT_IN, ITERATIVE_DEAD_CONT_OUT); | 324 testShrinkingReducer(ITERATIVE_DEAD_CONT_IN, ITERATIVE_DEAD_CONT_OUT); |
| 248 testShrinkingReducer(BETA_CONT_LIN_IN, BETA_CONT_LIN_OUT); | 325 testShrinkingReducer(BETA_CONT_LIN_IN, BETA_CONT_LIN_OUT); |
| 249 testShrinkingReducer(RECURSIVE_BETA_CONT_LIN_IN, RECURSIVE_BETA_CONT_LIN_OUT); | 326 testShrinkingReducer(RECURSIVE_BETA_CONT_LIN_IN, RECURSIVE_BETA_CONT_LIN_OUT); |
| 250 testShrinkingReducer(USED_BETA_CONT_LIN_IN, USED_BETA_CONT_LIN_OUT); | 327 testShrinkingReducer(USED_BETA_CONT_LIN_IN, USED_BETA_CONT_LIN_OUT); |
| 251 testShrinkingReducer(ETA_CONT_IN, ETA_CONT_OUT); | 328 testShrinkingReducer(ETA_CONT_IN, ETA_CONT_OUT); |
| 329 testShrinkingReducer(DEAD_PARAMETER_IN, DEAD_PARAMETER_OUT); |
| 330 testShrinkingReducer(CREATE_ETA_CONT_IN, CREATE_ETA_CONT_OUT); |
| 252 } | 331 } |
| OLD | NEW |