Skip to content

Commit 4ebf8fb

Browse files
gh-115480: Type and constant propagation for int BINARY_OPs (GH-115478)
1 parent ed23839 commit 4ebf8fb

File tree

3 files changed

+126
-16
lines changed

3 files changed

+126
-16
lines changed

Python/optimizer_analysis.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,18 @@ sym_new_const(_Py_UOpsAbstractInterpContext *ctx, PyObject *const_val)
341341
return temp;
342342
}
343343

344+
static inline bool
345+
is_const(_Py_UOpsSymType *sym)
346+
{
347+
return sym->const_val != NULL;
348+
}
349+
350+
static inline PyObject *
351+
get_const(_Py_UOpsSymType *sym)
352+
{
353+
return sym->const_val;
354+
}
355+
344356
static _Py_UOpsSymType*
345357
sym_new_null(_Py_UOpsAbstractInterpContext *ctx)
346358
{

Python/tier2_redundancy_eliminator_bytecodes.c

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,62 @@ dummy_func(void) {
8181

8282

8383
op(_BINARY_OP_ADD_INT, (left, right -- res)) {
84-
// TODO constant propagation
85-
(void)left;
86-
(void)right;
87-
res = sym_new_known_type(ctx, &PyLong_Type);
88-
if (res == NULL) {
89-
goto out_of_space;
84+
if (is_const(left) && is_const(right)) {
85+
assert(PyLong_CheckExact(get_const(left)));
86+
assert(PyLong_CheckExact(get_const(right)));
87+
PyObject *temp = _PyLong_Add((PyLongObject *)get_const(left),
88+
(PyLongObject *)get_const(right));
89+
if (temp == NULL) {
90+
goto error;
91+
}
92+
res = sym_new_const(ctx, temp);
93+
// TODO replace opcode with constant propagated one and add tests!
94+
}
95+
else {
96+
res = sym_new_known_type(ctx, &PyLong_Type);
97+
if (res == NULL) {
98+
goto out_of_space;
99+
}
100+
}
101+
}
102+
103+
op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) {
104+
if (is_const(left) && is_const(right)) {
105+
assert(PyLong_CheckExact(get_const(left)));
106+
assert(PyLong_CheckExact(get_const(right)));
107+
PyObject *temp = _PyLong_Subtract((PyLongObject *)get_const(left),
108+
(PyLongObject *)get_const(right));
109+
if (temp == NULL) {
110+
goto error;
111+
}
112+
res = sym_new_const(ctx, temp);
113+
// TODO replace opcode with constant propagated one and add tests!
114+
}
115+
else {
116+
res = sym_new_known_type(ctx, &PyLong_Type);
117+
if (res == NULL) {
118+
goto out_of_space;
119+
}
120+
}
121+
}
122+
123+
op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) {
124+
if (is_const(left) && is_const(right)) {
125+
assert(PyLong_CheckExact(get_const(left)));
126+
assert(PyLong_CheckExact(get_const(right)));
127+
PyObject *temp = _PyLong_Multiply((PyLongObject *)get_const(left),
128+
(PyLongObject *)get_const(right));
129+
if (temp == NULL) {
130+
goto error;
131+
}
132+
res = sym_new_const(ctx, temp);
133+
// TODO replace opcode with constant propagated one and add tests!
134+
}
135+
else {
136+
res = sym_new_known_type(ctx, &PyLong_Type);
137+
if (res == NULL) {
138+
goto out_of_space;
139+
}
90140
}
91141
}
92142

Python/tier2_redundancy_eliminator_cases.c.h

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,28 @@
180180
}
181181

182182
case _BINARY_OP_MULTIPLY_INT: {
183+
_Py_UOpsSymType *right;
184+
_Py_UOpsSymType *left;
183185
_Py_UOpsSymType *res;
184-
res = sym_new_unknown(ctx);
185-
if (res == NULL) goto out_of_space;
186+
right = stack_pointer[-1];
187+
left = stack_pointer[-2];
188+
if (is_const(left) && is_const(right)) {
189+
assert(PyLong_CheckExact(get_const(left)));
190+
assert(PyLong_CheckExact(get_const(right)));
191+
PyObject *temp = _PyLong_Multiply((PyLongObject *)get_const(left),
192+
(PyLongObject *)get_const(right));
193+
if (temp == NULL) {
194+
goto error;
195+
}
196+
res = sym_new_const(ctx, temp);
197+
// TODO replace opcode with constant propagated one and add tests!
198+
}
199+
else {
200+
res = sym_new_known_type(ctx, &PyLong_Type);
201+
if (res == NULL) {
202+
goto out_of_space;
203+
}
204+
}
186205
stack_pointer[-2] = res;
187206
stack_pointer += -1;
188207
break;
@@ -194,22 +213,51 @@
194213
_Py_UOpsSymType *res;
195214
right = stack_pointer[-1];
196215
left = stack_pointer[-2];
197-
// TODO constant propagation
198-
(void)left;
199-
(void)right;
200-
res = sym_new_known_type(ctx, &PyLong_Type);
201-
if (res == NULL) {
202-
goto out_of_space;
216+
if (is_const(left) && is_const(right)) {
217+
assert(PyLong_CheckExact(get_const(left)));
218+
assert(PyLong_CheckExact(get_const(right)));
219+
PyObject *temp = _PyLong_Add((PyLongObject *)get_const(left),
220+
(PyLongObject *)get_const(right));
221+
if (temp == NULL) {
222+
goto error;
223+
}
224+
res = sym_new_const(ctx, temp);
225+
// TODO replace opcode with constant propagated one and add tests!
226+
}
227+
else {
228+
res = sym_new_known_type(ctx, &PyLong_Type);
229+
if (res == NULL) {
230+
goto out_of_space;
231+
}
203232
}
204233
stack_pointer[-2] = res;
205234
stack_pointer += -1;
206235
break;
207236
}
208237

209238
case _BINARY_OP_SUBTRACT_INT: {
239+
_Py_UOpsSymType *right;
240+
_Py_UOpsSymType *left;
210241
_Py_UOpsSymType *res;
211-
res = sym_new_unknown(ctx);
212-
if (res == NULL) goto out_of_space;
242+
right = stack_pointer[-1];
243+
left = stack_pointer[-2];
244+
if (is_const(left) && is_const(right)) {
245+
assert(PyLong_CheckExact(get_const(left)));
246+
assert(PyLong_CheckExact(get_const(right)));
247+
PyObject *temp = _PyLong_Subtract((PyLongObject *)get_const(left),
248+
(PyLongObject *)get_const(right));
249+
if (temp == NULL) {
250+
goto error;
251+
}
252+
res = sym_new_const(ctx, temp);
253+
// TODO replace opcode with constant propagated one and add tests!
254+
}
255+
else {
256+
res = sym_new_known_type(ctx, &PyLong_Type);
257+
if (res == NULL) {
258+
goto out_of_space;
259+
}
260+
}
213261
stack_pointer[-2] = res;
214262
stack_pointer += -1;
215263
break;

0 commit comments

Comments
 (0)