From e123866e6edee6648752ae9882c90ed1d981c264 Mon Sep 17 00:00:00 2001 From: Sei Lisa Date: Mon, 24 Dec 2018 11:44:03 +0100 Subject: [PATCH] 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. --- lslopt/lslfoldconst.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lslopt/lslfoldconst.py b/lslopt/lslfoldconst.py index e470c77..dd08107 100644 --- a/lslopt/lslfoldconst.py +++ b/lslopt/lslfoldconst.py @@ -245,6 +245,16 @@ class foldconst(object): 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): """When we know that the parent is interested only in the truth value of the node, we can perform further optimizations. This function deals @@ -297,6 +307,19 @@ class foldconst(object): self.FoldTree(parent, index) 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': # bool(-a) equals bool(a)