Repository navigation
Support for large numbers of args/kws with Python 3.10 #7866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
7ad9642
ebea710
3107840
fd6669b
f3ad535
29953e7
28a22ee
f726b3a
974da74
dbb4dec
7231d71
2a01061
1d38efa
f766532
7e8d424
cd04a5e
224c514
9d234a2
af48701
9ed27ea
530284e
9bb2ee5
ba83ffb
265a426
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -668,6 +668,44 @@ def peep_hole_call_function_ex_to_call_function_kw(func_ir): | |
| stmt = ir.Assign(new_call, stmt.target, stmt.loc) | ||
| # Update the definition | ||
| func_ir._definitions[stmt.target.name].append(new_call) | ||
| elif ( | ||
| isinstance(stmt, ir.Assign) | ||
| and isinstance(stmt.value, ir.Expr) | ||
| and stmt.value.op == "call" | ||
| and stmt.value.vararg is not None | ||
| ): | ||
| # If there is a call with vararg we need to check | ||
| # if the list -> tuple conversion failed and if so | ||
| # throw an error. | ||
| call = stmt.value | ||
| args = call.args | ||
| vararg = call.vararg | ||
| if args: | ||
| # If we have vararg then args is expected to | ||
| # be an empty list. | ||
| raise UnsupportedError(errmsg) | ||
| vararg_loc = i - 1 | ||
| args_def = None | ||
| not_found = True | ||
| while vararg_loc >= 0 and not_found: | ||
| args_def = blk.body[vararg_loc] | ||
| if ( | ||
| isinstance(args_def, ir.Assign) | ||
| and args_def.target.name == vararg.name | ||
| ): | ||
| not_found = False | ||
| else: | ||
| vararg_loc -= 1 | ||
| if not_found: | ||
| # If we couldn't find where the args are created | ||
| # then we can't handle this format. | ||
| raise UnsupportedError(errmsg) | ||
| else: | ||
| # If this value is still a list to tuple raise the | ||
| # exception. | ||
| expr = blk.body[vararg_loc].value | ||
| if isinstance(expr, ir.Expr) and expr.op == "list_to_tuple": | ||
| raise UnsupportedError(errmsg) | ||
|
|
||
| new_body.append(stmt) | ||
| # Update the block body if we updated the IR | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is replacing, not updating?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -396,7 +396,7 @@ def inline_func(flag): | |||||
| # self.assertEqual(a, b) | ||||||
|
|
||||||
| @skip_unless_py10 | ||||||
| def test_large_kws_uninlined_controlflow(self): | ||||||
| def test_large_args_uninlined_controlflow(self): | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(suggest same change throughout).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||||||
| """ | ||||||
| Tests generating large args when one of the inputs | ||||||
| has the change suggested in the error message | ||||||
|
|
@@ -450,6 +450,121 @@ def inline_func(flag): | |||||
| b = cfunc(False) | ||||||
| self.assertEqual(a, b) | ||||||
|
|
||||||
| @skip_unless_py10 | ||||||
| def test_all_args_inline_controlflow(self): | ||||||
| """ | ||||||
| Tests generating only large args when one of the inputs | ||||||
| has inlined controlflow. This requires a special check | ||||||
| inside peep_hole_call_function_ex_to_call_function_kw | ||||||
| because it usually only handles varkwargs. | ||||||
| """ | ||||||
| def inline_func(flag): | ||||||
| return sum_jit_func( | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1 if flag else 2, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| ) | ||||||
|
|
||||||
| with pytest.raises( | ||||||
| UnsupportedError, | ||||||
| match="You can resolve this issue by moving the control flow out" | ||||||
| ): | ||||||
| njit()(inline_func)(False) | ||||||
| # Uncomment sections when inlined control flow is | ||||||
| # actually supported. | ||||||
| # py_func = inline_func | ||||||
| # cfunc = njit()(inline_func) | ||||||
| # a = py_func(False) | ||||||
| # b = cfunc(False) | ||||||
| # self.assertEqual(a, b) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove? Same reasoning as above.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||||||
|
|
||||||
| @skip_unless_py10 | ||||||
| def test_all_args_uninlined_controlflow(self): | ||||||
| """ | ||||||
| Tests generating large args when one of the inputs | ||||||
| has the change suggested in the error message | ||||||
| for inlined control flow. | ||||||
| """ | ||||||
| def inline_func(flag): | ||||||
| a_val = 1 if flag else 2 | ||||||
| return sum_jit_func( | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| a_val, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| 1, | ||||||
| ) | ||||||
|
|
||||||
| py_func = inline_func | ||||||
| cfunc = njit()(inline_func) | ||||||
| a = py_func(False) | ||||||
| b = cfunc(False) | ||||||
| self.assertEqual(a, b) | ||||||
|
|
||||||
| @skip_unless_py10 | ||||||
| def test_large_kws_inline_controlflow(self): | ||||||
| """ | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Leaving thought trail in case we need it in the future. This probably doesn't present to be a problem)
With bytecode from:
the code here scan back from the call to
my_func2to find the definition ofargs, which is suppose to be aLIST_TO_TUPLEopcode, but is replaced bypeep_hole_list_to_tuple; otherwise, the later check will reject this call.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have also tried to trick this part of the code with the walrus operator but Numba is already miscompiling this on mainline: