mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 15:48:21 +00:00
Optimize min/max in comparisons; undo problematic optimization.
For floats: When const >= function.max, comparisons of function > const always yield FALSE. When const < function.min, comparisons of function > const always yield TRUE. When const > function.max, comparisons of function < const always yield TRUE. When const <= function.min, comparisons of function < const always yield FALSE. For integers: When min = -1, cond(function > -1) is the same as cond(!~function). When min = -1, cond(function < 0) is the same as cond(~function). To implement the above, we got rid of the cond(x < 0) -> cond(x & 0x80000000) optimization, which has caused more trouble than it has solved for just 1 byte gain. When min = 0, cond(function > 0) is the same as cond(function). When min = 0, cond(function < 1) is the same as cond(!function). Similar expressions can be obtained for max in [-1, 0], but it's not worth it, as there are no functions with -1 as maximum, and the ones with max=0 also have min=0 (always return 0).
This commit is contained in:
parent
22e057e2ec
commit
4ba71993a4
1 changed files with 92 additions and 10 deletions
|
@ -481,15 +481,53 @@ class foldconst(object):
|
|||
|
||||
return
|
||||
|
||||
# This optimization turns out to be counter-productive for some
|
||||
# common cases, e.g. it turns i >= 0 into !(i & 0x80000000)
|
||||
# instead of the more optimal (integer)-1 < i. So we revert it
|
||||
# where appropriate (in FoldTree, case '!', and above, case '|').
|
||||
if nt == '<':
|
||||
if child[1]['nt'] == 'CONST' and child[1]['value'] == 0:
|
||||
nt = node['nt'] = '&'
|
||||
child[1]['value'] = int(-2147483648)
|
||||
# Fall through to check & 0x80000000
|
||||
if nt == '<' and child[0]['t'] == child[1]['t'] == 'integer':
|
||||
sym = None
|
||||
for a in (0, 1):
|
||||
if child[a]['nt'] == 'FNCALL':
|
||||
sym = self.symtab[0][child[a]['name']]
|
||||
break
|
||||
|
||||
# cond(FNCALL < 0) -> cond(~FNCALL) if min == -1
|
||||
if (child[1]['nt'] == 'CONST' and child[1]['value'] == 0
|
||||
and child[0]['nt'] == 'FNCALL'
|
||||
and 'min' in sym and sym['min'] == -1
|
||||
):
|
||||
node = parent[index] = {'nt':'~', 't':'integer',
|
||||
'ch':[child[0]]}
|
||||
self.FoldTree(parent, index)
|
||||
return
|
||||
|
||||
# cond(FNCALL > -1) -> cond(!~FNCALL) if min == -1
|
||||
if (child[0]['nt'] == 'CONST' and child[0]['value'] == -1
|
||||
and child[1]['nt'] == 'FNCALL'
|
||||
and 'min' in sym and sym['min'] == -1
|
||||
):
|
||||
node = parent[index] = {'nt':'!', 't':'integer',
|
||||
'ch':[{'nt':'~', 't':'integer',
|
||||
'ch':[child[1]]}
|
||||
]}
|
||||
self.FoldTree(parent, index)
|
||||
return
|
||||
|
||||
# cond(FNCALL < 1) -> cond(!FNCALL) if min == 0
|
||||
if (child[1]['nt'] == 'CONST' and child[1]['value'] == 1
|
||||
and child[0]['nt'] == 'FNCALL'
|
||||
and 'min' in sym and sym['min'] == 0
|
||||
):
|
||||
node = parent[index] = {'nt':'!', 't':'integer',
|
||||
'ch':[child[0]]}
|
||||
self.FoldTree(parent, index)
|
||||
return
|
||||
|
||||
# cond(FNCALL > 0) -> cond(FNCALL) if min == 0
|
||||
if (child[0]['nt'] == 'CONST' and child[0]['value'] == 0
|
||||
and child[1]['nt'] == 'FNCALL'
|
||||
and 'min' in sym and sym['min'] == 0
|
||||
):
|
||||
node = parent[index] = child[1]
|
||||
self.FoldTree(parent, index)
|
||||
return
|
||||
|
||||
if nt == '&':
|
||||
|
||||
|
@ -1129,6 +1167,50 @@ class foldconst(object):
|
|||
# fall through to check for '<'
|
||||
|
||||
if nt == '<':
|
||||
if child[0]['t'] == child[1]['t'] in ('integer', 'float'):
|
||||
if (child[0]['nt'] == 'CONST'
|
||||
and child[1]['nt'] == 'FNCALL'
|
||||
and self.FnSEF(child[1])
|
||||
):
|
||||
# CONST < FNCALL aka FNCALL > CONST
|
||||
# when FNCALL.max <= CONST: always false
|
||||
# when CONST < FNCALL.min: always true
|
||||
if ('max' in self.symtab[0][child[1]['name']]
|
||||
and child[0]['value'] >=
|
||||
self.symtab[0][child[1]['name']]['max']
|
||||
):
|
||||
parent[index] = {'nt':'CONST', 't':'integer',
|
||||
'SEF':True, 'value':0}
|
||||
return
|
||||
if ('min' in self.symtab[0][child[1]['name']]
|
||||
and child[0]['value'] <
|
||||
self.symtab[0][child[1]['name']]['min']
|
||||
):
|
||||
parent[index] = {'nt':'CONST', 't':'integer',
|
||||
'SEF':True, 'value':1}
|
||||
return
|
||||
if (child[1]['nt'] == 'CONST'
|
||||
and child[0]['nt'] == 'FNCALL'
|
||||
and self.FnSEF(child[0])
|
||||
):
|
||||
# FNCALL < CONST
|
||||
# when CONST > FNCALL.max: always true
|
||||
# when CONST <= FNCALL.min: always false
|
||||
if ('max' in self.symtab[0][child[0]['name']]
|
||||
and child[1]['value'] >
|
||||
self.symtab[0][child[0]['name']]['max']
|
||||
):
|
||||
parent[index] = {'nt':'CONST', 't':'integer',
|
||||
'SEF':True, 'value':1}
|
||||
return
|
||||
if ('min' in self.symtab[0][child[0]['name']]
|
||||
and child[1]['value'] <=
|
||||
self.symtab[0][child[0]['name']]['min']
|
||||
):
|
||||
parent[index] = {'nt':'CONST', 't':'integer',
|
||||
'SEF':True, 'value':0}
|
||||
return
|
||||
|
||||
# Convert 2147483647<i and i<-2147483648 to i&0
|
||||
if child[0]['t'] == child[1]['t'] == 'integer' \
|
||||
and (child[0]['nt'] == 'CONST' and child[0]['value'] == 2147483647
|
||||
|
@ -1136,7 +1218,7 @@ class foldconst(object):
|
|||
a, b = 0, 1
|
||||
# Put the constant in child[b]
|
||||
if child[a]['nt'] == 'CONST':
|
||||
a, b = 1, 0
|
||||
a, b = b, a
|
||||
nt = node['nt'] = '&'
|
||||
child[b]['value'] = 0
|
||||
# fall through to check for '&'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue