Apply DeMorgan in some cases that were not caught.

Example: the optimization of if(i < 2 || i) was suboptimal, because FoldTree was done before FoldCond. In a first stage, the || was removed: if(!!(i < 2 | i)); when folded, the inner ! was optimized first and the result was if(!(1 < i & (!i))), which FoldCond wasn't smart enough to handle.

The new optimization takes over from there, and converts if(!(!a & b)) with b boolean, in any order, to if(a | !b). When applied to the above expression, it gets folded to if(i < 2 | i) as expected, which is optimal.

Also, new function: IsAndBool (see docstring), used on b in the above example.
This commit is contained in:
Sei Lisa 2018-12-24 11:44:03 +01:00
parent fa547cd9e8
commit e123866e6e

View file

@ -245,6 +245,16 @@ class foldconst(object):
return False return False
def IsAndBool(self, node):
"""For bitwise AND, in some cases we can relax the condition to this:
when bit 0 is 0, all other bits are guaranteed to be 0 as well. That's
the case of -bool which is the only case we deal with here, but an
important one because we generate it as an intermediate result in some
operations.
"""
return (node.nt == 'NEG' and self.IsBool(node.ch[0])
or self.IsBool(node))
def FoldCond(self, parent, index, ParentIsNegation = False): def FoldCond(self, parent, index, ParentIsNegation = False):
"""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
of the node, we can perform further optimizations. This function deals of the node, we can perform further optimizations. This function deals
@ -297,6 +307,19 @@ class foldconst(object):
self.FoldTree(parent, index) self.FoldTree(parent, index)
return return
if (child[0].nt == '&'
and any(child[0].ch[i].nt == '!'
and self.IsAndBool(child[0].ch[1-i]) for i in (0, 1))
):
# We can remove at least one !
child[0].nt = '|'
for i in (0, 1):
child[0].ch[i] = nr(nt='!', t='integer',
ch=[child[0].ch[i]], SEF=child[0].ch[i].SEF)
parent[index] = child[0]
self.FoldTree(parent, index)
self.FoldCond(parent, index)
return
if nt == 'NEG': if nt == 'NEG':
# bool(-a) equals bool(a) # bool(-a) equals bool(a)