@@ -2224,5 +2224,202 @@ def test_validate_uop_unused_size_mismatch(self):
2224
2224
"Inputs must have equal sizes" ):
2225
2225
self .run_cases_test (input , input2 , output )
2226
2226
2227
+ def test_pure_uop_body_copied_in (self ):
2228
+ # Note: any non-escaping call works.
2229
+ # In this case, we use PyStackRef_IsNone.
2230
+ input = """
2231
+ pure op(OP, (foo -- res)) {
2232
+ res = PyStackRef_IsNone(foo);
2233
+ }
2234
+ """
2235
+ input2 = """
2236
+ op(OP, (foo -- res)) {
2237
+ REPLACE_OPCODE_IF_EVALUATES_PURE(foo);
2238
+ res = sym_new_known(ctx, foo);
2239
+ }
2240
+ """
2241
+ output = """
2242
+ case OP: {
2243
+ JitOptRef foo;
2244
+ JitOptRef res;
2245
+ foo = stack_pointer[-1];
2246
+ if (
2247
+ sym_is_safe_const(ctx, foo)
2248
+ ) {
2249
+ JitOptRef foo_sym = foo;
2250
+ _PyStackRef foo = sym_get_const_as_stackref(ctx, foo_sym);
2251
+ _PyStackRef res_stackref;
2252
+ /* Start of uop copied from bytecodes for constant evaluation */
2253
+ res_stackref = PyStackRef_IsNone(foo);
2254
+ /* End of uop copied from bytecodes for constant evaluation */
2255
+ res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
2256
+ stack_pointer[-1] = res;
2257
+ break;
2258
+ }
2259
+ res = sym_new_known(ctx, foo);
2260
+ stack_pointer[-1] = res;
2261
+ break;
2262
+ }
2263
+ """
2264
+ self .run_cases_test (input , input2 , output )
2265
+
2266
+ def test_pure_uop_body_copied_in_deopt (self ):
2267
+ # Note: any non-escaping call works.
2268
+ # In this case, we use PyStackRef_IsNone.
2269
+ input = """
2270
+ pure op(OP, (foo -- res)) {
2271
+ DEOPT_IF(PyStackRef_IsNull(foo));
2272
+ res = foo;
2273
+ }
2274
+ """
2275
+ input2 = """
2276
+ op(OP, (foo -- res)) {
2277
+ REPLACE_OPCODE_IF_EVALUATES_PURE(foo);
2278
+ res = foo;
2279
+ }
2280
+ """
2281
+ output = """
2282
+ case OP: {
2283
+ JitOptRef foo;
2284
+ JitOptRef res;
2285
+ foo = stack_pointer[-1];
2286
+ if (
2287
+ sym_is_safe_const(ctx, foo)
2288
+ ) {
2289
+ JitOptRef foo_sym = foo;
2290
+ _PyStackRef foo = sym_get_const_as_stackref(ctx, foo_sym);
2291
+ _PyStackRef res_stackref;
2292
+ /* Start of uop copied from bytecodes for constant evaluation */
2293
+ if (PyStackRef_IsNull(foo)) {
2294
+ ctx->done = true;
2295
+ break;
2296
+ }
2297
+ res_stackref = foo;
2298
+ /* End of uop copied from bytecodes for constant evaluation */
2299
+ res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
2300
+ stack_pointer[-1] = res;
2301
+ break;
2302
+ }
2303
+ res = foo;
2304
+ stack_pointer[-1] = res;
2305
+ break;
2306
+ }
2307
+ """
2308
+ self .run_cases_test (input , input2 , output )
2309
+
2310
+ def test_pure_uop_body_copied_in_error_if (self ):
2311
+ # Note: any non-escaping call works.
2312
+ # In this case, we use PyStackRef_IsNone.
2313
+ input = """
2314
+ pure op(OP, (foo -- res)) {
2315
+ ERROR_IF(PyStackRef_IsNull(foo));
2316
+ res = foo;
2317
+ }
2318
+ """
2319
+ input2 = """
2320
+ op(OP, (foo -- res)) {
2321
+ REPLACE_OPCODE_IF_EVALUATES_PURE(foo);
2322
+ res = foo;
2323
+ }
2324
+ """
2325
+ output = """
2326
+ case OP: {
2327
+ JitOptRef foo;
2328
+ JitOptRef res;
2329
+ foo = stack_pointer[-1];
2330
+ if (
2331
+ sym_is_safe_const(ctx, foo)
2332
+ ) {
2333
+ JitOptRef foo_sym = foo;
2334
+ _PyStackRef foo = sym_get_const_as_stackref(ctx, foo_sym);
2335
+ _PyStackRef res_stackref;
2336
+ /* Start of uop copied from bytecodes for constant evaluation */
2337
+ if (PyStackRef_IsNull(foo)) {
2338
+ goto error;
2339
+ }
2340
+ res_stackref = foo;
2341
+ /* End of uop copied from bytecodes for constant evaluation */
2342
+ res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
2343
+ stack_pointer[-1] = res;
2344
+ break;
2345
+ }
2346
+ res = foo;
2347
+ stack_pointer[-1] = res;
2348
+ break;
2349
+ }
2350
+ """
2351
+ self .run_cases_test (input , input2 , output )
2352
+
2353
+
2354
+ def test_replace_opcode_uop_body_copied_in_complex (self ):
2355
+ input = """
2356
+ pure op(OP, (foo -- res)) {
2357
+ if (foo) {
2358
+ res = PyStackRef_IsNone(foo);
2359
+ }
2360
+ else {
2361
+ res = 1;
2362
+ }
2363
+ }
2364
+ """
2365
+ input2 = """
2366
+ op(OP, (foo -- res)) {
2367
+ REPLACE_OPCODE_IF_EVALUATES_PURE(foo);
2368
+ res = sym_new_known(ctx, foo);
2369
+ }
2370
+ """
2371
+ output = """
2372
+ case OP: {
2373
+ JitOptRef foo;
2374
+ JitOptRef res;
2375
+ foo = stack_pointer[-1];
2376
+ if (
2377
+ sym_is_safe_const(ctx, foo)
2378
+ ) {
2379
+ JitOptRef foo_sym = foo;
2380
+ _PyStackRef foo = sym_get_const_as_stackref(ctx, foo_sym);
2381
+ _PyStackRef res_stackref;
2382
+ /* Start of uop copied from bytecodes for constant evaluation */
2383
+ if (foo) {
2384
+ res_stackref = PyStackRef_IsNone(foo);
2385
+ }
2386
+ else {
2387
+ res_stackref = 1;
2388
+ }
2389
+ /* End of uop copied from bytecodes for constant evaluation */
2390
+ res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
2391
+ stack_pointer[-1] = res;
2392
+ break;
2393
+ }
2394
+ res = sym_new_known(ctx, foo);
2395
+ stack_pointer[-1] = res;
2396
+ break;
2397
+ }
2398
+ """
2399
+ self .run_cases_test (input , input2 , output )
2400
+
2401
+ def test_replace_opocode_uop_reject_array_effects (self ):
2402
+ input = """
2403
+ pure op(OP, (foo[2] -- res)) {
2404
+ if (foo) {
2405
+ res = PyStackRef_IsNone(foo);
2406
+ }
2407
+ else {
2408
+ res = 1;
2409
+ }
2410
+ }
2411
+ """
2412
+ input2 = """
2413
+ op(OP, (foo[2] -- res)) {
2414
+ REPLACE_OPCODE_IF_EVALUATES_PURE(foo);
2415
+ res = sym_new_unknown(ctx);
2416
+ }
2417
+ """
2418
+ output = """
2419
+ """
2420
+ with self .assertRaisesRegex (SyntaxError ,
2421
+ "Pure evaluation cannot take array-like inputs" ):
2422
+ self .run_cases_test (input , input2 , output )
2423
+
2227
2424
if __name__ == "__main__" :
2228
2425
unittest .main ()
0 commit comments