diff options
-rw-r--r-- | opt.c | 17 | ||||
-rwxr-xr-x | tests.sh | 7 | ||||
-rw-r--r-- | tests/test_and_false_or_true.out | 1 |
3 files changed, 25 insertions, 0 deletions
@@ -50,6 +50,7 @@ static char *fake_and_arg = "-a"; static char *fake_or_arg = "-o"; +static char *fake_not_arg = "!"; /** * A contrained integer range. @@ -433,6 +434,14 @@ static struct expr *optimize_and_expr(const struct opt_state *state, struct expr } else if (lhs->always_false) { debug_opt(state, "-O1: short-circuit: %e <==> %e\n", expr, lhs); return extract_child_expr(expr, &expr->lhs); + } else if (lhs->always_true && rhs == &expr_false) { + debug_opt(state, "-O1: strength reduction: %e <==> ", expr); + struct expr *ret = extract_child_expr(expr, &expr->lhs); + ret = negate_expr(ret, &fake_not_arg); + if (ret) { + debug_opt(state, "%e\n", ret); + } + return ret; } else if (optlevel >= 2 && lhs->pure && rhs == &expr_false) { debug_opt(state, "-O2: purity: %e <==> %e\n", expr, rhs); return extract_child_expr(expr, &expr->rhs); @@ -493,6 +502,14 @@ static struct expr *optimize_or_expr(const struct opt_state *state, struct expr } else if (rhs == &expr_false) { debug_opt(state, "-O1: disjunctive syllogism: %e <==> %e\n", expr, lhs); return extract_child_expr(expr, &expr->lhs); + } else if (lhs->always_false && rhs == &expr_true) { + debug_opt(state, "-O1: strength reduction: %e <==> ", expr); + struct expr *ret = extract_child_expr(expr, &expr->lhs); + ret = negate_expr(ret, &fake_not_arg); + if (ret) { + debug_opt(state, "%e\n", ret); + } + return ret; } else if (optlevel >= 2 && lhs->pure && rhs == &expr_true) { debug_opt(state, "-O2: purity: %e <==> %e\n", expr, rhs); return extract_child_expr(expr, &expr->rhs); @@ -609,6 +609,7 @@ gnu_tests=( test_and_purity test_not_reachability test_comma_reachability + test_and_false_or_true ) bfs_tests=( @@ -2003,6 +2004,12 @@ function test_de_morgan_or() { bfs_diff basic \( \! -name 'foo' -o \! -type f \) } +function test_and_false_or_true() { + # Test (-a lhs(always_true) false) <==> (! lhs), + # (-a lhs(always_false) true) <==> (! lhs) + bfs_diff basic -prune -false -o -true +} + function test_data_flow_depth() { bfs_diff basic -depth +1 -depth -4 } diff --git a/tests/test_and_false_or_true.out b/tests/test_and_false_or_true.out new file mode 100644 index 0000000..15a13db --- /dev/null +++ b/tests/test_and_false_or_true.out @@ -0,0 +1 @@ +basic |