Implement a first version of IsBool and use it to optimize && -> &

This commit is contained in:
Sei Lisa 2015-03-28 23:49:10 +01:00
parent 08f48a5c32
commit 2cb9ad6fe5

View file

@ -81,8 +81,19 @@ class foldconst(object):
boolean expressions. This function returns whether we know for sure boolean expressions. This function returns whether we know for sure
that the result is boolean. that the result is boolean.
""" """
return False # TODO: implement IsBool nt = node['nt']
# Ideas include some functions like llSameGroup and llDetectedGroup. if nt in ('<', '!', '>', '<=', '>=', '==', '||', '&&') \
or nt == '!=' and node['ch'][0]['t'] != 'list' \
or nt == 'CONST' and node['t'] == 'integer' and node['value'] in (0, 1):
return True
if nt == 'FNCALL':
sym = self.symtab[0][node['name']]
if sym['Typ'] == 'integer' and 'min' in sym and 'max' in sym \
and sym['min'] == 0 and sym['max'] == 1:
return True
return False
def FoldCond(self, parent, index): def FoldCond(self, parent, index):
"""When we know that the parent is interested only in the truth value """When we know that the parent is interested only in the truth value
@ -136,17 +147,47 @@ class foldconst(object):
self.FoldCond(child, 1) self.FoldCond(child, 1)
a, b = 0, 1 a, b = 0, 1
if child[a]['nt'] == 'CONST': # Put constant in child[b] if present
if child[b]['nt'] != 'CONST':
a, b = 1, 0 a, b = 1, 0
if child[b]['nt'] == 'CONST' and child[b]['value'] and 'SEF' in child[a]: if child[b]['nt'] == 'CONST' and child[b]['value'] and 'SEF' in child[a]:
parent[index] = child[b] parent[index] = child[b]
child[b]['value'] = 1 child[b]['value'] = -1
return return
# TODO: on bitwise OR, detect if both operands are negated.
# If so treat it as an AND, checking if the operands are boolean if child[0]['nt'] == child[1]['nt'] == '!':
# to try to simplify them to an expression of the form !(a&b) # Both operands are negated.
# when possible. Or if one is bool and the other is not, to an # If they are boolean, the expression can be turned into
# expression of the form !(a&-b) (if b is bool). # !(a&b) which hopefully will have a ! uptree if it came
# from a && and cancel out (if not, we still remove one
# ! so it's good). If one is bool, another transformation
# can be performed: !nonbool|!bool -> !(nonbool&-bool)
# which is still a gain.
a, b = 0, 1
# Put the bool in child[b]['ch'][0].
if not self.IsBool(child[b]['ch'][0]):
a, b = 1, 0
if self.IsBool(child[b]['ch'][0]):
if not self.IsBool(child[a]['ch'][0]):
# HACK: Wrap in a a dummy node so that the code
# below can extract it properly, without swapping
# left and right hand sides (purely for aesthetic
# reasons).
child[b] = {'ch':[
{'nt':'NEG', 't':'integer',
'ch':[child[b]['ch'][0]]}
]}
node = parent[index] = {'nt':'!', 't':'integer',
'ch':[{'nt':'&','t':'integer',
'ch':[child[0]['ch'][0],
child[1]['ch'][0]]
}]
}
# Fold the node we've just synthesized
# (this deals with SEF)
self.FoldTree(parent, index)
return
# TODO: Convert bool(x < 0) to bool(x & 0x80000000) # TODO: Convert bool(x < 0) to bool(x & 0x80000000)
# TODO: If function domain starts at -1, treat & 0x80000000 as ~ # TODO: If function domain starts at -1, treat & 0x80000000 as ~