From a53da184d59f3b6064430306f275f322ed60ad10 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 16 Jul 2020 14:43:38 -0400 Subject: [PATCH 308/315] FIXME: offset_region2 folding; avoid state-bloat due to non_heap on ADDR_EXPR during optimization --- gcc/analyzer/region-model2.cc | 12 ++++++++++++ gcc/analyzer/sm-malloc.cc | 11 ++++++++--- .../gcc.dg/analyzer/torture/loop-inc-ptr-3.c | 18 ++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc index a6aac080615..924b74b1d56 100644 --- a/gcc/analyzer/region-model2.cc +++ b/gcc/analyzer/region-model2.cc @@ -3924,6 +3924,18 @@ region_model2_manager::get_offset_region (const region2 *parent, if (zerop (cst_offset)) return get_cast_region (parent, type); + /* Fold OFFSET_REGION(OFFSET_REGION(REG, X), Y) + to OFFSET_REGION(REG, (X + Y)). */ + if (const offset_region2 *parent_offset_reg + = parent->dyn_cast_offset_region2 ()) + { + const svalue2 *sval_x = parent_offset_reg->get_byte_offset (); + const svalue2 *sval_sum + = get_or_create_binop (byte_offset->get_type (), + PLUS_EXPR, sval_x, byte_offset); + return get_offset_region (parent->get_parent_region (), type, sval_sum); + } + // FIXME: should only alloc_region_id if consolidation fails region2 *offset_reg = new offset_region2 (alloc_region_id (), parent, type, byte_offset); diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index 417fa54ebc3..cbc619733f6 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -745,6 +745,11 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt, if (any_pointer_p (lhs)) on_zero_assignment (sm_ctxt, node, stmt,lhs); + /* If we have "LHS = &EXPR;" and EXPR is something other than a MEM_REF, + transition LHS from start to non_heap. + Doing it for ADDR_EXPR(MEM_REF()) is likely wrong, and can lead to + unbounded chains of unmergeable sm-state on pointer arithmetic in loops + when optimization is enabled. */ if (const gassign *assign_stmt = dyn_cast (stmt)) { enum tree_code op = gimple_assign_rhs_code (assign_stmt); @@ -753,9 +758,9 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt, tree lhs = gimple_assign_lhs (assign_stmt); if (lhs) { - // FIXME: - //lhs = sm_ctxt->get_readable_tree (lhs); - sm_ctxt->on_transition (node, stmt, lhs, m_start, m_non_heap); + tree addr_expr = gimple_assign_rhs1 (assign_stmt); + if (TREE_CODE (TREE_OPERAND (addr_expr, 0)) != MEM_REF) + sm_ctxt->on_transition (node, stmt, lhs, m_start, m_non_heap); } } } diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c new file mode 100644 index 00000000000..1d3576d9308 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c @@ -0,0 +1,18 @@ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */ + +#include "../analyzer-decls.h" + +void test (int *p, int a, int b, int count) +{ + int n = count; + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + while (n--) + { + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ + *p++ = a; + *p++ = b; + } + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} -- 2.26.2