diff --git a/examples/lvn.py b/examples/lvn.py index cf7f834bc..5b3428930 100644 --- a/examples/lvn.py +++ b/examples/lvn.py @@ -199,6 +199,9 @@ def _lookup(value2num, value): 'le': lambda a, b: a <= b, 'ne': lambda a, b: a != b, 'eq': lambda a, b: a == b, + 'or': lambda a, b: a or b, + 'and': lambda a, b: a and b, + 'not': lambda a: not a } @@ -212,6 +215,14 @@ def _fold(num2const, value): # Equivalent arguments may be evaluated for equality. # E.g. `eq x x`, where `x` is not a constant evaluates to `true`. return value.op != 'ne' + + if value.op in {'and', 'or'} and any(v in num2const for v in value.args): + # Short circuiting the logical operators `and` and `or` for two cases: + # (1) `and x c0` -> false, where `c0` a constant that evaluates to `false`. + # (2) `or x c1` -> true, where `c1` a constant that evaluates to `true`. + const_val = num2const[value.args[0] if value.args[0] in num2const else value.args[1]] + if (value.op == 'and' and not const_val) or (value.op == 'or' and const_val): + return const_val return None except ZeroDivisionError: # If we hit a dynamic error, bail! return None diff --git a/examples/test/lvn/logical-operators.bril b/examples/test/lvn/logical-operators.bril new file mode 100644 index 000000000..88f5701ef --- /dev/null +++ b/examples/test/lvn/logical-operators.bril @@ -0,0 +1,26 @@ +# ARGS: -f + +@main(arg1: bool, arg2: bool) { + t: int = const true; + f: int = const false; + + constant_fold1: bool = and f t; + constant_fold2: bool = and t f; + constant_fold3: bool = or t f; + constant_fold4: bool = or f t; + constant_fold5: bool = not t; + constant_fold6: bool = not f; + + should_fold1: bool = and f arg1; + should_fold2: bool = and arg1 f; + should_fold3: bool = or t arg1; + should_fold4: bool = or arg1 t; + + no_fold1: bool = and t arg1; + no_fold2: bool = and arg1 t; + no_fold3: bool = or f arg1; + no_fold4: bool = or arg1 f; + no_fold5: bool = and arg1 arg2; + no_fold6: bool = or arg1 arg2; + no_fold7: bool = not arg1; +} diff --git a/examples/test/lvn/logical-operators.out b/examples/test/lvn/logical-operators.out new file mode 100644 index 000000000..12028ea58 --- /dev/null +++ b/examples/test/lvn/logical-operators.out @@ -0,0 +1,21 @@ +@main(arg1: bool, arg2: bool) { + t: int = const true; + f: int = const false; + constant_fold1: bool = const false; + constant_fold2: bool = const false; + constant_fold3: bool = const true; + constant_fold4: bool = const true; + constant_fold5: bool = const false; + constant_fold6: bool = const true; + should_fold1: bool = const false; + should_fold2: bool = const false; + should_fold3: bool = const true; + should_fold4: bool = const true; + no_fold1: bool = and t arg1; + no_fold2: bool = and arg1 t; + no_fold3: bool = or f arg1; + no_fold4: bool = or arg1 f; + no_fold5: bool = and arg1 arg2; + no_fold6: bool = or arg1 arg2; + no_fold7: bool = not arg1; +}