|
10 | 10 | #include "goto_symex_is_constant.h"
|
11 | 11 | #include "goto_symex_state.h"
|
12 | 12 |
|
| 13 | +#include <util/arith_tools.h> |
13 | 14 | #include <util/format_expr.h>
|
14 | 15 |
|
15 | 16 | /// Print the constant propagation map in a human-friendly format.
|
@@ -44,15 +45,50 @@ void goto_statet::apply_condition(
|
44 | 45 | const goto_symex_statet &previous_state,
|
45 | 46 | const namespacet &ns)
|
46 | 47 | {
|
47 |
| - if(condition.id() == ID_and) |
| 48 | + if(auto and_expr = expr_try_dynamic_cast<and_exprt>(condition)) |
48 | 49 | {
|
49 |
| - for(const auto &op : condition.operands()) |
| 50 | + // A == B && C == D && E == F ... |
| 51 | + // --> |
| 52 | + // Apply each condition individually |
| 53 | + for(const auto &op : and_expr->operands()) |
50 | 54 | apply_condition(op, previous_state, ns);
|
51 | 55 | }
|
52 |
| - else if(condition.id() == ID_equal) |
| 56 | + else if(auto not_expr = expr_try_dynamic_cast<not_exprt>(condition)) |
53 | 57 | {
|
54 |
| - exprt lhs = to_equal_expr(condition).lhs(); |
55 |
| - exprt rhs = to_equal_expr(condition).rhs(); |
| 58 | + const exprt &operand = not_expr->op(); |
| 59 | + if(auto notequal_expr = expr_try_dynamic_cast<notequal_exprt>(operand)) |
| 60 | + { |
| 61 | + // !(A != B) |
| 62 | + // --> |
| 63 | + // A == B |
| 64 | + apply_condition( |
| 65 | + equal_exprt{notequal_expr->lhs(), notequal_expr->rhs()}, |
| 66 | + previous_state, |
| 67 | + ns); |
| 68 | + } |
| 69 | + else if(auto equal_expr = expr_try_dynamic_cast<equal_exprt>(operand)) |
| 70 | + { |
| 71 | + // !(A == B) |
| 72 | + // --> |
| 73 | + // A != B |
| 74 | + apply_condition( |
| 75 | + notequal_exprt{equal_expr->lhs(), equal_expr->rhs()}, |
| 76 | + previous_state, |
| 77 | + ns); |
| 78 | + } |
| 79 | + else |
| 80 | + { |
| 81 | + // !A |
| 82 | + // --> |
| 83 | + // A == false |
| 84 | + apply_condition(equal_exprt{operand, false_exprt{}}, previous_state, ns); |
| 85 | + } |
| 86 | + } |
| 87 | + else if(auto equal_expr = expr_try_dynamic_cast<equal_exprt>(condition)) |
| 88 | + { |
| 89 | + // Base case: try to apply a single equality constraint |
| 90 | + exprt lhs = equal_expr->lhs(); |
| 91 | + exprt rhs = equal_expr->rhs(); |
56 | 92 | if(is_ssa_expr(rhs))
|
57 | 93 | std::swap(lhs, rhs);
|
58 | 94 |
|
@@ -84,4 +120,33 @@ void goto_statet::apply_condition(
|
84 | 120 | }
|
85 | 121 | }
|
86 | 122 | }
|
| 123 | + else if( |
| 124 | + can_cast_expr<symbol_exprt>(condition) && condition.type() == bool_typet()) |
| 125 | + { |
| 126 | + // A |
| 127 | + // --> |
| 128 | + // A == true |
| 129 | + apply_condition(equal_exprt{condition, true_exprt()}, previous_state, ns); |
| 130 | + } |
| 131 | + else if( |
| 132 | + can_cast_expr<notequal_exprt>(condition) && |
| 133 | + expr_checked_cast<notequal_exprt>(condition).lhs().type() == bool_typet{}) |
| 134 | + { |
| 135 | + // A != (true|false) |
| 136 | + // --> |
| 137 | + // A == (false|true) |
| 138 | + const notequal_exprt ¬equal_expr = |
| 139 | + expr_dynamic_cast<notequal_exprt>(condition); |
| 140 | + exprt lhs = notequal_expr.lhs(); |
| 141 | + exprt rhs = notequal_expr.rhs(); |
| 142 | + if(is_ssa_expr(rhs)) |
| 143 | + std::swap(lhs, rhs); |
| 144 | + |
| 145 | + if(rhs.is_true()) |
| 146 | + apply_condition(equal_exprt{lhs, false_exprt{}}, previous_state, ns); |
| 147 | + else if(rhs.is_false()) |
| 148 | + apply_condition(equal_exprt{lhs, true_exprt{}}, previous_state, ns); |
| 149 | + else |
| 150 | + UNREACHABLE; |
| 151 | + } |
87 | 152 | }
|
0 commit comments