1 1.1 mrg /* Tracking equivalence classes and constraints at a point on an execution path. 2 1.1.1.2 mrg Copyright (C) 2019-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by David Malcolm <dmalcolm (at) redhat.com>. 4 1.1 mrg 5 1.1 mrg This file is part of GCC. 6 1.1 mrg 7 1.1 mrg GCC is free software; you can redistribute it and/or modify it 8 1.1 mrg under the terms of the GNU General Public License as published by 9 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 10 1.1 mrg any later version. 11 1.1 mrg 12 1.1 mrg GCC is distributed in the hope that it will be useful, but 13 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 1.1 mrg General Public License for more details. 16 1.1 mrg 17 1.1 mrg You should have received a copy of the GNU General Public License 18 1.1 mrg along with GCC; see the file COPYING3. If not see 19 1.1 mrg <http://www.gnu.org/licenses/>. */ 20 1.1 mrg 21 1.1 mrg #include "config.h" 22 1.1 mrg #include "system.h" 23 1.1 mrg #include "coretypes.h" 24 1.1 mrg #include "tree.h" 25 1.1 mrg #include "function.h" 26 1.1 mrg #include "basic-block.h" 27 1.1 mrg #include "gimple.h" 28 1.1 mrg #include "gimple-iterator.h" 29 1.1 mrg #include "fold-const.h" 30 1.1 mrg #include "selftest.h" 31 1.1 mrg #include "diagnostic-core.h" 32 1.1 mrg #include "graphviz.h" 33 1.1 mrg #include "function.h" 34 1.1.1.2 mrg #include "json.h" 35 1.1 mrg #include "analyzer/analyzer.h" 36 1.1 mrg #include "ordered-hash-map.h" 37 1.1 mrg #include "options.h" 38 1.1 mrg #include "cgraph.h" 39 1.1 mrg #include "cfg.h" 40 1.1 mrg #include "digraph.h" 41 1.1 mrg #include "analyzer/supergraph.h" 42 1.1 mrg #include "sbitmap.h" 43 1.1 mrg #include "bitmap.h" 44 1.1 mrg #include "tristate.h" 45 1.1.1.2 mrg #include "analyzer/analyzer-logging.h" 46 1.1.1.2 mrg #include "analyzer/call-string.h" 47 1.1.1.2 mrg #include "analyzer/program-point.h" 48 1.1.1.2 mrg #include "analyzer/store.h" 49 1.1 mrg #include "analyzer/region-model.h" 50 1.1 mrg #include "analyzer/constraint-manager.h" 51 1.1 mrg #include "analyzer/analyzer-selftests.h" 52 1.1.1.2 mrg #include "tree-pretty-print.h" 53 1.1 mrg 54 1.1 mrg #if ENABLE_ANALYZER 55 1.1 mrg 56 1.1 mrg namespace ana { 57 1.1 mrg 58 1.1.1.2 mrg static tristate 59 1.1.1.2 mrg compare_constants (tree lhs_const, enum tree_code op, tree rhs_const) 60 1.1 mrg { 61 1.1.1.2 mrg tree comparison 62 1.1.1.2 mrg = fold_binary (op, boolean_type_node, lhs_const, rhs_const); 63 1.1.1.2 mrg if (comparison == boolean_true_node) 64 1.1.1.2 mrg return tristate (tristate::TS_TRUE); 65 1.1.1.2 mrg if (comparison == boolean_false_node) 66 1.1.1.2 mrg return tristate (tristate::TS_FALSE); 67 1.1.1.2 mrg return tristate (tristate::TS_UNKNOWN); 68 1.1.1.2 mrg } 69 1.1 mrg 70 1.1.1.2 mrg /* Return true iff CST is below the maximum value for its type. */ 71 1.1 mrg 72 1.1.1.2 mrg static bool 73 1.1.1.2 mrg can_plus_one_p (tree cst) 74 1.1.1.2 mrg { 75 1.1.1.2 mrg gcc_assert (CONSTANT_CLASS_P (cst)); 76 1.1.1.2 mrg return tree_int_cst_lt (cst, TYPE_MAX_VALUE (TREE_TYPE (cst))); 77 1.1.1.2 mrg } 78 1.1 mrg 79 1.1.1.2 mrg /* Return (CST + 1). */ 80 1.1 mrg 81 1.1.1.2 mrg static tree 82 1.1.1.2 mrg plus_one (tree cst) 83 1.1 mrg { 84 1.1.1.2 mrg gcc_assert (CONSTANT_CLASS_P (cst)); 85 1.1.1.2 mrg gcc_assert (can_plus_one_p (cst)); 86 1.1.1.2 mrg tree result = fold_build2 (PLUS_EXPR, TREE_TYPE (cst), 87 1.1.1.2 mrg cst, integer_one_node); 88 1.1.1.2 mrg gcc_assert (CONSTANT_CLASS_P (result)); 89 1.1.1.2 mrg return result; 90 1.1.1.2 mrg } 91 1.1 mrg 92 1.1.1.2 mrg /* Return true iff CST is above the minimum value for its type. */ 93 1.1 mrg 94 1.1.1.2 mrg static bool 95 1.1.1.2 mrg can_minus_one_p (tree cst) 96 1.1.1.2 mrg { 97 1.1.1.2 mrg gcc_assert (CONSTANT_CLASS_P (cst)); 98 1.1.1.2 mrg return tree_int_cst_lt (TYPE_MIN_VALUE (TREE_TYPE (cst)), cst); 99 1.1.1.2 mrg } 100 1.1 mrg 101 1.1.1.2 mrg /* Return (CST - 1). */ 102 1.1.1.2 mrg 103 1.1.1.2 mrg static tree 104 1.1.1.2 mrg minus_one (tree cst) 105 1.1.1.2 mrg { 106 1.1.1.2 mrg gcc_assert (CONSTANT_CLASS_P (cst)); 107 1.1.1.2 mrg gcc_assert (can_minus_one_p (cst)); 108 1.1.1.2 mrg tree result = fold_build2 (MINUS_EXPR, TREE_TYPE (cst), 109 1.1.1.2 mrg cst, integer_one_node); 110 1.1.1.2 mrg gcc_assert (CONSTANT_CLASS_P (result)); 111 1.1.1.2 mrg return result; 112 1.1.1.2 mrg } 113 1.1 mrg 114 1.1 mrg /* struct bound. */ 115 1.1 mrg 116 1.1 mrg /* Ensure that this bound is closed by converting an open bound to a 117 1.1 mrg closed one. */ 118 1.1 mrg 119 1.1 mrg void 120 1.1.1.2 mrg bound::ensure_closed (enum bound_kind bound_kind) 121 1.1 mrg { 122 1.1 mrg if (!m_closed) 123 1.1 mrg { 124 1.1 mrg /* Offset by 1 in the appropriate direction. 125 1.1 mrg For example, convert 3 < x into 4 <= x, 126 1.1 mrg and convert x < 5 into x <= 4. */ 127 1.1 mrg gcc_assert (CONSTANT_CLASS_P (m_constant)); 128 1.1.1.2 mrg m_constant = fold_build2 (bound_kind == BK_UPPER ? MINUS_EXPR : PLUS_EXPR, 129 1.1 mrg TREE_TYPE (m_constant), 130 1.1 mrg m_constant, integer_one_node); 131 1.1 mrg gcc_assert (CONSTANT_CLASS_P (m_constant)); 132 1.1 mrg m_closed = true; 133 1.1 mrg } 134 1.1 mrg } 135 1.1 mrg 136 1.1 mrg /* Get "<=" vs "<" for this bound. */ 137 1.1 mrg 138 1.1 mrg const char * 139 1.1 mrg bound::get_relation_as_str () const 140 1.1 mrg { 141 1.1 mrg if (m_closed) 142 1.1 mrg return "<="; 143 1.1 mrg else 144 1.1 mrg return "<"; 145 1.1 mrg } 146 1.1 mrg 147 1.1 mrg /* struct range. */ 148 1.1 mrg 149 1.1 mrg /* Dump this range to PP, which must support %E for tree. */ 150 1.1 mrg 151 1.1 mrg void 152 1.1.1.2 mrg range::dump_to_pp (pretty_printer *pp) const 153 1.1.1.2 mrg { 154 1.1.1.2 mrg if (m_lower_bound.m_constant) 155 1.1.1.2 mrg { 156 1.1.1.2 mrg if (m_upper_bound.m_constant) 157 1.1.1.2 mrg pp_printf (pp, "%qE %s x %s %qE", 158 1.1.1.2 mrg m_lower_bound.m_constant, 159 1.1.1.2 mrg m_lower_bound.get_relation_as_str (), 160 1.1.1.2 mrg m_upper_bound.get_relation_as_str (), 161 1.1.1.2 mrg m_upper_bound.m_constant); 162 1.1.1.2 mrg else 163 1.1.1.2 mrg pp_printf (pp, "%qE %s x", 164 1.1.1.2 mrg m_lower_bound.m_constant, 165 1.1.1.2 mrg m_lower_bound.get_relation_as_str ()); 166 1.1.1.2 mrg } 167 1.1.1.2 mrg else 168 1.1.1.2 mrg { 169 1.1.1.2 mrg if (m_upper_bound.m_constant) 170 1.1.1.2 mrg pp_printf (pp, "x %s %qE", 171 1.1.1.2 mrg m_upper_bound.get_relation_as_str (), 172 1.1.1.2 mrg m_upper_bound.m_constant); 173 1.1.1.2 mrg else 174 1.1.1.2 mrg pp_string (pp, "x"); 175 1.1.1.2 mrg } 176 1.1.1.2 mrg } 177 1.1.1.2 mrg 178 1.1.1.2 mrg /* Dump this range to stderr. */ 179 1.1.1.2 mrg 180 1.1.1.2 mrg DEBUG_FUNCTION void 181 1.1.1.2 mrg range::dump () const 182 1.1 mrg { 183 1.1.1.2 mrg pretty_printer pp; 184 1.1.1.2 mrg pp_format_decoder (&pp) = default_tree_printer; 185 1.1.1.2 mrg pp_show_color (&pp) = pp_show_color (global_dc->printer); 186 1.1.1.2 mrg pp.buffer->stream = stderr; 187 1.1.1.2 mrg dump_to_pp (&pp); 188 1.1.1.2 mrg pp_newline (&pp); 189 1.1.1.2 mrg pp_flush (&pp); 190 1.1 mrg } 191 1.1 mrg 192 1.1 mrg /* Determine if there is only one possible value for this range. 193 1.1.1.2 mrg If so, return the constant; otherwise, return NULL_TREE. */ 194 1.1 mrg 195 1.1.1.2 mrg tree 196 1.1.1.2 mrg range::constrained_to_single_element () 197 1.1 mrg { 198 1.1.1.2 mrg if (m_lower_bound.m_constant == NULL_TREE 199 1.1.1.2 mrg || m_upper_bound.m_constant == NULL_TREE) 200 1.1.1.2 mrg return NULL_TREE; 201 1.1.1.2 mrg 202 1.1 mrg if (!INTEGRAL_TYPE_P (TREE_TYPE (m_lower_bound.m_constant))) 203 1.1.1.2 mrg return NULL_TREE; 204 1.1 mrg if (!INTEGRAL_TYPE_P (TREE_TYPE (m_upper_bound.m_constant))) 205 1.1.1.2 mrg return NULL_TREE; 206 1.1 mrg 207 1.1 mrg /* Convert any open bounds to closed bounds. */ 208 1.1.1.2 mrg m_lower_bound.ensure_closed (BK_LOWER); 209 1.1.1.2 mrg m_upper_bound.ensure_closed (BK_UPPER); 210 1.1 mrg 211 1.1 mrg // Are they equal? 212 1.1 mrg tree comparison = fold_binary (EQ_EXPR, boolean_type_node, 213 1.1 mrg m_lower_bound.m_constant, 214 1.1 mrg m_upper_bound.m_constant); 215 1.1 mrg if (comparison == boolean_true_node) 216 1.1.1.2 mrg return m_lower_bound.m_constant; 217 1.1.1.2 mrg else 218 1.1.1.2 mrg return NULL_TREE; 219 1.1.1.2 mrg } 220 1.1.1.2 mrg 221 1.1.1.2 mrg /* Eval the condition "X OP RHS_CONST" for X within the range. */ 222 1.1.1.2 mrg 223 1.1.1.2 mrg tristate 224 1.1.1.2 mrg range::eval_condition (enum tree_code op, tree rhs_const) const 225 1.1.1.2 mrg { 226 1.1.1.2 mrg range copy (*this); 227 1.1.1.2 mrg if (tree single_element = copy.constrained_to_single_element ()) 228 1.1.1.2 mrg return compare_constants (single_element, op, rhs_const); 229 1.1.1.2 mrg 230 1.1.1.2 mrg switch (op) 231 1.1.1.2 mrg { 232 1.1.1.2 mrg case EQ_EXPR: 233 1.1.1.2 mrg if (below_lower_bound (rhs_const)) 234 1.1.1.2 mrg return tristate (tristate::TS_FALSE); 235 1.1.1.2 mrg if (above_upper_bound (rhs_const)) 236 1.1.1.2 mrg return tristate (tristate::TS_FALSE); 237 1.1.1.2 mrg break; 238 1.1.1.2 mrg 239 1.1.1.2 mrg case LT_EXPR: 240 1.1.1.2 mrg case LE_EXPR: 241 1.1.1.2 mrg /* Qn: "X </<= RHS_CONST". */ 242 1.1.1.2 mrg /* If RHS_CONST > upper bound, then it's true. 243 1.1.1.2 mrg If RHS_CONST < lower bound, then it's false. 244 1.1.1.2 mrg Otherwise unknown. */ 245 1.1.1.2 mrg if (above_upper_bound (rhs_const)) 246 1.1.1.2 mrg return tristate (tristate::TS_TRUE); 247 1.1.1.2 mrg if (below_lower_bound (rhs_const)) 248 1.1.1.2 mrg return tristate (tristate::TS_FALSE); 249 1.1.1.2 mrg break; 250 1.1.1.2 mrg 251 1.1.1.2 mrg case NE_EXPR: 252 1.1.1.2 mrg /* Qn: "X != RHS_CONST". */ 253 1.1.1.2 mrg /* If RHS_CONST < lower bound, then it's true. 254 1.1.1.2 mrg If RHS_CONST > upper bound, then it's false. 255 1.1.1.2 mrg Otherwise unknown. */ 256 1.1.1.2 mrg if (below_lower_bound (rhs_const)) 257 1.1.1.2 mrg return tristate (tristate::TS_TRUE); 258 1.1.1.2 mrg if (above_upper_bound (rhs_const)) 259 1.1.1.2 mrg return tristate (tristate::TS_TRUE); 260 1.1.1.2 mrg break; 261 1.1.1.2 mrg 262 1.1.1.2 mrg case GE_EXPR: 263 1.1.1.2 mrg case GT_EXPR: 264 1.1.1.2 mrg /* Qn: "X >=/> RHS_CONST". */ 265 1.1.1.2 mrg if (above_upper_bound (rhs_const)) 266 1.1.1.2 mrg return tristate (tristate::TS_FALSE); 267 1.1.1.2 mrg if (below_lower_bound (rhs_const)) 268 1.1.1.2 mrg return tristate (tristate::TS_TRUE); 269 1.1.1.2 mrg break; 270 1.1.1.2 mrg 271 1.1.1.2 mrg default: 272 1.1.1.2 mrg gcc_unreachable (); 273 1.1.1.2 mrg break; 274 1.1.1.2 mrg } 275 1.1.1.2 mrg return tristate (tristate::TS_UNKNOWN); 276 1.1.1.2 mrg } 277 1.1.1.2 mrg 278 1.1.1.2 mrg /* Return true if RHS_CONST is below the lower bound of this range. */ 279 1.1.1.2 mrg 280 1.1.1.2 mrg bool 281 1.1.1.2 mrg range::below_lower_bound (tree rhs_const) const 282 1.1.1.2 mrg { 283 1.1.1.2 mrg if (!m_lower_bound.m_constant) 284 1.1.1.2 mrg return false; 285 1.1.1.2 mrg 286 1.1.1.2 mrg return compare_constants (rhs_const, 287 1.1.1.2 mrg m_lower_bound.m_closed ? LT_EXPR : LE_EXPR, 288 1.1.1.2 mrg m_lower_bound.m_constant).is_true (); 289 1.1.1.2 mrg } 290 1.1.1.2 mrg 291 1.1.1.2 mrg /* Return true if RHS_CONST is above the upper bound of this range. */ 292 1.1.1.2 mrg 293 1.1.1.2 mrg bool 294 1.1.1.2 mrg range::above_upper_bound (tree rhs_const) const 295 1.1.1.2 mrg { 296 1.1.1.2 mrg if (!m_upper_bound.m_constant) 297 1.1.1.2 mrg return false; 298 1.1.1.2 mrg 299 1.1.1.2 mrg return compare_constants (rhs_const, 300 1.1.1.2 mrg m_upper_bound.m_closed ? GT_EXPR : GE_EXPR, 301 1.1.1.2 mrg m_upper_bound.m_constant).is_true (); 302 1.1.1.2 mrg } 303 1.1.1.2 mrg 304 1.1.1.2 mrg /* Attempt to add B to the bound of the given kind of this range. 305 1.1.1.2 mrg Return true if feasible; false if infeasible. */ 306 1.1.1.2 mrg 307 1.1.1.2 mrg bool 308 1.1.1.2 mrg range::add_bound (bound b, enum bound_kind bound_kind) 309 1.1.1.2 mrg { 310 1.1.1.2 mrg b.ensure_closed (bound_kind); 311 1.1.1.2 mrg 312 1.1.1.2 mrg switch (bound_kind) 313 1.1.1.2 mrg { 314 1.1.1.2 mrg default: 315 1.1.1.2 mrg gcc_unreachable (); 316 1.1.1.2 mrg case BK_LOWER: 317 1.1.1.2 mrg /* Discard redundant bounds. */ 318 1.1.1.2 mrg if (m_lower_bound.m_constant) 319 1.1.1.2 mrg { 320 1.1.1.2 mrg m_lower_bound.ensure_closed (BK_LOWER); 321 1.1.1.2 mrg if (tree_int_cst_le (b.m_constant, 322 1.1.1.2 mrg m_lower_bound.m_constant)) 323 1.1.1.2 mrg return true; 324 1.1.1.2 mrg } 325 1.1.1.2 mrg if (m_upper_bound.m_constant) 326 1.1.1.2 mrg { 327 1.1.1.2 mrg m_upper_bound.ensure_closed (BK_UPPER); 328 1.1.1.2 mrg /* Reject B <= V <= UPPER when B > UPPER. */ 329 1.1.1.2 mrg if (!tree_int_cst_le (b.m_constant, 330 1.1.1.2 mrg m_upper_bound.m_constant)) 331 1.1.1.2 mrg return false; 332 1.1.1.2 mrg } 333 1.1.1.2 mrg m_lower_bound = b; 334 1.1.1.2 mrg break; 335 1.1.1.2 mrg 336 1.1.1.2 mrg case BK_UPPER: 337 1.1.1.2 mrg /* Discard redundant bounds. */ 338 1.1.1.2 mrg if (m_upper_bound.m_constant) 339 1.1.1.2 mrg { 340 1.1.1.2 mrg m_upper_bound.ensure_closed (BK_UPPER); 341 1.1.1.2 mrg if (!tree_int_cst_lt (b.m_constant, 342 1.1.1.2 mrg m_upper_bound.m_constant)) 343 1.1.1.2 mrg return true; 344 1.1.1.2 mrg } 345 1.1.1.2 mrg if (m_lower_bound.m_constant) 346 1.1.1.2 mrg { 347 1.1.1.2 mrg m_lower_bound.ensure_closed (BK_LOWER); 348 1.1.1.2 mrg /* Reject LOWER <= V <= B when LOWER > B. */ 349 1.1.1.2 mrg if (!tree_int_cst_le (m_lower_bound.m_constant, 350 1.1.1.2 mrg b.m_constant)) 351 1.1.1.2 mrg return false; 352 1.1.1.2 mrg } 353 1.1.1.2 mrg m_upper_bound = b; 354 1.1.1.2 mrg break; 355 1.1.1.2 mrg } 356 1.1.1.2 mrg 357 1.1.1.2 mrg return true; 358 1.1.1.2 mrg } 359 1.1.1.2 mrg 360 1.1.1.2 mrg /* Attempt to add (RANGE OP RHS_CONST) as a bound to this range. 361 1.1.1.2 mrg Return true if feasible; false if infeasible. */ 362 1.1.1.2 mrg 363 1.1.1.2 mrg bool 364 1.1.1.2 mrg range::add_bound (enum tree_code op, tree rhs_const) 365 1.1.1.2 mrg { 366 1.1.1.2 mrg switch (op) 367 1.1.1.2 mrg { 368 1.1.1.2 mrg default: 369 1.1.1.2 mrg return true; 370 1.1.1.2 mrg case LT_EXPR: 371 1.1.1.2 mrg /* "V < RHS_CONST" */ 372 1.1.1.2 mrg return add_bound (bound (rhs_const, false), BK_UPPER); 373 1.1.1.2 mrg case LE_EXPR: 374 1.1.1.2 mrg /* "V <= RHS_CONST" */ 375 1.1.1.2 mrg return add_bound (bound (rhs_const, true), BK_UPPER); 376 1.1.1.2 mrg case GE_EXPR: 377 1.1.1.2 mrg /* "V >= RHS_CONST" */ 378 1.1.1.2 mrg return add_bound (bound (rhs_const, true), BK_LOWER); 379 1.1.1.2 mrg case GT_EXPR: 380 1.1.1.2 mrg /* "V > RHS_CONST" */ 381 1.1.1.2 mrg return add_bound (bound (rhs_const, false), BK_LOWER); 382 1.1.1.2 mrg } 383 1.1.1.2 mrg } 384 1.1.1.2 mrg 385 1.1.1.2 mrg /* struct bounded_range. */ 386 1.1.1.2 mrg 387 1.1.1.2 mrg bounded_range::bounded_range (const_tree lower, const_tree upper) 388 1.1.1.2 mrg : m_lower (const_cast<tree> (lower)), 389 1.1.1.2 mrg m_upper (const_cast<tree> (upper)) 390 1.1.1.2 mrg { 391 1.1.1.2 mrg if (lower && upper) 392 1.1.1.2 mrg { 393 1.1.1.2 mrg gcc_assert (TREE_CODE (m_lower) == INTEGER_CST); 394 1.1.1.2 mrg gcc_assert (TREE_CODE (m_upper) == INTEGER_CST); 395 1.1.1.2 mrg /* We should have lower <= upper. */ 396 1.1.1.2 mrg gcc_assert (!tree_int_cst_lt (m_upper, m_lower)); 397 1.1.1.2 mrg } 398 1.1.1.2 mrg else 399 1.1.1.2 mrg { 400 1.1.1.2 mrg /* Purely for pending on-stack values, for 401 1.1.1.2 mrg writing back to. */ 402 1.1.1.2 mrg gcc_assert (m_lower == NULL_TREE); 403 1.1.1.2 mrg gcc_assert (m_lower == NULL_TREE); 404 1.1.1.2 mrg } 405 1.1.1.2 mrg } 406 1.1.1.2 mrg 407 1.1.1.2 mrg static void 408 1.1.1.2 mrg dump_cst (pretty_printer *pp, tree cst, bool show_types) 409 1.1.1.2 mrg { 410 1.1.1.2 mrg gcc_assert (cst); 411 1.1.1.2 mrg if (show_types) 412 1.1.1.2 mrg { 413 1.1.1.2 mrg pp_character (pp, '('); 414 1.1.1.2 mrg dump_generic_node (pp, TREE_TYPE (cst), 0, (dump_flags_t)0, false); 415 1.1.1.2 mrg pp_character (pp, ')'); 416 1.1.1.2 mrg } 417 1.1.1.2 mrg dump_generic_node (pp, cst, 0, (dump_flags_t)0, false); 418 1.1.1.2 mrg } 419 1.1.1.2 mrg 420 1.1.1.2 mrg /* Dump this object to PP. */ 421 1.1.1.2 mrg 422 1.1.1.2 mrg void 423 1.1.1.2 mrg bounded_range::dump_to_pp (pretty_printer *pp, bool show_types) const 424 1.1.1.2 mrg { 425 1.1.1.2 mrg if (tree_int_cst_equal (m_lower, m_upper)) 426 1.1.1.2 mrg dump_cst (pp, m_lower, show_types); 427 1.1.1.2 mrg else 428 1.1.1.2 mrg { 429 1.1.1.2 mrg pp_character (pp, '['); 430 1.1.1.2 mrg dump_cst (pp, m_lower, show_types); 431 1.1.1.2 mrg pp_string (pp, ", "); 432 1.1.1.2 mrg dump_cst (pp, m_upper, show_types); 433 1.1.1.2 mrg pp_character (pp, ']'); 434 1.1.1.2 mrg } 435 1.1.1.2 mrg } 436 1.1.1.2 mrg 437 1.1.1.2 mrg /* Dump this object to stderr. */ 438 1.1.1.2 mrg 439 1.1.1.2 mrg void 440 1.1.1.2 mrg bounded_range::dump (bool show_types) const 441 1.1.1.2 mrg { 442 1.1.1.2 mrg pretty_printer pp; 443 1.1.1.2 mrg pp_format_decoder (&pp) = default_tree_printer; 444 1.1.1.2 mrg pp_show_color (&pp) = pp_show_color (global_dc->printer); 445 1.1.1.2 mrg pp.buffer->stream = stderr; 446 1.1.1.2 mrg dump_to_pp (&pp, show_types); 447 1.1.1.2 mrg pp_newline (&pp); 448 1.1.1.2 mrg pp_flush (&pp); 449 1.1.1.2 mrg } 450 1.1.1.2 mrg 451 1.1.1.2 mrg json::object * 452 1.1.1.2 mrg bounded_range::to_json () const 453 1.1.1.2 mrg { 454 1.1.1.2 mrg json::object *range_obj = new json::object (); 455 1.1.1.2 mrg set_json_attr (range_obj, "lower", m_lower); 456 1.1.1.2 mrg set_json_attr (range_obj, "upper", m_upper); 457 1.1.1.2 mrg return range_obj; 458 1.1.1.2 mrg } 459 1.1.1.2 mrg 460 1.1.1.2 mrg /* Subroutine of bounded_range::to_json. */ 461 1.1.1.2 mrg 462 1.1.1.2 mrg void 463 1.1.1.2 mrg bounded_range::set_json_attr (json::object *obj, const char *name, tree value) 464 1.1.1.2 mrg { 465 1.1.1.2 mrg pretty_printer pp; 466 1.1.1.2 mrg pp_format_decoder (&pp) = default_tree_printer; 467 1.1.1.2 mrg pp_printf (&pp, "%E", value); 468 1.1.1.2 mrg obj->set (name, new json::string (pp_formatted_text (&pp))); 469 1.1.1.2 mrg } 470 1.1.1.2 mrg 471 1.1.1.2 mrg 472 1.1.1.2 mrg /* Return true iff CST is within this range. */ 473 1.1.1.2 mrg 474 1.1.1.2 mrg bool 475 1.1.1.2 mrg bounded_range::contains_p (tree cst) const 476 1.1.1.2 mrg { 477 1.1.1.2 mrg /* Reject if below lower bound. */ 478 1.1.1.2 mrg if (tree_int_cst_lt (cst, m_lower)) 479 1.1.1.2 mrg return false; 480 1.1.1.2 mrg /* Reject if above lower bound. */ 481 1.1.1.2 mrg if (tree_int_cst_lt (m_upper, cst)) 482 1.1.1.2 mrg return false; 483 1.1.1.2 mrg return true; 484 1.1.1.2 mrg } 485 1.1.1.2 mrg 486 1.1.1.2 mrg /* If this range intersects OTHER, return true, writing 487 1.1.1.2 mrg the intersection to *OUT if OUT is non-NULL. 488 1.1.1.2 mrg Return false if they do not intersect. */ 489 1.1.1.2 mrg 490 1.1.1.2 mrg bool 491 1.1.1.2 mrg bounded_range::intersects_p (const bounded_range &other, 492 1.1.1.2 mrg bounded_range *out) const 493 1.1.1.2 mrg { 494 1.1.1.2 mrg const tree max_lower 495 1.1.1.2 mrg = (tree_int_cst_le (m_lower, other.m_lower) 496 1.1.1.2 mrg ? other.m_lower : m_lower); 497 1.1.1.2 mrg gcc_assert (TREE_CODE (max_lower) == INTEGER_CST); 498 1.1.1.2 mrg const tree min_upper 499 1.1.1.2 mrg = (tree_int_cst_le (m_upper, other.m_upper) 500 1.1.1.2 mrg ? m_upper : other.m_upper); 501 1.1.1.2 mrg gcc_assert (TREE_CODE (min_upper) == INTEGER_CST); 502 1.1.1.2 mrg 503 1.1.1.2 mrg if (tree_int_cst_le (max_lower, min_upper)) 504 1.1.1.2 mrg { 505 1.1.1.2 mrg if (out) 506 1.1.1.2 mrg *out = bounded_range (max_lower, min_upper); 507 1.1.1.2 mrg return true; 508 1.1.1.2 mrg } 509 1.1.1.2 mrg else 510 1.1.1.2 mrg return false; 511 1.1.1.2 mrg } 512 1.1.1.2 mrg 513 1.1.1.2 mrg bool 514 1.1.1.2 mrg bounded_range::operator== (const bounded_range &other) const 515 1.1.1.2 mrg { 516 1.1.1.2 mrg return (TREE_TYPE (m_lower) == TREE_TYPE (other.m_lower) 517 1.1.1.2 mrg && TREE_TYPE (m_upper) == TREE_TYPE (other.m_upper) 518 1.1.1.2 mrg && tree_int_cst_equal (m_lower, other.m_lower) 519 1.1.1.2 mrg && tree_int_cst_equal (m_upper, other.m_upper)); 520 1.1.1.2 mrg } 521 1.1.1.2 mrg 522 1.1.1.2 mrg int 523 1.1.1.2 mrg bounded_range::cmp (const bounded_range &br1, const bounded_range &br2) 524 1.1.1.2 mrg { 525 1.1.1.2 mrg if (int cmp_lower = tree_int_cst_compare (br1.m_lower, 526 1.1.1.2 mrg br2.m_lower)) 527 1.1.1.2 mrg return cmp_lower; 528 1.1.1.2 mrg return tree_int_cst_compare (br1.m_upper, br2.m_upper); 529 1.1.1.2 mrg } 530 1.1.1.2 mrg 531 1.1.1.2 mrg /* struct bounded_ranges. */ 532 1.1.1.2 mrg 533 1.1.1.2 mrg /* Construct a bounded_ranges instance from a single range. */ 534 1.1.1.2 mrg 535 1.1.1.2 mrg bounded_ranges::bounded_ranges (const bounded_range &range) 536 1.1.1.2 mrg : m_ranges (1) 537 1.1.1.2 mrg { 538 1.1.1.2 mrg m_ranges.quick_push (range); 539 1.1.1.2 mrg canonicalize (); 540 1.1.1.2 mrg validate (); 541 1.1.1.2 mrg } 542 1.1.1.2 mrg 543 1.1.1.2 mrg /* Construct a bounded_ranges instance from multiple ranges. */ 544 1.1.1.2 mrg 545 1.1.1.2 mrg bounded_ranges::bounded_ranges (const vec<bounded_range> &ranges) 546 1.1.1.2 mrg : m_ranges (ranges.length ()) 547 1.1.1.2 mrg { 548 1.1.1.2 mrg m_ranges.safe_splice (ranges); 549 1.1.1.2 mrg canonicalize (); 550 1.1.1.2 mrg validate (); 551 1.1.1.2 mrg } 552 1.1.1.2 mrg 553 1.1.1.2 mrg /* Construct a bounded_ranges instance for values of LHS for which 554 1.1.1.2 mrg (LHS OP RHS_CONST) is true (e.g. "(LHS > 3)". */ 555 1.1.1.2 mrg 556 1.1.1.2 mrg bounded_ranges::bounded_ranges (enum tree_code op, tree rhs_const) 557 1.1.1.2 mrg : m_ranges () 558 1.1.1.2 mrg { 559 1.1.1.2 mrg gcc_assert (TREE_CODE (rhs_const) == INTEGER_CST); 560 1.1.1.2 mrg tree type = TREE_TYPE (rhs_const); 561 1.1.1.2 mrg switch (op) 562 1.1.1.2 mrg { 563 1.1.1.2 mrg default: 564 1.1.1.2 mrg gcc_unreachable (); 565 1.1.1.2 mrg case EQ_EXPR: 566 1.1.1.2 mrg m_ranges.safe_push (bounded_range (rhs_const, rhs_const)); 567 1.1.1.2 mrg break; 568 1.1.1.2 mrg 569 1.1.1.2 mrg case GE_EXPR: 570 1.1.1.2 mrg m_ranges.safe_push (bounded_range (rhs_const, TYPE_MAX_VALUE (type))); 571 1.1.1.2 mrg break; 572 1.1.1.2 mrg 573 1.1.1.2 mrg case LE_EXPR: 574 1.1.1.2 mrg m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type), rhs_const)); 575 1.1.1.2 mrg break; 576 1.1.1.2 mrg 577 1.1.1.2 mrg case NE_EXPR: 578 1.1.1.2 mrg if (tree_int_cst_lt (TYPE_MIN_VALUE (type), rhs_const)) 579 1.1.1.2 mrg m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type), 580 1.1.1.2 mrg minus_one (rhs_const))); 581 1.1.1.2 mrg if (tree_int_cst_lt (rhs_const, TYPE_MAX_VALUE (type))) 582 1.1.1.2 mrg m_ranges.safe_push (bounded_range (plus_one (rhs_const), 583 1.1.1.2 mrg TYPE_MAX_VALUE (type))); 584 1.1.1.2 mrg break; 585 1.1.1.2 mrg case GT_EXPR: 586 1.1.1.2 mrg if (tree_int_cst_lt (rhs_const, TYPE_MAX_VALUE (type))) 587 1.1.1.2 mrg m_ranges.safe_push (bounded_range (plus_one (rhs_const), 588 1.1.1.2 mrg TYPE_MAX_VALUE (type))); 589 1.1.1.2 mrg break; 590 1.1.1.2 mrg case LT_EXPR: 591 1.1.1.2 mrg if (tree_int_cst_lt (TYPE_MIN_VALUE (type), rhs_const)) 592 1.1.1.2 mrg m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type), 593 1.1.1.2 mrg minus_one (rhs_const))); 594 1.1.1.2 mrg break; 595 1.1.1.2 mrg } 596 1.1.1.2 mrg canonicalize (); 597 1.1.1.2 mrg validate (); 598 1.1.1.2 mrg } 599 1.1.1.2 mrg 600 1.1.1.2 mrg /* Subroutine of ctors for fixing up m_ranges. 601 1.1.1.2 mrg Also, initialize m_hash. */ 602 1.1.1.2 mrg 603 1.1.1.2 mrg void 604 1.1.1.2 mrg bounded_ranges::canonicalize () 605 1.1.1.2 mrg { 606 1.1.1.2 mrg /* Sort the ranges. */ 607 1.1.1.2 mrg m_ranges.qsort ([](const void *p1, const void *p2) -> int 608 1.1.1.2 mrg { 609 1.1.1.2 mrg const bounded_range &br1 = *(const bounded_range *)p1; 610 1.1.1.2 mrg const bounded_range &br2 = *(const bounded_range *)p2; 611 1.1.1.2 mrg return bounded_range::cmp (br1, br2); 612 1.1.1.2 mrg }); 613 1.1.1.2 mrg 614 1.1.1.2 mrg /* Merge ranges that are touching or overlapping. */ 615 1.1.1.2 mrg for (unsigned i = 1; i < m_ranges.length (); ) 616 1.1.1.2 mrg { 617 1.1.1.2 mrg bounded_range *prev = &m_ranges[i - 1]; 618 1.1.1.2 mrg const bounded_range *next = &m_ranges[i]; 619 1.1.1.2 mrg if (prev->intersects_p (*next, NULL) 620 1.1.1.2 mrg || (can_plus_one_p (prev->m_upper) 621 1.1.1.2 mrg && tree_int_cst_equal (plus_one (prev->m_upper), 622 1.1.1.2 mrg next->m_lower))) 623 1.1.1.2 mrg { 624 1.1.1.2 mrg prev->m_upper = next->m_upper; 625 1.1.1.2 mrg m_ranges.ordered_remove (i); 626 1.1.1.2 mrg } 627 1.1.1.2 mrg else 628 1.1.1.2 mrg i++; 629 1.1.1.2 mrg } 630 1.1.1.2 mrg 631 1.1.1.2 mrg /* Initialize m_hash. */ 632 1.1.1.2 mrg inchash::hash hstate (0); 633 1.1.1.2 mrg for (const auto &iter : m_ranges) 634 1.1.1.2 mrg { 635 1.1.1.2 mrg inchash::add_expr (iter.m_lower, hstate); 636 1.1.1.2 mrg inchash::add_expr (iter.m_upper, hstate); 637 1.1.1.2 mrg } 638 1.1.1.2 mrg m_hash = hstate.end (); 639 1.1.1.2 mrg } 640 1.1.1.2 mrg 641 1.1.1.2 mrg /* Assert that this object is valid. */ 642 1.1.1.2 mrg 643 1.1.1.2 mrg void 644 1.1.1.2 mrg bounded_ranges::validate () const 645 1.1.1.2 mrg { 646 1.1.1.2 mrg /* Skip this in a release build. */ 647 1.1.1.2 mrg #if !CHECKING_P 648 1.1.1.2 mrg return; 649 1.1.1.2 mrg #endif 650 1.1.1.2 mrg 651 1.1.1.2 mrg for (unsigned i = 1; i < m_ranges.length (); i++) 652 1.1.1.2 mrg { 653 1.1.1.2 mrg const bounded_range &prev = m_ranges[i - 1]; 654 1.1.1.2 mrg const bounded_range &next = m_ranges[i]; 655 1.1.1.2 mrg 656 1.1.1.2 mrg /* Give up if we somehow have incompatible different types. */ 657 1.1.1.2 mrg if (!types_compatible_p (TREE_TYPE (prev.m_upper), 658 1.1.1.2 mrg TREE_TYPE (next.m_lower))) 659 1.1.1.2 mrg continue; 660 1.1.1.2 mrg 661 1.1.1.2 mrg /* Verify sorted. */ 662 1.1.1.2 mrg gcc_assert (tree_int_cst_lt (prev.m_upper, next.m_lower)); 663 1.1.1.2 mrg 664 1.1.1.2 mrg gcc_assert (can_plus_one_p (prev.m_upper)); 665 1.1.1.2 mrg /* otherwise there's no room for "next". */ 666 1.1.1.2 mrg 667 1.1.1.2 mrg /* Verify no ranges touch each other. */ 668 1.1.1.2 mrg gcc_assert (tree_int_cst_lt (plus_one (prev.m_upper), next.m_lower)); 669 1.1.1.2 mrg } 670 1.1.1.2 mrg } 671 1.1.1.2 mrg 672 1.1.1.2 mrg /* bounded_ranges equality operator. */ 673 1.1.1.2 mrg 674 1.1.1.2 mrg bool 675 1.1.1.2 mrg bounded_ranges::operator== (const bounded_ranges &other) const 676 1.1.1.2 mrg { 677 1.1.1.2 mrg if (m_ranges.length () != other.m_ranges.length ()) 678 1.1.1.2 mrg return false; 679 1.1.1.2 mrg for (unsigned i = 0; i < m_ranges.length (); i++) 680 1.1.1.2 mrg { 681 1.1.1.2 mrg if (m_ranges[i] != other.m_ranges[i]) 682 1.1.1.2 mrg return false; 683 1.1.1.2 mrg } 684 1.1.1.2 mrg return true; 685 1.1.1.2 mrg } 686 1.1.1.2 mrg 687 1.1.1.2 mrg /* Dump this object to PP. */ 688 1.1.1.2 mrg 689 1.1.1.2 mrg void 690 1.1.1.2 mrg bounded_ranges::dump_to_pp (pretty_printer *pp, bool show_types) const 691 1.1.1.2 mrg { 692 1.1.1.2 mrg pp_character (pp, '{'); 693 1.1.1.2 mrg for (unsigned i = 0; i < m_ranges.length (); ++i) 694 1.1.1.2 mrg { 695 1.1.1.2 mrg if (i > 0) 696 1.1.1.2 mrg pp_string (pp, ", "); 697 1.1.1.2 mrg m_ranges[i].dump_to_pp (pp, show_types); 698 1.1.1.2 mrg } 699 1.1.1.2 mrg pp_character (pp, '}'); 700 1.1.1.2 mrg } 701 1.1.1.2 mrg 702 1.1.1.2 mrg /* Dump this object to stderr. */ 703 1.1.1.2 mrg 704 1.1.1.2 mrg DEBUG_FUNCTION void 705 1.1.1.2 mrg bounded_ranges::dump (bool show_types) const 706 1.1.1.2 mrg { 707 1.1.1.2 mrg pretty_printer pp; 708 1.1.1.2 mrg pp_format_decoder (&pp) = default_tree_printer; 709 1.1.1.2 mrg pp_show_color (&pp) = pp_show_color (global_dc->printer); 710 1.1.1.2 mrg pp.buffer->stream = stderr; 711 1.1.1.2 mrg dump_to_pp (&pp, show_types); 712 1.1.1.2 mrg pp_newline (&pp); 713 1.1.1.2 mrg pp_flush (&pp); 714 1.1.1.2 mrg } 715 1.1.1.2 mrg 716 1.1.1.2 mrg json::value * 717 1.1.1.2 mrg bounded_ranges::to_json () const 718 1.1.1.2 mrg { 719 1.1.1.2 mrg json::array *arr_obj = new json::array (); 720 1.1.1.2 mrg 721 1.1.1.2 mrg for (unsigned i = 0; i < m_ranges.length (); ++i) 722 1.1.1.2 mrg arr_obj->append (m_ranges[i].to_json ()); 723 1.1.1.2 mrg 724 1.1.1.2 mrg return arr_obj; 725 1.1.1.2 mrg } 726 1.1.1.2 mrg 727 1.1.1.2 mrg /* Determine whether (X OP RHS_CONST) is known to be true or false 728 1.1.1.2 mrg for all X in the ranges expressed by this object. */ 729 1.1.1.2 mrg 730 1.1.1.2 mrg tristate 731 1.1.1.2 mrg bounded_ranges::eval_condition (enum tree_code op, 732 1.1.1.2 mrg tree rhs_const, 733 1.1.1.2 mrg bounded_ranges_manager *mgr) const 734 1.1.1.2 mrg { 735 1.1.1.2 mrg /* Convert (X OP RHS_CONST) to a bounded_ranges instance and find 736 1.1.1.2 mrg the intersection of that with this object. */ 737 1.1.1.2 mrg bounded_ranges other (op, rhs_const); 738 1.1.1.2 mrg const bounded_ranges *intersection 739 1.1.1.2 mrg = mgr->get_or_create_intersection (this, &other); 740 1.1.1.2 mrg 741 1.1.1.2 mrg if (intersection->m_ranges.length () > 0) 742 1.1.1.2 mrg { 743 1.1.1.2 mrg /* We can use pointer equality to check for equality, 744 1.1.1.2 mrg due to instance consolidation. */ 745 1.1.1.2 mrg if (intersection == this) 746 1.1.1.2 mrg return tristate (tristate::TS_TRUE); 747 1.1.1.2 mrg else 748 1.1.1.2 mrg return tristate (tristate::TS_UNKNOWN); 749 1.1.1.2 mrg } 750 1.1.1.2 mrg else 751 1.1.1.2 mrg /* No intersection. */ 752 1.1.1.2 mrg return tristate (tristate::TS_FALSE); 753 1.1.1.2 mrg } 754 1.1.1.2 mrg 755 1.1.1.2 mrg /* Return true if CST is within any of the ranges. */ 756 1.1.1.2 mrg 757 1.1.1.2 mrg bool 758 1.1.1.2 mrg bounded_ranges::contain_p (tree cst) const 759 1.1.1.2 mrg { 760 1.1.1.2 mrg gcc_assert (TREE_CODE (cst) == INTEGER_CST); 761 1.1.1.2 mrg for (const auto &iter : m_ranges) 762 1.1.1.2 mrg { 763 1.1.1.2 mrg /* TODO: should we optimize this based on sorting? */ 764 1.1.1.2 mrg if (iter.contains_p (cst)) 765 1.1.1.2 mrg return true; 766 1.1.1.2 mrg } 767 1.1.1.2 mrg return false; 768 1.1.1.2 mrg } 769 1.1.1.2 mrg 770 1.1.1.2 mrg int 771 1.1.1.2 mrg bounded_ranges::cmp (const bounded_ranges *a, const bounded_ranges *b) 772 1.1.1.2 mrg { 773 1.1.1.2 mrg if (int cmp_length = ((int)a->m_ranges.length () 774 1.1.1.2 mrg - (int)b->m_ranges.length ())) 775 1.1.1.2 mrg return cmp_length; 776 1.1.1.2 mrg for (unsigned i = 0; i < a->m_ranges.length (); i++) 777 1.1.1.2 mrg { 778 1.1.1.2 mrg if (int cmp_range = bounded_range::cmp (a->m_ranges[i], b->m_ranges[i])) 779 1.1.1.2 mrg return cmp_range; 780 1.1.1.2 mrg } 781 1.1.1.2 mrg /* They are equal. They ought to have been consolidated, so we should 782 1.1.1.2 mrg have two pointers to the same object. */ 783 1.1.1.2 mrg gcc_assert (a == b); 784 1.1.1.2 mrg return 0; 785 1.1.1.2 mrg } 786 1.1.1.2 mrg 787 1.1.1.2 mrg /* class bounded_ranges_manager. */ 788 1.1.1.2 mrg 789 1.1.1.2 mrg /* bounded_ranges_manager's dtor. */ 790 1.1.1.2 mrg 791 1.1.1.2 mrg bounded_ranges_manager::~bounded_ranges_manager () 792 1.1.1.2 mrg { 793 1.1.1.2 mrg /* Delete the managed objects. */ 794 1.1.1.2 mrg for (const auto &iter : m_map) 795 1.1.1.2 mrg delete iter.second; 796 1.1.1.2 mrg } 797 1.1.1.2 mrg 798 1.1.1.2 mrg /* Get the bounded_ranges instance for the empty set, creating it if 799 1.1.1.2 mrg necessary. */ 800 1.1.1.2 mrg 801 1.1.1.2 mrg const bounded_ranges * 802 1.1.1.2 mrg bounded_ranges_manager::get_or_create_empty () 803 1.1.1.2 mrg { 804 1.1.1.2 mrg auto_vec<bounded_range> empty_vec; 805 1.1.1.2 mrg 806 1.1.1.2 mrg return consolidate (new bounded_ranges (empty_vec)); 807 1.1.1.2 mrg } 808 1.1.1.2 mrg 809 1.1.1.2 mrg /* Get the bounded_ranges instance for {CST}, creating it if necessary. */ 810 1.1.1.2 mrg 811 1.1.1.2 mrg const bounded_ranges * 812 1.1.1.2 mrg bounded_ranges_manager::get_or_create_point (const_tree cst) 813 1.1.1.2 mrg { 814 1.1.1.2 mrg gcc_assert (TREE_CODE (cst) == INTEGER_CST); 815 1.1.1.2 mrg 816 1.1.1.2 mrg return get_or_create_range (cst, cst); 817 1.1.1.2 mrg } 818 1.1.1.2 mrg 819 1.1.1.2 mrg /* Get the bounded_ranges instance for {[LOWER_BOUND..UPPER_BOUND]}, 820 1.1.1.2 mrg creating it if necessary. */ 821 1.1.1.2 mrg 822 1.1.1.2 mrg const bounded_ranges * 823 1.1.1.2 mrg bounded_ranges_manager::get_or_create_range (const_tree lower_bound, 824 1.1.1.2 mrg const_tree upper_bound) 825 1.1.1.2 mrg { 826 1.1.1.2 mrg gcc_assert (TREE_CODE (lower_bound) == INTEGER_CST); 827 1.1.1.2 mrg gcc_assert (TREE_CODE (upper_bound) == INTEGER_CST); 828 1.1.1.2 mrg 829 1.1.1.2 mrg return consolidate 830 1.1.1.2 mrg (new bounded_ranges (bounded_range (lower_bound, upper_bound))); 831 1.1.1.2 mrg } 832 1.1.1.2 mrg 833 1.1.1.2 mrg /* Get the bounded_ranges instance for the union of OTHERS, 834 1.1.1.2 mrg creating it if necessary. */ 835 1.1.1.2 mrg 836 1.1.1.2 mrg const bounded_ranges * 837 1.1.1.2 mrg bounded_ranges_manager:: 838 1.1.1.2 mrg get_or_create_union (const vec <const bounded_ranges *> &others) 839 1.1.1.2 mrg { 840 1.1.1.2 mrg auto_vec<bounded_range> ranges; 841 1.1.1.2 mrg for (const auto &r : others) 842 1.1.1.2 mrg ranges.safe_splice (r->m_ranges); 843 1.1.1.2 mrg return consolidate (new bounded_ranges (ranges)); 844 1.1.1.2 mrg } 845 1.1.1.2 mrg 846 1.1.1.2 mrg /* Get the bounded_ranges instance for the intersection of A and B, 847 1.1.1.2 mrg creating it if necessary. */ 848 1.1.1.2 mrg 849 1.1.1.2 mrg const bounded_ranges * 850 1.1.1.2 mrg bounded_ranges_manager::get_or_create_intersection (const bounded_ranges *a, 851 1.1.1.2 mrg const bounded_ranges *b) 852 1.1.1.2 mrg { 853 1.1.1.2 mrg auto_vec<bounded_range> ranges; 854 1.1.1.2 mrg unsigned a_idx = 0; 855 1.1.1.2 mrg unsigned b_idx = 0; 856 1.1.1.2 mrg while (a_idx < a->m_ranges.length () 857 1.1.1.2 mrg && b_idx < b->m_ranges.length ()) 858 1.1.1.2 mrg { 859 1.1.1.2 mrg const bounded_range &r_a = a->m_ranges[a_idx]; 860 1.1.1.2 mrg const bounded_range &r_b = b->m_ranges[b_idx]; 861 1.1.1.2 mrg 862 1.1.1.2 mrg bounded_range intersection (NULL_TREE, NULL_TREE); 863 1.1.1.2 mrg if (r_a.intersects_p (r_b, &intersection)) 864 1.1.1.2 mrg { 865 1.1.1.2 mrg ranges.safe_push (intersection); 866 1.1.1.2 mrg } 867 1.1.1.2 mrg if (tree_int_cst_lt (r_a.m_lower, r_b.m_lower)) 868 1.1.1.2 mrg { 869 1.1.1.2 mrg a_idx++; 870 1.1.1.2 mrg } 871 1.1.1.2 mrg else 872 1.1.1.2 mrg { 873 1.1.1.2 mrg if (tree_int_cst_lt (r_a.m_upper, r_b.m_upper)) 874 1.1.1.2 mrg a_idx++; 875 1.1.1.2 mrg else 876 1.1.1.2 mrg b_idx++; 877 1.1.1.2 mrg } 878 1.1.1.2 mrg } 879 1.1.1.2 mrg 880 1.1.1.2 mrg return consolidate (new bounded_ranges (ranges)); 881 1.1.1.2 mrg } 882 1.1.1.2 mrg 883 1.1.1.2 mrg /* Get the bounded_ranges instance for the inverse of OTHER relative 884 1.1.1.2 mrg to TYPE, creating it if necessary. 885 1.1.1.2 mrg This is for use when handling "default" in switch statements, where 886 1.1.1.2 mrg OTHER represents all the other cases. */ 887 1.1.1.2 mrg 888 1.1.1.2 mrg const bounded_ranges * 889 1.1.1.2 mrg bounded_ranges_manager::get_or_create_inverse (const bounded_ranges *other, 890 1.1.1.2 mrg tree type) 891 1.1.1.2 mrg { 892 1.1.1.2 mrg tree min_val = TYPE_MIN_VALUE (type); 893 1.1.1.2 mrg tree max_val = TYPE_MAX_VALUE (type); 894 1.1.1.2 mrg if (other->m_ranges.length () == 0) 895 1.1.1.2 mrg return get_or_create_range (min_val, max_val); 896 1.1.1.2 mrg auto_vec<bounded_range> ranges; 897 1.1.1.2 mrg tree first_lb = other->m_ranges[0].m_lower; 898 1.1.1.2 mrg if (tree_int_cst_lt (min_val, first_lb) 899 1.1.1.2 mrg && can_minus_one_p (first_lb)) 900 1.1.1.2 mrg ranges.safe_push (bounded_range (min_val, 901 1.1.1.2 mrg minus_one (first_lb))); 902 1.1.1.2 mrg for (unsigned i = 1; i < other->m_ranges.length (); i++) 903 1.1.1.2 mrg { 904 1.1.1.2 mrg tree prev_ub = other->m_ranges[i - 1].m_upper; 905 1.1.1.2 mrg tree iter_lb = other->m_ranges[i].m_lower; 906 1.1.1.2 mrg gcc_assert (tree_int_cst_lt (prev_ub, iter_lb)); 907 1.1.1.2 mrg if (can_plus_one_p (prev_ub) && can_minus_one_p (iter_lb)) 908 1.1.1.2 mrg ranges.safe_push (bounded_range (plus_one (prev_ub), 909 1.1.1.2 mrg minus_one (iter_lb))); 910 1.1.1.2 mrg } 911 1.1.1.2 mrg tree last_ub 912 1.1.1.2 mrg = other->m_ranges[other->m_ranges.length () - 1].m_upper; 913 1.1.1.2 mrg if (tree_int_cst_lt (last_ub, max_val) 914 1.1.1.2 mrg && can_plus_one_p (last_ub)) 915 1.1.1.2 mrg ranges.safe_push (bounded_range (plus_one (last_ub), max_val)); 916 1.1.1.2 mrg 917 1.1.1.2 mrg return consolidate (new bounded_ranges (ranges)); 918 1.1.1.2 mrg } 919 1.1.1.2 mrg 920 1.1.1.2 mrg /* If an object equal to INST is already present, delete INST and 921 1.1.1.2 mrg return the existing object. 922 1.1.1.2 mrg Otherwise add INST and return it. */ 923 1.1.1.2 mrg 924 1.1.1.2 mrg const bounded_ranges * 925 1.1.1.2 mrg bounded_ranges_manager::consolidate (bounded_ranges *inst) 926 1.1.1.2 mrg { 927 1.1.1.2 mrg if (bounded_ranges **slot = m_map.get (inst)) 928 1.1.1.2 mrg { 929 1.1.1.2 mrg delete inst; 930 1.1.1.2 mrg return *slot; 931 1.1.1.2 mrg } 932 1.1.1.2 mrg m_map.put (inst, inst); 933 1.1.1.2 mrg return inst; 934 1.1.1.2 mrg } 935 1.1.1.2 mrg 936 1.1.1.2 mrg /* Get the bounded_ranges instance for EDGE of SWITCH_STMT, 937 1.1.1.2 mrg creating it if necessary, and caching it by edge. */ 938 1.1.1.2 mrg 939 1.1.1.2 mrg const bounded_ranges * 940 1.1.1.2 mrg bounded_ranges_manager:: 941 1.1.1.2 mrg get_or_create_ranges_for_switch (const switch_cfg_superedge *edge, 942 1.1.1.2 mrg const gswitch *switch_stmt) 943 1.1.1.2 mrg { 944 1.1.1.2 mrg /* Look in per-edge cache. */ 945 1.1.1.2 mrg if (const bounded_ranges ** slot = m_edge_cache.get (edge)) 946 1.1.1.2 mrg return *slot; 947 1.1.1.2 mrg 948 1.1.1.2 mrg /* Not yet in cache. */ 949 1.1.1.2 mrg const bounded_ranges *all_cases_ranges 950 1.1.1.2 mrg = create_ranges_for_switch (*edge, switch_stmt); 951 1.1.1.2 mrg m_edge_cache.put (edge, all_cases_ranges); 952 1.1.1.2 mrg return all_cases_ranges; 953 1.1.1.2 mrg } 954 1.1.1.2 mrg 955 1.1.1.2 mrg /* Get the bounded_ranges instance for EDGE of SWITCH_STMT, 956 1.1.1.2 mrg creating it if necessary, for edges for which the per-edge 957 1.1.1.2 mrg cache has not yet been populated. */ 958 1.1.1.2 mrg 959 1.1.1.2 mrg const bounded_ranges * 960 1.1.1.2 mrg bounded_ranges_manager:: 961 1.1.1.2 mrg create_ranges_for_switch (const switch_cfg_superedge &edge, 962 1.1.1.2 mrg const gswitch *switch_stmt) 963 1.1.1.2 mrg { 964 1.1.1.2 mrg /* Get the ranges for each case label. */ 965 1.1.1.2 mrg auto_vec <const bounded_ranges *> case_ranges_vec 966 1.1.1.2 mrg (gimple_switch_num_labels (switch_stmt)); 967 1.1.1.2 mrg 968 1.1.1.2 mrg for (tree case_label : edge.get_case_labels ()) 969 1.1.1.2 mrg { 970 1.1.1.2 mrg /* Get the ranges for this case label. */ 971 1.1.1.2 mrg const bounded_ranges *case_ranges 972 1.1.1.2 mrg = make_case_label_ranges (switch_stmt, case_label); 973 1.1.1.2 mrg case_ranges_vec.quick_push (case_ranges); 974 1.1.1.2 mrg } 975 1.1.1.2 mrg 976 1.1.1.2 mrg /* Combine all the ranges for each case label into a single collection 977 1.1.1.2 mrg of ranges. */ 978 1.1.1.2 mrg const bounded_ranges *all_cases_ranges 979 1.1.1.2 mrg = get_or_create_union (case_ranges_vec); 980 1.1.1.2 mrg return all_cases_ranges; 981 1.1.1.2 mrg } 982 1.1.1.2 mrg 983 1.1.1.2 mrg /* Get the bounded_ranges instance for CASE_LABEL within 984 1.1.1.2 mrg SWITCH_STMT. */ 985 1.1.1.2 mrg 986 1.1.1.2 mrg const bounded_ranges * 987 1.1.1.2 mrg bounded_ranges_manager:: 988 1.1.1.2 mrg make_case_label_ranges (const gswitch *switch_stmt, 989 1.1.1.2 mrg tree case_label) 990 1.1.1.2 mrg { 991 1.1.1.2 mrg gcc_assert (TREE_CODE (case_label) == CASE_LABEL_EXPR); 992 1.1.1.2 mrg tree lower_bound = CASE_LOW (case_label); 993 1.1.1.2 mrg tree upper_bound = CASE_HIGH (case_label); 994 1.1.1.2 mrg if (lower_bound) 995 1.1.1.2 mrg { 996 1.1.1.2 mrg if (upper_bound) 997 1.1.1.2 mrg /* Range. */ 998 1.1.1.2 mrg return get_or_create_range (lower_bound, upper_bound); 999 1.1.1.2 mrg else 1000 1.1.1.2 mrg /* Single-value. */ 1001 1.1.1.2 mrg return get_or_create_point (lower_bound); 1002 1.1.1.2 mrg } 1003 1.1.1.2 mrg else 1004 1.1.1.2 mrg { 1005 1.1.1.2 mrg /* The default case. 1006 1.1.1.2 mrg Add exclusions based on the other cases. */ 1007 1.1.1.2 mrg auto_vec <const bounded_ranges *> other_case_ranges 1008 1.1.1.2 mrg (gimple_switch_num_labels (switch_stmt)); 1009 1.1.1.2 mrg for (unsigned other_idx = 1; 1010 1.1.1.2 mrg other_idx < gimple_switch_num_labels (switch_stmt); 1011 1.1.1.2 mrg other_idx++) 1012 1.1.1.2 mrg { 1013 1.1.1.2 mrg tree other_label = gimple_switch_label (switch_stmt, 1014 1.1.1.2 mrg other_idx); 1015 1.1.1.2 mrg const bounded_ranges *other_ranges 1016 1.1.1.2 mrg = make_case_label_ranges (switch_stmt, other_label); 1017 1.1.1.2 mrg other_case_ranges.quick_push (other_ranges); 1018 1.1.1.2 mrg } 1019 1.1.1.2 mrg const bounded_ranges *other_cases_ranges 1020 1.1.1.2 mrg = get_or_create_union (other_case_ranges); 1021 1.1.1.2 mrg tree type = TREE_TYPE (gimple_switch_index (switch_stmt)); 1022 1.1.1.2 mrg return get_or_create_inverse (other_cases_ranges, type); 1023 1.1.1.2 mrg } 1024 1.1.1.2 mrg } 1025 1.1.1.2 mrg 1026 1.1.1.2 mrg /* Dump the number of objects of each class that were managed by this 1027 1.1.1.2 mrg manager to LOGGER. 1028 1.1.1.2 mrg If SHOW_OBJS is true, also dump the objects themselves. */ 1029 1.1.1.2 mrg 1030 1.1.1.2 mrg void 1031 1.1.1.2 mrg bounded_ranges_manager::log_stats (logger *logger, bool show_objs) const 1032 1.1.1.2 mrg { 1033 1.1.1.2 mrg LOG_SCOPE (logger); 1034 1.1.1.2 mrg logger->log (" # %s: %li", "ranges", (long)m_map.elements ()); 1035 1.1.1.2 mrg if (!show_objs) 1036 1.1.1.2 mrg return; 1037 1.1.1.2 mrg 1038 1.1.1.2 mrg auto_vec<const bounded_ranges *> vec_objs (m_map.elements ()); 1039 1.1.1.2 mrg for (const auto &iter : m_map) 1040 1.1.1.2 mrg vec_objs.quick_push (iter.second); 1041 1.1.1.2 mrg vec_objs.qsort 1042 1.1.1.2 mrg ([](const void *p1, const void *p2) -> int 1043 1.1.1.2 mrg { 1044 1.1.1.2 mrg const bounded_ranges *br1 = *(const bounded_ranges * const *)p1; 1045 1.1.1.2 mrg const bounded_ranges *br2 = *(const bounded_ranges * const *)p2; 1046 1.1.1.2 mrg return bounded_ranges::cmp (br1, br2); 1047 1.1.1.2 mrg }); 1048 1.1.1.2 mrg 1049 1.1.1.2 mrg for (const auto &iter : vec_objs) 1050 1.1 mrg { 1051 1.1.1.2 mrg logger->start_log_line (); 1052 1.1.1.2 mrg pretty_printer *pp = logger->get_printer (); 1053 1.1.1.2 mrg pp_string (pp, " "); 1054 1.1.1.2 mrg iter->dump_to_pp (pp, true); 1055 1.1.1.2 mrg logger->end_log_line (); 1056 1.1 mrg } 1057 1.1 mrg } 1058 1.1 mrg 1059 1.1 mrg /* class equiv_class. */ 1060 1.1 mrg 1061 1.1 mrg /* equiv_class's default ctor. */ 1062 1.1 mrg 1063 1.1 mrg equiv_class::equiv_class () 1064 1.1.1.2 mrg : m_constant (NULL_TREE), m_cst_sval (NULL), m_vars () 1065 1.1 mrg { 1066 1.1 mrg } 1067 1.1 mrg 1068 1.1 mrg /* equiv_class's copy ctor. */ 1069 1.1 mrg 1070 1.1 mrg equiv_class::equiv_class (const equiv_class &other) 1071 1.1.1.2 mrg : m_constant (other.m_constant), m_cst_sval (other.m_cst_sval), 1072 1.1 mrg m_vars (other.m_vars.length ()) 1073 1.1 mrg { 1074 1.1.1.2 mrg for (const svalue *sval : other.m_vars) 1075 1.1.1.2 mrg m_vars.quick_push (sval); 1076 1.1 mrg } 1077 1.1 mrg 1078 1.1 mrg /* Print an all-on-one-line representation of this equiv_class to PP, 1079 1.1 mrg which must support %E for trees. */ 1080 1.1 mrg 1081 1.1 mrg void 1082 1.1 mrg equiv_class::print (pretty_printer *pp) const 1083 1.1 mrg { 1084 1.1 mrg pp_character (pp, '{'); 1085 1.1 mrg int i; 1086 1.1.1.2 mrg const svalue *sval; 1087 1.1.1.2 mrg FOR_EACH_VEC_ELT (m_vars, i, sval) 1088 1.1 mrg { 1089 1.1 mrg if (i > 0) 1090 1.1 mrg pp_string (pp, " == "); 1091 1.1.1.2 mrg sval->dump_to_pp (pp, true); 1092 1.1 mrg } 1093 1.1 mrg if (m_constant) 1094 1.1 mrg { 1095 1.1 mrg if (i > 0) 1096 1.1 mrg pp_string (pp, " == "); 1097 1.1.1.2 mrg pp_printf (pp, "[m_constant]%qE", m_constant); 1098 1.1 mrg } 1099 1.1 mrg pp_character (pp, '}'); 1100 1.1 mrg } 1101 1.1 mrg 1102 1.1.1.2 mrg /* Return a new json::object of the form 1103 1.1.1.2 mrg {"svals" : [str], 1104 1.1.1.2 mrg "constant" : optional str}. */ 1105 1.1.1.2 mrg 1106 1.1.1.2 mrg json::object * 1107 1.1.1.2 mrg equiv_class::to_json () const 1108 1.1.1.2 mrg { 1109 1.1.1.2 mrg json::object *ec_obj = new json::object (); 1110 1.1.1.2 mrg 1111 1.1.1.2 mrg json::array *sval_arr = new json::array (); 1112 1.1.1.2 mrg for (const svalue *sval : m_vars) 1113 1.1.1.2 mrg sval_arr->append (sval->to_json ()); 1114 1.1.1.2 mrg ec_obj->set ("svals", sval_arr); 1115 1.1.1.2 mrg 1116 1.1.1.2 mrg if (m_constant) 1117 1.1.1.2 mrg { 1118 1.1.1.2 mrg pretty_printer pp; 1119 1.1.1.2 mrg pp_format_decoder (&pp) = default_tree_printer; 1120 1.1.1.2 mrg pp_printf (&pp, "%qE", m_constant); 1121 1.1.1.2 mrg ec_obj->set ("constant", new json::string (pp_formatted_text (&pp))); 1122 1.1.1.2 mrg } 1123 1.1.1.2 mrg 1124 1.1.1.2 mrg return ec_obj; 1125 1.1.1.2 mrg } 1126 1.1.1.2 mrg 1127 1.1.1.2 mrg /* Generate a hash value for this equiv_class. 1128 1.1.1.2 mrg This relies on the ordering of m_vars, and so this object needs to 1129 1.1.1.2 mrg have been canonicalized for this to be meaningful. */ 1130 1.1 mrg 1131 1.1 mrg hashval_t 1132 1.1 mrg equiv_class::hash () const 1133 1.1 mrg { 1134 1.1 mrg inchash::hash hstate; 1135 1.1 mrg 1136 1.1 mrg inchash::add_expr (m_constant, hstate); 1137 1.1.1.2 mrg for (const svalue * sval : m_vars) 1138 1.1.1.2 mrg hstate.add_ptr (sval); 1139 1.1 mrg return hstate.end (); 1140 1.1 mrg } 1141 1.1 mrg 1142 1.1.1.2 mrg /* Equality operator for equiv_class. 1143 1.1.1.2 mrg This relies on the ordering of m_vars, and so this object 1144 1.1.1.2 mrg and OTHER need to have been canonicalized for this to be 1145 1.1.1.2 mrg meaningful. */ 1146 1.1 mrg 1147 1.1 mrg bool 1148 1.1 mrg equiv_class::operator== (const equiv_class &other) 1149 1.1 mrg { 1150 1.1 mrg if (m_constant != other.m_constant) 1151 1.1 mrg return false; // TODO: use tree equality here? 1152 1.1 mrg 1153 1.1.1.2 mrg /* FIXME: should we compare m_cst_sval? */ 1154 1.1 mrg 1155 1.1 mrg if (m_vars.length () != other.m_vars.length ()) 1156 1.1 mrg return false; 1157 1.1 mrg 1158 1.1 mrg int i; 1159 1.1.1.2 mrg const svalue *sval; 1160 1.1.1.2 mrg FOR_EACH_VEC_ELT (m_vars, i, sval) 1161 1.1.1.2 mrg if (sval != other.m_vars[i]) 1162 1.1 mrg return false; 1163 1.1 mrg 1164 1.1 mrg return true; 1165 1.1 mrg } 1166 1.1 mrg 1167 1.1 mrg /* Add SID to this equiv_class, using CM to check if it's a constant. */ 1168 1.1 mrg 1169 1.1 mrg void 1170 1.1.1.2 mrg equiv_class::add (const svalue *sval) 1171 1.1 mrg { 1172 1.1.1.2 mrg gcc_assert (sval); 1173 1.1.1.2 mrg if (tree cst = sval->maybe_get_constant ()) 1174 1.1 mrg { 1175 1.1 mrg gcc_assert (CONSTANT_CLASS_P (cst)); 1176 1.1 mrg /* FIXME: should we canonicalize which svalue is the constant 1177 1.1 mrg when there are multiple equal constants? */ 1178 1.1 mrg m_constant = cst; 1179 1.1.1.2 mrg m_cst_sval = sval; 1180 1.1 mrg } 1181 1.1.1.2 mrg m_vars.safe_push (sval); 1182 1.1 mrg } 1183 1.1 mrg 1184 1.1 mrg /* Remove SID from this equivalence class. 1185 1.1 mrg Return true if SID was the last var in the equivalence class (suggesting 1186 1.1 mrg a possible leak). */ 1187 1.1 mrg 1188 1.1 mrg bool 1189 1.1.1.2 mrg equiv_class::del (const svalue *sval) 1190 1.1 mrg { 1191 1.1.1.2 mrg gcc_assert (sval); 1192 1.1.1.2 mrg gcc_assert (sval != m_cst_sval); 1193 1.1 mrg 1194 1.1 mrg int i; 1195 1.1.1.2 mrg const svalue *iv; 1196 1.1 mrg FOR_EACH_VEC_ELT (m_vars, i, iv) 1197 1.1 mrg { 1198 1.1.1.2 mrg if (iv == sval) 1199 1.1 mrg { 1200 1.1 mrg m_vars[i] = m_vars[m_vars.length () - 1]; 1201 1.1 mrg m_vars.pop (); 1202 1.1 mrg return m_vars.length () == 0; 1203 1.1 mrg } 1204 1.1 mrg } 1205 1.1 mrg 1206 1.1.1.2 mrg /* SVAL must be in the class. */ 1207 1.1 mrg gcc_unreachable (); 1208 1.1 mrg return false; 1209 1.1 mrg } 1210 1.1 mrg 1211 1.1 mrg /* Get a representative member of this class, for handling cases 1212 1.1 mrg where the IDs can change mid-traversal. */ 1213 1.1 mrg 1214 1.1.1.2 mrg const svalue * 1215 1.1 mrg equiv_class::get_representative () const 1216 1.1 mrg { 1217 1.1.1.2 mrg gcc_assert (m_vars.length () > 0); 1218 1.1.1.2 mrg return m_vars[0]; 1219 1.1 mrg } 1220 1.1 mrg 1221 1.1.1.2 mrg /* Sort the svalues within this equiv_class. */ 1222 1.1 mrg 1223 1.1 mrg void 1224 1.1.1.2 mrg equiv_class::canonicalize () 1225 1.1 mrg { 1226 1.1.1.2 mrg m_vars.qsort (svalue::cmp_ptr_ptr); 1227 1.1 mrg } 1228 1.1 mrg 1229 1.1.1.2 mrg /* Return true if this EC contains a variable, false if it merely 1230 1.1.1.2 mrg contains constants. 1231 1.1.1.2 mrg Subroutine of constraint_manager::canonicalize, for removing 1232 1.1.1.2 mrg redundant ECs. */ 1233 1.1 mrg 1234 1.1.1.2 mrg bool 1235 1.1.1.2 mrg equiv_class::contains_non_constant_p () const 1236 1.1 mrg { 1237 1.1.1.2 mrg if (m_constant) 1238 1.1.1.2 mrg { 1239 1.1.1.2 mrg for (auto iter : m_vars) 1240 1.1.1.2 mrg if (iter->maybe_get_constant ()) 1241 1.1.1.2 mrg continue; 1242 1.1.1.2 mrg else 1243 1.1.1.2 mrg /* We have {non-constant == constant}. */ 1244 1.1.1.2 mrg return true; 1245 1.1.1.2 mrg /* We only have constants. */ 1246 1.1.1.2 mrg return false; 1247 1.1.1.2 mrg } 1248 1.1.1.2 mrg else 1249 1.1.1.2 mrg /* Return true if we have {non-constant == non-constant}. */ 1250 1.1.1.2 mrg return m_vars.length () > 1; 1251 1.1 mrg } 1252 1.1 mrg 1253 1.1 mrg /* Get a debug string for C_OP. */ 1254 1.1 mrg 1255 1.1 mrg const char * 1256 1.1 mrg constraint_op_code (enum constraint_op c_op) 1257 1.1 mrg { 1258 1.1 mrg switch (c_op) 1259 1.1 mrg { 1260 1.1 mrg default: 1261 1.1 mrg gcc_unreachable (); 1262 1.1 mrg case CONSTRAINT_NE: return "!="; 1263 1.1 mrg case CONSTRAINT_LT: return "<"; 1264 1.1 mrg case CONSTRAINT_LE: return "<="; 1265 1.1 mrg } 1266 1.1 mrg } 1267 1.1 mrg 1268 1.1 mrg /* Convert C_OP to an enum tree_code. */ 1269 1.1 mrg 1270 1.1 mrg enum tree_code 1271 1.1 mrg constraint_tree_code (enum constraint_op c_op) 1272 1.1 mrg { 1273 1.1 mrg switch (c_op) 1274 1.1 mrg { 1275 1.1 mrg default: 1276 1.1 mrg gcc_unreachable (); 1277 1.1 mrg case CONSTRAINT_NE: return NE_EXPR; 1278 1.1 mrg case CONSTRAINT_LT: return LT_EXPR; 1279 1.1 mrg case CONSTRAINT_LE: return LE_EXPR; 1280 1.1 mrg } 1281 1.1 mrg } 1282 1.1 mrg 1283 1.1 mrg /* Given "lhs C_OP rhs", determine "lhs T_OP rhs". 1284 1.1 mrg 1285 1.1 mrg For example, given "x < y", then "x > y" is false. */ 1286 1.1 mrg 1287 1.1 mrg static tristate 1288 1.1 mrg eval_constraint_op_for_op (enum constraint_op c_op, enum tree_code t_op) 1289 1.1 mrg { 1290 1.1 mrg switch (c_op) 1291 1.1 mrg { 1292 1.1 mrg default: 1293 1.1 mrg gcc_unreachable (); 1294 1.1 mrg case CONSTRAINT_NE: 1295 1.1 mrg if (t_op == EQ_EXPR) 1296 1.1 mrg return tristate (tristate::TS_FALSE); 1297 1.1 mrg if (t_op == NE_EXPR) 1298 1.1 mrg return tristate (tristate::TS_TRUE); 1299 1.1 mrg break; 1300 1.1 mrg case CONSTRAINT_LT: 1301 1.1 mrg if (t_op == LT_EXPR || t_op == LE_EXPR || t_op == NE_EXPR) 1302 1.1 mrg return tristate (tristate::TS_TRUE); 1303 1.1 mrg if (t_op == EQ_EXPR || t_op == GT_EXPR || t_op == GE_EXPR) 1304 1.1 mrg return tristate (tristate::TS_FALSE); 1305 1.1 mrg break; 1306 1.1 mrg case CONSTRAINT_LE: 1307 1.1 mrg if (t_op == LE_EXPR) 1308 1.1 mrg return tristate (tristate::TS_TRUE); 1309 1.1 mrg if (t_op == GT_EXPR) 1310 1.1 mrg return tristate (tristate::TS_FALSE); 1311 1.1 mrg break; 1312 1.1 mrg } 1313 1.1 mrg return tristate (tristate::TS_UNKNOWN); 1314 1.1 mrg } 1315 1.1 mrg 1316 1.1 mrg /* class constraint. */ 1317 1.1 mrg 1318 1.1 mrg /* Print this constraint to PP (which must support %E for trees), 1319 1.1 mrg using CM to look up equiv_class instances from ids. */ 1320 1.1 mrg 1321 1.1 mrg void 1322 1.1 mrg constraint::print (pretty_printer *pp, const constraint_manager &cm) const 1323 1.1 mrg { 1324 1.1 mrg m_lhs.print (pp); 1325 1.1 mrg pp_string (pp, ": "); 1326 1.1 mrg m_lhs.get_obj (cm).print (pp); 1327 1.1 mrg pp_string (pp, " "); 1328 1.1 mrg pp_string (pp, constraint_op_code (m_op)); 1329 1.1 mrg pp_string (pp, " "); 1330 1.1 mrg m_rhs.print (pp); 1331 1.1 mrg pp_string (pp, ": "); 1332 1.1 mrg m_rhs.get_obj (cm).print (pp); 1333 1.1 mrg } 1334 1.1 mrg 1335 1.1.1.2 mrg /* Return a new json::object of the form 1336 1.1.1.2 mrg {"lhs" : int, the EC index 1337 1.1.1.2 mrg "op" : str, 1338 1.1.1.2 mrg "rhs" : int, the EC index}. */ 1339 1.1.1.2 mrg 1340 1.1.1.2 mrg json::object * 1341 1.1.1.2 mrg constraint::to_json () const 1342 1.1.1.2 mrg { 1343 1.1.1.2 mrg json::object *con_obj = new json::object (); 1344 1.1.1.2 mrg 1345 1.1.1.2 mrg con_obj->set ("lhs", new json::integer_number (m_lhs.as_int ())); 1346 1.1.1.2 mrg con_obj->set ("op", new json::string (constraint_op_code (m_op))); 1347 1.1.1.2 mrg con_obj->set ("rhs", new json::integer_number (m_rhs.as_int ())); 1348 1.1.1.2 mrg 1349 1.1.1.2 mrg return con_obj; 1350 1.1.1.2 mrg } 1351 1.1.1.2 mrg 1352 1.1 mrg /* Generate a hash value for this constraint. */ 1353 1.1 mrg 1354 1.1 mrg hashval_t 1355 1.1 mrg constraint::hash () const 1356 1.1 mrg { 1357 1.1 mrg inchash::hash hstate; 1358 1.1 mrg hstate.add_int (m_lhs.m_idx); 1359 1.1 mrg hstate.add_int (m_op); 1360 1.1 mrg hstate.add_int (m_rhs.m_idx); 1361 1.1 mrg return hstate.end (); 1362 1.1 mrg } 1363 1.1 mrg 1364 1.1 mrg /* Equality operator for constraints. */ 1365 1.1 mrg 1366 1.1 mrg bool 1367 1.1 mrg constraint::operator== (const constraint &other) const 1368 1.1 mrg { 1369 1.1 mrg if (m_lhs != other.m_lhs) 1370 1.1 mrg return false; 1371 1.1 mrg if (m_op != other.m_op) 1372 1.1 mrg return false; 1373 1.1 mrg if (m_rhs != other.m_rhs) 1374 1.1 mrg return false; 1375 1.1 mrg return true; 1376 1.1 mrg } 1377 1.1 mrg 1378 1.1.1.2 mrg /* Return true if this constraint is implied by OTHER. */ 1379 1.1.1.2 mrg 1380 1.1.1.2 mrg bool 1381 1.1.1.2 mrg constraint::implied_by (const constraint &other, 1382 1.1.1.2 mrg const constraint_manager &cm) const 1383 1.1.1.2 mrg { 1384 1.1.1.2 mrg if (m_lhs == other.m_lhs) 1385 1.1.1.2 mrg if (tree rhs_const = m_rhs.get_obj (cm).get_any_constant ()) 1386 1.1.1.2 mrg if (tree other_rhs_const = other.m_rhs.get_obj (cm).get_any_constant ()) 1387 1.1.1.2 mrg if (m_lhs.get_obj (cm).get_any_constant () == NULL_TREE) 1388 1.1.1.2 mrg if (m_op == other.m_op) 1389 1.1.1.2 mrg switch (m_op) 1390 1.1.1.2 mrg { 1391 1.1.1.2 mrg default: 1392 1.1.1.2 mrg break; 1393 1.1.1.2 mrg case CONSTRAINT_LE: 1394 1.1.1.2 mrg case CONSTRAINT_LT: 1395 1.1.1.2 mrg if (compare_constants (rhs_const, 1396 1.1.1.2 mrg GE_EXPR, 1397 1.1.1.2 mrg other_rhs_const).is_true ()) 1398 1.1.1.2 mrg return true; 1399 1.1.1.2 mrg break; 1400 1.1.1.2 mrg } 1401 1.1.1.2 mrg return false; 1402 1.1.1.2 mrg } 1403 1.1.1.2 mrg 1404 1.1.1.2 mrg /* class bounded_ranges_constraint. */ 1405 1.1.1.2 mrg 1406 1.1.1.2 mrg void 1407 1.1.1.2 mrg bounded_ranges_constraint::print (pretty_printer *pp, 1408 1.1.1.2 mrg const constraint_manager &cm) const 1409 1.1.1.2 mrg { 1410 1.1.1.2 mrg m_ec_id.print (pp); 1411 1.1.1.2 mrg pp_string (pp, ": "); 1412 1.1.1.2 mrg m_ec_id.get_obj (cm).print (pp); 1413 1.1.1.2 mrg pp_string (pp, ": "); 1414 1.1.1.2 mrg m_ranges->dump_to_pp (pp, true); 1415 1.1.1.2 mrg } 1416 1.1.1.2 mrg 1417 1.1.1.2 mrg json::object * 1418 1.1.1.2 mrg bounded_ranges_constraint::to_json () const 1419 1.1.1.2 mrg { 1420 1.1.1.2 mrg json::object *con_obj = new json::object (); 1421 1.1.1.2 mrg 1422 1.1.1.2 mrg con_obj->set ("ec", new json::integer_number (m_ec_id.as_int ())); 1423 1.1.1.2 mrg con_obj->set ("ranges", m_ranges->to_json ()); 1424 1.1.1.2 mrg 1425 1.1.1.2 mrg return con_obj; 1426 1.1.1.2 mrg } 1427 1.1.1.2 mrg 1428 1.1.1.2 mrg bool 1429 1.1.1.2 mrg bounded_ranges_constraint:: 1430 1.1.1.2 mrg operator== (const bounded_ranges_constraint &other) const 1431 1.1.1.2 mrg { 1432 1.1.1.2 mrg if (m_ec_id != other.m_ec_id) 1433 1.1.1.2 mrg return false; 1434 1.1.1.2 mrg 1435 1.1.1.2 mrg /* We can compare by pointer, since the bounded_ranges_manager 1436 1.1.1.2 mrg consolidates instances. */ 1437 1.1.1.2 mrg return m_ranges == other.m_ranges; 1438 1.1.1.2 mrg } 1439 1.1.1.2 mrg 1440 1.1.1.2 mrg void 1441 1.1.1.2 mrg bounded_ranges_constraint::add_to_hash (inchash::hash *hstate) const 1442 1.1.1.2 mrg { 1443 1.1.1.2 mrg hstate->add_int (m_ec_id.m_idx); 1444 1.1.1.2 mrg hstate->merge_hash (m_ranges->get_hash ()); 1445 1.1.1.2 mrg } 1446 1.1.1.2 mrg 1447 1.1 mrg /* class equiv_class_id. */ 1448 1.1 mrg 1449 1.1 mrg /* Get the underlying equiv_class for this ID from CM. */ 1450 1.1 mrg 1451 1.1 mrg const equiv_class & 1452 1.1 mrg equiv_class_id::get_obj (const constraint_manager &cm) const 1453 1.1 mrg { 1454 1.1 mrg return cm.get_equiv_class_by_index (m_idx); 1455 1.1 mrg } 1456 1.1 mrg 1457 1.1 mrg /* Access the underlying equiv_class for this ID from CM. */ 1458 1.1 mrg 1459 1.1 mrg equiv_class & 1460 1.1 mrg equiv_class_id::get_obj (constraint_manager &cm) const 1461 1.1 mrg { 1462 1.1 mrg return cm.get_equiv_class_by_index (m_idx); 1463 1.1 mrg } 1464 1.1 mrg 1465 1.1 mrg /* Print this equiv_class_id to PP. */ 1466 1.1 mrg 1467 1.1 mrg void 1468 1.1 mrg equiv_class_id::print (pretty_printer *pp) const 1469 1.1 mrg { 1470 1.1 mrg if (null_p ()) 1471 1.1 mrg pp_printf (pp, "null"); 1472 1.1 mrg else 1473 1.1 mrg pp_printf (pp, "ec%i", m_idx); 1474 1.1 mrg } 1475 1.1 mrg 1476 1.1 mrg /* class constraint_manager. */ 1477 1.1 mrg 1478 1.1 mrg /* constraint_manager's copy ctor. */ 1479 1.1 mrg 1480 1.1 mrg constraint_manager::constraint_manager (const constraint_manager &other) 1481 1.1 mrg : m_equiv_classes (other.m_equiv_classes.length ()), 1482 1.1.1.2 mrg m_constraints (other.m_constraints.length ()), 1483 1.1.1.2 mrg m_bounded_ranges_constraints (other.m_bounded_ranges_constraints.length ()), 1484 1.1.1.2 mrg m_mgr (other.m_mgr) 1485 1.1 mrg { 1486 1.1 mrg int i; 1487 1.1 mrg equiv_class *ec; 1488 1.1 mrg FOR_EACH_VEC_ELT (other.m_equiv_classes, i, ec) 1489 1.1 mrg m_equiv_classes.quick_push (new equiv_class (*ec)); 1490 1.1 mrg constraint *c; 1491 1.1 mrg FOR_EACH_VEC_ELT (other.m_constraints, i, c) 1492 1.1 mrg m_constraints.quick_push (*c); 1493 1.1.1.2 mrg for (const auto &iter : other.m_bounded_ranges_constraints) 1494 1.1.1.2 mrg m_bounded_ranges_constraints.quick_push (iter); 1495 1.1 mrg } 1496 1.1 mrg 1497 1.1 mrg /* constraint_manager's assignment operator. */ 1498 1.1 mrg 1499 1.1 mrg constraint_manager& 1500 1.1 mrg constraint_manager::operator= (const constraint_manager &other) 1501 1.1 mrg { 1502 1.1 mrg gcc_assert (m_equiv_classes.length () == 0); 1503 1.1 mrg gcc_assert (m_constraints.length () == 0); 1504 1.1.1.2 mrg gcc_assert (m_bounded_ranges_constraints.length () == 0); 1505 1.1 mrg 1506 1.1 mrg int i; 1507 1.1 mrg equiv_class *ec; 1508 1.1 mrg m_equiv_classes.reserve (other.m_equiv_classes.length ()); 1509 1.1 mrg FOR_EACH_VEC_ELT (other.m_equiv_classes, i, ec) 1510 1.1 mrg m_equiv_classes.quick_push (new equiv_class (*ec)); 1511 1.1 mrg constraint *c; 1512 1.1 mrg m_constraints.reserve (other.m_constraints.length ()); 1513 1.1 mrg FOR_EACH_VEC_ELT (other.m_constraints, i, c) 1514 1.1 mrg m_constraints.quick_push (*c); 1515 1.1.1.2 mrg for (const auto &iter : other.m_bounded_ranges_constraints) 1516 1.1.1.2 mrg m_bounded_ranges_constraints.quick_push (iter); 1517 1.1 mrg 1518 1.1 mrg return *this; 1519 1.1 mrg } 1520 1.1 mrg 1521 1.1 mrg /* Generate a hash value for this constraint_manager. */ 1522 1.1 mrg 1523 1.1 mrg hashval_t 1524 1.1 mrg constraint_manager::hash () const 1525 1.1 mrg { 1526 1.1 mrg inchash::hash hstate; 1527 1.1 mrg int i; 1528 1.1 mrg equiv_class *ec; 1529 1.1 mrg constraint *c; 1530 1.1 mrg 1531 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, i, ec) 1532 1.1 mrg hstate.merge_hash (ec->hash ()); 1533 1.1 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 1534 1.1 mrg hstate.merge_hash (c->hash ()); 1535 1.1.1.2 mrg for (const auto &iter : m_bounded_ranges_constraints) 1536 1.1.1.2 mrg iter.add_to_hash (&hstate); 1537 1.1 mrg return hstate.end (); 1538 1.1 mrg } 1539 1.1 mrg 1540 1.1 mrg /* Equality operator for constraint_manager. */ 1541 1.1 mrg 1542 1.1 mrg bool 1543 1.1 mrg constraint_manager::operator== (const constraint_manager &other) const 1544 1.1 mrg { 1545 1.1 mrg if (m_equiv_classes.length () != other.m_equiv_classes.length ()) 1546 1.1 mrg return false; 1547 1.1 mrg if (m_constraints.length () != other.m_constraints.length ()) 1548 1.1 mrg return false; 1549 1.1.1.2 mrg if (m_bounded_ranges_constraints.length () 1550 1.1.1.2 mrg != other.m_bounded_ranges_constraints.length ()) 1551 1.1.1.2 mrg return false; 1552 1.1 mrg 1553 1.1 mrg int i; 1554 1.1 mrg equiv_class *ec; 1555 1.1 mrg 1556 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, i, ec) 1557 1.1 mrg if (!(*ec == *other.m_equiv_classes[i])) 1558 1.1 mrg return false; 1559 1.1 mrg 1560 1.1 mrg constraint *c; 1561 1.1 mrg 1562 1.1 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 1563 1.1 mrg if (!(*c == other.m_constraints[i])) 1564 1.1 mrg return false; 1565 1.1 mrg 1566 1.1.1.2 mrg for (unsigned i = 0; i < m_bounded_ranges_constraints.length (); i++) 1567 1.1.1.2 mrg { 1568 1.1.1.2 mrg if (m_bounded_ranges_constraints[i] 1569 1.1.1.2 mrg != other.m_bounded_ranges_constraints[i]) 1570 1.1.1.2 mrg return false; 1571 1.1.1.2 mrg } 1572 1.1.1.2 mrg 1573 1.1 mrg return true; 1574 1.1 mrg } 1575 1.1 mrg 1576 1.1 mrg /* Print this constraint_manager to PP (which must support %E for trees). */ 1577 1.1 mrg 1578 1.1 mrg void 1579 1.1 mrg constraint_manager::print (pretty_printer *pp) const 1580 1.1 mrg { 1581 1.1 mrg pp_string (pp, "{"); 1582 1.1 mrg int i; 1583 1.1 mrg equiv_class *ec; 1584 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, i, ec) 1585 1.1 mrg { 1586 1.1 mrg if (i > 0) 1587 1.1 mrg pp_string (pp, ", "); 1588 1.1 mrg equiv_class_id (i).print (pp); 1589 1.1 mrg pp_string (pp, ": "); 1590 1.1 mrg ec->print (pp); 1591 1.1 mrg } 1592 1.1 mrg pp_string (pp, " | "); 1593 1.1 mrg constraint *c; 1594 1.1 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 1595 1.1 mrg { 1596 1.1 mrg if (i > 0) 1597 1.1 mrg pp_string (pp, " && "); 1598 1.1 mrg c->print (pp, *this); 1599 1.1 mrg } 1600 1.1.1.2 mrg if (m_bounded_ranges_constraints.length ()) 1601 1.1.1.2 mrg { 1602 1.1.1.2 mrg pp_string (pp, " | "); 1603 1.1.1.2 mrg i = 0; 1604 1.1.1.2 mrg for (const auto &iter : m_bounded_ranges_constraints) 1605 1.1.1.2 mrg { 1606 1.1.1.2 mrg if (i > 0) 1607 1.1.1.2 mrg pp_string (pp, " && "); 1608 1.1.1.2 mrg iter.print (pp, *this); 1609 1.1.1.2 mrg i++; 1610 1.1.1.2 mrg } 1611 1.1.1.2 mrg } 1612 1.1 mrg pp_printf (pp, "}"); 1613 1.1 mrg } 1614 1.1 mrg 1615 1.1.1.2 mrg /* Dump a representation of this constraint_manager to PP 1616 1.1 mrg (which must support %E for trees). */ 1617 1.1 mrg 1618 1.1 mrg void 1619 1.1.1.2 mrg constraint_manager::dump_to_pp (pretty_printer *pp, bool multiline) const 1620 1.1 mrg { 1621 1.1.1.2 mrg if (multiline) 1622 1.1.1.2 mrg pp_string (pp, " "); 1623 1.1.1.2 mrg pp_string (pp, "equiv classes:"); 1624 1.1.1.2 mrg if (multiline) 1625 1.1.1.2 mrg pp_newline (pp); 1626 1.1.1.2 mrg else 1627 1.1.1.2 mrg pp_string (pp, " {"); 1628 1.1 mrg int i; 1629 1.1 mrg equiv_class *ec; 1630 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, i, ec) 1631 1.1 mrg { 1632 1.1.1.2 mrg if (multiline) 1633 1.1.1.2 mrg pp_string (pp, " "); 1634 1.1.1.2 mrg else if (i > 0) 1635 1.1.1.2 mrg pp_string (pp, ", "); 1636 1.1 mrg equiv_class_id (i).print (pp); 1637 1.1 mrg pp_string (pp, ": "); 1638 1.1 mrg ec->print (pp); 1639 1.1.1.2 mrg if (multiline) 1640 1.1.1.2 mrg pp_newline (pp); 1641 1.1 mrg } 1642 1.1.1.2 mrg if (multiline) 1643 1.1.1.2 mrg pp_string (pp, " "); 1644 1.1.1.2 mrg else 1645 1.1.1.2 mrg pp_string (pp, "}"); 1646 1.1.1.2 mrg pp_string (pp, "constraints:"); 1647 1.1.1.2 mrg if (multiline) 1648 1.1.1.2 mrg pp_newline (pp); 1649 1.1.1.2 mrg else 1650 1.1.1.2 mrg pp_string (pp, "{"); 1651 1.1 mrg constraint *c; 1652 1.1 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 1653 1.1 mrg { 1654 1.1.1.2 mrg if (multiline) 1655 1.1.1.2 mrg pp_string (pp, " "); 1656 1.1.1.2 mrg pp_printf (pp, "%i: ", i); 1657 1.1 mrg c->print (pp, *this); 1658 1.1.1.2 mrg if (multiline) 1659 1.1.1.2 mrg pp_newline (pp); 1660 1.1 mrg } 1661 1.1.1.2 mrg if (!multiline) 1662 1.1.1.2 mrg pp_string (pp, "}"); 1663 1.1.1.2 mrg if (m_bounded_ranges_constraints.length ()) 1664 1.1.1.2 mrg { 1665 1.1.1.2 mrg if (multiline) 1666 1.1.1.2 mrg pp_string (pp, " "); 1667 1.1.1.2 mrg pp_string (pp, "ranges:"); 1668 1.1.1.2 mrg if (multiline) 1669 1.1.1.2 mrg pp_newline (pp); 1670 1.1.1.2 mrg else 1671 1.1.1.2 mrg pp_string (pp, "{"); 1672 1.1.1.2 mrg i = 0; 1673 1.1.1.2 mrg for (const auto &iter : m_bounded_ranges_constraints) 1674 1.1.1.2 mrg { 1675 1.1.1.2 mrg if (multiline) 1676 1.1.1.2 mrg pp_string (pp, " "); 1677 1.1.1.2 mrg else if (i > 0) 1678 1.1.1.2 mrg pp_string (pp, " && "); 1679 1.1.1.2 mrg iter.print (pp, *this); 1680 1.1.1.2 mrg if (multiline) 1681 1.1.1.2 mrg pp_newline (pp); 1682 1.1.1.2 mrg i++; 1683 1.1.1.2 mrg } 1684 1.1.1.2 mrg if (!multiline) 1685 1.1.1.2 mrg pp_string (pp, "}"); 1686 1.1.1.2 mrg } 1687 1.1 mrg } 1688 1.1 mrg 1689 1.1 mrg /* Dump a multiline representation of this constraint_manager to FP. */ 1690 1.1 mrg 1691 1.1 mrg void 1692 1.1 mrg constraint_manager::dump (FILE *fp) const 1693 1.1 mrg { 1694 1.1 mrg pretty_printer pp; 1695 1.1 mrg pp_format_decoder (&pp) = default_tree_printer; 1696 1.1 mrg pp_show_color (&pp) = pp_show_color (global_dc->printer); 1697 1.1 mrg pp.buffer->stream = fp; 1698 1.1.1.2 mrg dump_to_pp (&pp, true); 1699 1.1 mrg pp_flush (&pp); 1700 1.1 mrg } 1701 1.1 mrg 1702 1.1 mrg /* Dump a multiline representation of this constraint_manager to stderr. */ 1703 1.1 mrg 1704 1.1 mrg DEBUG_FUNCTION void 1705 1.1 mrg constraint_manager::dump () const 1706 1.1 mrg { 1707 1.1 mrg dump (stderr); 1708 1.1 mrg } 1709 1.1 mrg 1710 1.1 mrg /* Dump a multiline representation of CM to stderr. */ 1711 1.1 mrg 1712 1.1 mrg DEBUG_FUNCTION void 1713 1.1 mrg debug (const constraint_manager &cm) 1714 1.1 mrg { 1715 1.1 mrg cm.dump (); 1716 1.1 mrg } 1717 1.1 mrg 1718 1.1.1.2 mrg /* Return a new json::object of the form 1719 1.1.1.2 mrg {"ecs" : array of objects, one per equiv_class 1720 1.1.1.2 mrg "constraints" : array of objects, one per constraint}. */ 1721 1.1.1.2 mrg 1722 1.1.1.2 mrg json::object * 1723 1.1.1.2 mrg constraint_manager::to_json () const 1724 1.1.1.2 mrg { 1725 1.1.1.2 mrg json::object *cm_obj = new json::object (); 1726 1.1.1.2 mrg 1727 1.1.1.2 mrg /* Equivalence classes. */ 1728 1.1.1.2 mrg { 1729 1.1.1.2 mrg json::array *ec_arr = new json::array (); 1730 1.1.1.2 mrg for (const equiv_class *ec : m_equiv_classes) 1731 1.1.1.2 mrg ec_arr->append (ec->to_json ()); 1732 1.1.1.2 mrg cm_obj->set ("ecs", ec_arr); 1733 1.1.1.2 mrg } 1734 1.1.1.2 mrg 1735 1.1.1.2 mrg /* Constraints. */ 1736 1.1.1.2 mrg { 1737 1.1.1.2 mrg json::array *con_arr = new json::array (); 1738 1.1.1.2 mrg for (const constraint &c : m_constraints) 1739 1.1.1.2 mrg con_arr->append (c.to_json ()); 1740 1.1.1.2 mrg cm_obj->set ("constraints", con_arr); 1741 1.1.1.2 mrg } 1742 1.1.1.2 mrg 1743 1.1.1.2 mrg /* m_bounded_ranges_constraints. */ 1744 1.1.1.2 mrg { 1745 1.1.1.2 mrg json::array *con_arr = new json::array (); 1746 1.1.1.2 mrg for (const auto &c : m_bounded_ranges_constraints) 1747 1.1.1.2 mrg con_arr->append (c.to_json ()); 1748 1.1.1.2 mrg cm_obj->set ("bounded_ranges_constraints", con_arr); 1749 1.1.1.2 mrg } 1750 1.1.1.2 mrg 1751 1.1.1.2 mrg return cm_obj; 1752 1.1.1.2 mrg } 1753 1.1.1.2 mrg 1754 1.1 mrg /* Attempt to add the constraint LHS OP RHS to this constraint_manager. 1755 1.1 mrg Return true if the constraint could be added (or is already true). 1756 1.1 mrg Return false if the constraint contradicts existing knowledge. */ 1757 1.1 mrg 1758 1.1 mrg bool 1759 1.1.1.2 mrg constraint_manager::add_constraint (const svalue *lhs, 1760 1.1.1.2 mrg enum tree_code op, 1761 1.1.1.2 mrg const svalue *rhs) 1762 1.1.1.2 mrg { 1763 1.1.1.2 mrg lhs = lhs->unwrap_any_unmergeable (); 1764 1.1.1.2 mrg rhs = rhs->unwrap_any_unmergeable (); 1765 1.1.1.2 mrg 1766 1.1.1.2 mrg /* Nothing can be known about unknown/poisoned values. */ 1767 1.1.1.2 mrg if (!lhs->can_have_associated_state_p () 1768 1.1.1.2 mrg || !rhs->can_have_associated_state_p ()) 1769 1.1.1.2 mrg /* Not a contradiction. */ 1770 1.1.1.2 mrg return true; 1771 1.1.1.2 mrg 1772 1.1.1.2 mrg /* Check the conditions on svalues. */ 1773 1.1.1.2 mrg { 1774 1.1.1.2 mrg tristate t_cond = eval_condition (lhs, op, rhs); 1775 1.1.1.2 mrg 1776 1.1.1.2 mrg /* If we already have the condition, do nothing. */ 1777 1.1.1.2 mrg if (t_cond.is_true ()) 1778 1.1.1.2 mrg return true; 1779 1.1.1.2 mrg 1780 1.1.1.2 mrg /* Reject a constraint that would contradict existing knowledge, as 1781 1.1.1.2 mrg unsatisfiable. */ 1782 1.1.1.2 mrg if (t_cond.is_false ()) 1783 1.1.1.2 mrg return false; 1784 1.1.1.2 mrg } 1785 1.1.1.2 mrg 1786 1.1 mrg equiv_class_id lhs_ec_id = get_or_add_equiv_class (lhs); 1787 1.1 mrg equiv_class_id rhs_ec_id = get_or_add_equiv_class (rhs); 1788 1.1.1.2 mrg 1789 1.1.1.2 mrg /* Check the stronger conditions on ECs. */ 1790 1.1.1.2 mrg { 1791 1.1.1.2 mrg tristate t = eval_condition (lhs_ec_id, op, rhs_ec_id); 1792 1.1.1.2 mrg 1793 1.1.1.2 mrg /* Discard constraints that are already known. */ 1794 1.1.1.2 mrg if (t.is_true ()) 1795 1.1.1.2 mrg return true; 1796 1.1.1.2 mrg 1797 1.1.1.2 mrg /* Reject unsatisfiable constraints. */ 1798 1.1.1.2 mrg if (t.is_false ()) 1799 1.1.1.2 mrg return false; 1800 1.1.1.2 mrg } 1801 1.1.1.2 mrg 1802 1.1.1.2 mrg /* If adding 1803 1.1.1.2 mrg (SVAL + OFFSET) > CST, 1804 1.1.1.2 mrg then that can imply: 1805 1.1.1.2 mrg SVAL > (CST - OFFSET). */ 1806 1.1.1.2 mrg if (const binop_svalue *lhs_binop = lhs->dyn_cast_binop_svalue ()) 1807 1.1.1.2 mrg if (tree rhs_cst = rhs->maybe_get_constant ()) 1808 1.1.1.2 mrg if (tree offset = lhs_binop->get_arg1 ()->maybe_get_constant ()) 1809 1.1.1.2 mrg if ((op == GT_EXPR || op == LT_EXPR 1810 1.1.1.2 mrg || op == GE_EXPR || op == LE_EXPR) 1811 1.1.1.2 mrg && lhs_binop->get_op () == PLUS_EXPR) 1812 1.1.1.2 mrg { 1813 1.1.1.2 mrg tree offset_of_cst = fold_build2 (MINUS_EXPR, TREE_TYPE (rhs_cst), 1814 1.1.1.2 mrg rhs_cst, offset); 1815 1.1.1.2 mrg const svalue *implied_lhs = lhs_binop->get_arg0 (); 1816 1.1.1.2 mrg enum tree_code implied_op = op; 1817 1.1.1.2 mrg const svalue *implied_rhs 1818 1.1.1.2 mrg = m_mgr->get_or_create_constant_svalue (offset_of_cst); 1819 1.1.1.2 mrg if (!add_constraint (implied_lhs, implied_op, implied_rhs)) 1820 1.1.1.2 mrg return false; 1821 1.1.1.2 mrg /* The above add_constraint could lead to EC merger, so we need 1822 1.1.1.2 mrg to refresh the EC IDs. */ 1823 1.1.1.2 mrg lhs_ec_id = get_or_add_equiv_class (lhs); 1824 1.1.1.2 mrg rhs_ec_id = get_or_add_equiv_class (rhs); 1825 1.1.1.2 mrg } 1826 1.1.1.2 mrg 1827 1.1.1.2 mrg add_unknown_constraint (lhs_ec_id, op, rhs_ec_id); 1828 1.1.1.2 mrg return true; 1829 1.1 mrg } 1830 1.1 mrg 1831 1.1 mrg /* Attempt to add the constraint LHS_EC_ID OP RHS_EC_ID to this 1832 1.1 mrg constraint_manager. 1833 1.1 mrg Return true if the constraint could be added (or is already true). 1834 1.1 mrg Return false if the constraint contradicts existing knowledge. */ 1835 1.1 mrg 1836 1.1 mrg bool 1837 1.1 mrg constraint_manager::add_constraint (equiv_class_id lhs_ec_id, 1838 1.1.1.2 mrg enum tree_code op, 1839 1.1.1.2 mrg equiv_class_id rhs_ec_id) 1840 1.1 mrg { 1841 1.1 mrg tristate t = eval_condition (lhs_ec_id, op, rhs_ec_id); 1842 1.1 mrg 1843 1.1 mrg /* Discard constraints that are already known. */ 1844 1.1 mrg if (t.is_true ()) 1845 1.1 mrg return true; 1846 1.1 mrg 1847 1.1 mrg /* Reject unsatisfiable constraints. */ 1848 1.1 mrg if (t.is_false ()) 1849 1.1 mrg return false; 1850 1.1 mrg 1851 1.1.1.2 mrg add_unknown_constraint (lhs_ec_id, op, rhs_ec_id); 1852 1.1.1.2 mrg return true; 1853 1.1.1.2 mrg } 1854 1.1.1.2 mrg 1855 1.1.1.2 mrg /* Add the constraint LHS_EC_ID OP RHS_EC_ID to this constraint_manager, 1856 1.1.1.2 mrg where the constraint has already been checked for being "unknown". */ 1857 1.1.1.2 mrg 1858 1.1.1.2 mrg void 1859 1.1.1.2 mrg constraint_manager::add_unknown_constraint (equiv_class_id lhs_ec_id, 1860 1.1.1.2 mrg enum tree_code op, 1861 1.1.1.2 mrg equiv_class_id rhs_ec_id) 1862 1.1.1.2 mrg { 1863 1.1 mrg gcc_assert (lhs_ec_id != rhs_ec_id); 1864 1.1 mrg 1865 1.1 mrg /* For now, simply accumulate constraints, without attempting any further 1866 1.1 mrg optimization. */ 1867 1.1 mrg switch (op) 1868 1.1 mrg { 1869 1.1 mrg case EQ_EXPR: 1870 1.1 mrg { 1871 1.1 mrg /* Merge rhs_ec into lhs_ec. */ 1872 1.1 mrg equiv_class &lhs_ec_obj = lhs_ec_id.get_obj (*this); 1873 1.1 mrg const equiv_class &rhs_ec_obj = rhs_ec_id.get_obj (*this); 1874 1.1 mrg 1875 1.1 mrg int i; 1876 1.1.1.2 mrg const svalue *sval; 1877 1.1.1.2 mrg FOR_EACH_VEC_ELT (rhs_ec_obj.m_vars, i, sval) 1878 1.1.1.2 mrg lhs_ec_obj.add (sval); 1879 1.1 mrg 1880 1.1 mrg if (rhs_ec_obj.m_constant) 1881 1.1 mrg { 1882 1.1 mrg lhs_ec_obj.m_constant = rhs_ec_obj.m_constant; 1883 1.1.1.2 mrg lhs_ec_obj.m_cst_sval = rhs_ec_obj.m_cst_sval; 1884 1.1 mrg } 1885 1.1 mrg 1886 1.1 mrg /* Drop rhs equivalence class, overwriting it with the 1887 1.1 mrg final ec (which might be the same one). */ 1888 1.1 mrg equiv_class_id final_ec_id = m_equiv_classes.length () - 1; 1889 1.1 mrg equiv_class *old_ec = m_equiv_classes[rhs_ec_id.m_idx]; 1890 1.1 mrg equiv_class *final_ec = m_equiv_classes.pop (); 1891 1.1 mrg if (final_ec != old_ec) 1892 1.1 mrg m_equiv_classes[rhs_ec_id.m_idx] = final_ec; 1893 1.1 mrg delete old_ec; 1894 1.1.1.2 mrg if (lhs_ec_id == final_ec_id) 1895 1.1.1.2 mrg lhs_ec_id = rhs_ec_id; 1896 1.1 mrg 1897 1.1 mrg /* Update the constraints. */ 1898 1.1 mrg constraint *c; 1899 1.1 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 1900 1.1 mrg { 1901 1.1 mrg /* Update references to the rhs_ec so that 1902 1.1 mrg they refer to the lhs_ec. */ 1903 1.1 mrg if (c->m_lhs == rhs_ec_id) 1904 1.1 mrg c->m_lhs = lhs_ec_id; 1905 1.1 mrg if (c->m_rhs == rhs_ec_id) 1906 1.1 mrg c->m_rhs = lhs_ec_id; 1907 1.1 mrg 1908 1.1 mrg /* Renumber all constraints that refer to the final rhs_ec 1909 1.1 mrg to the old rhs_ec, where the old final_ec now lives. */ 1910 1.1 mrg if (c->m_lhs == final_ec_id) 1911 1.1 mrg c->m_lhs = rhs_ec_id; 1912 1.1 mrg if (c->m_rhs == final_ec_id) 1913 1.1 mrg c->m_rhs = rhs_ec_id; 1914 1.1 mrg } 1915 1.1.1.2 mrg bounded_ranges_constraint *brc; 1916 1.1.1.2 mrg FOR_EACH_VEC_ELT (m_bounded_ranges_constraints, i, brc) 1917 1.1.1.2 mrg { 1918 1.1.1.2 mrg if (brc->m_ec_id == rhs_ec_id) 1919 1.1.1.2 mrg brc->m_ec_id = lhs_ec_id; 1920 1.1.1.2 mrg if (brc->m_ec_id == final_ec_id) 1921 1.1.1.2 mrg brc->m_ec_id = rhs_ec_id; 1922 1.1.1.2 mrg } 1923 1.1.1.2 mrg 1924 1.1.1.2 mrg /* We may now have self-comparisons due to the merger; these 1925 1.1.1.2 mrg constraints should be removed. */ 1926 1.1.1.2 mrg unsigned read_index, write_index; 1927 1.1.1.2 mrg VEC_ORDERED_REMOVE_IF (m_constraints, read_index, write_index, c, 1928 1.1.1.2 mrg (c->m_lhs == c->m_rhs)); 1929 1.1 mrg } 1930 1.1 mrg break; 1931 1.1 mrg case GE_EXPR: 1932 1.1 mrg add_constraint_internal (rhs_ec_id, CONSTRAINT_LE, lhs_ec_id); 1933 1.1 mrg break; 1934 1.1 mrg case LE_EXPR: 1935 1.1 mrg add_constraint_internal (lhs_ec_id, CONSTRAINT_LE, rhs_ec_id); 1936 1.1 mrg break; 1937 1.1 mrg case NE_EXPR: 1938 1.1 mrg add_constraint_internal (lhs_ec_id, CONSTRAINT_NE, rhs_ec_id); 1939 1.1 mrg break; 1940 1.1 mrg case GT_EXPR: 1941 1.1 mrg add_constraint_internal (rhs_ec_id, CONSTRAINT_LT, lhs_ec_id); 1942 1.1 mrg break; 1943 1.1 mrg case LT_EXPR: 1944 1.1 mrg add_constraint_internal (lhs_ec_id, CONSTRAINT_LT, rhs_ec_id); 1945 1.1 mrg break; 1946 1.1 mrg default: 1947 1.1 mrg /* do nothing. */ 1948 1.1 mrg break; 1949 1.1 mrg } 1950 1.1 mrg validate (); 1951 1.1 mrg } 1952 1.1 mrg 1953 1.1 mrg /* Subroutine of constraint_manager::add_constraint, for handling all 1954 1.1 mrg operations other than equality (for which equiv classes are merged). */ 1955 1.1 mrg 1956 1.1 mrg void 1957 1.1 mrg constraint_manager::add_constraint_internal (equiv_class_id lhs_id, 1958 1.1 mrg enum constraint_op c_op, 1959 1.1 mrg equiv_class_id rhs_id) 1960 1.1 mrg { 1961 1.1.1.2 mrg if (m_constraints.length () >= (unsigned)param_analyzer_max_constraints) 1962 1.1.1.2 mrg return; 1963 1.1.1.2 mrg 1964 1.1.1.2 mrg constraint new_c (lhs_id, c_op, rhs_id); 1965 1.1.1.2 mrg 1966 1.1.1.2 mrg /* Remove existing constraints that would be implied by the 1967 1.1.1.2 mrg new constraint. */ 1968 1.1.1.2 mrg unsigned read_index, write_index; 1969 1.1.1.2 mrg constraint *c; 1970 1.1.1.2 mrg VEC_ORDERED_REMOVE_IF (m_constraints, read_index, write_index, c, 1971 1.1.1.2 mrg (c->implied_by (new_c, *this))); 1972 1.1.1.2 mrg 1973 1.1 mrg /* Add the constraint. */ 1974 1.1.1.2 mrg m_constraints.safe_push (new_c); 1975 1.1.1.2 mrg 1976 1.1.1.2 mrg /* We don't yet update m_bounded_ranges_constraints here yet. */ 1977 1.1 mrg 1978 1.1 mrg if (!flag_analyzer_transitivity) 1979 1.1 mrg return; 1980 1.1 mrg 1981 1.1 mrg if (c_op != CONSTRAINT_NE) 1982 1.1 mrg { 1983 1.1 mrg /* The following can potentially add EQ_EXPR facts, which could lead 1984 1.1 mrg to ECs being merged, which would change the meaning of the EC IDs. 1985 1.1 mrg Hence we need to do this via representatives. */ 1986 1.1.1.2 mrg const svalue *lhs = lhs_id.get_obj (*this).get_representative (); 1987 1.1.1.2 mrg const svalue *rhs = rhs_id.get_obj (*this).get_representative (); 1988 1.1 mrg 1989 1.1 mrg /* We have LHS </<= RHS */ 1990 1.1 mrg 1991 1.1 mrg /* Handle transitivity of ordering by adding additional constraints 1992 1.1 mrg based on what we already knew. 1993 1.1 mrg 1994 1.1 mrg So if we have already have: 1995 1.1 mrg (a < b) 1996 1.1 mrg (c < d) 1997 1.1 mrg Then adding: 1998 1.1 mrg (b < c) 1999 1.1 mrg will also add: 2000 1.1 mrg (a < c) 2001 1.1 mrg (b < d) 2002 1.1 mrg We need to recurse to ensure we also add: 2003 1.1 mrg (a < d). 2004 1.1 mrg We call the checked add_constraint to avoid adding constraints 2005 1.1 mrg that are already present. Doing so also ensures termination 2006 1.1 mrg in the case of cycles. 2007 1.1 mrg 2008 1.1 mrg We also check for single-element ranges, adding EQ_EXPR facts 2009 1.1 mrg where we discover them. For example 3 < x < 5 implies 2010 1.1 mrg that x == 4 (if x is an integer). */ 2011 1.1 mrg for (unsigned i = 0; i < m_constraints.length (); i++) 2012 1.1 mrg { 2013 1.1 mrg const constraint *other = &m_constraints[i]; 2014 1.1 mrg if (other->is_ordering_p ()) 2015 1.1 mrg { 2016 1.1 mrg /* Refresh the EC IDs, in case any mergers have happened. */ 2017 1.1 mrg lhs_id = get_or_add_equiv_class (lhs); 2018 1.1 mrg rhs_id = get_or_add_equiv_class (rhs); 2019 1.1 mrg 2020 1.1 mrg tree lhs_const = lhs_id.get_obj (*this).m_constant; 2021 1.1 mrg tree rhs_const = rhs_id.get_obj (*this).m_constant; 2022 1.1 mrg tree other_lhs_const 2023 1.1 mrg = other->m_lhs.get_obj (*this).m_constant; 2024 1.1 mrg tree other_rhs_const 2025 1.1 mrg = other->m_rhs.get_obj (*this).m_constant; 2026 1.1 mrg 2027 1.1 mrg /* We have "LHS </<= RHS" and "other.lhs </<= other.rhs". */ 2028 1.1 mrg 2029 1.1 mrg /* If we have LHS </<= RHS and RHS </<= LHS, then we have a 2030 1.1 mrg cycle. */ 2031 1.1 mrg if (rhs_id == other->m_lhs 2032 1.1 mrg && other->m_rhs == lhs_id) 2033 1.1 mrg { 2034 1.1 mrg /* We must have equality for this to be possible. */ 2035 1.1 mrg gcc_assert (c_op == CONSTRAINT_LE 2036 1.1 mrg && other->m_op == CONSTRAINT_LE); 2037 1.1 mrg add_constraint (lhs_id, EQ_EXPR, rhs_id); 2038 1.1 mrg /* Adding an equality will merge the two ECs and potentially 2039 1.1 mrg reorganize the constraints. Stop iterating. */ 2040 1.1 mrg return; 2041 1.1 mrg } 2042 1.1 mrg /* Otherwise, check for transitivity. */ 2043 1.1 mrg if (rhs_id == other->m_lhs) 2044 1.1 mrg { 2045 1.1 mrg /* With RHS == other.lhs, we have: 2046 1.1 mrg "LHS </<= (RHS, other.lhs) </<= other.rhs" 2047 1.1 mrg and thus this implies "LHS </<= other.rhs". */ 2048 1.1 mrg 2049 1.1 mrg /* Do we have a tightly-constrained range? */ 2050 1.1 mrg if (lhs_const 2051 1.1 mrg && !rhs_const 2052 1.1 mrg && other_rhs_const) 2053 1.1 mrg { 2054 1.1 mrg range r (bound (lhs_const, c_op == CONSTRAINT_LE), 2055 1.1 mrg bound (other_rhs_const, 2056 1.1 mrg other->m_op == CONSTRAINT_LE)); 2057 1.1.1.2 mrg if (tree constant = r.constrained_to_single_element ()) 2058 1.1 mrg { 2059 1.1.1.2 mrg const svalue *cst_sval 2060 1.1.1.2 mrg = m_mgr->get_or_create_constant_svalue (constant); 2061 1.1 mrg add_constraint 2062 1.1 mrg (rhs_id, EQ_EXPR, 2063 1.1.1.2 mrg get_or_add_equiv_class (cst_sval)); 2064 1.1 mrg return; 2065 1.1 mrg } 2066 1.1 mrg } 2067 1.1 mrg 2068 1.1 mrg /* Otherwise, add the constraint implied by transitivity. */ 2069 1.1 mrg enum tree_code new_op 2070 1.1 mrg = ((c_op == CONSTRAINT_LE && other->m_op == CONSTRAINT_LE) 2071 1.1 mrg ? LE_EXPR : LT_EXPR); 2072 1.1 mrg add_constraint (lhs_id, new_op, other->m_rhs); 2073 1.1 mrg } 2074 1.1 mrg else if (other->m_rhs == lhs_id) 2075 1.1 mrg { 2076 1.1 mrg /* With other.rhs == LHS, we have: 2077 1.1 mrg "other.lhs </<= (other.rhs, LHS) </<= RHS" 2078 1.1 mrg and thus this implies "other.lhs </<= RHS". */ 2079 1.1 mrg 2080 1.1 mrg /* Do we have a tightly-constrained range? */ 2081 1.1 mrg if (other_lhs_const 2082 1.1 mrg && !lhs_const 2083 1.1 mrg && rhs_const) 2084 1.1 mrg { 2085 1.1 mrg range r (bound (other_lhs_const, 2086 1.1 mrg other->m_op == CONSTRAINT_LE), 2087 1.1 mrg bound (rhs_const, 2088 1.1 mrg c_op == CONSTRAINT_LE)); 2089 1.1.1.2 mrg if (tree constant = r.constrained_to_single_element ()) 2090 1.1 mrg { 2091 1.1.1.2 mrg const svalue *cst_sval 2092 1.1.1.2 mrg = m_mgr->get_or_create_constant_svalue (constant); 2093 1.1 mrg add_constraint 2094 1.1 mrg (lhs_id, EQ_EXPR, 2095 1.1.1.2 mrg get_or_add_equiv_class (cst_sval)); 2096 1.1 mrg return; 2097 1.1 mrg } 2098 1.1 mrg } 2099 1.1 mrg 2100 1.1 mrg /* Otherwise, add the constraint implied by transitivity. */ 2101 1.1 mrg enum tree_code new_op 2102 1.1 mrg = ((c_op == CONSTRAINT_LE && other->m_op == CONSTRAINT_LE) 2103 1.1 mrg ? LE_EXPR : LT_EXPR); 2104 1.1 mrg add_constraint (other->m_lhs, new_op, rhs_id); 2105 1.1 mrg } 2106 1.1 mrg } 2107 1.1 mrg } 2108 1.1 mrg } 2109 1.1 mrg } 2110 1.1 mrg 2111 1.1.1.2 mrg /* Attempt to add the constraint that SVAL is within RANGES to this 2112 1.1.1.2 mrg constraint_manager. 2113 1.1.1.2 mrg 2114 1.1.1.2 mrg Return true if the constraint was successfully added (or is already 2115 1.1.1.2 mrg known to be true). 2116 1.1.1.2 mrg Return false if the constraint contradicts existing knowledge. */ 2117 1.1.1.2 mrg 2118 1.1.1.2 mrg bool 2119 1.1.1.2 mrg constraint_manager::add_bounded_ranges (const svalue *sval, 2120 1.1.1.2 mrg const bounded_ranges *ranges) 2121 1.1.1.2 mrg { 2122 1.1.1.2 mrg sval = sval->unwrap_any_unmergeable (); 2123 1.1.1.2 mrg 2124 1.1.1.2 mrg /* Nothing can be known about unknown/poisoned values. */ 2125 1.1.1.2 mrg if (!sval->can_have_associated_state_p ()) 2126 1.1.1.2 mrg /* Not a contradiction. */ 2127 1.1.1.2 mrg return true; 2128 1.1.1.2 mrg 2129 1.1.1.2 mrg /* If SVAL is a constant, then we can look at RANGES directly. */ 2130 1.1.1.2 mrg if (tree cst = sval->maybe_get_constant ()) 2131 1.1.1.2 mrg { 2132 1.1.1.2 mrg /* If the ranges contain CST, then it's a successful no-op; 2133 1.1.1.2 mrg otherwise it's a contradiction. */ 2134 1.1.1.2 mrg return ranges->contain_p (cst); 2135 1.1.1.2 mrg } 2136 1.1.1.2 mrg 2137 1.1.1.2 mrg equiv_class_id ec_id = get_or_add_equiv_class (sval); 2138 1.1.1.2 mrg 2139 1.1.1.2 mrg /* If the EC has a constant, it's either true or false. */ 2140 1.1.1.2 mrg const equiv_class &ec = ec_id.get_obj (*this); 2141 1.1.1.2 mrg if (tree ec_cst = ec.get_any_constant ()) 2142 1.1.1.2 mrg { 2143 1.1.1.2 mrg if (ranges->contain_p (ec_cst)) 2144 1.1.1.2 mrg /* We already have SVAL == EC_CST, within RANGES, so 2145 1.1.1.2 mrg we can discard RANGES and succeed. */ 2146 1.1.1.2 mrg return true; 2147 1.1.1.2 mrg else 2148 1.1.1.2 mrg /* We already have SVAL == EC_CST, not within RANGES, so 2149 1.1.1.2 mrg we can reject RANGES as a contradiction. */ 2150 1.1.1.2 mrg return false; 2151 1.1.1.2 mrg } 2152 1.1.1.2 mrg 2153 1.1.1.2 mrg /* We have at most one per ec_id. */ 2154 1.1.1.2 mrg /* Iterate through each range in RANGES. */ 2155 1.1.1.2 mrg for (auto iter : m_bounded_ranges_constraints) 2156 1.1.1.2 mrg { 2157 1.1.1.2 mrg if (iter.m_ec_id == ec_id) 2158 1.1.1.2 mrg { 2159 1.1.1.2 mrg /* Update with intersection, or fail if empty. */ 2160 1.1.1.2 mrg bounded_ranges_manager *mgr = get_range_manager (); 2161 1.1.1.2 mrg const bounded_ranges *intersection 2162 1.1.1.2 mrg = mgr->get_or_create_intersection (iter.m_ranges, ranges); 2163 1.1.1.2 mrg if (intersection->empty_p ()) 2164 1.1.1.2 mrg { 2165 1.1.1.2 mrg /* No intersection; fail. */ 2166 1.1.1.2 mrg return false; 2167 1.1.1.2 mrg } 2168 1.1.1.2 mrg else 2169 1.1.1.2 mrg { 2170 1.1.1.2 mrg /* Update with intersection; succeed. */ 2171 1.1.1.2 mrg iter.m_ranges = intersection; 2172 1.1.1.2 mrg validate (); 2173 1.1.1.2 mrg return true; 2174 1.1.1.2 mrg } 2175 1.1.1.2 mrg } 2176 1.1.1.2 mrg } 2177 1.1.1.2 mrg m_bounded_ranges_constraints.safe_push 2178 1.1.1.2 mrg (bounded_ranges_constraint (ec_id, ranges)); 2179 1.1.1.2 mrg 2180 1.1.1.2 mrg validate (); 2181 1.1.1.2 mrg 2182 1.1.1.2 mrg return true; 2183 1.1.1.2 mrg } 2184 1.1.1.2 mrg 2185 1.1.1.2 mrg /* Look for SVAL within the equivalence classes of this constraint_manager; 2186 1.1.1.2 mrg if found, return true, writing the id to *OUT if OUT is non-NULL, 2187 1.1.1.2 mrg otherwise return false. */ 2188 1.1 mrg 2189 1.1 mrg bool 2190 1.1.1.2 mrg constraint_manager::get_equiv_class_by_svalue (const svalue *sval, 2191 1.1.1.2 mrg equiv_class_id *out) const 2192 1.1 mrg { 2193 1.1 mrg /* TODO: should we have a map, rather than these searches? */ 2194 1.1 mrg int i; 2195 1.1 mrg equiv_class *ec; 2196 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, i, ec) 2197 1.1 mrg { 2198 1.1 mrg int j; 2199 1.1.1.2 mrg const svalue *iv; 2200 1.1 mrg FOR_EACH_VEC_ELT (ec->m_vars, j, iv) 2201 1.1.1.2 mrg if (iv == sval) 2202 1.1 mrg { 2203 1.1.1.2 mrg if (out) 2204 1.1.1.2 mrg *out = equiv_class_id (i); 2205 1.1 mrg return true; 2206 1.1 mrg } 2207 1.1 mrg } 2208 1.1 mrg return false; 2209 1.1 mrg } 2210 1.1 mrg 2211 1.1.1.2 mrg /* Ensure that SVAL has an equivalence class within this constraint_manager; 2212 1.1 mrg return the ID of the class. */ 2213 1.1 mrg 2214 1.1 mrg equiv_class_id 2215 1.1.1.2 mrg constraint_manager::get_or_add_equiv_class (const svalue *sval) 2216 1.1 mrg { 2217 1.1 mrg equiv_class_id result (-1); 2218 1.1 mrg 2219 1.1.1.2 mrg gcc_assert (sval->can_have_associated_state_p ()); 2220 1.1.1.2 mrg 2221 1.1.1.2 mrg /* Convert all NULL pointers to (void *) to avoid state explosions 2222 1.1.1.2 mrg involving all of the various (foo *)NULL vs (bar *)NULL. */ 2223 1.1.1.2 mrg if (sval->get_type ()) 2224 1.1.1.2 mrg if (POINTER_TYPE_P (sval->get_type ())) 2225 1.1.1.2 mrg if (tree cst = sval->maybe_get_constant ()) 2226 1.1.1.2 mrg if (zerop (cst)) 2227 1.1.1.2 mrg sval = m_mgr->get_or_create_constant_svalue (null_pointer_node); 2228 1.1.1.2 mrg 2229 1.1.1.2 mrg /* Try svalue match. */ 2230 1.1.1.2 mrg if (get_equiv_class_by_svalue (sval, &result)) 2231 1.1 mrg return result; 2232 1.1 mrg 2233 1.1 mrg /* Try equality of constants. */ 2234 1.1.1.2 mrg if (tree cst = sval->maybe_get_constant ()) 2235 1.1 mrg { 2236 1.1 mrg int i; 2237 1.1 mrg equiv_class *ec; 2238 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, i, ec) 2239 1.1 mrg if (ec->m_constant 2240 1.1 mrg && types_compatible_p (TREE_TYPE (cst), 2241 1.1 mrg TREE_TYPE (ec->m_constant))) 2242 1.1 mrg { 2243 1.1 mrg tree eq = fold_binary (EQ_EXPR, boolean_type_node, 2244 1.1 mrg cst, ec->m_constant); 2245 1.1 mrg if (eq == boolean_true_node) 2246 1.1 mrg { 2247 1.1.1.2 mrg ec->add (sval); 2248 1.1 mrg return equiv_class_id (i); 2249 1.1 mrg } 2250 1.1 mrg } 2251 1.1 mrg } 2252 1.1 mrg 2253 1.1 mrg 2254 1.1 mrg /* Not found. */ 2255 1.1 mrg equiv_class *new_ec = new equiv_class (); 2256 1.1.1.2 mrg new_ec->add (sval); 2257 1.1 mrg m_equiv_classes.safe_push (new_ec); 2258 1.1 mrg 2259 1.1 mrg equiv_class_id new_id (m_equiv_classes.length () - 1); 2260 1.1 mrg 2261 1.1 mrg return new_id; 2262 1.1 mrg } 2263 1.1 mrg 2264 1.1 mrg /* Evaluate the condition LHS_EC OP RHS_EC. */ 2265 1.1 mrg 2266 1.1 mrg tristate 2267 1.1 mrg constraint_manager::eval_condition (equiv_class_id lhs_ec, 2268 1.1 mrg enum tree_code op, 2269 1.1.1.2 mrg equiv_class_id rhs_ec) const 2270 1.1 mrg { 2271 1.1 mrg if (lhs_ec == rhs_ec) 2272 1.1 mrg { 2273 1.1 mrg switch (op) 2274 1.1 mrg { 2275 1.1 mrg case EQ_EXPR: 2276 1.1 mrg case GE_EXPR: 2277 1.1 mrg case LE_EXPR: 2278 1.1 mrg return tristate (tristate::TS_TRUE); 2279 1.1 mrg 2280 1.1 mrg case NE_EXPR: 2281 1.1 mrg case GT_EXPR: 2282 1.1 mrg case LT_EXPR: 2283 1.1 mrg return tristate (tristate::TS_FALSE); 2284 1.1 mrg default: 2285 1.1 mrg break; 2286 1.1 mrg } 2287 1.1 mrg } 2288 1.1 mrg 2289 1.1 mrg tree lhs_const = lhs_ec.get_obj (*this).get_any_constant (); 2290 1.1 mrg tree rhs_const = rhs_ec.get_obj (*this).get_any_constant (); 2291 1.1 mrg if (lhs_const && rhs_const) 2292 1.1 mrg { 2293 1.1.1.2 mrg tristate result_for_constants 2294 1.1.1.2 mrg = compare_constants (lhs_const, op, rhs_const); 2295 1.1.1.2 mrg if (result_for_constants.is_known ()) 2296 1.1.1.2 mrg return result_for_constants; 2297 1.1 mrg } 2298 1.1 mrg 2299 1.1 mrg enum tree_code swapped_op = swap_tree_comparison (op); 2300 1.1 mrg 2301 1.1 mrg int i; 2302 1.1 mrg constraint *c; 2303 1.1 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 2304 1.1 mrg { 2305 1.1 mrg if (c->m_lhs == lhs_ec 2306 1.1 mrg && c->m_rhs == rhs_ec) 2307 1.1 mrg { 2308 1.1 mrg tristate result_for_constraint 2309 1.1 mrg = eval_constraint_op_for_op (c->m_op, op); 2310 1.1 mrg if (result_for_constraint.is_known ()) 2311 1.1 mrg return result_for_constraint; 2312 1.1 mrg } 2313 1.1.1.2 mrg /* Swapped operands. */ 2314 1.1.1.2 mrg if (c->m_lhs == rhs_ec 2315 1.1.1.2 mrg && c->m_rhs == lhs_ec) 2316 1.1.1.2 mrg { 2317 1.1.1.2 mrg tristate result_for_constraint 2318 1.1.1.2 mrg = eval_constraint_op_for_op (c->m_op, swapped_op); 2319 1.1.1.2 mrg if (result_for_constraint.is_known ()) 2320 1.1.1.2 mrg return result_for_constraint; 2321 1.1.1.2 mrg } 2322 1.1.1.2 mrg } 2323 1.1.1.2 mrg 2324 1.1.1.2 mrg /* We don't use m_bounded_ranges_constraints here yet. */ 2325 1.1.1.2 mrg 2326 1.1.1.2 mrg return tristate (tristate::TS_UNKNOWN); 2327 1.1.1.2 mrg } 2328 1.1.1.2 mrg 2329 1.1.1.2 mrg range 2330 1.1.1.2 mrg constraint_manager::get_ec_bounds (equiv_class_id ec_id) const 2331 1.1.1.2 mrg { 2332 1.1.1.2 mrg range result; 2333 1.1.1.2 mrg 2334 1.1.1.2 mrg int i; 2335 1.1.1.2 mrg constraint *c; 2336 1.1.1.2 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 2337 1.1.1.2 mrg { 2338 1.1.1.2 mrg if (c->m_lhs == ec_id) 2339 1.1.1.2 mrg { 2340 1.1.1.2 mrg if (tree other_cst = c->m_rhs.get_obj (*this).get_any_constant ()) 2341 1.1.1.2 mrg switch (c->m_op) 2342 1.1.1.2 mrg { 2343 1.1.1.2 mrg default: 2344 1.1.1.2 mrg gcc_unreachable (); 2345 1.1.1.2 mrg case CONSTRAINT_NE: 2346 1.1.1.2 mrg continue; 2347 1.1.1.2 mrg 2348 1.1.1.2 mrg case CONSTRAINT_LT: 2349 1.1.1.2 mrg /* We have "EC_ID < OTHER_CST". */ 2350 1.1.1.2 mrg result.add_bound (bound (other_cst, false), BK_UPPER); 2351 1.1.1.2 mrg break; 2352 1.1.1.2 mrg 2353 1.1.1.2 mrg case CONSTRAINT_LE: 2354 1.1.1.2 mrg /* We have "EC_ID <= OTHER_CST". */ 2355 1.1.1.2 mrg result.add_bound (bound (other_cst, true), BK_UPPER); 2356 1.1.1.2 mrg break; 2357 1.1.1.2 mrg } 2358 1.1.1.2 mrg } 2359 1.1.1.2 mrg if (c->m_rhs == ec_id) 2360 1.1.1.2 mrg { 2361 1.1.1.2 mrg if (tree other_cst = c->m_lhs.get_obj (*this).get_any_constant ()) 2362 1.1.1.2 mrg switch (c->m_op) 2363 1.1.1.2 mrg { 2364 1.1.1.2 mrg default: 2365 1.1.1.2 mrg gcc_unreachable (); 2366 1.1.1.2 mrg case CONSTRAINT_NE: 2367 1.1.1.2 mrg continue; 2368 1.1.1.2 mrg 2369 1.1.1.2 mrg case CONSTRAINT_LT: 2370 1.1.1.2 mrg /* We have "OTHER_CST < EC_ID" 2371 1.1.1.2 mrg i.e. "EC_ID > OTHER_CST". */ 2372 1.1.1.2 mrg result.add_bound (bound (other_cst, false), BK_LOWER); 2373 1.1.1.2 mrg break; 2374 1.1.1.2 mrg 2375 1.1.1.2 mrg case CONSTRAINT_LE: 2376 1.1.1.2 mrg /* We have "OTHER_CST <= EC_ID" 2377 1.1.1.2 mrg i.e. "EC_ID >= OTHER_CST". */ 2378 1.1.1.2 mrg result.add_bound (bound (other_cst, true), BK_LOWER); 2379 1.1.1.2 mrg break; 2380 1.1.1.2 mrg } 2381 1.1.1.2 mrg } 2382 1.1.1.2 mrg } 2383 1.1.1.2 mrg 2384 1.1.1.2 mrg return result; 2385 1.1.1.2 mrg } 2386 1.1.1.2 mrg 2387 1.1.1.2 mrg /* Evaluate the condition LHS_EC OP RHS_CONST, avoiding the creation 2388 1.1.1.2 mrg of equiv_class instances. */ 2389 1.1.1.2 mrg 2390 1.1.1.2 mrg tristate 2391 1.1.1.2 mrg constraint_manager::eval_condition (equiv_class_id lhs_ec, 2392 1.1.1.2 mrg enum tree_code op, 2393 1.1.1.2 mrg tree rhs_const) const 2394 1.1.1.2 mrg { 2395 1.1.1.2 mrg gcc_assert (!lhs_ec.null_p ()); 2396 1.1.1.2 mrg gcc_assert (CONSTANT_CLASS_P (rhs_const)); 2397 1.1.1.2 mrg 2398 1.1.1.2 mrg if (tree lhs_const = lhs_ec.get_obj (*this).get_any_constant ()) 2399 1.1.1.2 mrg return compare_constants (lhs_const, op, rhs_const); 2400 1.1.1.2 mrg 2401 1.1.1.2 mrg /* Check for known inequalities of the form 2402 1.1.1.2 mrg (LHS_EC != OTHER_CST) or (OTHER_CST != LHS_EC). 2403 1.1.1.2 mrg If RHS_CONST == OTHER_CST, then we also know that LHS_EC != OTHER_CST. 2404 1.1.1.2 mrg For example, we might have the constraint 2405 1.1.1.2 mrg ptr != (void *)0 2406 1.1.1.2 mrg so we want the condition 2407 1.1.1.2 mrg ptr == (foo *)0 2408 1.1.1.2 mrg to be false. */ 2409 1.1.1.2 mrg int i; 2410 1.1.1.2 mrg constraint *c; 2411 1.1.1.2 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 2412 1.1.1.2 mrg { 2413 1.1.1.2 mrg if (c->m_op == CONSTRAINT_NE) 2414 1.1.1.2 mrg { 2415 1.1.1.2 mrg if (c->m_lhs == lhs_ec) 2416 1.1.1.2 mrg { 2417 1.1.1.2 mrg if (tree other_cst = c->m_rhs.get_obj (*this).get_any_constant ()) 2418 1.1.1.2 mrg if (compare_constants 2419 1.1.1.2 mrg (rhs_const, EQ_EXPR, other_cst).is_true ()) 2420 1.1.1.2 mrg { 2421 1.1.1.2 mrg switch (op) 2422 1.1.1.2 mrg { 2423 1.1.1.2 mrg case EQ_EXPR: 2424 1.1.1.2 mrg return tristate (tristate::TS_FALSE); 2425 1.1.1.2 mrg case NE_EXPR: 2426 1.1.1.2 mrg return tristate (tristate::TS_TRUE); 2427 1.1.1.2 mrg default: 2428 1.1.1.2 mrg break; 2429 1.1.1.2 mrg } 2430 1.1.1.2 mrg } 2431 1.1.1.2 mrg } 2432 1.1.1.2 mrg if (c->m_rhs == lhs_ec) 2433 1.1.1.2 mrg { 2434 1.1.1.2 mrg if (tree other_cst = c->m_lhs.get_obj (*this).get_any_constant ()) 2435 1.1.1.2 mrg if (compare_constants 2436 1.1.1.2 mrg (rhs_const, EQ_EXPR, other_cst).is_true ()) 2437 1.1.1.2 mrg { 2438 1.1.1.2 mrg switch (op) 2439 1.1.1.2 mrg { 2440 1.1.1.2 mrg case EQ_EXPR: 2441 1.1.1.2 mrg return tristate (tristate::TS_FALSE); 2442 1.1.1.2 mrg case NE_EXPR: 2443 1.1.1.2 mrg return tristate (tristate::TS_TRUE); 2444 1.1.1.2 mrg default: 2445 1.1.1.2 mrg break; 2446 1.1.1.2 mrg } 2447 1.1.1.2 mrg } 2448 1.1.1.2 mrg } 2449 1.1.1.2 mrg } 2450 1.1.1.2 mrg } 2451 1.1.1.2 mrg 2452 1.1.1.2 mrg bounded_ranges_manager *mgr = get_range_manager (); 2453 1.1.1.2 mrg for (const auto &iter : m_bounded_ranges_constraints) 2454 1.1.1.2 mrg if (iter.m_ec_id == lhs_ec) 2455 1.1.1.2 mrg return iter.m_ranges->eval_condition (op, rhs_const, mgr); 2456 1.1.1.2 mrg 2457 1.1.1.2 mrg /* Look at existing bounds on LHS_EC. */ 2458 1.1.1.2 mrg range lhs_bounds = get_ec_bounds (lhs_ec); 2459 1.1.1.2 mrg tristate result = lhs_bounds.eval_condition (op, rhs_const); 2460 1.1.1.2 mrg if (result.is_known ()) 2461 1.1.1.2 mrg return result; 2462 1.1.1.2 mrg 2463 1.1.1.2 mrg /* Also reject if range::add_bound fails. */ 2464 1.1.1.2 mrg if (!lhs_bounds.add_bound (op, rhs_const)) 2465 1.1.1.2 mrg return tristate (false); 2466 1.1.1.2 mrg 2467 1.1.1.2 mrg return tristate::unknown (); 2468 1.1.1.2 mrg } 2469 1.1.1.2 mrg 2470 1.1.1.2 mrg /* Evaluate the condition LHS OP RHS, without modifying this 2471 1.1.1.2 mrg constraint_manager (avoiding the creation of equiv_class instances). */ 2472 1.1.1.2 mrg 2473 1.1.1.2 mrg tristate 2474 1.1.1.2 mrg constraint_manager::eval_condition (const svalue *lhs, 2475 1.1.1.2 mrg enum tree_code op, 2476 1.1.1.2 mrg const svalue *rhs) const 2477 1.1.1.2 mrg { 2478 1.1.1.2 mrg lhs = lhs->unwrap_any_unmergeable (); 2479 1.1.1.2 mrg rhs = rhs->unwrap_any_unmergeable (); 2480 1.1.1.2 mrg 2481 1.1.1.2 mrg /* Nothing can be known about unknown or poisoned values. */ 2482 1.1.1.2 mrg if (lhs->get_kind () == SK_UNKNOWN 2483 1.1.1.2 mrg || lhs->get_kind () == SK_POISONED 2484 1.1.1.2 mrg || rhs->get_kind () == SK_UNKNOWN 2485 1.1.1.2 mrg || rhs->get_kind () == SK_POISONED) 2486 1.1.1.2 mrg return tristate (tristate::TS_UNKNOWN); 2487 1.1.1.2 mrg 2488 1.1.1.2 mrg if (lhs == rhs 2489 1.1.1.2 mrg && !(FLOAT_TYPE_P (lhs->get_type ()) 2490 1.1.1.2 mrg || FLOAT_TYPE_P (rhs->get_type ()))) 2491 1.1.1.2 mrg { 2492 1.1.1.2 mrg switch (op) 2493 1.1.1.2 mrg { 2494 1.1.1.2 mrg case EQ_EXPR: 2495 1.1.1.2 mrg case GE_EXPR: 2496 1.1.1.2 mrg case LE_EXPR: 2497 1.1.1.2 mrg return tristate (tristate::TS_TRUE); 2498 1.1.1.2 mrg 2499 1.1.1.2 mrg case NE_EXPR: 2500 1.1.1.2 mrg case GT_EXPR: 2501 1.1.1.2 mrg case LT_EXPR: 2502 1.1.1.2 mrg return tristate (tristate::TS_FALSE); 2503 1.1.1.2 mrg default: 2504 1.1.1.2 mrg break; 2505 1.1.1.2 mrg } 2506 1.1.1.2 mrg } 2507 1.1.1.2 mrg 2508 1.1.1.2 mrg equiv_class_id lhs_ec (-1); 2509 1.1.1.2 mrg equiv_class_id rhs_ec (-1); 2510 1.1.1.2 mrg get_equiv_class_by_svalue (lhs, &lhs_ec); 2511 1.1.1.2 mrg get_equiv_class_by_svalue (rhs, &rhs_ec); 2512 1.1.1.2 mrg if (!lhs_ec.null_p () && !rhs_ec.null_p ()) 2513 1.1.1.2 mrg { 2514 1.1.1.2 mrg tristate result_for_ecs 2515 1.1.1.2 mrg = eval_condition (lhs_ec, op, rhs_ec); 2516 1.1.1.2 mrg if (result_for_ecs.is_known ()) 2517 1.1.1.2 mrg return result_for_ecs; 2518 1.1.1.2 mrg } 2519 1.1.1.2 mrg 2520 1.1.1.2 mrg /* If at least one is not in an EC, we have no constraints 2521 1.1.1.2 mrg comparing LHS and RHS yet. 2522 1.1.1.2 mrg They might still be comparable if one (or both) is a constant. 2523 1.1.1.2 mrg 2524 1.1.1.2 mrg Alternatively, we can also get here if we had ECs but they weren't 2525 1.1.1.2 mrg comparable. Again, constant comparisons might give an answer. */ 2526 1.1.1.2 mrg tree lhs_const = lhs->maybe_get_constant (); 2527 1.1.1.2 mrg tree rhs_const = rhs->maybe_get_constant (); 2528 1.1.1.2 mrg if (lhs_const && rhs_const) 2529 1.1.1.2 mrg { 2530 1.1.1.2 mrg tristate result_for_constants 2531 1.1.1.2 mrg = compare_constants (lhs_const, op, rhs_const); 2532 1.1.1.2 mrg if (result_for_constants.is_known ()) 2533 1.1.1.2 mrg return result_for_constants; 2534 1.1.1.2 mrg } 2535 1.1.1.2 mrg 2536 1.1.1.2 mrg if (!lhs_ec.null_p ()) 2537 1.1.1.2 mrg { 2538 1.1.1.2 mrg if (rhs_const) 2539 1.1.1.2 mrg return eval_condition (lhs_ec, op, rhs_const); 2540 1.1.1.2 mrg } 2541 1.1.1.2 mrg if (!rhs_ec.null_p ()) 2542 1.1.1.2 mrg { 2543 1.1.1.2 mrg if (lhs_const) 2544 1.1 mrg { 2545 1.1.1.2 mrg enum tree_code swapped_op = swap_tree_comparison (op); 2546 1.1.1.2 mrg return eval_condition (rhs_ec, swapped_op, lhs_const); 2547 1.1 mrg } 2548 1.1 mrg } 2549 1.1 mrg 2550 1.1 mrg return tristate (tristate::TS_UNKNOWN); 2551 1.1 mrg } 2552 1.1 mrg 2553 1.1.1.2 mrg /* Delete any information about svalues identified by P. 2554 1.1 mrg Such instances are removed from equivalence classes, and any 2555 1.1 mrg redundant ECs and constraints are also removed. 2556 1.1 mrg Accumulate stats into STATS. */ 2557 1.1 mrg 2558 1.1.1.2 mrg template <typename PurgeCriteria> 2559 1.1 mrg void 2560 1.1.1.2 mrg constraint_manager::purge (const PurgeCriteria &p, purge_stats *stats) 2561 1.1 mrg { 2562 1.1.1.2 mrg /* Delete any svalues identified by P within the various equivalence 2563 1.1 mrg classes. */ 2564 1.1 mrg for (unsigned ec_idx = 0; ec_idx < m_equiv_classes.length (); ) 2565 1.1 mrg { 2566 1.1 mrg equiv_class *ec = m_equiv_classes[ec_idx]; 2567 1.1 mrg 2568 1.1 mrg int i; 2569 1.1.1.2 mrg const svalue *sval; 2570 1.1 mrg bool delete_ec = false; 2571 1.1.1.2 mrg FOR_EACH_VEC_ELT (ec->m_vars, i, sval) 2572 1.1 mrg { 2573 1.1.1.2 mrg if (sval == ec->m_cst_sval) 2574 1.1 mrg continue; 2575 1.1.1.2 mrg if (p.should_purge_p (sval)) 2576 1.1 mrg { 2577 1.1.1.2 mrg if (ec->del (sval)) 2578 1.1 mrg if (!ec->m_constant) 2579 1.1 mrg delete_ec = true; 2580 1.1 mrg } 2581 1.1 mrg } 2582 1.1 mrg 2583 1.1 mrg if (delete_ec) 2584 1.1 mrg { 2585 1.1 mrg delete ec; 2586 1.1 mrg m_equiv_classes.ordered_remove (ec_idx); 2587 1.1 mrg if (stats) 2588 1.1 mrg stats->m_num_equiv_classes++; 2589 1.1 mrg 2590 1.1 mrg /* Update the constraints, potentially removing some. */ 2591 1.1 mrg for (unsigned con_idx = 0; con_idx < m_constraints.length (); ) 2592 1.1 mrg { 2593 1.1 mrg constraint *c = &m_constraints[con_idx]; 2594 1.1 mrg 2595 1.1 mrg /* Remove constraints that refer to the deleted EC. */ 2596 1.1 mrg if (c->m_lhs == ec_idx 2597 1.1 mrg || c->m_rhs == ec_idx) 2598 1.1 mrg { 2599 1.1 mrg m_constraints.ordered_remove (con_idx); 2600 1.1 mrg if (stats) 2601 1.1 mrg stats->m_num_constraints++; 2602 1.1 mrg } 2603 1.1 mrg else 2604 1.1 mrg { 2605 1.1 mrg /* Renumber constraints that refer to ECs that have 2606 1.1 mrg had their idx changed. */ 2607 1.1 mrg c->m_lhs.update_for_removal (ec_idx); 2608 1.1 mrg c->m_rhs.update_for_removal (ec_idx); 2609 1.1 mrg 2610 1.1 mrg con_idx++; 2611 1.1 mrg } 2612 1.1 mrg } 2613 1.1.1.2 mrg 2614 1.1.1.2 mrg /* Update bounded_ranges_constraint instances. */ 2615 1.1.1.2 mrg for (unsigned r_idx = 0; 2616 1.1.1.2 mrg r_idx < m_bounded_ranges_constraints.length (); ) 2617 1.1.1.2 mrg { 2618 1.1.1.2 mrg bounded_ranges_constraint *brc 2619 1.1.1.2 mrg = &m_bounded_ranges_constraints[r_idx]; 2620 1.1.1.2 mrg 2621 1.1.1.2 mrg /* Remove if it refers to the deleted EC. */ 2622 1.1.1.2 mrg if (brc->m_ec_id == ec_idx) 2623 1.1.1.2 mrg { 2624 1.1.1.2 mrg m_bounded_ranges_constraints.ordered_remove (r_idx); 2625 1.1.1.2 mrg if (stats) 2626 1.1.1.2 mrg stats->m_num_bounded_ranges_constraints++; 2627 1.1.1.2 mrg } 2628 1.1.1.2 mrg else 2629 1.1.1.2 mrg { 2630 1.1.1.2 mrg /* Renumber any EC ids that refer to ECs that have 2631 1.1.1.2 mrg had their idx changed. */ 2632 1.1.1.2 mrg brc->m_ec_id.update_for_removal (ec_idx); 2633 1.1.1.2 mrg r_idx++; 2634 1.1.1.2 mrg } 2635 1.1.1.2 mrg } 2636 1.1 mrg } 2637 1.1 mrg else 2638 1.1 mrg ec_idx++; 2639 1.1 mrg } 2640 1.1 mrg 2641 1.1 mrg /* Now delete any constraints that are purely between constants. */ 2642 1.1 mrg for (unsigned con_idx = 0; con_idx < m_constraints.length (); ) 2643 1.1 mrg { 2644 1.1 mrg constraint *c = &m_constraints[con_idx]; 2645 1.1 mrg if (m_equiv_classes[c->m_lhs.m_idx]->m_vars.length () == 0 2646 1.1 mrg && m_equiv_classes[c->m_rhs.m_idx]->m_vars.length () == 0) 2647 1.1 mrg { 2648 1.1 mrg m_constraints.ordered_remove (con_idx); 2649 1.1 mrg if (stats) 2650 1.1 mrg stats->m_num_constraints++; 2651 1.1 mrg } 2652 1.1 mrg else 2653 1.1 mrg { 2654 1.1 mrg con_idx++; 2655 1.1 mrg } 2656 1.1 mrg } 2657 1.1 mrg 2658 1.1 mrg /* Finally, delete any ECs that purely contain constants and aren't 2659 1.1 mrg referenced by any constraints. */ 2660 1.1 mrg for (unsigned ec_idx = 0; ec_idx < m_equiv_classes.length (); ) 2661 1.1 mrg { 2662 1.1 mrg equiv_class *ec = m_equiv_classes[ec_idx]; 2663 1.1 mrg if (ec->m_vars.length () == 0) 2664 1.1 mrg { 2665 1.1 mrg equiv_class_id ec_id (ec_idx); 2666 1.1 mrg bool has_constraint = false; 2667 1.1 mrg for (unsigned con_idx = 0; con_idx < m_constraints.length (); 2668 1.1 mrg con_idx++) 2669 1.1 mrg { 2670 1.1 mrg constraint *c = &m_constraints[con_idx]; 2671 1.1 mrg if (c->m_lhs == ec_id 2672 1.1 mrg || c->m_rhs == ec_id) 2673 1.1 mrg { 2674 1.1 mrg has_constraint = true; 2675 1.1 mrg break; 2676 1.1 mrg } 2677 1.1 mrg } 2678 1.1 mrg if (!has_constraint) 2679 1.1 mrg { 2680 1.1 mrg delete ec; 2681 1.1 mrg m_equiv_classes.ordered_remove (ec_idx); 2682 1.1 mrg if (stats) 2683 1.1 mrg stats->m_num_equiv_classes++; 2684 1.1 mrg 2685 1.1 mrg /* Renumber constraints that refer to ECs that have 2686 1.1 mrg had their idx changed. */ 2687 1.1 mrg for (unsigned con_idx = 0; con_idx < m_constraints.length (); 2688 1.1 mrg con_idx++) 2689 1.1 mrg { 2690 1.1 mrg constraint *c = &m_constraints[con_idx]; 2691 1.1 mrg c->m_lhs.update_for_removal (ec_idx); 2692 1.1 mrg c->m_rhs.update_for_removal (ec_idx); 2693 1.1 mrg } 2694 1.1.1.2 mrg 2695 1.1.1.2 mrg /* Likewise for m_bounded_ranges_constraints. */ 2696 1.1.1.2 mrg for (unsigned r_idx = 0; 2697 1.1.1.2 mrg r_idx < m_bounded_ranges_constraints.length (); 2698 1.1.1.2 mrg r_idx++) 2699 1.1.1.2 mrg { 2700 1.1.1.2 mrg bounded_ranges_constraint *brc 2701 1.1.1.2 mrg = &m_bounded_ranges_constraints[r_idx]; 2702 1.1.1.2 mrg brc->m_ec_id.update_for_removal (ec_idx); 2703 1.1.1.2 mrg } 2704 1.1.1.2 mrg 2705 1.1 mrg continue; 2706 1.1 mrg } 2707 1.1 mrg } 2708 1.1 mrg ec_idx++; 2709 1.1 mrg } 2710 1.1 mrg 2711 1.1 mrg validate (); 2712 1.1 mrg } 2713 1.1 mrg 2714 1.1.1.2 mrg /* Implementation of PurgeCriteria: purge svalues that are not live 2715 1.1.1.2 mrg with respect to LIVE_SVALUES and MODEL. */ 2716 1.1.1.2 mrg 2717 1.1.1.2 mrg class dead_svalue_purger 2718 1.1.1.2 mrg { 2719 1.1.1.2 mrg public: 2720 1.1.1.2 mrg dead_svalue_purger (const svalue_set &live_svalues, 2721 1.1.1.2 mrg const region_model *model) 2722 1.1.1.2 mrg : m_live_svalues (live_svalues), m_model (model) 2723 1.1.1.2 mrg { 2724 1.1.1.2 mrg } 2725 1.1.1.2 mrg 2726 1.1.1.2 mrg bool should_purge_p (const svalue *sval) const 2727 1.1.1.2 mrg { 2728 1.1.1.2 mrg return !sval->live_p (&m_live_svalues, m_model); 2729 1.1.1.2 mrg } 2730 1.1.1.2 mrg 2731 1.1.1.2 mrg private: 2732 1.1.1.2 mrg const svalue_set &m_live_svalues; 2733 1.1.1.2 mrg const region_model *m_model; 2734 1.1.1.2 mrg }; 2735 1.1.1.2 mrg 2736 1.1.1.2 mrg /* Purge dead svalues from equivalence classes and update constraints 2737 1.1.1.2 mrg accordingly. */ 2738 1.1 mrg 2739 1.1 mrg void 2740 1.1.1.2 mrg constraint_manager:: 2741 1.1.1.2 mrg on_liveness_change (const svalue_set &live_svalues, 2742 1.1.1.2 mrg const region_model *model) 2743 1.1 mrg { 2744 1.1.1.2 mrg dead_svalue_purger p (live_svalues, model); 2745 1.1.1.2 mrg purge (p, NULL); 2746 1.1.1.2 mrg } 2747 1.1.1.2 mrg 2748 1.1.1.2 mrg class svalue_purger 2749 1.1.1.2 mrg { 2750 1.1.1.2 mrg public: 2751 1.1.1.2 mrg svalue_purger (const svalue *sval) : m_sval (sval) {} 2752 1.1.1.2 mrg 2753 1.1.1.2 mrg bool should_purge_p (const svalue *sval) const 2754 1.1.1.2 mrg { 2755 1.1.1.2 mrg return sval->involves_p (m_sval); 2756 1.1.1.2 mrg } 2757 1.1.1.2 mrg 2758 1.1.1.2 mrg private: 2759 1.1.1.2 mrg const svalue *m_sval; 2760 1.1.1.2 mrg }; 2761 1.1.1.2 mrg 2762 1.1.1.2 mrg /* Purge any state involving SVAL. */ 2763 1.1.1.2 mrg 2764 1.1.1.2 mrg void 2765 1.1.1.2 mrg constraint_manager::purge_state_involving (const svalue *sval) 2766 1.1.1.2 mrg { 2767 1.1.1.2 mrg svalue_purger p (sval); 2768 1.1.1.2 mrg purge (p, NULL); 2769 1.1 mrg } 2770 1.1 mrg 2771 1.1 mrg /* Comparator for use by constraint_manager::canonicalize. 2772 1.1 mrg Sort a pair of equiv_class instances, using the representative 2773 1.1.1.2 mrg svalue as a sort key. */ 2774 1.1 mrg 2775 1.1 mrg static int 2776 1.1 mrg equiv_class_cmp (const void *p1, const void *p2) 2777 1.1 mrg { 2778 1.1 mrg const equiv_class *ec1 = *(const equiv_class * const *)p1; 2779 1.1 mrg const equiv_class *ec2 = *(const equiv_class * const *)p2; 2780 1.1 mrg 2781 1.1.1.2 mrg const svalue *rep1 = ec1->get_representative (); 2782 1.1.1.2 mrg const svalue *rep2 = ec2->get_representative (); 2783 1.1 mrg 2784 1.1.1.2 mrg gcc_assert (rep1); 2785 1.1.1.2 mrg gcc_assert (rep2); 2786 1.1.1.2 mrg 2787 1.1.1.2 mrg return svalue::cmp_ptr (rep1, rep2); 2788 1.1 mrg } 2789 1.1 mrg 2790 1.1 mrg /* Comparator for use by constraint_manager::canonicalize. 2791 1.1 mrg Sort a pair of constraint instances. */ 2792 1.1 mrg 2793 1.1 mrg static int 2794 1.1 mrg constraint_cmp (const void *p1, const void *p2) 2795 1.1 mrg { 2796 1.1 mrg const constraint *c1 = (const constraint *)p1; 2797 1.1 mrg const constraint *c2 = (const constraint *)p2; 2798 1.1 mrg int lhs_cmp = c1->m_lhs.as_int () - c2->m_lhs.as_int (); 2799 1.1 mrg if (lhs_cmp) 2800 1.1 mrg return lhs_cmp; 2801 1.1 mrg int rhs_cmp = c1->m_rhs.as_int () - c2->m_rhs.as_int (); 2802 1.1 mrg if (rhs_cmp) 2803 1.1 mrg return rhs_cmp; 2804 1.1 mrg return c1->m_op - c2->m_op; 2805 1.1 mrg } 2806 1.1 mrg 2807 1.1.1.2 mrg /* Purge redundant equivalence classes and constraints, and reorder them 2808 1.1.1.2 mrg within this constraint_manager into a canonical order, to increase the 2809 1.1 mrg chances of finding equality with another instance. */ 2810 1.1 mrg 2811 1.1 mrg void 2812 1.1.1.2 mrg constraint_manager::canonicalize () 2813 1.1 mrg { 2814 1.1.1.2 mrg /* First, sort svalues within the ECs. */ 2815 1.1 mrg unsigned i; 2816 1.1 mrg equiv_class *ec; 2817 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, i, ec) 2818 1.1 mrg ec->canonicalize (); 2819 1.1 mrg 2820 1.1.1.2 mrg /* TODO: remove constraints where both sides have a constant, and are 2821 1.1.1.2 mrg thus implicit. But does this break transitivity? */ 2822 1.1 mrg 2823 1.1.1.2 mrg /* We will be purging and reordering ECs. 2824 1.1.1.2 mrg We will need to remap the equiv_class_ids in the constraints, 2825 1.1 mrg so we need to store the original index of each EC. 2826 1.1.1.2 mrg Build a lookup table, mapping from the representative svalue 2827 1.1.1.2 mrg to the original equiv_class_id of that svalue. */ 2828 1.1.1.2 mrg hash_map<const svalue *, equiv_class_id> original_ec_id; 2829 1.1.1.2 mrg const unsigned orig_num_equiv_classes = m_equiv_classes.length (); 2830 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, i, ec) 2831 1.1 mrg { 2832 1.1.1.2 mrg const svalue *rep = ec->get_representative (); 2833 1.1.1.2 mrg gcc_assert (rep); 2834 1.1.1.2 mrg original_ec_id.put (rep, i); 2835 1.1.1.2 mrg } 2836 1.1.1.2 mrg 2837 1.1.1.2 mrg /* Find ECs used by constraints. */ 2838 1.1.1.2 mrg hash_set<const equiv_class *> used_ecs; 2839 1.1.1.2 mrg constraint *c; 2840 1.1.1.2 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 2841 1.1.1.2 mrg { 2842 1.1.1.2 mrg used_ecs.add (m_equiv_classes[c->m_lhs.as_int ()]); 2843 1.1.1.2 mrg used_ecs.add (m_equiv_classes[c->m_rhs.as_int ()]); 2844 1.1 mrg } 2845 1.1 mrg 2846 1.1.1.2 mrg for (const auto &iter : m_bounded_ranges_constraints) 2847 1.1.1.2 mrg used_ecs.add (m_equiv_classes[iter.m_ec_id.as_int ()]); 2848 1.1.1.2 mrg 2849 1.1.1.2 mrg /* Purge unused ECs: those that aren't used by constraints and 2850 1.1.1.2 mrg that effectively have only one svalue (either in m_constant 2851 1.1.1.2 mrg or in m_vars). */ 2852 1.1.1.2 mrg { 2853 1.1.1.2 mrg /* "unordered remove if" from a vec. */ 2854 1.1.1.2 mrg unsigned i = 0; 2855 1.1.1.2 mrg while (i < m_equiv_classes.length ()) 2856 1.1.1.2 mrg { 2857 1.1.1.2 mrg equiv_class *ec = m_equiv_classes[i]; 2858 1.1.1.2 mrg if (!used_ecs.contains (ec) 2859 1.1.1.2 mrg && !ec->contains_non_constant_p ()) 2860 1.1.1.2 mrg { 2861 1.1.1.2 mrg m_equiv_classes.unordered_remove (i); 2862 1.1.1.2 mrg delete ec; 2863 1.1.1.2 mrg } 2864 1.1.1.2 mrg else 2865 1.1.1.2 mrg i++; 2866 1.1.1.2 mrg } 2867 1.1.1.2 mrg } 2868 1.1.1.2 mrg 2869 1.1.1.2 mrg /* Next, sort the surviving ECs into a canonical order. */ 2870 1.1 mrg m_equiv_classes.qsort (equiv_class_cmp); 2871 1.1 mrg 2872 1.1 mrg /* Populate ec_id_map based on the old vs new EC ids. */ 2873 1.1.1.2 mrg one_way_id_map<equiv_class_id> ec_id_map (orig_num_equiv_classes); 2874 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, i, ec) 2875 1.1 mrg { 2876 1.1.1.2 mrg const svalue *rep = ec->get_representative (); 2877 1.1.1.2 mrg gcc_assert (rep); 2878 1.1.1.2 mrg ec_id_map.put (*original_ec_id.get (rep), i); 2879 1.1 mrg } 2880 1.1 mrg 2881 1.1.1.2 mrg /* Use ec_id_map to update the EC ids within the constraints. */ 2882 1.1 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 2883 1.1 mrg { 2884 1.1 mrg ec_id_map.update (&c->m_lhs); 2885 1.1 mrg ec_id_map.update (&c->m_rhs); 2886 1.1 mrg } 2887 1.1 mrg 2888 1.1.1.2 mrg for (auto &iter : m_bounded_ranges_constraints) 2889 1.1.1.2 mrg ec_id_map.update (&iter.m_ec_id); 2890 1.1.1.2 mrg 2891 1.1 mrg /* Finally, sort the constraints. */ 2892 1.1 mrg m_constraints.qsort (constraint_cmp); 2893 1.1 mrg } 2894 1.1 mrg 2895 1.1 mrg /* Concrete subclass of fact_visitor for use by constraint_manager::merge. 2896 1.1 mrg For every fact in CM_A, see if it is also true in *CM_B. Add such 2897 1.1 mrg facts to *OUT. */ 2898 1.1 mrg 2899 1.1 mrg class merger_fact_visitor : public fact_visitor 2900 1.1 mrg { 2901 1.1 mrg public: 2902 1.1.1.2 mrg merger_fact_visitor (const constraint_manager *cm_b, 2903 1.1 mrg constraint_manager *out) 2904 1.1 mrg : m_cm_b (cm_b), m_out (out) 2905 1.1 mrg {} 2906 1.1 mrg 2907 1.1.1.2 mrg void on_fact (const svalue *lhs, enum tree_code code, const svalue *rhs) 2908 1.1 mrg FINAL OVERRIDE 2909 1.1 mrg { 2910 1.1.1.2 mrg /* Special-case for widening. */ 2911 1.1.1.2 mrg if (lhs->get_kind () == SK_WIDENING) 2912 1.1.1.2 mrg if (!m_cm_b->get_equiv_class_by_svalue (lhs, NULL)) 2913 1.1.1.2 mrg { 2914 1.1.1.2 mrg /* LHS isn't constrained within m_cm_b. */ 2915 1.1.1.2 mrg bool sat = m_out->add_constraint (lhs, code, rhs); 2916 1.1.1.2 mrg gcc_assert (sat); 2917 1.1.1.2 mrg return; 2918 1.1.1.2 mrg } 2919 1.1.1.2 mrg 2920 1.1 mrg if (m_cm_b->eval_condition (lhs, code, rhs).is_true ()) 2921 1.1 mrg { 2922 1.1 mrg bool sat = m_out->add_constraint (lhs, code, rhs); 2923 1.1.1.2 mrg if (!sat) 2924 1.1.1.2 mrg { 2925 1.1.1.2 mrg /* If -fanalyzer-transitivity is off, we can encounter cases 2926 1.1.1.2 mrg where at least one of the two constraint_managers being merged 2927 1.1.1.2 mrg is infeasible, but we only discover that infeasibility 2928 1.1.1.2 mrg during merging (PR analyzer/96650). 2929 1.1.1.2 mrg Silently drop such constraints. */ 2930 1.1.1.2 mrg gcc_assert (!flag_analyzer_transitivity); 2931 1.1.1.2 mrg } 2932 1.1.1.2 mrg } 2933 1.1.1.2 mrg } 2934 1.1.1.2 mrg 2935 1.1.1.2 mrg void on_ranges (const svalue *lhs_sval, 2936 1.1.1.2 mrg const bounded_ranges *ranges) FINAL OVERRIDE 2937 1.1.1.2 mrg { 2938 1.1.1.2 mrg for (const auto &iter : m_cm_b->m_bounded_ranges_constraints) 2939 1.1.1.2 mrg { 2940 1.1.1.2 mrg const equiv_class &ec_rhs = iter.m_ec_id.get_obj (*m_cm_b); 2941 1.1.1.2 mrg for (unsigned i = 0; i < ec_rhs.m_vars.length (); i++) 2942 1.1.1.2 mrg { 2943 1.1.1.2 mrg const svalue *rhs_sval = ec_rhs.m_vars[i]; 2944 1.1.1.2 mrg if (lhs_sval == rhs_sval) 2945 1.1.1.2 mrg { 2946 1.1.1.2 mrg /* Union of the two ranges. */ 2947 1.1.1.2 mrg auto_vec <const bounded_ranges *> pair (2); 2948 1.1.1.2 mrg pair.quick_push (ranges); 2949 1.1.1.2 mrg pair.quick_push (iter.m_ranges); 2950 1.1.1.2 mrg bounded_ranges_manager *ranges_mgr 2951 1.1.1.2 mrg = m_cm_b->get_range_manager (); 2952 1.1.1.2 mrg const bounded_ranges *union_ 2953 1.1.1.2 mrg = ranges_mgr->get_or_create_union (pair); 2954 1.1.1.2 mrg bool sat = m_out->add_bounded_ranges (lhs_sval, union_); 2955 1.1.1.2 mrg gcc_assert (sat); 2956 1.1.1.2 mrg } 2957 1.1.1.2 mrg } 2958 1.1 mrg } 2959 1.1 mrg } 2960 1.1 mrg 2961 1.1 mrg private: 2962 1.1.1.2 mrg const constraint_manager *m_cm_b; 2963 1.1 mrg constraint_manager *m_out; 2964 1.1 mrg }; 2965 1.1 mrg 2966 1.1 mrg /* Use MERGER to merge CM_A and CM_B into *OUT. 2967 1.1 mrg If one thinks of a constraint_manager as a subset of N-dimensional 2968 1.1 mrg space, this takes the union of the points of CM_A and CM_B, and 2969 1.1 mrg expresses that into *OUT. Alternatively, it can be thought of 2970 1.1 mrg as the intersection of the constraints. */ 2971 1.1 mrg 2972 1.1 mrg void 2973 1.1 mrg constraint_manager::merge (const constraint_manager &cm_a, 2974 1.1 mrg const constraint_manager &cm_b, 2975 1.1.1.2 mrg constraint_manager *out) 2976 1.1 mrg { 2977 1.1 mrg /* Merge the equivalence classes and constraints. 2978 1.1 mrg The easiest way to do this seems to be to enumerate all of the facts 2979 1.1.1.2 mrg in cm_a, see which are also true in cm_b, 2980 1.1 mrg and add those to *OUT. */ 2981 1.1.1.2 mrg merger_fact_visitor v (&cm_b, out); 2982 1.1.1.2 mrg cm_a.for_each_fact (&v); 2983 1.1 mrg } 2984 1.1 mrg 2985 1.1 mrg /* Call VISITOR's on_fact vfunc repeatedly to express the various 2986 1.1 mrg equivalence classes and constraints. 2987 1.1 mrg This is used by constraint_manager::merge to find the common 2988 1.1 mrg facts between two input constraint_managers. */ 2989 1.1 mrg 2990 1.1 mrg void 2991 1.1 mrg constraint_manager::for_each_fact (fact_visitor *visitor) const 2992 1.1 mrg { 2993 1.1 mrg /* First, call EQ_EXPR within the various equivalence classes. */ 2994 1.1 mrg unsigned ec_idx; 2995 1.1 mrg equiv_class *ec; 2996 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, ec_idx, ec) 2997 1.1 mrg { 2998 1.1.1.2 mrg if (ec->m_cst_sval) 2999 1.1 mrg { 3000 1.1 mrg unsigned i; 3001 1.1.1.2 mrg const svalue *sval; 3002 1.1.1.2 mrg FOR_EACH_VEC_ELT (ec->m_vars, i, sval) 3003 1.1.1.2 mrg visitor->on_fact (ec->m_cst_sval, EQ_EXPR, sval); 3004 1.1 mrg } 3005 1.1 mrg for (unsigned i = 0; i < ec->m_vars.length (); i++) 3006 1.1 mrg for (unsigned j = i + 1; j < ec->m_vars.length (); j++) 3007 1.1 mrg visitor->on_fact (ec->m_vars[i], EQ_EXPR, ec->m_vars[j]); 3008 1.1 mrg } 3009 1.1 mrg 3010 1.1 mrg /* Now, express the various constraints. */ 3011 1.1 mrg unsigned con_idx; 3012 1.1 mrg constraint *c; 3013 1.1 mrg FOR_EACH_VEC_ELT (m_constraints, con_idx, c) 3014 1.1 mrg { 3015 1.1 mrg const equiv_class &ec_lhs = c->m_lhs.get_obj (*this); 3016 1.1 mrg const equiv_class &ec_rhs = c->m_rhs.get_obj (*this); 3017 1.1 mrg enum tree_code code = constraint_tree_code (c->m_op); 3018 1.1 mrg 3019 1.1.1.2 mrg if (ec_lhs.m_cst_sval) 3020 1.1 mrg { 3021 1.1 mrg for (unsigned j = 0; j < ec_rhs.m_vars.length (); j++) 3022 1.1 mrg { 3023 1.1.1.2 mrg visitor->on_fact (ec_lhs.m_cst_sval, code, ec_rhs.m_vars[j]); 3024 1.1 mrg } 3025 1.1 mrg } 3026 1.1 mrg for (unsigned i = 0; i < ec_lhs.m_vars.length (); i++) 3027 1.1 mrg { 3028 1.1.1.2 mrg if (ec_rhs.m_cst_sval) 3029 1.1.1.2 mrg visitor->on_fact (ec_lhs.m_vars[i], code, ec_rhs.m_cst_sval); 3030 1.1 mrg for (unsigned j = 0; j < ec_rhs.m_vars.length (); j++) 3031 1.1 mrg visitor->on_fact (ec_lhs.m_vars[i], code, ec_rhs.m_vars[j]); 3032 1.1 mrg } 3033 1.1 mrg } 3034 1.1.1.2 mrg 3035 1.1.1.2 mrg for (const auto &iter : m_bounded_ranges_constraints) 3036 1.1.1.2 mrg { 3037 1.1.1.2 mrg const equiv_class &ec_lhs = iter.m_ec_id.get_obj (*this); 3038 1.1.1.2 mrg for (unsigned i = 0; i < ec_lhs.m_vars.length (); i++) 3039 1.1.1.2 mrg { 3040 1.1.1.2 mrg const svalue *lhs_sval = ec_lhs.m_vars[i]; 3041 1.1.1.2 mrg visitor->on_ranges (lhs_sval, iter.m_ranges); 3042 1.1.1.2 mrg } 3043 1.1.1.2 mrg } 3044 1.1 mrg } 3045 1.1 mrg 3046 1.1 mrg /* Assert that this object is valid. */ 3047 1.1 mrg 3048 1.1 mrg void 3049 1.1 mrg constraint_manager::validate () const 3050 1.1 mrg { 3051 1.1 mrg /* Skip this in a release build. */ 3052 1.1 mrg #if !CHECKING_P 3053 1.1 mrg return; 3054 1.1 mrg #endif 3055 1.1 mrg 3056 1.1 mrg int i; 3057 1.1 mrg equiv_class *ec; 3058 1.1 mrg FOR_EACH_VEC_ELT (m_equiv_classes, i, ec) 3059 1.1 mrg { 3060 1.1 mrg gcc_assert (ec); 3061 1.1 mrg 3062 1.1 mrg int j; 3063 1.1.1.2 mrg const svalue *sval; 3064 1.1.1.2 mrg FOR_EACH_VEC_ELT (ec->m_vars, j, sval) 3065 1.1.1.2 mrg gcc_assert (sval); 3066 1.1 mrg if (ec->m_constant) 3067 1.1 mrg { 3068 1.1 mrg gcc_assert (CONSTANT_CLASS_P (ec->m_constant)); 3069 1.1.1.2 mrg gcc_assert (ec->m_cst_sval); 3070 1.1 mrg } 3071 1.1 mrg #if 0 3072 1.1 mrg else 3073 1.1 mrg gcc_assert (ec->m_vars.length () > 0); 3074 1.1 mrg #endif 3075 1.1 mrg } 3076 1.1 mrg 3077 1.1 mrg constraint *c; 3078 1.1 mrg FOR_EACH_VEC_ELT (m_constraints, i, c) 3079 1.1 mrg { 3080 1.1 mrg gcc_assert (!c->m_lhs.null_p ()); 3081 1.1.1.2 mrg gcc_assert (c->m_lhs.as_int () < (int)m_equiv_classes.length ()); 3082 1.1 mrg gcc_assert (!c->m_rhs.null_p ()); 3083 1.1.1.2 mrg gcc_assert (c->m_rhs.as_int () < (int)m_equiv_classes.length ()); 3084 1.1 mrg } 3085 1.1.1.2 mrg 3086 1.1.1.2 mrg for (const auto &iter : m_bounded_ranges_constraints) 3087 1.1.1.2 mrg { 3088 1.1.1.2 mrg gcc_assert (!iter.m_ec_id.null_p ()); 3089 1.1.1.2 mrg gcc_assert (iter.m_ec_id.as_int () < (int)m_equiv_classes.length ()); 3090 1.1.1.2 mrg } 3091 1.1.1.2 mrg } 3092 1.1.1.2 mrg 3093 1.1.1.2 mrg bounded_ranges_manager * 3094 1.1.1.2 mrg constraint_manager::get_range_manager () const 3095 1.1.1.2 mrg { 3096 1.1.1.2 mrg return m_mgr->get_range_manager (); 3097 1.1 mrg } 3098 1.1 mrg 3099 1.1 mrg #if CHECKING_P 3100 1.1 mrg 3101 1.1 mrg namespace selftest { 3102 1.1 mrg 3103 1.1 mrg /* Various constraint_manager selftests. 3104 1.1 mrg These have to be written in terms of a region_model, since 3105 1.1.1.2 mrg the latter is responsible for managing svalue instances. */ 3106 1.1.1.2 mrg 3107 1.1.1.2 mrg /* Verify that range::add_bound works as expected. */ 3108 1.1.1.2 mrg 3109 1.1.1.2 mrg static void 3110 1.1.1.2 mrg test_range () 3111 1.1.1.2 mrg { 3112 1.1.1.2 mrg tree int_0 = build_int_cst (integer_type_node, 0); 3113 1.1.1.2 mrg tree int_1 = build_int_cst (integer_type_node, 1); 3114 1.1.1.2 mrg tree int_2 = build_int_cst (integer_type_node, 2); 3115 1.1.1.2 mrg tree int_5 = build_int_cst (integer_type_node, 5); 3116 1.1.1.2 mrg 3117 1.1.1.2 mrg { 3118 1.1.1.2 mrg range r; 3119 1.1.1.2 mrg ASSERT_FALSE (r.constrained_to_single_element ()); 3120 1.1.1.2 mrg 3121 1.1.1.2 mrg /* (r >= 1). */ 3122 1.1.1.2 mrg ASSERT_TRUE (r.add_bound (GE_EXPR, int_1)); 3123 1.1.1.2 mrg 3124 1.1.1.2 mrg /* Redundant. */ 3125 1.1.1.2 mrg ASSERT_TRUE (r.add_bound (GE_EXPR, int_0)); 3126 1.1.1.2 mrg ASSERT_TRUE (r.add_bound (GT_EXPR, int_0)); 3127 1.1.1.2 mrg 3128 1.1.1.2 mrg ASSERT_FALSE (r.constrained_to_single_element ()); 3129 1.1.1.2 mrg 3130 1.1.1.2 mrg /* Contradiction. */ 3131 1.1.1.2 mrg ASSERT_FALSE (r.add_bound (LT_EXPR, int_1)); 3132 1.1.1.2 mrg 3133 1.1.1.2 mrg /* (r < 5). */ 3134 1.1.1.2 mrg ASSERT_TRUE (r.add_bound (LT_EXPR, int_5)); 3135 1.1.1.2 mrg ASSERT_FALSE (r.constrained_to_single_element ()); 3136 1.1.1.2 mrg 3137 1.1.1.2 mrg /* Contradiction. */ 3138 1.1.1.2 mrg ASSERT_FALSE (r.add_bound (GE_EXPR, int_5)); 3139 1.1.1.2 mrg 3140 1.1.1.2 mrg /* (r < 2). */ 3141 1.1.1.2 mrg ASSERT_TRUE (r.add_bound (LT_EXPR, int_2)); 3142 1.1.1.2 mrg ASSERT_TRUE (r.constrained_to_single_element ()); 3143 1.1.1.2 mrg 3144 1.1.1.2 mrg /* Redundant. */ 3145 1.1.1.2 mrg ASSERT_TRUE (r.add_bound (LE_EXPR, int_1)); 3146 1.1.1.2 mrg ASSERT_TRUE (r.constrained_to_single_element ()); 3147 1.1.1.2 mrg } 3148 1.1.1.2 mrg } 3149 1.1 mrg 3150 1.1 mrg /* Verify that setting and getting simple conditions within a region_model 3151 1.1 mrg work (thus exercising the underlying constraint_manager). */ 3152 1.1 mrg 3153 1.1 mrg static void 3154 1.1 mrg test_constraint_conditions () 3155 1.1 mrg { 3156 1.1 mrg tree int_42 = build_int_cst (integer_type_node, 42); 3157 1.1 mrg tree int_0 = build_int_cst (integer_type_node, 0); 3158 1.1 mrg 3159 1.1 mrg tree x = build_global_decl ("x", integer_type_node); 3160 1.1 mrg tree y = build_global_decl ("y", integer_type_node); 3161 1.1 mrg tree z = build_global_decl ("z", integer_type_node); 3162 1.1 mrg 3163 1.1 mrg /* Self-comparisons. */ 3164 1.1 mrg { 3165 1.1.1.2 mrg region_model_manager mgr; 3166 1.1.1.2 mrg region_model model (&mgr); 3167 1.1 mrg ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, x); 3168 1.1 mrg ASSERT_CONDITION_TRUE (model, x, LE_EXPR, x); 3169 1.1 mrg ASSERT_CONDITION_TRUE (model, x, GE_EXPR, x); 3170 1.1 mrg ASSERT_CONDITION_FALSE (model, x, NE_EXPR, x); 3171 1.1 mrg ASSERT_CONDITION_FALSE (model, x, LT_EXPR, x); 3172 1.1 mrg ASSERT_CONDITION_FALSE (model, x, GT_EXPR, x); 3173 1.1 mrg } 3174 1.1 mrg 3175 1.1.1.2 mrg /* Adding self-equality shouldn't add equiv classes. */ 3176 1.1.1.2 mrg { 3177 1.1.1.2 mrg region_model_manager mgr; 3178 1.1.1.2 mrg region_model model (&mgr); 3179 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, x); 3180 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, int_42, EQ_EXPR, int_42); 3181 1.1.1.2 mrg /* ...even when done directly via svalues: */ 3182 1.1.1.2 mrg const svalue *sval_int_42 = model.get_rvalue (int_42, NULL); 3183 1.1.1.2 mrg bool sat = model.get_constraints ()->add_constraint (sval_int_42, 3184 1.1.1.2 mrg EQ_EXPR, 3185 1.1.1.2 mrg sval_int_42); 3186 1.1.1.2 mrg ASSERT_TRUE (sat); 3187 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0); 3188 1.1.1.2 mrg } 3189 1.1.1.2 mrg 3190 1.1 mrg /* x == y. */ 3191 1.1 mrg { 3192 1.1.1.2 mrg region_model_manager mgr; 3193 1.1.1.2 mrg region_model model (&mgr); 3194 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y); 3195 1.1 mrg 3196 1.1 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y); 3197 1.1 mrg 3198 1.1 mrg ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, y); 3199 1.1 mrg ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y); 3200 1.1 mrg ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y); 3201 1.1 mrg ASSERT_CONDITION_FALSE (model, x, NE_EXPR, y); 3202 1.1 mrg ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y); 3203 1.1 mrg ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y); 3204 1.1 mrg 3205 1.1 mrg /* Swapped operands. */ 3206 1.1 mrg ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, x); 3207 1.1 mrg ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x); 3208 1.1 mrg ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x); 3209 1.1 mrg ASSERT_CONDITION_FALSE (model, y, NE_EXPR, x); 3210 1.1 mrg ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x); 3211 1.1 mrg ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x); 3212 1.1 mrg 3213 1.1 mrg /* Comparison with other var. */ 3214 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, z); 3215 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, z); 3216 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z); 3217 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, z); 3218 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, z); 3219 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, z); 3220 1.1 mrg } 3221 1.1 mrg 3222 1.1 mrg /* x == y, then y == z */ 3223 1.1 mrg { 3224 1.1.1.2 mrg region_model_manager mgr; 3225 1.1.1.2 mrg region_model model (&mgr); 3226 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y); 3227 1.1 mrg 3228 1.1 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y); 3229 1.1 mrg ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, z); 3230 1.1 mrg 3231 1.1 mrg ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, z); 3232 1.1 mrg ASSERT_CONDITION_TRUE (model, x, LE_EXPR, z); 3233 1.1 mrg ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z); 3234 1.1 mrg ASSERT_CONDITION_FALSE (model, x, NE_EXPR, z); 3235 1.1 mrg ASSERT_CONDITION_FALSE (model, x, LT_EXPR, z); 3236 1.1 mrg ASSERT_CONDITION_FALSE (model, x, GT_EXPR, z); 3237 1.1 mrg } 3238 1.1 mrg 3239 1.1 mrg /* x != y. */ 3240 1.1 mrg { 3241 1.1.1.2 mrg region_model_manager mgr; 3242 1.1.1.2 mrg region_model model (&mgr); 3243 1.1 mrg 3244 1.1 mrg ADD_SAT_CONSTRAINT (model, x, NE_EXPR, y); 3245 1.1 mrg 3246 1.1 mrg ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y); 3247 1.1 mrg ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y); 3248 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, y); 3249 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, y); 3250 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, y); 3251 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, y); 3252 1.1 mrg 3253 1.1 mrg /* Swapped operands. */ 3254 1.1 mrg ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x); 3255 1.1 mrg ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x); 3256 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, LE_EXPR, x); 3257 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, GE_EXPR, x); 3258 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, LT_EXPR, x); 3259 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, GT_EXPR, x); 3260 1.1 mrg 3261 1.1 mrg /* Comparison with other var. */ 3262 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, z); 3263 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, z); 3264 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z); 3265 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, z); 3266 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, z); 3267 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, z); 3268 1.1 mrg } 3269 1.1 mrg 3270 1.1 mrg /* x < y. */ 3271 1.1 mrg { 3272 1.1.1.2 mrg region_model_manager mgr; 3273 1.1.1.2 mrg region_model model (&mgr); 3274 1.1 mrg 3275 1.1 mrg ADD_SAT_CONSTRAINT (model, x, LT_EXPR, y); 3276 1.1 mrg 3277 1.1 mrg ASSERT_CONDITION_TRUE (model, x, LT_EXPR, y); 3278 1.1 mrg ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y); 3279 1.1 mrg ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y); 3280 1.1 mrg ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y); 3281 1.1 mrg ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y); 3282 1.1 mrg ASSERT_CONDITION_FALSE (model, x, GE_EXPR, y); 3283 1.1 mrg 3284 1.1 mrg /* Swapped operands. */ 3285 1.1 mrg ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x); 3286 1.1 mrg ASSERT_CONDITION_FALSE (model, y, LE_EXPR, x); 3287 1.1 mrg ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x); 3288 1.1 mrg ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x); 3289 1.1 mrg ASSERT_CONDITION_TRUE (model, y, GT_EXPR, x); 3290 1.1 mrg ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x); 3291 1.1 mrg } 3292 1.1 mrg 3293 1.1 mrg /* x <= y. */ 3294 1.1 mrg { 3295 1.1.1.2 mrg region_model_manager mgr; 3296 1.1.1.2 mrg region_model model (&mgr); 3297 1.1 mrg 3298 1.1 mrg ADD_SAT_CONSTRAINT (model, x, LE_EXPR, y); 3299 1.1 mrg 3300 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, y); 3301 1.1 mrg ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y); 3302 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, y); 3303 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y); 3304 1.1 mrg ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y); 3305 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, y); 3306 1.1 mrg 3307 1.1 mrg /* Swapped operands. */ 3308 1.1 mrg ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x); 3309 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, LE_EXPR, x); 3310 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, NE_EXPR, x); 3311 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, x); 3312 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, GT_EXPR, x); 3313 1.1 mrg ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x); 3314 1.1 mrg } 3315 1.1 mrg 3316 1.1 mrg /* x > y. */ 3317 1.1 mrg { 3318 1.1.1.2 mrg region_model_manager mgr; 3319 1.1.1.2 mrg region_model model (&mgr); 3320 1.1 mrg 3321 1.1 mrg ADD_SAT_CONSTRAINT (model, x, GT_EXPR, y); 3322 1.1 mrg 3323 1.1 mrg ASSERT_CONDITION_TRUE (model, x, GT_EXPR, y); 3324 1.1 mrg ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y); 3325 1.1 mrg ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y); 3326 1.1 mrg ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y); 3327 1.1 mrg ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y); 3328 1.1 mrg ASSERT_CONDITION_FALSE (model, x, LE_EXPR, y); 3329 1.1 mrg 3330 1.1 mrg /* Swapped operands. */ 3331 1.1 mrg ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x); 3332 1.1 mrg ASSERT_CONDITION_FALSE (model, y, GE_EXPR, x); 3333 1.1 mrg ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x); 3334 1.1 mrg ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x); 3335 1.1 mrg ASSERT_CONDITION_TRUE (model, y, LT_EXPR, x); 3336 1.1 mrg ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x); 3337 1.1 mrg } 3338 1.1 mrg 3339 1.1 mrg /* x >= y. */ 3340 1.1 mrg { 3341 1.1.1.2 mrg region_model_manager mgr; 3342 1.1.1.2 mrg region_model model (&mgr); 3343 1.1 mrg 3344 1.1 mrg ADD_SAT_CONSTRAINT (model, x, GE_EXPR, y); 3345 1.1 mrg 3346 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, y); 3347 1.1 mrg ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y); 3348 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, y); 3349 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y); 3350 1.1 mrg ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y); 3351 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, y); 3352 1.1 mrg 3353 1.1 mrg /* Swapped operands. */ 3354 1.1 mrg ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x); 3355 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, GE_EXPR, x); 3356 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, NE_EXPR, x); 3357 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, x); 3358 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, y, LT_EXPR, x); 3359 1.1 mrg ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x); 3360 1.1 mrg } 3361 1.1 mrg 3362 1.1 mrg // TODO: implied orderings 3363 1.1 mrg 3364 1.1 mrg /* Constants. */ 3365 1.1 mrg { 3366 1.1.1.2 mrg region_model_manager mgr; 3367 1.1.1.2 mrg region_model model (&mgr); 3368 1.1 mrg ASSERT_CONDITION_FALSE (model, int_0, EQ_EXPR, int_42); 3369 1.1 mrg ASSERT_CONDITION_TRUE (model, int_0, NE_EXPR, int_42); 3370 1.1 mrg ASSERT_CONDITION_TRUE (model, int_0, LT_EXPR, int_42); 3371 1.1 mrg ASSERT_CONDITION_TRUE (model, int_0, LE_EXPR, int_42); 3372 1.1 mrg ASSERT_CONDITION_FALSE (model, int_0, GT_EXPR, int_42); 3373 1.1 mrg ASSERT_CONDITION_FALSE (model, int_0, GE_EXPR, int_42); 3374 1.1 mrg } 3375 1.1 mrg 3376 1.1 mrg /* x == 0, y == 42. */ 3377 1.1 mrg { 3378 1.1.1.2 mrg region_model_manager mgr; 3379 1.1.1.2 mrg region_model model (&mgr); 3380 1.1 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0); 3381 1.1 mrg ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, int_42); 3382 1.1 mrg 3383 1.1 mrg ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y); 3384 1.1 mrg ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y); 3385 1.1 mrg ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y); 3386 1.1 mrg ASSERT_CONDITION_FALSE (model, x, GE_EXPR, y); 3387 1.1 mrg ASSERT_CONDITION_TRUE (model, x, LT_EXPR, y); 3388 1.1 mrg ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y); 3389 1.1 mrg } 3390 1.1 mrg 3391 1.1 mrg /* Unsatisfiable combinations. */ 3392 1.1 mrg 3393 1.1 mrg /* x == y && x != y. */ 3394 1.1 mrg { 3395 1.1.1.2 mrg region_model_manager mgr; 3396 1.1.1.2 mrg region_model model (&mgr); 3397 1.1 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y); 3398 1.1 mrg ADD_UNSAT_CONSTRAINT (model, x, NE_EXPR, y); 3399 1.1 mrg } 3400 1.1 mrg 3401 1.1 mrg /* x == 0 then x == 42. */ 3402 1.1 mrg { 3403 1.1.1.2 mrg region_model_manager mgr; 3404 1.1.1.2 mrg region_model model (&mgr); 3405 1.1 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0); 3406 1.1 mrg ADD_UNSAT_CONSTRAINT (model, x, EQ_EXPR, int_42); 3407 1.1 mrg } 3408 1.1 mrg 3409 1.1 mrg /* x == 0 then x != 0. */ 3410 1.1 mrg { 3411 1.1.1.2 mrg region_model_manager mgr; 3412 1.1.1.2 mrg region_model model (&mgr); 3413 1.1 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0); 3414 1.1 mrg ADD_UNSAT_CONSTRAINT (model, x, NE_EXPR, int_0); 3415 1.1 mrg } 3416 1.1 mrg 3417 1.1 mrg /* x == 0 then x > 0. */ 3418 1.1 mrg { 3419 1.1.1.2 mrg region_model_manager mgr; 3420 1.1.1.2 mrg region_model model (&mgr); 3421 1.1 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0); 3422 1.1 mrg ADD_UNSAT_CONSTRAINT (model, x, GT_EXPR, int_0); 3423 1.1 mrg } 3424 1.1 mrg 3425 1.1 mrg /* x != y && x == y. */ 3426 1.1 mrg { 3427 1.1.1.2 mrg region_model_manager mgr; 3428 1.1.1.2 mrg region_model model (&mgr); 3429 1.1 mrg ADD_SAT_CONSTRAINT (model, x, NE_EXPR, y); 3430 1.1 mrg ADD_UNSAT_CONSTRAINT (model, x, EQ_EXPR, y); 3431 1.1 mrg } 3432 1.1 mrg 3433 1.1 mrg /* x <= y && x > y. */ 3434 1.1 mrg { 3435 1.1.1.2 mrg region_model_manager mgr; 3436 1.1.1.2 mrg region_model model (&mgr); 3437 1.1 mrg ADD_SAT_CONSTRAINT (model, x, LE_EXPR, y); 3438 1.1 mrg ADD_UNSAT_CONSTRAINT (model, x, GT_EXPR, y); 3439 1.1 mrg } 3440 1.1 mrg 3441 1.1 mrg // etc 3442 1.1 mrg } 3443 1.1 mrg 3444 1.1 mrg /* Test transitivity of conditions. */ 3445 1.1 mrg 3446 1.1 mrg static void 3447 1.1 mrg test_transitivity () 3448 1.1 mrg { 3449 1.1 mrg tree a = build_global_decl ("a", integer_type_node); 3450 1.1 mrg tree b = build_global_decl ("b", integer_type_node); 3451 1.1 mrg tree c = build_global_decl ("c", integer_type_node); 3452 1.1 mrg tree d = build_global_decl ("d", integer_type_node); 3453 1.1 mrg 3454 1.1 mrg /* a == b, then c == d, then c == b. */ 3455 1.1 mrg { 3456 1.1.1.2 mrg region_model_manager mgr; 3457 1.1.1.2 mrg region_model model (&mgr); 3458 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, b); 3459 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, b, EQ_EXPR, c); 3460 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, c, EQ_EXPR, d); 3461 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, d); 3462 1.1 mrg 3463 1.1 mrg ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, b); 3464 1.1 mrg ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, b); 3465 1.1 mrg 3466 1.1 mrg ADD_SAT_CONSTRAINT (model, c, EQ_EXPR, d); 3467 1.1 mrg ASSERT_CONDITION_TRUE (model, c, EQ_EXPR, d); 3468 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, d); 3469 1.1 mrg 3470 1.1 mrg ADD_SAT_CONSTRAINT (model, c, EQ_EXPR, b); 3471 1.1 mrg ASSERT_CONDITION_TRUE (model, c, EQ_EXPR, b); 3472 1.1 mrg ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, d); 3473 1.1 mrg } 3474 1.1 mrg 3475 1.1 mrg /* Transitivity: "a < b", "b < c" should imply "a < c". */ 3476 1.1 mrg { 3477 1.1.1.2 mrg region_model_manager mgr; 3478 1.1.1.2 mrg region_model model (&mgr); 3479 1.1 mrg ADD_SAT_CONSTRAINT (model, a, LT_EXPR, b); 3480 1.1 mrg ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c); 3481 1.1 mrg 3482 1.1 mrg ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c); 3483 1.1 mrg ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c); 3484 1.1 mrg } 3485 1.1 mrg 3486 1.1 mrg /* Transitivity: "a <= b", "b < c" should imply "a < c". */ 3487 1.1 mrg { 3488 1.1.1.2 mrg region_model_manager mgr; 3489 1.1.1.2 mrg region_model model (&mgr); 3490 1.1 mrg ADD_SAT_CONSTRAINT (model, a, LE_EXPR, b); 3491 1.1 mrg ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c); 3492 1.1 mrg 3493 1.1 mrg ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c); 3494 1.1 mrg ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c); 3495 1.1 mrg } 3496 1.1 mrg 3497 1.1 mrg /* Transitivity: "a <= b", "b <= c" should imply "a <= c". */ 3498 1.1 mrg { 3499 1.1.1.2 mrg region_model_manager mgr; 3500 1.1.1.2 mrg region_model model (&mgr); 3501 1.1 mrg ADD_SAT_CONSTRAINT (model, a, LE_EXPR, b); 3502 1.1 mrg ADD_SAT_CONSTRAINT (model, b, LE_EXPR, c); 3503 1.1 mrg 3504 1.1 mrg ASSERT_CONDITION_TRUE (model, a, LE_EXPR, c); 3505 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, c); 3506 1.1 mrg } 3507 1.1 mrg 3508 1.1 mrg /* Transitivity: "a > b", "b > c" should imply "a > c". */ 3509 1.1 mrg { 3510 1.1.1.2 mrg region_model_manager mgr; 3511 1.1.1.2 mrg region_model model (&mgr); 3512 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b); 3513 1.1 mrg ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c); 3514 1.1 mrg 3515 1.1 mrg ASSERT_CONDITION_TRUE (model, a, GT_EXPR, c); 3516 1.1 mrg ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c); 3517 1.1 mrg } 3518 1.1 mrg 3519 1.1 mrg /* Transitivity: "a >= b", "b > c" should imply " a > c". */ 3520 1.1 mrg { 3521 1.1.1.2 mrg region_model_manager mgr; 3522 1.1.1.2 mrg region_model model (&mgr); 3523 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b); 3524 1.1 mrg ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c); 3525 1.1 mrg 3526 1.1 mrg ASSERT_CONDITION_TRUE (model, a, GT_EXPR, c); 3527 1.1 mrg ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c); 3528 1.1 mrg } 3529 1.1 mrg 3530 1.1 mrg /* Transitivity: "a >= b", "b >= c" should imply "a >= c". */ 3531 1.1 mrg { 3532 1.1.1.2 mrg region_model_manager mgr; 3533 1.1.1.2 mrg region_model model (&mgr); 3534 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b); 3535 1.1 mrg ADD_SAT_CONSTRAINT (model, b, GE_EXPR, c); 3536 1.1 mrg 3537 1.1 mrg ASSERT_CONDITION_TRUE (model, a, GE_EXPR, c); 3538 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, c); 3539 1.1 mrg } 3540 1.1 mrg 3541 1.1 mrg /* Transitivity: "(a < b)", "(c < d)", "(b < c)" should 3542 1.1 mrg imply the easy cases: 3543 1.1 mrg (a < c) 3544 1.1 mrg (b < d) 3545 1.1 mrg but also that: 3546 1.1 mrg (a < d). */ 3547 1.1 mrg { 3548 1.1.1.2 mrg region_model_manager mgr; 3549 1.1.1.2 mrg region_model model (&mgr); 3550 1.1 mrg ADD_SAT_CONSTRAINT (model, a, LT_EXPR, b); 3551 1.1 mrg ADD_SAT_CONSTRAINT (model, c, LT_EXPR, d); 3552 1.1 mrg ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c); 3553 1.1 mrg 3554 1.1 mrg ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c); 3555 1.1 mrg ASSERT_CONDITION_TRUE (model, b, LT_EXPR, d); 3556 1.1 mrg ASSERT_CONDITION_TRUE (model, a, LT_EXPR, d); 3557 1.1 mrg } 3558 1.1 mrg 3559 1.1 mrg /* Transitivity: "a >= b", "b >= a" should imply that a == b. */ 3560 1.1 mrg { 3561 1.1.1.2 mrg region_model_manager mgr; 3562 1.1.1.2 mrg region_model model (&mgr); 3563 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b); 3564 1.1 mrg ADD_SAT_CONSTRAINT (model, b, GE_EXPR, a); 3565 1.1 mrg 3566 1.1 mrg // TODO: 3567 1.1 mrg ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, b); 3568 1.1.1.2 mrg 3569 1.1.1.2 mrg /* The ECs for a and b should have merged, and any constraints removed. */ 3570 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1); 3571 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0); 3572 1.1 mrg } 3573 1.1 mrg 3574 1.1 mrg /* Transitivity: "a >= b", "b > a" should be impossible. */ 3575 1.1 mrg { 3576 1.1.1.2 mrg region_model_manager mgr; 3577 1.1.1.2 mrg region_model model (&mgr); 3578 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b); 3579 1.1 mrg ADD_UNSAT_CONSTRAINT (model, b, GT_EXPR, a); 3580 1.1 mrg } 3581 1.1 mrg 3582 1.1 mrg /* Transitivity: "a >= b", "b >= c", "c >= a" should imply 3583 1.1 mrg that a == b == c. */ 3584 1.1 mrg { 3585 1.1.1.2 mrg region_model_manager mgr; 3586 1.1.1.2 mrg region_model model (&mgr); 3587 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b); 3588 1.1 mrg ADD_SAT_CONSTRAINT (model, b, GE_EXPR, c); 3589 1.1 mrg ADD_SAT_CONSTRAINT (model, c, GE_EXPR, a); 3590 1.1 mrg 3591 1.1 mrg ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, c); 3592 1.1 mrg } 3593 1.1 mrg 3594 1.1 mrg /* Transitivity: "a > b", "b > c", "c > a" 3595 1.1 mrg should be impossible. */ 3596 1.1 mrg { 3597 1.1.1.2 mrg region_model_manager mgr; 3598 1.1.1.2 mrg region_model model (&mgr); 3599 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b); 3600 1.1 mrg ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c); 3601 1.1 mrg ADD_UNSAT_CONSTRAINT (model, c, GT_EXPR, a); 3602 1.1 mrg } 3603 1.1 mrg 3604 1.1 mrg } 3605 1.1 mrg 3606 1.1 mrg /* Test various conditionals involving constants where the results 3607 1.1 mrg ought to be implied based on the values of the constants. */ 3608 1.1 mrg 3609 1.1 mrg static void 3610 1.1 mrg test_constant_comparisons () 3611 1.1 mrg { 3612 1.1.1.2 mrg tree int_1 = build_int_cst (integer_type_node, 1); 3613 1.1 mrg tree int_3 = build_int_cst (integer_type_node, 3); 3614 1.1 mrg tree int_4 = build_int_cst (integer_type_node, 4); 3615 1.1 mrg tree int_5 = build_int_cst (integer_type_node, 5); 3616 1.1 mrg 3617 1.1 mrg tree int_1023 = build_int_cst (integer_type_node, 1023); 3618 1.1 mrg tree int_1024 = build_int_cst (integer_type_node, 1024); 3619 1.1 mrg 3620 1.1 mrg tree a = build_global_decl ("a", integer_type_node); 3621 1.1 mrg tree b = build_global_decl ("b", integer_type_node); 3622 1.1 mrg 3623 1.1.1.2 mrg tree a_plus_one = build2 (PLUS_EXPR, integer_type_node, a, int_1); 3624 1.1.1.2 mrg 3625 1.1 mrg /* Given a >= 1024, then a <= 1023 should be impossible. */ 3626 1.1 mrg { 3627 1.1.1.2 mrg region_model_manager mgr; 3628 1.1.1.2 mrg region_model model (&mgr); 3629 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_1024); 3630 1.1 mrg ADD_UNSAT_CONSTRAINT (model, a, LE_EXPR, int_1023); 3631 1.1 mrg } 3632 1.1 mrg 3633 1.1 mrg /* a > 4. */ 3634 1.1 mrg { 3635 1.1.1.2 mrg region_model_manager mgr; 3636 1.1.1.2 mrg region_model model (&mgr); 3637 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_4); 3638 1.1 mrg ASSERT_CONDITION_TRUE (model, a, GT_EXPR, int_4); 3639 1.1 mrg ASSERT_CONDITION_TRUE (model, a, NE_EXPR, int_3); 3640 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, a, NE_EXPR, int_5); 3641 1.1 mrg } 3642 1.1 mrg 3643 1.1 mrg /* a <= 4. */ 3644 1.1 mrg { 3645 1.1.1.2 mrg region_model_manager mgr; 3646 1.1.1.2 mrg region_model model (&mgr); 3647 1.1 mrg ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4); 3648 1.1 mrg ASSERT_CONDITION_FALSE (model, a, GT_EXPR, int_4); 3649 1.1 mrg ASSERT_CONDITION_FALSE (model, a, GT_EXPR, int_5); 3650 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, a, NE_EXPR, int_3); 3651 1.1 mrg } 3652 1.1 mrg 3653 1.1 mrg /* If "a > b" and "a == 3", then "b == 4" ought to be unsatisfiable. */ 3654 1.1 mrg { 3655 1.1.1.2 mrg region_model_manager mgr; 3656 1.1.1.2 mrg region_model model (&mgr); 3657 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b); 3658 1.1 mrg ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_3); 3659 1.1 mrg ADD_UNSAT_CONSTRAINT (model, b, EQ_EXPR, int_4); 3660 1.1 mrg } 3661 1.1 mrg 3662 1.1 mrg /* Various tests of int ranges where there is only one possible candidate. */ 3663 1.1 mrg { 3664 1.1 mrg /* If "a <= 4" && "a > 3", then "a == 4", 3665 1.1 mrg assuming a is of integral type. */ 3666 1.1 mrg { 3667 1.1.1.2 mrg region_model_manager mgr; 3668 1.1.1.2 mrg region_model model (&mgr); 3669 1.1 mrg ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4); 3670 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3); 3671 1.1 mrg ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4); 3672 1.1 mrg } 3673 1.1 mrg 3674 1.1 mrg /* If "a > 3" && "a <= 4", then "a == 4", 3675 1.1 mrg assuming a is of integral type. */ 3676 1.1 mrg { 3677 1.1.1.2 mrg region_model_manager mgr; 3678 1.1.1.2 mrg region_model model (&mgr); 3679 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3); 3680 1.1 mrg ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4); 3681 1.1 mrg ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4); 3682 1.1 mrg } 3683 1.1 mrg /* If "a > 3" && "a < 5", then "a == 4", 3684 1.1 mrg assuming a is of integral type. */ 3685 1.1 mrg { 3686 1.1.1.2 mrg region_model_manager mgr; 3687 1.1.1.2 mrg region_model model (&mgr); 3688 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3); 3689 1.1 mrg ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5); 3690 1.1 mrg ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4); 3691 1.1 mrg } 3692 1.1 mrg /* If "a >= 4" && "a < 5", then "a == 4", 3693 1.1 mrg assuming a is of integral type. */ 3694 1.1 mrg { 3695 1.1.1.2 mrg region_model_manager mgr; 3696 1.1.1.2 mrg region_model model (&mgr); 3697 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_4); 3698 1.1 mrg ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5); 3699 1.1 mrg ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4); 3700 1.1 mrg } 3701 1.1 mrg /* If "a >= 4" && "a <= 4", then "a == 4". */ 3702 1.1 mrg { 3703 1.1.1.2 mrg region_model_manager mgr; 3704 1.1.1.2 mrg region_model model (&mgr); 3705 1.1 mrg ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_4); 3706 1.1 mrg ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4); 3707 1.1 mrg ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4); 3708 1.1 mrg } 3709 1.1 mrg } 3710 1.1 mrg 3711 1.1 mrg /* As above, but for floating-point: 3712 1.1 mrg if "f > 3" && "f <= 4" we don't know that f == 4. */ 3713 1.1 mrg { 3714 1.1 mrg tree f = build_global_decl ("f", double_type_node); 3715 1.1 mrg tree float_3 = build_real_from_int_cst (double_type_node, int_3); 3716 1.1 mrg tree float_4 = build_real_from_int_cst (double_type_node, int_4); 3717 1.1 mrg 3718 1.1.1.2 mrg region_model_manager mgr; 3719 1.1.1.2 mrg region_model model (&mgr); 3720 1.1 mrg ADD_SAT_CONSTRAINT (model, f, GT_EXPR, float_3); 3721 1.1 mrg ADD_SAT_CONSTRAINT (model, f, LE_EXPR, float_4); 3722 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, float_4); 3723 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, int_4); 3724 1.1 mrg } 3725 1.1.1.2 mrg 3726 1.1.1.2 mrg /* "a > 3 && a <= 3" should be impossible. */ 3727 1.1.1.2 mrg { 3728 1.1.1.2 mrg region_model_manager mgr; 3729 1.1.1.2 mrg region_model model (&mgr); 3730 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3); 3731 1.1.1.2 mrg ADD_UNSAT_CONSTRAINT (model, a, LE_EXPR, int_3); 3732 1.1.1.2 mrg } 3733 1.1.1.2 mrg 3734 1.1.1.2 mrg /* "(a + 1) > 3 && a < 3" should be impossible. */ 3735 1.1.1.2 mrg { 3736 1.1.1.2 mrg region_model_manager mgr; 3737 1.1.1.2 mrg { 3738 1.1.1.2 mrg region_model model (&mgr); 3739 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a_plus_one, GT_EXPR, int_3); 3740 1.1.1.2 mrg ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_3); 3741 1.1.1.2 mrg } 3742 1.1.1.2 mrg { 3743 1.1.1.2 mrg region_model model (&mgr); 3744 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_3); 3745 1.1.1.2 mrg ADD_UNSAT_CONSTRAINT (model, a_plus_one, GT_EXPR, int_3); 3746 1.1.1.2 mrg } 3747 1.1.1.2 mrg } 3748 1.1.1.2 mrg 3749 1.1.1.2 mrg /* "3 < a < 4" should be impossible for integer a. */ 3750 1.1.1.2 mrg { 3751 1.1.1.2 mrg region_model_manager mgr; 3752 1.1.1.2 mrg { 3753 1.1.1.2 mrg region_model model (&mgr); 3754 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a); 3755 1.1.1.2 mrg ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4); 3756 1.1.1.2 mrg } 3757 1.1.1.2 mrg { 3758 1.1.1.2 mrg region_model model (&mgr); 3759 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, int_1, LT_EXPR, a); 3760 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a); 3761 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5); 3762 1.1.1.2 mrg ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4); 3763 1.1.1.2 mrg } 3764 1.1.1.2 mrg { 3765 1.1.1.2 mrg region_model model (&mgr); 3766 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, int_1, LT_EXPR, a); 3767 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5); 3768 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a); 3769 1.1.1.2 mrg ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4); 3770 1.1.1.2 mrg } 3771 1.1.1.2 mrg { 3772 1.1.1.2 mrg region_model model (&mgr); 3773 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_4); 3774 1.1.1.2 mrg ADD_UNSAT_CONSTRAINT (model, int_3, LT_EXPR, a); 3775 1.1.1.2 mrg } 3776 1.1.1.2 mrg { 3777 1.1.1.2 mrg region_model model (&mgr); 3778 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3); 3779 1.1.1.2 mrg ADD_UNSAT_CONSTRAINT (model, int_4, GT_EXPR, a); 3780 1.1.1.2 mrg } 3781 1.1.1.2 mrg { 3782 1.1.1.2 mrg region_model model (&mgr); 3783 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, int_4, GT_EXPR, a); 3784 1.1.1.2 mrg ADD_UNSAT_CONSTRAINT (model, a, GT_EXPR, int_3); 3785 1.1.1.2 mrg } 3786 1.1.1.2 mrg } 3787 1.1 mrg } 3788 1.1 mrg 3789 1.1 mrg /* Verify various lower-level implementation details about 3790 1.1 mrg constraint_manager. */ 3791 1.1 mrg 3792 1.1 mrg static void 3793 1.1 mrg test_constraint_impl () 3794 1.1 mrg { 3795 1.1 mrg tree int_42 = build_int_cst (integer_type_node, 42); 3796 1.1 mrg tree int_0 = build_int_cst (integer_type_node, 0); 3797 1.1 mrg 3798 1.1 mrg tree x = build_global_decl ("x", integer_type_node); 3799 1.1 mrg tree y = build_global_decl ("y", integer_type_node); 3800 1.1 mrg tree z = build_global_decl ("z", integer_type_node); 3801 1.1 mrg 3802 1.1 mrg /* x == y. */ 3803 1.1 mrg { 3804 1.1.1.2 mrg region_model_manager mgr; 3805 1.1.1.2 mrg region_model model (&mgr); 3806 1.1 mrg 3807 1.1 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y); 3808 1.1 mrg 3809 1.1 mrg /* Assert various things about the insides of model. */ 3810 1.1 mrg constraint_manager *cm = model.get_constraints (); 3811 1.1 mrg ASSERT_EQ (cm->m_constraints.length (), 0); 3812 1.1 mrg ASSERT_EQ (cm->m_equiv_classes.length (), 1); 3813 1.1 mrg } 3814 1.1 mrg 3815 1.1 mrg /* y <= z; x == y. */ 3816 1.1 mrg { 3817 1.1.1.2 mrg region_model_manager mgr; 3818 1.1.1.2 mrg region_model model (&mgr); 3819 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y); 3820 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z); 3821 1.1 mrg 3822 1.1 mrg ADD_SAT_CONSTRAINT (model, y, GE_EXPR, z); 3823 1.1 mrg ASSERT_CONDITION_TRUE (model, y, GE_EXPR, z); 3824 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z); 3825 1.1 mrg 3826 1.1 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y); 3827 1.1 mrg 3828 1.1 mrg /* Assert various things about the insides of model. */ 3829 1.1 mrg constraint_manager *cm = model.get_constraints (); 3830 1.1 mrg ASSERT_EQ (cm->m_constraints.length (), 1); 3831 1.1 mrg ASSERT_EQ (cm->m_equiv_classes.length (), 2); 3832 1.1 mrg 3833 1.1 mrg /* Ensure that we merged the constraints. */ 3834 1.1 mrg ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z); 3835 1.1 mrg } 3836 1.1 mrg 3837 1.1 mrg /* y <= z; y == x. */ 3838 1.1 mrg { 3839 1.1.1.2 mrg region_model_manager mgr; 3840 1.1.1.2 mrg region_model model (&mgr); 3841 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y); 3842 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z); 3843 1.1 mrg 3844 1.1 mrg ADD_SAT_CONSTRAINT (model, y, GE_EXPR, z); 3845 1.1 mrg ASSERT_CONDITION_TRUE (model, y, GE_EXPR, z); 3846 1.1 mrg ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z); 3847 1.1 mrg 3848 1.1 mrg ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, x); 3849 1.1 mrg 3850 1.1 mrg /* Assert various things about the insides of model. */ 3851 1.1 mrg constraint_manager *cm = model.get_constraints (); 3852 1.1 mrg ASSERT_EQ (cm->m_constraints.length (), 1); 3853 1.1 mrg ASSERT_EQ (cm->m_equiv_classes.length (), 2); 3854 1.1 mrg 3855 1.1 mrg /* Ensure that we merged the constraints. */ 3856 1.1 mrg ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z); 3857 1.1 mrg } 3858 1.1 mrg 3859 1.1 mrg /* x == 0, then x != 42. */ 3860 1.1 mrg { 3861 1.1.1.2 mrg region_model_manager mgr; 3862 1.1.1.2 mrg region_model model (&mgr); 3863 1.1 mrg 3864 1.1 mrg ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0); 3865 1.1 mrg ADD_SAT_CONSTRAINT (model, x, NE_EXPR, int_42); 3866 1.1 mrg 3867 1.1 mrg /* Assert various things about the insides of model. */ 3868 1.1 mrg constraint_manager *cm = model.get_constraints (); 3869 1.1.1.2 mrg ASSERT_EQ (cm->m_constraints.length (), 0); 3870 1.1.1.2 mrg ASSERT_EQ (cm->m_equiv_classes.length (), 1); 3871 1.1 mrg } 3872 1.1 mrg 3873 1.1 mrg // TODO: selftest for merging ecs "in the middle" 3874 1.1 mrg // where a non-final one gets overwritten 3875 1.1 mrg 3876 1.1 mrg // TODO: selftest where there are pre-existing constraints 3877 1.1 mrg } 3878 1.1 mrg 3879 1.1 mrg /* Check that operator== and hashing works as expected for the 3880 1.1 mrg various types. */ 3881 1.1 mrg 3882 1.1 mrg static void 3883 1.1 mrg test_equality () 3884 1.1 mrg { 3885 1.1 mrg tree x = build_global_decl ("x", integer_type_node); 3886 1.1 mrg tree y = build_global_decl ("y", integer_type_node); 3887 1.1 mrg 3888 1.1 mrg { 3889 1.1.1.2 mrg region_model_manager mgr; 3890 1.1.1.2 mrg region_model model0 (&mgr); 3891 1.1.1.2 mrg region_model model1 (&mgr); 3892 1.1 mrg 3893 1.1 mrg constraint_manager *cm0 = model0.get_constraints (); 3894 1.1 mrg constraint_manager *cm1 = model1.get_constraints (); 3895 1.1 mrg 3896 1.1 mrg ASSERT_EQ (cm0->hash (), cm1->hash ()); 3897 1.1 mrg ASSERT_EQ (*cm0, *cm1); 3898 1.1 mrg 3899 1.1 mrg ASSERT_EQ (model0.hash (), model1.hash ()); 3900 1.1 mrg ASSERT_EQ (model0, model1); 3901 1.1 mrg 3902 1.1 mrg ADD_SAT_CONSTRAINT (model1, x, EQ_EXPR, y); 3903 1.1 mrg ASSERT_NE (cm0->hash (), cm1->hash ()); 3904 1.1 mrg ASSERT_NE (*cm0, *cm1); 3905 1.1 mrg 3906 1.1 mrg ASSERT_NE (model0.hash (), model1.hash ()); 3907 1.1 mrg ASSERT_NE (model0, model1); 3908 1.1 mrg 3909 1.1.1.2 mrg region_model model2 (&mgr); 3910 1.1 mrg constraint_manager *cm2 = model2.get_constraints (); 3911 1.1 mrg /* Make the same change to cm2. */ 3912 1.1 mrg ADD_SAT_CONSTRAINT (model2, x, EQ_EXPR, y); 3913 1.1 mrg ASSERT_EQ (cm1->hash (), cm2->hash ()); 3914 1.1 mrg ASSERT_EQ (*cm1, *cm2); 3915 1.1 mrg 3916 1.1 mrg ASSERT_EQ (model1.hash (), model2.hash ()); 3917 1.1 mrg ASSERT_EQ (model1, model2); 3918 1.1 mrg } 3919 1.1 mrg } 3920 1.1 mrg 3921 1.1 mrg /* Verify tracking inequality of a variable against many constants. */ 3922 1.1 mrg 3923 1.1 mrg static void 3924 1.1 mrg test_many_constants () 3925 1.1 mrg { 3926 1.1.1.2 mrg program_point point (program_point::origin ()); 3927 1.1 mrg tree a = build_global_decl ("a", integer_type_node); 3928 1.1 mrg 3929 1.1.1.2 mrg region_model_manager mgr; 3930 1.1.1.2 mrg region_model model (&mgr); 3931 1.1 mrg auto_vec<tree> constants; 3932 1.1 mrg for (int i = 0; i < 20; i++) 3933 1.1 mrg { 3934 1.1 mrg tree constant = build_int_cst (integer_type_node, i); 3935 1.1 mrg constants.safe_push (constant); 3936 1.1 mrg ADD_SAT_CONSTRAINT (model, a, NE_EXPR, constant); 3937 1.1 mrg 3938 1.1 mrg /* Merge, and check the result. */ 3939 1.1 mrg region_model other (model); 3940 1.1 mrg 3941 1.1.1.2 mrg region_model merged (&mgr); 3942 1.1.1.2 mrg ASSERT_TRUE (model.can_merge_with_p (other, point, &merged)); 3943 1.1.1.2 mrg model.canonicalize (); 3944 1.1.1.2 mrg merged.canonicalize (); 3945 1.1 mrg ASSERT_EQ (model, merged); 3946 1.1 mrg 3947 1.1 mrg for (int j = 0; j <= i; j++) 3948 1.1 mrg ASSERT_CONDITION_TRUE (model, a, NE_EXPR, constants[j]); 3949 1.1 mrg } 3950 1.1 mrg } 3951 1.1 mrg 3952 1.1.1.2 mrg /* Verify that purging state relating to a variable doesn't leave stray 3953 1.1.1.2 mrg equivalence classes (after canonicalization). */ 3954 1.1.1.2 mrg 3955 1.1.1.2 mrg static void 3956 1.1.1.2 mrg test_purging (void) 3957 1.1.1.2 mrg { 3958 1.1.1.2 mrg tree int_0 = build_int_cst (integer_type_node, 0); 3959 1.1.1.2 mrg tree a = build_global_decl ("a", integer_type_node); 3960 1.1.1.2 mrg tree b = build_global_decl ("b", integer_type_node); 3961 1.1.1.2 mrg 3962 1.1.1.2 mrg /* "a != 0". */ 3963 1.1.1.2 mrg { 3964 1.1.1.2 mrg region_model_manager mgr; 3965 1.1.1.2 mrg region_model model (&mgr); 3966 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0); 3967 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2); 3968 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1); 3969 1.1.1.2 mrg 3970 1.1.1.2 mrg /* Purge state for "a". */ 3971 1.1.1.2 mrg const svalue *sval_a = model.get_rvalue (a, NULL); 3972 1.1.1.2 mrg model.purge_state_involving (sval_a, NULL); 3973 1.1.1.2 mrg model.canonicalize (); 3974 1.1.1.2 mrg /* We should have an empty constraint_manager. */ 3975 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0); 3976 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0); 3977 1.1.1.2 mrg } 3978 1.1.1.2 mrg 3979 1.1.1.2 mrg /* "a != 0" && "b != 0". */ 3980 1.1.1.2 mrg { 3981 1.1.1.2 mrg region_model_manager mgr; 3982 1.1.1.2 mrg region_model model (&mgr); 3983 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0); 3984 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, b, NE_EXPR, int_0); 3985 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 3); 3986 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 2); 3987 1.1.1.2 mrg 3988 1.1.1.2 mrg /* Purge state for "a". */ 3989 1.1.1.2 mrg const svalue *sval_a = model.get_rvalue (a, NULL); 3990 1.1.1.2 mrg model.purge_state_involving (sval_a, NULL); 3991 1.1.1.2 mrg model.canonicalize (); 3992 1.1.1.2 mrg /* We should just have the constraint/ECs involving b != 0. */ 3993 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2); 3994 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1); 3995 1.1.1.2 mrg ASSERT_CONDITION_TRUE (model, b, NE_EXPR, int_0); 3996 1.1.1.2 mrg } 3997 1.1.1.2 mrg 3998 1.1.1.2 mrg /* "a != 0" && "b == 0". */ 3999 1.1.1.2 mrg { 4000 1.1.1.2 mrg region_model_manager mgr; 4001 1.1.1.2 mrg region_model model (&mgr); 4002 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0); 4003 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, b, EQ_EXPR, int_0); 4004 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2); 4005 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1); 4006 1.1.1.2 mrg 4007 1.1.1.2 mrg /* Purge state for "a". */ 4008 1.1.1.2 mrg const svalue *sval_a = model.get_rvalue (a, NULL); 4009 1.1.1.2 mrg model.purge_state_involving (sval_a, NULL); 4010 1.1.1.2 mrg model.canonicalize (); 4011 1.1.1.2 mrg /* We should just have the EC involving b == 0. */ 4012 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1); 4013 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0); 4014 1.1.1.2 mrg ASSERT_CONDITION_TRUE (model, b, EQ_EXPR, int_0); 4015 1.1.1.2 mrg } 4016 1.1.1.2 mrg 4017 1.1.1.2 mrg /* "a == 0". */ 4018 1.1.1.2 mrg { 4019 1.1.1.2 mrg region_model_manager mgr; 4020 1.1.1.2 mrg region_model model (&mgr); 4021 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0); 4022 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1); 4023 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0); 4024 1.1.1.2 mrg 4025 1.1.1.2 mrg /* Purge state for "a". */ 4026 1.1.1.2 mrg const svalue *sval_a = model.get_rvalue (a, NULL); 4027 1.1.1.2 mrg model.purge_state_involving (sval_a, NULL); 4028 1.1.1.2 mrg model.canonicalize (); 4029 1.1.1.2 mrg /* We should have an empty constraint_manager. */ 4030 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0); 4031 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0); 4032 1.1.1.2 mrg } 4033 1.1.1.2 mrg 4034 1.1.1.2 mrg /* "a == 0" && "b != 0". */ 4035 1.1.1.2 mrg { 4036 1.1.1.2 mrg region_model_manager mgr; 4037 1.1.1.2 mrg region_model model (&mgr); 4038 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0); 4039 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, b, NE_EXPR, int_0); 4040 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2); 4041 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1); 4042 1.1.1.2 mrg 4043 1.1.1.2 mrg /* Purge state for "a". */ 4044 1.1.1.2 mrg const svalue *sval_a = model.get_rvalue (a, NULL); 4045 1.1.1.2 mrg model.purge_state_involving (sval_a, NULL); 4046 1.1.1.2 mrg model.canonicalize (); 4047 1.1.1.2 mrg /* We should just have the constraint/ECs involving b != 0. */ 4048 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2); 4049 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1); 4050 1.1.1.2 mrg ASSERT_CONDITION_TRUE (model, b, NE_EXPR, int_0); 4051 1.1.1.2 mrg } 4052 1.1.1.2 mrg 4053 1.1.1.2 mrg /* "a == 0" && "b == 0". */ 4054 1.1.1.2 mrg { 4055 1.1.1.2 mrg region_model_manager mgr; 4056 1.1.1.2 mrg region_model model (&mgr); 4057 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0); 4058 1.1.1.2 mrg ADD_SAT_CONSTRAINT (model, b, EQ_EXPR, int_0); 4059 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1); 4060 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0); 4061 1.1.1.2 mrg 4062 1.1.1.2 mrg /* Purge state for "a". */ 4063 1.1.1.2 mrg const svalue *sval_a = model.get_rvalue (a, NULL); 4064 1.1.1.2 mrg model.purge_state_involving (sval_a, NULL); 4065 1.1.1.2 mrg model.canonicalize (); 4066 1.1.1.2 mrg /* We should just have the EC involving b == 0. */ 4067 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1); 4068 1.1.1.2 mrg ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0); 4069 1.1.1.2 mrg ASSERT_CONDITION_TRUE (model, b, EQ_EXPR, int_0); 4070 1.1.1.2 mrg } 4071 1.1.1.2 mrg } 4072 1.1.1.2 mrg 4073 1.1.1.2 mrg /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */ 4074 1.1.1.2 mrg 4075 1.1.1.2 mrg static void 4076 1.1.1.2 mrg assert_dump_bounded_range_eq (const location &loc, 4077 1.1.1.2 mrg const bounded_range &range, 4078 1.1.1.2 mrg const char *expected) 4079 1.1.1.2 mrg { 4080 1.1.1.2 mrg auto_fix_quotes sentinel; 4081 1.1.1.2 mrg pretty_printer pp; 4082 1.1.1.2 mrg pp_format_decoder (&pp) = default_tree_printer; 4083 1.1.1.2 mrg range.dump_to_pp (&pp, false); 4084 1.1.1.2 mrg ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected); 4085 1.1.1.2 mrg } 4086 1.1.1.2 mrg 4087 1.1.1.2 mrg /* Assert that BR.dump (false) is EXPECTED. */ 4088 1.1.1.2 mrg 4089 1.1.1.2 mrg #define ASSERT_DUMP_BOUNDED_RANGE_EQ(BR, EXPECTED) \ 4090 1.1.1.2 mrg SELFTEST_BEGIN_STMT \ 4091 1.1.1.2 mrg assert_dump_bounded_range_eq ((SELFTEST_LOCATION), (BR), (EXPECTED)); \ 4092 1.1.1.2 mrg SELFTEST_END_STMT 4093 1.1.1.2 mrg 4094 1.1.1.2 mrg /* Verify that bounded_range works as expected. */ 4095 1.1.1.2 mrg 4096 1.1.1.2 mrg static void 4097 1.1.1.2 mrg test_bounded_range () 4098 1.1.1.2 mrg { 4099 1.1.1.2 mrg tree u8_0 = build_int_cst (unsigned_char_type_node, 0); 4100 1.1.1.2 mrg tree u8_1 = build_int_cst (unsigned_char_type_node, 1); 4101 1.1.1.2 mrg tree u8_64 = build_int_cst (unsigned_char_type_node, 64); 4102 1.1.1.2 mrg tree u8_128 = build_int_cst (unsigned_char_type_node, 128); 4103 1.1.1.2 mrg tree u8_255 = build_int_cst (unsigned_char_type_node, 255); 4104 1.1.1.2 mrg 4105 1.1.1.2 mrg tree s8_0 = build_int_cst (signed_char_type_node, 0); 4106 1.1.1.2 mrg tree s8_1 = build_int_cst (signed_char_type_node, 1); 4107 1.1.1.2 mrg tree s8_2 = build_int_cst (signed_char_type_node, 2); 4108 1.1.1.2 mrg 4109 1.1.1.2 mrg bounded_range br_u8_0 (u8_0, u8_0); 4110 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_0, "0"); 4111 1.1.1.2 mrg ASSERT_TRUE (br_u8_0.contains_p (u8_0)); 4112 1.1.1.2 mrg ASSERT_FALSE (br_u8_0.contains_p (u8_1)); 4113 1.1.1.2 mrg ASSERT_TRUE (br_u8_0.contains_p (s8_0)); 4114 1.1.1.2 mrg ASSERT_FALSE (br_u8_0.contains_p (s8_1)); 4115 1.1.1.2 mrg 4116 1.1.1.2 mrg bounded_range br_u8_0_1 (u8_0, u8_1); 4117 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_0_1, "[0, 1]"); 4118 1.1.1.2 mrg 4119 1.1.1.2 mrg bounded_range tmp (NULL_TREE, NULL_TREE); 4120 1.1.1.2 mrg ASSERT_TRUE (br_u8_0.intersects_p (br_u8_0_1, &tmp)); 4121 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGE_EQ (tmp, "0"); 4122 1.1.1.2 mrg 4123 1.1.1.2 mrg bounded_range br_u8_64_128 (u8_64, u8_128); 4124 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_64_128, "[64, 128]"); 4125 1.1.1.2 mrg 4126 1.1.1.2 mrg ASSERT_FALSE (br_u8_0.intersects_p (br_u8_64_128, NULL)); 4127 1.1.1.2 mrg ASSERT_FALSE (br_u8_64_128.intersects_p (br_u8_0, NULL)); 4128 1.1.1.2 mrg 4129 1.1.1.2 mrg bounded_range br_u8_128_255 (u8_128, u8_255); 4130 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_128_255, "[128, 255]"); 4131 1.1.1.2 mrg ASSERT_TRUE (br_u8_128_255.intersects_p (br_u8_64_128, &tmp)); 4132 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGE_EQ (tmp, "128"); 4133 1.1.1.2 mrg 4134 1.1.1.2 mrg bounded_range br_s8_2 (s8_2, s8_2); 4135 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGE_EQ (br_s8_2, "2"); 4136 1.1.1.2 mrg bounded_range br_s8_2_u8_255 (s8_2, u8_255); 4137 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGE_EQ (br_s8_2_u8_255, "[2, 255]"); 4138 1.1.1.2 mrg } 4139 1.1.1.2 mrg 4140 1.1.1.2 mrg /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */ 4141 1.1.1.2 mrg 4142 1.1.1.2 mrg static void 4143 1.1.1.2 mrg assert_dump_bounded_ranges_eq (const location &loc, 4144 1.1.1.2 mrg const bounded_ranges *ranges, 4145 1.1.1.2 mrg const char *expected) 4146 1.1.1.2 mrg { 4147 1.1.1.2 mrg auto_fix_quotes sentinel; 4148 1.1.1.2 mrg pretty_printer pp; 4149 1.1.1.2 mrg pp_format_decoder (&pp) = default_tree_printer; 4150 1.1.1.2 mrg ranges->dump_to_pp (&pp, false); 4151 1.1.1.2 mrg ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected); 4152 1.1.1.2 mrg } 4153 1.1.1.2 mrg 4154 1.1.1.2 mrg /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */ 4155 1.1.1.2 mrg 4156 1.1.1.2 mrg static void 4157 1.1.1.2 mrg assert_dump_bounded_ranges_eq (const location &loc, 4158 1.1.1.2 mrg const bounded_ranges &ranges, 4159 1.1.1.2 mrg const char *expected) 4160 1.1.1.2 mrg { 4161 1.1.1.2 mrg auto_fix_quotes sentinel; 4162 1.1.1.2 mrg pretty_printer pp; 4163 1.1.1.2 mrg pp_format_decoder (&pp) = default_tree_printer; 4164 1.1.1.2 mrg ranges.dump_to_pp (&pp, false); 4165 1.1.1.2 mrg ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected); 4166 1.1.1.2 mrg } 4167 1.1.1.2 mrg 4168 1.1.1.2 mrg /* Assert that BRS.dump (false) is EXPECTED. */ 4169 1.1.1.2 mrg 4170 1.1.1.2 mrg #define ASSERT_DUMP_BOUNDED_RANGES_EQ(BRS, EXPECTED) \ 4171 1.1.1.2 mrg SELFTEST_BEGIN_STMT \ 4172 1.1.1.2 mrg assert_dump_bounded_ranges_eq ((SELFTEST_LOCATION), (BRS), (EXPECTED)); \ 4173 1.1.1.2 mrg SELFTEST_END_STMT 4174 1.1.1.2 mrg 4175 1.1.1.2 mrg /* Verify that the bounded_ranges class works as expected. */ 4176 1.1.1.2 mrg 4177 1.1.1.2 mrg static void 4178 1.1.1.2 mrg test_bounded_ranges () 4179 1.1.1.2 mrg { 4180 1.1.1.2 mrg bounded_ranges_manager mgr; 4181 1.1.1.2 mrg 4182 1.1.1.2 mrg tree ch0 = build_int_cst (unsigned_char_type_node, 0); 4183 1.1.1.2 mrg tree ch1 = build_int_cst (unsigned_char_type_node, 1); 4184 1.1.1.2 mrg tree ch2 = build_int_cst (unsigned_char_type_node, 2); 4185 1.1.1.2 mrg tree ch3 = build_int_cst (unsigned_char_type_node, 3); 4186 1.1.1.2 mrg tree ch128 = build_int_cst (unsigned_char_type_node, 128); 4187 1.1.1.2 mrg tree ch129 = build_int_cst (unsigned_char_type_node, 129); 4188 1.1.1.2 mrg tree ch254 = build_int_cst (unsigned_char_type_node, 254); 4189 1.1.1.2 mrg tree ch255 = build_int_cst (unsigned_char_type_node, 255); 4190 1.1.1.2 mrg 4191 1.1.1.2 mrg const bounded_ranges *empty = mgr.get_or_create_empty (); 4192 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (empty, "{}"); 4193 1.1.1.2 mrg 4194 1.1.1.2 mrg const bounded_ranges *point0 = mgr.get_or_create_point (ch0); 4195 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (point0, "{0}"); 4196 1.1.1.2 mrg 4197 1.1.1.2 mrg const bounded_ranges *point1 = mgr.get_or_create_point (ch1); 4198 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (point1, "{1}"); 4199 1.1.1.2 mrg 4200 1.1.1.2 mrg const bounded_ranges *point2 = mgr.get_or_create_point (ch2); 4201 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (point2, "{2}"); 4202 1.1.1.2 mrg 4203 1.1.1.2 mrg const bounded_ranges *range0_128 = mgr.get_or_create_range (ch0, ch128); 4204 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (range0_128, "{[0, 128]}"); 4205 1.1.1.2 mrg 4206 1.1.1.2 mrg const bounded_ranges *range0_255 = mgr.get_or_create_range (ch0, ch255); 4207 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (range0_255, "{[0, 255]}"); 4208 1.1.1.2 mrg 4209 1.1.1.2 mrg ASSERT_FALSE (empty->contain_p (ch0)); 4210 1.1.1.2 mrg ASSERT_FALSE (empty->contain_p (ch1)); 4211 1.1.1.2 mrg ASSERT_FALSE (empty->contain_p (ch255)); 4212 1.1.1.2 mrg 4213 1.1.1.2 mrg ASSERT_TRUE (point0->contain_p (ch0)); 4214 1.1.1.2 mrg ASSERT_FALSE (point0->contain_p (ch1)); 4215 1.1.1.2 mrg ASSERT_FALSE (point0->contain_p (ch255)); 4216 1.1.1.2 mrg 4217 1.1.1.2 mrg ASSERT_FALSE (point1->contain_p (ch0)); 4218 1.1.1.2 mrg ASSERT_TRUE (point1->contain_p (ch1)); 4219 1.1.1.2 mrg ASSERT_FALSE (point0->contain_p (ch255)); 4220 1.1.1.2 mrg 4221 1.1.1.2 mrg ASSERT_TRUE (range0_128->contain_p (ch0)); 4222 1.1.1.2 mrg ASSERT_TRUE (range0_128->contain_p (ch1)); 4223 1.1.1.2 mrg ASSERT_TRUE (range0_128->contain_p (ch128)); 4224 1.1.1.2 mrg ASSERT_FALSE (range0_128->contain_p (ch129)); 4225 1.1.1.2 mrg ASSERT_FALSE (range0_128->contain_p (ch254)); 4226 1.1.1.2 mrg ASSERT_FALSE (range0_128->contain_p (ch255)); 4227 1.1.1.2 mrg 4228 1.1.1.2 mrg const bounded_ranges *inv0_128 4229 1.1.1.2 mrg = mgr.get_or_create_inverse (range0_128, unsigned_char_type_node); 4230 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (inv0_128, "{[129, 255]}"); 4231 1.1.1.2 mrg 4232 1.1.1.2 mrg const bounded_ranges *range128_129 = mgr.get_or_create_range (ch128, ch129); 4233 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (range128_129, "{[128, 129]}"); 4234 1.1.1.2 mrg 4235 1.1.1.2 mrg const bounded_ranges *inv128_129 4236 1.1.1.2 mrg = mgr.get_or_create_inverse (range128_129, unsigned_char_type_node); 4237 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (inv128_129, "{[0, 127], [130, 255]}"); 4238 1.1.1.2 mrg 4239 1.1.1.2 mrg /* Intersection. */ 4240 1.1.1.2 mrg { 4241 1.1.1.2 mrg /* Intersection of disjoint ranges should be empty set. */ 4242 1.1.1.2 mrg const bounded_ranges *intersect0_1 4243 1.1.1.2 mrg = mgr.get_or_create_intersection (point0, point1); 4244 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (intersect0_1, "{}"); 4245 1.1.1.2 mrg } 4246 1.1.1.2 mrg 4247 1.1.1.2 mrg /* Various tests of "union of ranges". */ 4248 1.1.1.2 mrg { 4249 1.1.1.2 mrg { 4250 1.1.1.2 mrg /* Touching points should be merged into a range. */ 4251 1.1.1.2 mrg auto_vec <const bounded_ranges *> v; 4252 1.1.1.2 mrg v.safe_push (point0); 4253 1.1.1.2 mrg v.safe_push (point1); 4254 1.1.1.2 mrg const bounded_ranges *union_0_and_1 = mgr.get_or_create_union (v); 4255 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (union_0_and_1, "{[0, 1]}"); 4256 1.1.1.2 mrg } 4257 1.1.1.2 mrg 4258 1.1.1.2 mrg { 4259 1.1.1.2 mrg /* Overlapping and out-of-order. */ 4260 1.1.1.2 mrg auto_vec <const bounded_ranges *> v; 4261 1.1.1.2 mrg v.safe_push (inv0_128); // {[129, 255]} 4262 1.1.1.2 mrg v.safe_push (range128_129); 4263 1.1.1.2 mrg const bounded_ranges *union_129_255_and_128_129 4264 1.1.1.2 mrg = mgr.get_or_create_union (v); 4265 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (union_129_255_and_128_129, "{[128, 255]}"); 4266 1.1.1.2 mrg } 4267 1.1.1.2 mrg 4268 1.1.1.2 mrg { 4269 1.1.1.2 mrg /* Union of R and inverse(R) should be full range of type. */ 4270 1.1.1.2 mrg auto_vec <const bounded_ranges *> v; 4271 1.1.1.2 mrg v.safe_push (range128_129); 4272 1.1.1.2 mrg v.safe_push (inv128_129); 4273 1.1.1.2 mrg const bounded_ranges *union_ = mgr.get_or_create_union (v); 4274 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (union_, "{[0, 255]}"); 4275 1.1.1.2 mrg } 4276 1.1.1.2 mrg 4277 1.1.1.2 mrg /* Union with an endpoint. */ 4278 1.1.1.2 mrg { 4279 1.1.1.2 mrg const bounded_ranges *range2_to_255 4280 1.1.1.2 mrg = mgr.get_or_create_range (ch2, ch255); 4281 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (range2_to_255, "{[2, 255]}"); 4282 1.1.1.2 mrg auto_vec <const bounded_ranges *> v; 4283 1.1.1.2 mrg v.safe_push (point0); 4284 1.1.1.2 mrg v.safe_push (point2); 4285 1.1.1.2 mrg v.safe_push (range2_to_255); 4286 1.1.1.2 mrg const bounded_ranges *union_ = mgr.get_or_create_union (v); 4287 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (union_, "{0, [2, 255]}"); 4288 1.1.1.2 mrg } 4289 1.1.1.2 mrg 4290 1.1.1.2 mrg /* Construct from vector of bounded_range. */ 4291 1.1.1.2 mrg { 4292 1.1.1.2 mrg auto_vec<bounded_range> v; 4293 1.1.1.2 mrg v.safe_push (bounded_range (ch2, ch2)); 4294 1.1.1.2 mrg v.safe_push (bounded_range (ch0, ch0)); 4295 1.1.1.2 mrg v.safe_push (bounded_range (ch2, ch255)); 4296 1.1.1.2 mrg bounded_ranges br (v); 4297 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (&br, "{0, [2, 255]}"); 4298 1.1.1.2 mrg } 4299 1.1.1.2 mrg } 4300 1.1.1.2 mrg 4301 1.1.1.2 mrg /* Various tests of "inverse". */ 4302 1.1.1.2 mrg { 4303 1.1.1.2 mrg { 4304 1.1.1.2 mrg const bounded_ranges *range_1_to_3 = mgr.get_or_create_range (ch1, ch3); 4305 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (range_1_to_3, "{[1, 3]}"); 4306 1.1.1.2 mrg const bounded_ranges *inv 4307 1.1.1.2 mrg = mgr.get_or_create_inverse (range_1_to_3, unsigned_char_type_node); 4308 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{0, [4, 255]}"); 4309 1.1.1.2 mrg } 4310 1.1.1.2 mrg { 4311 1.1.1.2 mrg const bounded_ranges *range_1_to_255 4312 1.1.1.2 mrg = mgr.get_or_create_range (ch1, ch255); 4313 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (range_1_to_255, "{[1, 255]}"); 4314 1.1.1.2 mrg const bounded_ranges *inv 4315 1.1.1.2 mrg = mgr.get_or_create_inverse (range_1_to_255, unsigned_char_type_node); 4316 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{0}"); 4317 1.1.1.2 mrg } 4318 1.1.1.2 mrg { 4319 1.1.1.2 mrg const bounded_ranges *range_0_to_254 4320 1.1.1.2 mrg = mgr.get_or_create_range (ch0, ch254); 4321 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (range_0_to_254, "{[0, 254]}"); 4322 1.1.1.2 mrg const bounded_ranges *inv 4323 1.1.1.2 mrg = mgr.get_or_create_inverse (range_0_to_254, unsigned_char_type_node); 4324 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{255}"); 4325 1.1.1.2 mrg } 4326 1.1.1.2 mrg } 4327 1.1.1.2 mrg 4328 1.1.1.2 mrg /* "case 'a'-'z': case 'A-Z':" vs "default:", for ASCII. */ 4329 1.1.1.2 mrg { 4330 1.1.1.2 mrg tree ch65 = build_int_cst (unsigned_char_type_node, 65); 4331 1.1.1.2 mrg tree ch90 = build_int_cst (unsigned_char_type_node, 90); 4332 1.1.1.2 mrg 4333 1.1.1.2 mrg tree ch97 = build_int_cst (unsigned_char_type_node, 97); 4334 1.1.1.2 mrg tree ch122 = build_int_cst (unsigned_char_type_node, 122); 4335 1.1.1.2 mrg 4336 1.1.1.2 mrg const bounded_ranges *A_to_Z = mgr.get_or_create_range (ch65, ch90); 4337 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (A_to_Z, "{[65, 90]}"); 4338 1.1.1.2 mrg const bounded_ranges *a_to_z = mgr.get_or_create_range (ch97, ch122); 4339 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (a_to_z, "{[97, 122]}"); 4340 1.1.1.2 mrg auto_vec <const bounded_ranges *> v; 4341 1.1.1.2 mrg v.safe_push (A_to_Z); 4342 1.1.1.2 mrg v.safe_push (a_to_z); 4343 1.1.1.2 mrg const bounded_ranges *label_ranges = mgr.get_or_create_union (v); 4344 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (label_ranges, "{[65, 90], [97, 122]}"); 4345 1.1.1.2 mrg const bounded_ranges *default_ranges 4346 1.1.1.2 mrg = mgr.get_or_create_inverse (label_ranges, unsigned_char_type_node); 4347 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (default_ranges, 4348 1.1.1.2 mrg "{[0, 64], [91, 96], [123, 255]}"); 4349 1.1.1.2 mrg } 4350 1.1.1.2 mrg 4351 1.1.1.2 mrg /* Verify ranges from ops. */ 4352 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (EQ_EXPR, ch128), 4353 1.1.1.2 mrg "{128}"); 4354 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch128), 4355 1.1.1.2 mrg "{[0, 127], [129, 255]}"); 4356 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LT_EXPR, ch128), 4357 1.1.1.2 mrg "{[0, 127]}"); 4358 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LE_EXPR, ch128), 4359 1.1.1.2 mrg "{[0, 128]}"); 4360 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GE_EXPR, ch128), 4361 1.1.1.2 mrg "{[128, 255]}"); 4362 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GT_EXPR, ch128), 4363 1.1.1.2 mrg "{[129, 255]}"); 4364 1.1.1.2 mrg /* Ops at endpoints of type ranges. */ 4365 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LE_EXPR, ch0), 4366 1.1.1.2 mrg "{0}"); 4367 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LT_EXPR, ch0), 4368 1.1.1.2 mrg "{}"); 4369 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch0), 4370 1.1.1.2 mrg "{[1, 255]}"); 4371 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GE_EXPR, ch255), 4372 1.1.1.2 mrg "{255}"); 4373 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GT_EXPR, ch255), 4374 1.1.1.2 mrg "{}"); 4375 1.1.1.2 mrg ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch255), 4376 1.1.1.2 mrg "{[0, 254]}"); 4377 1.1.1.2 mrg 4378 1.1.1.2 mrg /* Verify that instances are consolidated by mgr. */ 4379 1.1.1.2 mrg ASSERT_EQ (mgr.get_or_create_point (ch0), 4380 1.1.1.2 mrg mgr.get_or_create_point (ch0)); 4381 1.1.1.2 mrg ASSERT_NE (mgr.get_or_create_point (ch0), 4382 1.1.1.2 mrg mgr.get_or_create_point (ch1)); 4383 1.1.1.2 mrg } 4384 1.1.1.2 mrg 4385 1.1 mrg /* Run the selftests in this file, temporarily overriding 4386 1.1 mrg flag_analyzer_transitivity with TRANSITIVITY. */ 4387 1.1 mrg 4388 1.1 mrg static void 4389 1.1 mrg run_constraint_manager_tests (bool transitivity) 4390 1.1 mrg { 4391 1.1 mrg int saved_flag_analyzer_transitivity = flag_analyzer_transitivity; 4392 1.1 mrg flag_analyzer_transitivity = transitivity; 4393 1.1 mrg 4394 1.1.1.2 mrg test_range (); 4395 1.1 mrg test_constraint_conditions (); 4396 1.1 mrg if (flag_analyzer_transitivity) 4397 1.1 mrg { 4398 1.1 mrg /* These selftests assume transitivity. */ 4399 1.1 mrg test_transitivity (); 4400 1.1 mrg } 4401 1.1.1.2 mrg test_constant_comparisons (); 4402 1.1 mrg test_constraint_impl (); 4403 1.1 mrg test_equality (); 4404 1.1 mrg test_many_constants (); 4405 1.1.1.2 mrg test_purging (); 4406 1.1.1.2 mrg test_bounded_range (); 4407 1.1.1.2 mrg test_bounded_ranges (); 4408 1.1 mrg 4409 1.1 mrg flag_analyzer_transitivity = saved_flag_analyzer_transitivity; 4410 1.1 mrg } 4411 1.1 mrg 4412 1.1 mrg /* Run all of the selftests within this file. */ 4413 1.1 mrg 4414 1.1 mrg void 4415 1.1 mrg analyzer_constraint_manager_cc_tests () 4416 1.1 mrg { 4417 1.1 mrg /* Run the tests twice: with and without transitivity. */ 4418 1.1 mrg run_constraint_manager_tests (true); 4419 1.1 mrg run_constraint_manager_tests (false); 4420 1.1 mrg } 4421 1.1 mrg 4422 1.1 mrg } // namespace selftest 4423 1.1 mrg 4424 1.1 mrg #endif /* CHECKING_P */ 4425 1.1 mrg 4426 1.1 mrg } // namespace ana 4427 1.1 mrg 4428 1.1 mrg #endif /* #if ENABLE_ANALYZER */ 4429