]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Refactored all files. Renamed gcc/symb-execute-all-paths.cc/h files to gcc/gcc/crc_ve...
authorMariam Arutunian <mariamarutunian@gmail.com>
Tue, 27 Dec 2022 14:52:46 +0000 (18:52 +0400)
committerJeff Law <jlaw@ventanamicro>
Tue, 21 Mar 2023 15:03:20 +0000 (09:03 -0600)
    Changes in Traverse and execute CRC function v8:
      - Delete states and final_states vectores more deeply.

    Changes in LFSR matching v4:
      - Added support of CRC mixed case matching.

    Changes in Testsuit:
      - Added checks of found CRC in crc-2,4,5,7,8 tests.
      - Changed CRC detection search messages.

    Changes in sym_exec v12:
      - Added clear_states function.

30 files changed:
gcc/Makefile.in
gcc/crc_verification.cc [new file with mode: 0644]
gcc/crc_verification.h [new file with mode: 0644]
gcc/gimple-crc-optimization.cc
gcc/sym-exec/state.cc
gcc/sym-exec/state.h
gcc/testsuite/gcc.dg/crc-1.c
gcc/testsuite/gcc.dg/crc-10.c
gcc/testsuite/gcc.dg/crc-11.c
gcc/testsuite/gcc.dg/crc-12.c
gcc/testsuite/gcc.dg/crc-13.c
gcc/testsuite/gcc.dg/crc-14.c
gcc/testsuite/gcc.dg/crc-15.c
gcc/testsuite/gcc.dg/crc-16.c
gcc/testsuite/gcc.dg/crc-17.c
gcc/testsuite/gcc.dg/crc-18.c
gcc/testsuite/gcc.dg/crc-19.c
gcc/testsuite/gcc.dg/crc-2.c
gcc/testsuite/gcc.dg/crc-20.c
gcc/testsuite/gcc.dg/crc-21.c
gcc/testsuite/gcc.dg/crc-22.c
gcc/testsuite/gcc.dg/crc-23.c
gcc/testsuite/gcc.dg/crc-24.c
gcc/testsuite/gcc.dg/crc-3.c
gcc/testsuite/gcc.dg/crc-4.c
gcc/testsuite/gcc.dg/crc-5.c
gcc/testsuite/gcc.dg/crc-6.c
gcc/testsuite/gcc.dg/crc-7.c
gcc/testsuite/gcc.dg/crc-8.c
gcc/testsuite/gcc.dg/crc-9.c

index 0365e599cfaddf0edbda11abc96cb427da200ed9..f69dab2da352e10f145277750dea7014f930f646 100644 (file)
@@ -1647,7 +1647,7 @@ OBJS = \
        tree-iterator.o \
        tree-logical-location.o \
        tree-loop-distribution.o \
-       symb-execute-all-paths.o \
+       crc_verification.o \
        gimple-crc-optimization.o \
        sym-exec/expression.o \
        sym-exec/state.o \
diff --git a/gcc/crc_verification.cc b/gcc/crc_verification.cc
new file mode 100644 (file)
index 0000000..c261a75
--- /dev/null
@@ -0,0 +1,1501 @@
+/*
+   Execute symbolically all paths of the function.  Iterate loops only once․
+   Copyright (C) 2006-2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.   */
+
+#include "crc_verification.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "gimple.h"
+#include "ssa.h"
+#include "gimple-iterator.h"
+#include "tree-cfg.h"
+#include "cfganal.h"
+
+
+/* This function assigns symbolic values to the arguments of the fun.
+   (Not complete).  */
+
+bool
+crc_symbolic_execution::make_symbolic_func_args_and_sizes (function *fun,
+                                                      state *initial_state)
+{
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "\nMaking symbolic the following arguments "
+                       "of the function:\n");
+  /* Get size and name of function's arguments.  */
+  for (tree arg = DECL_ARGUMENTS (fun->decl); arg; arg = DECL_CHAIN (arg))
+    {
+      /* If the argument has a name and the size is integer
+        print that information.  */
+      if (TREE_CODE (DECL_SIZE (arg)) == INTEGER_CST && DECL_NAME (arg))
+       {
+         unsigned HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (arg));
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           fprintf (dump_file, "%s : %lu; ",
+                    IDENTIFIER_POINTER (DECL_NAME (arg)), size);
+         /* Add argument with its size to the state
+            and assign symbolic value.  */
+         initial_state->make_symbolic (arg, size);
+       }
+      else if (dump_file)
+       fprintf (dump_file, "Argument not const or no name.\n");
+    }
+  return true;
+}
+
+
+/* Add declared ssa variables to the state.  */
+
+bool
+crc_symbolic_execution::add_function_local_ssa_vars (function *fun,
+                                                state *initial_state)
+{
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "\n\nAdding the following ssa name declarations: \n");
+  unsigned ix;
+  tree name;
+  /* Get ssa names of the function.
+     Check type, add to the state with a size length array value.  */
+  FOR_EACH_SSA_NAME (ix, name, fun)
+      {
+       if (TREE_CODE (TREE_TYPE (name)) == INTEGER_TYPE)
+         {
+           if (TYPE_UNSIGNED (TREE_TYPE (name)))
+             {
+               // We need this info for symb execution.
+               if (dump_file && (dump_flags & TDF_DETAILS))
+                 fprintf (dump_file,
+                          "Unsigned, ");
+             }
+         }
+       else if (TREE_CODE (TREE_TYPE (name)) == POINTER_TYPE)
+         {
+           if (dump_file && (dump_flags & TDF_DETAILS))
+             fprintf (dump_file, "Pointer type, ");
+         }
+       else
+         {
+           /* Other type of variables aren't needed for CRC calculation.  */
+           if (dump_file && (dump_flags & TDF_DETAILS))
+             {
+               print_generic_expr (dump_file, name, dump_flags);
+               fprintf (dump_file, ", %s type, won't be considered.\n",
+                        get_tree_code_name (TREE_CODE (TREE_TYPE (name))));
+             }
+           continue;
+         }
+
+       unsigned HOST_WIDE_INT size
+           = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (name)));
+
+       if (dump_file && (dump_flags & TDF_DETAILS))
+         {
+           print_generic_expr (dump_file, name, dump_flags);
+           fprintf (dump_file, " size is %lu.\n", size);
+         }
+
+       /* Add ssa variable with its size to the state,
+          assign symbolic value.  */
+       initial_state->make_symbolic (name, size);
+      }
+  return true;
+}
+
+
+/* Calculate value of the rhs operation and assign to lhs variable.  */
+
+bool
+crc_symbolic_execution::execute_assign_statement (const gassign *gs)
+{
+  enum tree_code rhs_code = gimple_assign_rhs_code (gs);
+  tree lhs = gimple_assign_lhs (gs);
+  state *current_state = states.last ();
+
+  if (gimple_num_ops (gs) == 2)
+    {
+      tree op1 = gimple_assign_rhs1 (gs);
+      switch (rhs_code)
+       {
+         case BIT_NOT_EXPR:
+           {
+             if (current_state->do_complement (op1, lhs))
+               return true;
+             return false;
+           }
+         case MEM_REF:
+           {
+             /* FIXME: There can be something like
+                MEM[(some_type *)data + 1B],
+                in this case we just pass data.  */
+             if (current_state->do_mem_ref (TREE_OPERAND (op1, 0), lhs))
+               return true;
+             return false;
+           }
+         case NOP_EXPR:
+           {
+             if (current_state->do_assign (op1, lhs))
+               return true;
+             return false;
+           }
+         case SSA_NAME:
+           {
+             if (current_state->do_assign (op1, lhs))
+               return true;
+             return false;
+           }
+         case VAR_DECL:
+           {
+             if (current_state->do_assign (op1, lhs))
+               return true;
+             return false;
+           }
+         default:
+           {
+             if (dump_file)
+               fprintf (dump_file,
+                        "Warning, encountered unsupported unary operation "
+                        "with %s code while executing assign statement!\n",
+                        get_tree_code_name (rhs_code));
+             return false;
+           }
+       }
+    }
+  else if (gimple_num_ops (gs) == 3)
+    {
+      tree op1 = gimple_assign_rhs1 (gs);
+      tree op2 = gimple_assign_rhs2 (gs);
+      switch (rhs_code)
+       {
+         case LSHIFT_EXPR:
+           {
+             if (current_state->do_shift_left (op1, op2, lhs))
+               return true;
+             return false;
+           }
+         case RSHIFT_EXPR:
+           {
+             if (current_state->do_shift_right (op1, op2, lhs))
+               return true;
+             return false;
+           }
+         case BIT_AND_EXPR:
+           {
+             if (current_state->do_and (op1, op2, lhs))
+               return true;
+             return false;
+           }
+         case BIT_IOR_EXPR:
+           {
+             if (current_state->do_or (op1, op2, lhs))
+               return true;
+             return false;
+           }
+         case BIT_XOR_EXPR:
+           {
+             if (current_state->do_xor (op1, op2, lhs))
+               return true;
+             return false;
+           }
+         case PLUS_EXPR:
+           {
+             if (current_state->do_add (op1, op2, lhs))
+               return true;
+             return false;
+           }
+         case MINUS_EXPR:
+           {
+             if (current_state->do_sub (op1, op2, lhs))
+               return true;
+             return false;
+           }
+         case MULT_EXPR:
+           {
+             if (current_state->do_mul (op1, op2, lhs))
+               return true;
+             return false;
+           }
+         case POINTER_PLUS_EXPR:
+           {
+             if (current_state->do_pointer_plus (op1, op2, lhs))
+               return true;
+             return false;
+           }
+         case POINTER_DIFF_EXPR:
+           {
+             if (current_state->do_pointer_diff (op1, op2, lhs))
+               return true;
+             return false;
+           }
+         default:
+           {
+             if (dump_file)
+               fprintf (dump_file,
+                        "Warning, encountered unsupported binary operation "
+                        "with %s code while executing assign statement!\n",
+                        get_tree_code_name (rhs_code));
+             return false;
+           }
+       }
+    }
+  else
+    {
+      if (dump_file)
+       fprintf (dump_file,
+                "Warning, encountered unsupported operation, "
+                "with %s code while executing assign statement!\n",
+                get_tree_code_name (rhs_code));
+      return false;
+    }
+  return true;
+}
+
+
+/* If the next block of the edge1 dest is a back edge, add in the stack edge2.
+   Otherwise, add edge1 (the real execution path).
+
+   When loop counter is checked in the if condition,
+   we mustn't continue on real path,
+   as we don't want to iterate the loop second time.  */
+
+void
+add_edge (edge edge1, edge edge2, auto_vec<edge, 20> &stack)
+{
+  edge next_bb_edge = EDGE_SUCC (edge1->dest, 0);
+  if (next_bb_edge && (next_bb_edge->flags & EDGE_DFS_BACK))
+    {
+      /* FIXME: Compared variable's value will be incorrect,
+        not satisfiable for the path.
+        For example, if we have "for (int i=0; i<8; i++)",
+        i's value may not be 8 when we continue with the false branch.
+        But it's ok, as for checking CRC's value we don't need i's value.  */
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Won't iterate loop once more.\n");
+      stack.quick_push (edge2);
+    }
+  else
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Adding the edge into the stack.\n");
+
+      /* If the result of the condition is true/false,
+        continue execution only by the true branch.  */
+      stack.quick_push (edge1);
+    }
+}
+
+
+/* Add next basic blocks of the conditional block
+   for the execution path into the stack.
+   If the condition depends on symbolic values, keep both edges.
+   If the condition is true, keep true edge, else - false edge.  */
+
+void
+crc_symbolic_execution::add_next_bbs (basic_block cond_bb,
+                                 state *new_branch_state,
+                                 auto_vec<edge, 20> &stack)
+{
+  edge true_edge;
+  edge false_edge;
+  extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
+
+  if (new_branch_state->get_last_cond_status () == CS_SYM)
+    {
+
+      /* Add true branch's state into the states.
+        False branch's states will be kept in the current state.  */
+      states.quick_push (new_branch_state);
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Adding true and false edges into the stack.\n");
+
+      /* Add outgoing edges to the stack.  */
+      stack.quick_push (false_edge);
+      stack.quick_push (true_edge);
+
+      return;
+    }
+  else if (new_branch_state->get_last_cond_status () == CS_TRUE)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Condition is true.\n");
+      add_edge (true_edge, false_edge, stack);
+    }
+  else if (new_branch_state->get_last_cond_status () == CS_FALSE)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Condition is false.\n");
+      add_edge (false_edge, true_edge, stack);
+    }
+  else
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Something went wrong "
+                           "during handling conditional statement.\n");
+    }
+
+  /* When we continue execution of only one path,
+     there's no need of new state.  */
+  delete new_branch_state;
+}
+
+
+/* Keep conditions depending on symbolic variables in the states.  */
+
+bool
+crc_symbolic_execution::add_condition (const gcond *cond,
+                                  state *current_state,
+                                  state *new_branch_state)
+{
+  /* Keep conditions of each branch execution in its state.
+     Ex.
+       if (a == 0)  // a's value is unknown
+
+       new_branch_state.keep (a==0)
+       current_state.keep (a!=0)
+
+     The condition is kept in the bit level.
+     For ex.
+     If a's size is 8 and its value is {symb_a, 0, 0, 0, 0, 0, 0, 0},
+     then for a == 0 we'll have symb_a == 0 condition.
+  */
+
+  tree lhs = gimple_cond_lhs (cond);
+  tree rhs = gimple_cond_rhs (cond);
+  switch (gimple_cond_code (cond))
+    {
+      case EQ_EXPR:
+       {
+         new_branch_state->add_equal_cond (lhs, rhs);
+         if (new_branch_state->get_last_cond_status () == CS_SYM)
+           current_state->add_not_equal_cond (lhs, rhs);
+         return true;
+       }
+      case NE_EXPR:
+       {
+         new_branch_state->add_not_equal_cond (lhs, rhs);
+         if (new_branch_state->get_last_cond_status () == CS_SYM)
+           current_state->add_equal_cond (lhs, rhs);
+         return true;
+       }
+      case GT_EXPR:
+       {
+         new_branch_state->add_greater_than_cond (lhs, rhs);
+         if (new_branch_state->get_last_cond_status () == CS_SYM)
+           current_state->add_less_or_equal_cond (lhs, rhs);
+         return true;
+       }
+      case LT_EXPR:
+       {
+         new_branch_state->add_less_than_cond (lhs, rhs);
+         if (new_branch_state->get_last_cond_status () == CS_SYM)
+           current_state->add_greater_or_equal_cond (lhs, rhs);
+         return true;
+       }
+      case GE_EXPR:
+       {
+         new_branch_state->add_greater_or_equal_cond (lhs, rhs);
+         if (new_branch_state->get_last_cond_status () == CS_SYM)
+           current_state->add_less_than_cond (lhs, rhs);
+         return true;
+       }
+      case LE_EXPR:
+       {
+         new_branch_state->add_less_or_equal_cond (lhs, rhs);
+         if (new_branch_state->get_last_cond_status () == CS_SYM)
+           current_state->add_greater_than_cond (lhs, rhs);
+         return true;
+       }
+      default:
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           fprintf (dump_file, "Unsupported condition.\n");
+         return false;
+       }
+    }
+}
+
+
+/* Create new state for true and false branch.
+   Keep conditions in new created states.  */
+
+bool
+crc_symbolic_execution::resolve_condition (const gcond *cond,
+                                      auto_vec<edge, 20> &stack)
+{
+  /* Remove last state.  */
+  state *current_state = states.last ();
+  state *new_branch_state = new state (*current_state);
+
+  if (!add_condition (cond, current_state, new_branch_state))
+    return false;
+
+  add_next_bbs (cond->bb, new_branch_state, stack);
+  return true;
+}
+
+
+/* Keep the calculated value of the return value
+   and the conditions of the executed path.  */
+
+bool
+crc_symbolic_execution::keep_return_val_and_conditions (const greturn *ret)
+{
+  tree return_op = gimple_return_retval (ret);
+
+  if (!return_op)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "No return value.\n");
+      return false;
+    }
+
+  if (TREE_CODE (return_op) == INTEGER_CST)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Return value is a constant.\n");
+      return false;
+    }
+
+  /* Get calculated return value.  */
+  state *curr_state = states.last ();
+  value *return_value = curr_state->get_value (return_op);
+
+  if (!return_value)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Return value is not in the state.\n");
+      return false;
+    }
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "Return value is ");
+      state::print_value (return_value);
+    }
+
+  state *final_state = new state;
+
+  /* Keep return value's calculated value and conditions in the final state.  */
+  final_state->add_var_state (return_op, return_value);
+  final_state->bulk_add_conditions (curr_state->get_conditions ());
+  final_states.quick_push (final_state);
+
+  delete curr_state;
+  states.pop ();
+
+  return true;
+}
+
+
+/* Execute gimple statements of BB.
+   Keeping values of variables in the state.  */
+
+bool
+crc_symbolic_execution::execute_bb_gimple_statements (basic_block bb,
+                                                 auto_vec<edge, 20> &stack)
+{
+  for (gimple_stmt_iterator bsi = gsi_start_bb (bb);
+       !gsi_end_p (bsi); gsi_next (&bsi))
+    {
+      gimple *gs = gsi_stmt (bsi);
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Executing ");
+         print_gimple_stmt (dump_file, gs, dump_flags);
+       }
+      switch (gimple_code (gs))
+       {
+         case GIMPLE_ASSIGN:
+           {
+             if (!execute_assign_statement (as_a<const gassign *> (gs)))
+               return false;
+             break;
+           }
+         case GIMPLE_COND:
+           {
+             if (!resolve_condition (as_a<const gcond *> (gs), stack))
+               return false;
+             return true;
+           }
+         case GIMPLE_RETURN:
+           {
+             if (!keep_return_val_and_conditions (as_a<const greturn *> (gs)))
+               return false;
+             return true;
+           }
+         default:
+           {
+             if (dump_file)
+               fprintf (dump_file,
+                        "Warning, encountered unsupported statement, "
+                        "while executing gimple statements!\n");
+             return false;
+           }
+       }
+    }
+
+  /* Add each outgoing edge of the current block to the stack,
+     despite back edges.
+     This code isn't reachable if the last statement of the basic block
+     is a conditional statement or return statement.
+     Those cases are handled separately.  */
+
+  edge out_edge;
+  edge_iterator ei;
+  FOR_EACH_EDGE (out_edge, ei, bb->succs)
+    if (!(out_edge->flags & EDGE_DFS_BACK))
+      stack.quick_push (out_edge);
+    else if (!states.is_empty ())
+      {
+       /* Delete the state after executing the full path,
+          or encountering back edge.  */
+       delete states.last ();
+       states.pop ();
+      }
+
+  return true;
+}
+
+
+/* Assign values of phi instruction to its result.
+   Keep updated values in the state.  */
+
+bool
+crc_symbolic_execution::execute_bb_phi_statements (basic_block bb,
+                                              edge incoming_edge)
+{
+  for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+       gsi_next (&gsi))
+    {
+      gphi *phi = gsi.phi ();
+      tree lhs = gimple_phi_result (phi);
+
+      /* Don't consider virtual operands.  */
+      if (virtual_operand_p (lhs))
+       continue;
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Determining the value "
+                             "for the following phi.\n");
+         print_gimple_stmt (dump_file, phi, dump_flags);
+       }
+
+      tree rhs = PHI_ARG_DEF_FROM_EDGE (phi, incoming_edge);
+
+      state *current_state = states.last ();
+      if (!current_state->do_assign (rhs, lhs))
+       return false;
+    }
+  return true;
+}
+
+
+/* Execute all statements of BB.
+   Keeping values of variables in the state.  */
+
+bool
+crc_symbolic_execution::execute_bb_statements (basic_block bb,
+                                          edge incoming_edge,
+                                          auto_vec<edge, 20> &stack)
+{
+  if (!execute_bb_phi_statements (bb, incoming_edge))
+    return false;
+
+  return execute_bb_gimple_statements (bb, stack);
+}
+
+
+/* Traverse function fun's all paths from the first basic block to the last.
+   Each time iterate loops only once.
+   Symbolically execute statements of each path.  */
+
+bool
+crc_symbolic_execution::traverse_function (function *fun)
+{
+  /* TODO: Check whether back_edges can be determined by BB index,
+       if so, no need of EDGE_DFS_BACK flag.  */
+  mark_dfs_back_edges (fun);
+  /* Allocate stack for back-tracking up CFG.  */
+  auto_vec<edge, 20> stack (n_basic_blocks_for_fn (fun) + 1);
+
+  /* Push all successor edges of first block into the stack.
+     No need to execute first block.  */
+  edge e;
+  edge_iterator ei;
+  FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (fun)->succs)
+    stack.quick_push (e);
+
+  while (!stack.is_empty ())
+    {
+      /* Look at the edge on the top of the stack.  */
+      edge e = stack.last ();
+      stack.pop ();
+
+      /* Get dest block of the edge.  */
+      basic_block bb = e->dest;
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "\n\nExecuting BB <%d>\n\n", bb->index);
+
+      /* Symbolically execute statements.  */
+      if (!execute_bb_statements (bb, e, stack))
+       return false;
+    }
+  return true;
+}
+
+
+/* Symbolically execute function.  */
+
+bool
+crc_symbolic_execution::execute (function *fun)
+{
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "\nExecuting CRC-like function.\n");
+
+  /* Create initial state and push into the vector of states.  */
+  states.quick_push (new state);
+  state *initial_state = states.last ();
+
+  make_symbolic_func_args_and_sizes (fun, initial_state);
+
+  /* Add declared variables to the state.  */
+  add_function_local_ssa_vars (fun, initial_state);
+
+  /* Execute function's statements, keeping a state for each path.  */
+  return traverse_function (fun);
+}
+
+
+/* Determine which bit of data must be 1.  */
+
+unsigned HOST_WIDE_INT
+determine_index (tree data, bool is_shift_left)
+{
+  if (is_shift_left)
+    // FIXME: may be the data's size is larger,
+    //  but MSB is checked for the middle bit.
+    return tree_to_uhwi (TYPE_SIZE (TREE_TYPE (data))) - 1;
+  return 0;
+}
+
+
+/* Assign appropriate values to data, crc
+   and other phi results to calculate the polynomial.  */
+
+void
+assign_vals_to_header_phis (state *polynomial_state, basic_block bb,
+                           gphi *crc, gphi *data,
+                           bool is_shift_left)
+{
+  for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+       gsi_next (&gsi))
+    {
+
+      gphi *phi = gsi.phi ();
+      tree lhs = gimple_phi_result (phi);
+
+      /* Don't consider virtual operands.  */
+      if (virtual_operand_p (lhs))
+       continue;
+
+      if ((data && phi == data) || (!data && phi == crc))
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "Assigning the required value to ");
+             print_generic_expr (dump_file, lhs, dump_flags);
+             fprintf (dump_file, " variable.\n");
+           }
+         polynomial_state->do_assign_pow2 (lhs,
+                                           determine_index (lhs,
+                                                            is_shift_left));
+       }
+      else if (phi == crc)
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "Assigning 0 value to ");
+             print_generic_expr (dump_file, lhs, dump_flags);
+             fprintf (dump_file, " variable.\n");
+           }
+         polynomial_state->do_assign (build_zero_cst (TREE_TYPE (lhs)), lhs);
+       }
+      else if (TREE_CODE (PHI_ARG_DEF (phi, phi->nargs - 1)) == INTEGER_CST)
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "First value of phi is a constant, "
+                                 "assigning the number to ");
+             print_generic_expr (dump_file, lhs, dump_flags);
+             fprintf (dump_file, " variable.\n");
+           }
+         polynomial_state->do_assign (PHI_ARG_DEF (phi, phi->nargs - 1), lhs);
+       }
+      else
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "First value of phi isn't constant, "
+                                 "assigning to ");
+             print_generic_expr (dump_file, lhs, dump_flags);
+             fprintf (dump_file, " variable.\n");
+           }
+         polynomial_state->do_assign (build_zero_cst (TREE_TYPE (lhs)), lhs);
+       }
+    }
+}
+
+
+/* Execute the loop, which calculates crc with initial values,
+   to calculate the polynomial.  */
+
+bool
+crc_symbolic_execution::execute_crc_loop (class loop *crc_loop, gphi *crc,
+                                     gphi *data,
+                                     bool is_shift_left)
+{
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "\n\nTrying to calculate the polynomial.\n\n");
+
+  states.quick_push (new state);
+
+  basic_block bb = crc_loop->header;
+  assign_vals_to_header_phis (states.last (), bb, crc, data, is_shift_left);
+
+  auto_vec<edge, 20> stack (crc_loop->num_nodes);
+
+  execute_bb_gimple_statements (bb, stack);
+
+  /* stack may not be empty.  Successor BB's are added into the stack
+     from the execute_bb_gimple_statements function.  */
+  while (!stack.is_empty ())
+    {
+      /* Look at the edge on the top of the stack.  */
+      edge e = stack.last ();
+      stack.pop ();
+
+      /* Get dest block of the edge.  */
+      basic_block bb = e->dest;
+
+      /* Execute only basic blocks of the crc_loop.  */
+      if (!flow_bb_inside_loop_p (crc_loop, bb))
+       continue;
+
+
+      /* Execute statements.  */
+      if (!execute_bb_statements (bb, e, stack))
+       return false;
+    }
+
+  if (states.length () != 1)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "The number of states is not one.\n");
+      return false;
+    }
+  return true;
+}
+
+
+/* Return true if all bits of the polynomial are constants (0 or 1).
+   Otherwise return false.  */
+
+bool
+polynomial_is_known (const value *polynomial)
+{
+  for (size_t i = 0; i < polynomial->length (); i++)
+    {
+      if (!is_a<bit *> ((*polynomial)[i]))
+       return false;
+    }
+  return true;
+}
+
+
+/* Execute the loop, which is expected to calculate CRC,
+   to extract polynomial, assigning real numbers to crc and data.  */
+
+value *
+crc_symbolic_execution::extract_poly_and_create_lfsr (class loop *crc_loop,
+                                                 gphi *crc, gphi *data,
+                                                 bool is_shift_left)
+{
+  if (!execute_crc_loop (crc_loop, crc, data, is_shift_left))
+    return nullptr;
+
+  state *polynomial_state = states.last ();
+
+  /* Get the tree which will contain the value of the polynomial
+     at the end of the loop.  */
+  tree calculated_crc = PHI_ARG_DEF (crc, 0);
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "Getting the value of ");
+      print_generic_expr (dump_file, calculated_crc, dump_flags);
+      fprintf (dump_file, " variable.\n");
+    }
+
+  /* Get the value (bit vector) of the tree (it may be the polynomial).  */
+  value *polynomial = polynomial_state->get_value (calculated_crc);
+  if (!polynomial)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Polynomial's value is null");
+      return nullptr;
+    }
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      /* Note: It may not be the real polynomial.
+        If it's a bit reflected crc,
+        then to get a real polynomial,
+        it must be reflected and 1 bit added.  */
+      fprintf (dump_file, "Polynomial's value is ");
+      state::print_value (polynomial);
+    }
+
+  /* Check that polynomial's all bits are constants.  */
+  if (!polynomial_is_known (polynomial))
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+         fprintf (dump_file, "Polynomial's value is not constant.\n");
+      return nullptr;
+    }
+
+  return state::create_lfsr (calculated_crc, polynomial, is_shift_left);
+}
+
+
+/**************************** LFSR MATCHING *********************************/
+// TODO write in separate file.
+
+
+/* Returns true index1 and index2 differ by a factor of 8.  */
+
+bool
+acceptable_diff (size_t index1, size_t index2)
+{
+  size_t diff;
+  if (index1 > index2)
+    diff = index1 - index2;
+  else
+    diff = index2 - index1;
+
+  /* Indexes of the symbolic bit may differ by 0, 8, 16, 24, 32, ...  */
+  return diff % 8 == 0;
+}
+
+
+/* Returns true if the symb_exp is a bit_xor_expression and const_bit equals 1.
+   Otherwise, returns false.  */
+
+bool
+is_one (value_bit *const_bit)
+{
+  return is_a<bit *> (const_bit)
+        && (as_a<bit *> (const_bit))->get_val () == 1;
+}
+
+
+/* Returns true if bit is symbolic and its index differs from LFSR bit's index
+   by a factor of 8.
+   Sometimes calculated crc value is returned
+   after being shifted by 8's factor.  */
+
+bool
+is_a_valid_symb (value_bit *bit, size_t lfsr_bit_index)
+{
+  if (!is_a<symbolic_bit *> (bit))
+    return false;
+
+  size_t sym_bit_index = (as_a<symbolic_bit *> (bit))->get_index ();
+  return acceptable_diff (sym_bit_index, lfsr_bit_index);
+}
+
+
+/* Returns true if bit is crc[index+8*i]^data[index+8*i],
+   where i is a whole number.
+   Otherwise, returns false.  */
+
+bool
+is_a_valid_xor (value_bit *bit, size_t lfsr_bit_index)
+{
+  return is_a<bit_xor_expression *> (bit)
+        && is_a_valid_symb ((as_a<bit_xor_expression *> (bit))->get_left (),
+                            lfsr_bit_index)
+        && is_a_valid_symb ((as_a<bit_xor_expression *> (bit))->get_right (),
+                            lfsr_bit_index);
+}
+
+
+/* Returns true if the bit is a valid
+   crc[index+8*i] ^ data[index+8*i] ^ 1, or crc[index+8*i] ^ 1,
+   where i is a whole number.
+   index is the index of the LFSR bit from the same position as in CRC.
+
+   If there is lfsr[8] at LFSR value vectors' 9-th bit,
+   when in the crc vectors' 9-th bit's value must be
+   crc[8] or crc[16],...
+
+   Otherwise, returns false.  */
+
+bool
+is_a_valid_xor_one (value_bit *bit, size_t lfsr_bit_index)
+{
+  if (is_a<bit_xor_expression *> (bit))
+    {
+      value_bit *symb_exp = nullptr;
+      bit_xor_expression *xor_exp = as_a<bit_xor_expression *> (bit);
+      if (is_one (xor_exp->get_right ()))
+       symb_exp = xor_exp->get_left ();
+      else if (is_one (xor_exp->get_left ()))
+       symb_exp = xor_exp->get_right ();
+      else
+       return false;
+      return is_a_valid_xor (symb_exp, lfsr_bit_index)
+            || is_a_valid_symb (symb_exp, lfsr_bit_index);
+    }
+  else
+    return false;
+}
+
+
+/* Check whether the condition_exp and refernce_exp match.
+   This is done for finding the condition which checks MSB/LSB's value
+   (under which xor is/not done).  */
+
+bool
+may_be_xors_condition (value_bit *reference_exp, value_bit *condition_exp,
+                      size_t sb_index)
+{
+  if (!reference_exp)
+    return false;
+
+  if (!condition_exp)
+    return false;
+
+  if (is_a<bit_xor_expression *> (reference_exp))
+    {
+      if (is_one (as_a<bit_xor_expression *> (reference_exp)->get_right ()))
+       reference_exp = as_a<bit_xor_expression *>
+           (reference_exp)->get_left ();
+      else if (is_a<bit_xor_expression *> (condition_exp))
+       return may_be_xors_condition (as_a<bit_xor_expression *>
+                                         (reference_exp)->get_left (),
+                                     as_a<bit_xor_expression *>
+                                         (condition_exp)->get_left (),
+                                     sb_index)
+              && may_be_xors_condition (as_a<bit_xor_expression *>
+                                            (reference_exp)->get_right (),
+                                        as_a<bit_xor_expression *>
+                                            (condition_exp)->get_right (),
+                                        sb_index);
+      return false;
+    }
+  if (is_a<symbolic_bit *> (reference_exp)
+      && is_a<symbolic_bit *> (condition_exp))
+    {
+      symbolic_bit *condition_symbolic = as_a<symbolic_bit *> (condition_exp);
+      symbolic_bit *reference_symbolic = as_a<symbolic_bit *> (reference_exp);
+      return reference_symbolic->get_origin ()
+            == condition_symbolic->get_origin ()
+            && acceptable_diff (sb_index,
+                                condition_symbolic->get_index ());
+    }
+  if (is_a<symbolic_bit *> (reference_exp)
+      && is_a<bit_xor_expression *> (condition_exp))
+    return may_be_xors_condition (as_a<symbolic_bit *> (reference_exp),
+                                 as_a<bit_xor_expression *>
+                                     (condition_exp)->get_left (), sb_index)
+          || may_be_xors_condition (as_a<symbolic_bit *> (reference_exp),
+                                    as_a<bit_xor_expression *>
+                                        (condition_exp)->get_right (),
+                                    sb_index);
+  return false;
+}
+
+
+/* Checks whether the condition is checked for significant bit being 0 or 1.
+   If is_one is 1, when check whether the significant bit is 1 (xor branch),
+   if 0 whether the significant bit is 0 (not xor branch).  */
+
+bool
+check_condition (value_bit *symb_exp, unsigned char is_one,
+                size_t sb_index, state *final_state)
+{
+  for (auto iter = final_state->get_conditions ().begin ();
+       iter != final_state->get_conditions ().end (); ++iter)
+    {
+      /* Get ordinal condition.  */
+      bit_condition *condition = nullptr;
+      if (is_a<bit_condition *> (*iter))
+       condition = as_a<bit_condition *> (*iter);
+      else
+       continue;
+
+      /* If the condition may be for checking MSB/LSB being 1/0,
+        then if is_one is 1 and condition is for checking MSB/LSB being one or
+        if is_one is 0 and condition is for checking MSB/LSB being 0
+        return true, otherwise - false.  */
+      value_bit *cond_exp = (*iter)->get_left ();
+      if (may_be_xors_condition (symb_exp, cond_exp, sb_index))
+       {
+         if (!is_a<bit *> ((*iter)->get_right ()))
+           return false;
+
+         unsigned char comparison_val = as_a<bit *> ((*iter)->get_right ())
+             ->get_val ();
+         if (condition->get_cond_type () == EQ_EXPR)
+           return comparison_val == is_one;
+         if (condition->get_cond_type () == NE_EXPR)
+           return comparison_val != is_one;
+         return false;
+       }
+    }
+  return false;
+}
+
+
+/* Check whether LSB/MSB of LFSR and calculated (maybe)CRC match.
+   If LSB/MSB is checked for being one in the CRC code,
+   then here we check MSB/LSB.  */
+
+bool
+significant_bits_match (value_bit *crc, value_bit *lfsr,
+                       value_bit *conditions_crc,
+                       size_t sb_index, state *final_state)
+{
+  /* If LFSR's MSB/LSB value is a constant (0 or 1),
+     then CRC's MSB/LSB must have the same value.  */
+  if (is_a<bit *> (lfsr))
+    {
+      if (!((is_a<bit *> (crc)
+            && as_a<bit *> (crc)->get_val ()
+               == as_a<bit *> (lfsr)->get_val ())))
+       return false;
+      return true;
+    }
+    /* If LFSR's MSB/LSB value is a symbolic_bit
+       (that means MSB/LSB of the polynomial is 1),
+       then CRC's MSB/LSB must be 0 if the condition is false,
+       1 - if the condition is true.
+       (Because crc is xored with the polynomial in case LSB/MSB is 1).  */
+  else if (is_a<symbolic_bit *> (lfsr))
+    {
+      if (!(is_a<bit *> (crc) && ((as_a<bit *> (crc)->get_val () == 0
+                                  && check_condition (conditions_crc, 0,
+                                                      sb_index, final_state))
+                                 || (as_a<bit *> (crc)->get_val () == 1
+                                     && check_condition (conditions_crc, 1,
+                                                         sb_index,
+                                                         final_state)))))
+       return false;
+      return true;
+    }
+  return false;
+}
+
+
+/* Check whether significant bit of LFSR and calculated (maybe)CRC match.  */
+
+bool
+significant_bits_match (const value *lfsr,
+                       const value *crc_state,
+                       bool is_left_shift,
+                       value_bit *symb_val,
+                       size_t it_end,
+                       state *final_state)
+{
+  if (is_left_shift)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Checking 0 bit.\n");
+
+      if (!significant_bits_match ((*crc_state)[0], (*lfsr)[0], symb_val,
+                                  it_end - 1, final_state))
+       return false;
+    }
+  else
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Checking %lu bit.\n", it_end);
+
+      if (!significant_bits_match ((*crc_state)[it_end],
+                                  (*lfsr)[it_end], symb_val, 0, final_state))
+       return false;
+    }
+  return true;
+}
+
+
+/* Match the crc to the lfsr, where crc's all bit values are
+   symbolic_bits or symbolic_bits ^ 1, or
+   bit_xor_expression or bit_xor_expression ^ 1,
+   besides MSB/LSB (it may be constant).
+
+  Under this are considered the cases,
+  when sizes of crc and data are same and
+
+  1.  Data is xored with crc before the loop.
+  2.  Data is xored with crc in the loop.
+  3.  Data is xor-ed with crc only for checking the condition and
+      xor is done only on crc.  */
+
+bool
+lfsr_and_crc_bits_match (const value *lfsr,
+                        const value *crc_state,
+                        value_bit *symb_val,
+                        bool is_left_shift,
+                        size_t i, size_t it_end, size_t sb_index,
+                        state *final_state)
+{
+
+  /* Check whether significant bits of LFSR and CRC match.  */
+  if (!significant_bits_match (lfsr, crc_state, is_left_shift, symb_val,
+                              it_end, final_state))
+    return false;
+
+  for (; i < it_end; i++)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Checking %lu bit.\n", i);
+
+      /* Check the case when in lfsr we have LFSR (i)^LFSR (SBi),
+        where 0<i<LFSR_size and SBi is the index of MSB/LSB (LFSR_size-1/0).
+        In that case in crc_state (resulting CRC)
+        we must have crc (i+8*k)^1 case, when condition is true
+        and crc (i+8*k) when condition is false,
+        (as crc is xor-ed with the polynomial only if the LSB/MSB is one)
+        where k is a whole number
+        (in some implementations crc is shifted left or right by 8, 16...).  */
+      if (is_a<bit_xor_expression *> ((*lfsr)[i]))
+       {
+         size_t index = (as_a<bit_xor_expression *> ((*lfsr)[i]))->get_left ()
+             ->get_index ();
+         if (!((is_a_valid_xor_one ((*crc_state)[i], index)
+                && check_condition (
+                    as_a<bit_xor_expression *> ((*crc_state)[i])->get_left (),
+                    1, sb_index, final_state))
+               || (is_a_valid_symb ((*crc_state)[i], index)
+                   && check_condition ((*crc_state)[i], 0, sb_index,
+                                       final_state))
+               || (is_a_valid_xor ((*crc_state)[i], index)
+                   && check_condition ((*crc_state)[i], 0, sb_index,
+                                       final_state))))
+           return false;
+       }
+       /* Check the case when in LFSR we have LFSR (i), where 0<i<LFSR_size.
+          In that case in resulting CRC we must have crc (i+8*k) case,
+          when condition is true or condition is false.
+          If we have just LFSR (i), that means polynomial's i+-1 bit is 0,
+          so despite CRC is xor-ed or not, we will have crc (i).  */
+      else if (is_a<symbolic_bit *> ((*lfsr)[i]))
+       {
+         size_t index = (as_a<symbolic_bit *> ((*lfsr)[i]))->get_index ();
+         if (!((is_a_valid_symb ((*crc_state)[i], index)
+                || is_a_valid_xor ((*crc_state)[i], index))
+               && (check_condition ((*crc_state)[i], 0, sb_index, final_state)
+                   || check_condition ((*crc_state)[i], 1, sb_index,
+                                       final_state))))
+           return false;
+
+       }
+      else
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           fprintf (dump_file, "Not expected expression in LFSR.\n");
+         return false;
+       }
+    }
+  return true;
+}
+
+
+/* Returns true if in the CRC value's vector we have one of the form of
+   following consecutive bits
+   1.  0, then 1
+   2.  1, then 0
+   3.  0, then 0
+   4.  1, then 1
+   Otherwise returns false.
+   */
+
+bool
+maybe_neighbour_vals_of_crc (bit *curr_bit_val, value_bit *next_bit_val)
+{
+  if (!curr_bit_val)
+    return true;
+
+  /* As the value doesn't matter,
+     just check that next_bit_val is bit *.  */
+  if (is_a<bit *> (next_bit_val))
+    return true;
+  return false;
+}
+
+
+/* Returns true if in the CRC value's vector we have one of the form of
+   following consecutive bits
+   1. crc[], then crc[]
+   2. crc[], then crc[]^data[]
+   3. crc[], then crc[]^data[]^1
+   4. crc[], then crc[]^1
+   5. data[], then crc[]^data[]
+   6. data[], then crc[]^data[]^1
+   7. crc[], then crc[]^data1[]^data2[] TODO: Maybe needs a correction.
+   ...
+   Otherwise returns false.  */
+
+bool
+maybe_neighbour_vals_of_crc (symbolic_bit *curr_bit_val,
+                            value_bit *next_bit_val)
+{
+  if (!curr_bit_val)
+    return true;
+
+  /* If both are symbolic_bits,
+     check that they are bits of the same variable.  */
+  if (is_a<symbolic_bit *> (next_bit_val))
+    return curr_bit_val->get_origin ()
+          == as_a<symbolic_bit *> (next_bit_val)->get_origin ();
+  else if (is_a<bit_xor_expression *> (next_bit_val))
+    return maybe_neighbour_vals_of_crc (curr_bit_val,
+                                       as_a<bit_xor_expression *>
+                                           (next_bit_val)->get_left ())
+          || maybe_neighbour_vals_of_crc (curr_bit_val,
+                                          as_a<bit_xor_expression *>
+                                              (next_bit_val)->get_right ());
+  return false;
+}
+
+
+/* Check the case when current bit's value is crc[]^1 or crc[]^data[]^1.  */
+
+bool
+check_xor_right_1_case (value_bit *curr_xor_exp_left,
+                       value_bit *next_bit_val)
+{
+/* The case when current bit's value is crc[]^1 or crc[]^data[]^1,
+      next bit's - crc[].
+      There may not be ^ 0 case, as expressions are optimized.  */
+  if (is_a<symbolic_bit *> (next_bit_val))
+    {
+      if (is_a<symbolic_bit *> (curr_xor_exp_left))
+       return maybe_neighbour_vals_of_crc (as_a<symbolic_bit *>
+                                               (curr_xor_exp_left),
+                                           next_bit_val);
+      if (is_a<bit_xor_expression *> (curr_xor_exp_left))
+       return maybe_neighbour_vals_of_crc (as_a<bit_xor_expression *>
+                                               (curr_xor_exp_left),
+                                           next_bit_val);
+    }
+    /* The case when current bit's value is crc[]^data[]^1,
+      next bit's - crc[]^data[].  */
+  else if (is_a<bit_xor_expression *> (curr_xor_exp_left)
+          && is_a<bit_xor_expression *> (next_bit_val))
+    return maybe_neighbour_vals_of_crc
+       (as_a<bit_xor_expression *> (curr_xor_exp_left),
+        next_bit_val);
+  return false;
+}
+
+
+/* Check the case, when for the current bit we have crc[]^data[].  */
+
+bool
+check_xor_left_and_right_symb_case (bit_xor_expression *curr_xor_exp,
+                                   value_bit *next_bit_val)
+{
+  symbolic_bit *curr_xor_exp_left_sym
+      = as_a<symbolic_bit *> (curr_xor_exp->get_left ());
+  symbolic_bit *curr_xor_exp_right_sym
+      = as_a<symbolic_bit *> (curr_xor_exp->get_right ());
+
+  /* The case when current bit's value is crc[]^data[],
+     next bit's - crc[] or data[].  */
+  if (is_a<symbolic_bit *> (next_bit_val))
+    return maybe_neighbour_vals_of_crc (curr_xor_exp_left_sym,
+                                       next_bit_val)
+          || maybe_neighbour_vals_of_crc (curr_xor_exp_right_sym,
+                                          next_bit_val);
+    /* The case when current bit's value is crc[]^data[],
+       next bit's - something ^ something.  */
+  else if (is_a<bit_xor_expression *> (next_bit_val))
+    {
+      bit_xor_expression *next_bit_xor_exp = as_a<bit_xor_expression *>
+         (next_bit_val);
+      /* The case when current bit's value is crc[]^data[],
+        next bit's - crc[]^data[].  */
+      if (is_a<symbolic_bit *> (next_bit_xor_exp->get_right ())
+         && is_a<symbolic_bit *> (next_bit_xor_exp->get_left ()))
+       return
+           maybe_neighbour_vals_of_crc (curr_xor_exp_left_sym,
+                                        next_bit_xor_exp->get_left ())
+           && maybe_neighbour_vals_of_crc (curr_xor_exp_right_sym,
+                                           next_bit_xor_exp->get_right ());
+       /* The case when current bit's value is crc[]^data[],
+          next bit's - crc[]^data[]^1.  */
+      else if (is_a<bit *> (next_bit_xor_exp->get_right ())
+              && is_a<bit_xor_expression *> (next_bit_xor_exp->get_left ()))
+       return maybe_neighbour_vals_of_crc (curr_xor_exp,
+                                           next_bit_xor_exp->get_left ());
+    }
+  return false;
+}
+
+
+/* Returns true if in the CRC value's vector we have one of the form of
+   following consecutive bits
+   1. crc[]^1 or crc[]^data[]^1, then crc[]
+   2. crc[]^data[]^1, then crc[]^data[]
+   3. crc[]^data[], then crc[] or data[]
+   4. crc[]^data[], then crc[]^data[]
+   5. crc[]^data[], then crc[]^data[]^1
+   Otherwise returns false.  */
+
+bool
+maybe_neighbour_vals_of_crc (bit_xor_expression *curr_xor_exp,
+                            value_bit *next_bit_val)
+{
+  if (!curr_xor_exp)
+    return true;
+
+  /* The case when we have some_expression ^ 1
+     for the current bit's value.  */
+  if (is_a<bit *> (curr_xor_exp->get_right ()))
+    return check_xor_right_1_case (curr_xor_exp->get_left (), next_bit_val);
+    /* The case when current bit's value is crc[]^data[].  */
+  else if (is_a<symbolic_bit *> (curr_xor_exp->get_right ())
+          && is_a<symbolic_bit *> (curr_xor_exp->get_left ()))
+    return check_xor_left_and_right_symb_case (curr_xor_exp, next_bit_val);
+  return false;
+}
+
+
+/* Checks that crc_state's all bit values may be real CRC's values.
+   Returns true if crc_state matches the LFSR, otherwise - false.  */
+
+bool
+state_matches_lfsr (const value *lfsr,
+                   const value *crc_state,
+                   bool is_left_shift, state *final_state)
+{
+  /* Depending on whether it is bit forward or reversed CRC,
+     determine in which significant bit new value is added,
+     to examine that bit separately.
+     If in the CRC alg MSB (sb_index) is checked to be one for xor,
+     then here we check LSB separately (marginal bit).
+     If LSB (sb_index) is checked, then we separate MSB (marginal bit).  */
+  size_t it_beg = 0, sb_index = 0,
+      it_end = lfsr->length () < crc_state->length ()
+              ? lfsr->length () : crc_state->length ();
+  if (is_left_shift)
+    {
+      sb_index = it_end - 1;
+      it_beg = 1;
+    }
+  else
+    --it_end;
+
+  symbolic_bit *symb_bit = nullptr;
+  bit_xor_expression *xor_exp = nullptr;
+
+  /* Check what kind of values are in the returned crc_state
+     (which is expected to be CRC), except for marginal bit.  Return false,
+     if there is such a value which must not exist in the CRC value.  */
+  for (unsigned j = it_beg; j < it_end - 1; ++j)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Checking %u bit's "
+                           "and %u bit's compatibility.\n", j, j + 1);
+      switch ((*crc_state)[j]->get_type ())
+       {
+         case SYMBOLIC_BIT:
+           {
+             symb_bit = as_a<symbolic_bit *> ((*crc_state)[j]);
+             if (!maybe_neighbour_vals_of_crc (symb_bit, (*crc_state)[j + 1]))
+               return false;
+             break;
+           }
+         case BIT:
+           /* Except for marginal bit there mustn't be other constants.
+              (For some implementations we get constant values for CRC,
+              but we don't support those cases).  */
+           return false;
+         case BIT_XOR_EXPRESSION:
+           {
+             /* Calculated CRC may contain crc[]^data[],
+                or crc[]^1, or crc[]^data[]^1.  */
+             xor_exp = as_a<bit_xor_expression *> ((*crc_state)[j]);
+             if (!maybe_neighbour_vals_of_crc (xor_exp, (*crc_state)[j + 1]))
+               return false;
+             break;
+           }
+         default:
+           /* There may not be other type of bit values in the CRC.  */
+           return false;
+       }
+    }
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "Checks passed.  Starting bit by bit matching.\n");
+
+  /* Determine which value might have been checked in the condition.  */
+  value_bit *reference_val = nullptr;
+  if (symb_bit)
+    reference_val = symb_bit;
+  else if (!symb_bit)
+    reference_val = xor_exp;
+
+  /* Check whether crc_state and lfsr bits match.  */
+  return lfsr_and_crc_bits_match (lfsr, crc_state, reference_val, is_left_shift,
+                                 it_beg, it_end, sb_index, final_state);
+  return false;
+}
+
+
+/* Returns true if all states from final_states match the LFSR,
+   otherwise - false.  */
+
+bool
+all_states_match_lfsr (value *lfsr,
+                      bool is_left_shift,
+                      const vec<state *> &final_states)
+{
+  for (size_t i=0; i < final_states.length (); ++i)
+    {
+      state *final_state = final_states[i];
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Matching LFSR and following returned state.\n");
+         state::print_value (final_state->get_first_value ());
+         final_state->print_conditions ();
+       }
+      if (!state_matches_lfsr (lfsr, final_state->get_first_value (),
+                              is_left_shift, final_state))
+       return false;
+    }
+  return true;
+}
diff --git a/gcc/crc_verification.h b/gcc/crc_verification.h
new file mode 100644 (file)
index 0000000..59f7629
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+   Execute symbolically all paths of the function, iterating loops only once.
+   Calculate the value of the polynomial by executing loop with real values.
+   Check calculated final states of return values match determined LFSR.
+   Copyright (C) 2006-2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.   */
+
+#ifndef GCC_CRC_VERIFICATION
+#define GCC_CRC_VERIFICATION
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "cfgloop.h"
+#include "sym-exec/state.h"
+
+class crc_symbolic_execution {
+
+ private:
+  /* A vector of states to keep the current state of each executed path.  */
+  vec<state *> states;
+
+  /* A vector of final states
+     to keep the returned_value and path conditions.  */
+  vec<state *> final_states;
+
+/* Assign symbolic values to the arguments of the function
+   and keep in the state.  */
+  static bool make_symbolic_func_args_and_sizes (function *, state *);
+
+  /* Add declared ssa variables to the state.  */
+  static bool add_function_local_ssa_vars (function *, state *);
+
+  bool execute_assign_statement (const gassign *);
+
+  /* Add next basic blocks of the conditional block
+     for the execution path into the stack.  */
+  void add_next_bbs (basic_block, state *, auto_vec<edge, 20> &);
+
+  /* Keep conditions depending on symbolic variables in the states.  */
+  static bool add_condition (const gcond *, state *, state *);
+
+  /* Create new state for true and false branch.
+     Keep conditions in new created states.  */
+  bool resolve_condition (const gcond *, auto_vec<edge, 20> &);
+
+  /* Keep the calculated value of the return value
+     and the conditions of the executed path.  */
+  bool keep_return_val_and_conditions (const greturn *);
+
+  /* Execute gimple statements of the basic block.
+     Keeping values of variables in the state.  */
+  bool execute_bb_gimple_statements (basic_block, auto_vec<edge, 20> &);
+
+  /* Assign values of phi instruction to its result.
+     Keep updated values in the state.  */
+  bool execute_bb_phi_statements (basic_block, edge);
+
+  /* Execute all statements of the basic block.
+    Keeping values of variables in the state.  */
+  bool execute_bb_statements (basic_block, edge, auto_vec<edge, 20> &);
+
+/* Traverse function fun's all paths from the first basic block to the last.
+   Each time iterate loops only once.
+   Symbolically execute statements of each path.  */
+  bool traverse_function (function *);
+
+  /* Execute the loop, which calculates crc with initial values,
+   to calculate the polynomial.  */
+  bool execute_crc_loop (class loop *, gphi *, gphi *, bool);
+
+ public:
+
+  /* Symbolically execute the function and keep final states.  */
+  bool execute (function *);
+
+  /* Returns calculated polynomial by executing the loop
+     with concrete values.  */
+  value *extract_poly_and_create_lfsr (class loop *, gphi *, gphi *, bool);
+
+  const vec<state *> &get_final_states ()
+  {
+    return final_states;
+  }
+
+  crc_symbolic_execution ()
+  {
+    /* Reserve memory for the vectors of states.  */
+    states.create (30);
+    final_states.create (30);
+  }
+
+  ~crc_symbolic_execution ()
+  {
+    /* Free memory.  */
+    state::clear_states (&states);
+    state::clear_states (&final_states);
+  }
+};
+
+
+/**************************** LFSR MATCHING *********************************/
+// TODO write in separate file
+
+/* Returns true if all states match the LFSR, otherwise - false.  */
+bool
+all_states_match_lfsr (value *,
+                      bool,
+                      const vec<state *> &);
+
+
+/* Returns true if in the CRC value's vector we have one of the form of
+   following consecutive bits
+   1.  0, then 1
+   2.  1, then 0
+   3.  0, then 0
+   4.  1, then 1
+   Otherwise returns false.
+   */
+bool
+maybe_neighbour_vals_of_crc (bit *, value_bit *);
+
+
+/* Returns true if in the CRC value's vector we have one of the form of
+   following consecutive bits
+   1. crc[], then crc[]
+   2. crc[], then crc[]^data[]
+   3. crc[], then crc[]^data[]^1
+   4. crc[], then crc[]^1
+   5. data[], then crc[]^data[]
+   6. data[], then crc[]^data[]^1
+   7. crc[], then crc[]^data1[]^data2[] TODO: Maybe needs a correction.
+   ...
+   Otherwise returns false.  */
+bool
+maybe_neighbour_vals_of_crc (symbolic_bit *, value_bit *);
+
+
+/* Returns true if in the CRC value's vector we have one of the form of
+   following consecutive bits
+   1. crc[]^1 or crc[]^data[]^1, then crc[]
+   2. crc[]^data[]^1, then crc[]^data[]
+   3. crc[]^data[], then crc[] or data[]
+   4. crc[]^data[], then crc[]^data[]
+   5. crc[]^data[], then crc[]^data[]^1
+   Otherwise returns false.  */
+bool
+maybe_neighbour_vals_of_crc (bit_xor_expression *,
+                            value_bit *);
+
+
+#endif //GCC_CRC_VERIFICATION
index 44cf08ebc704902ec02be05e6701f3d27aa79f27..a792769f347ec14025246dd796ae313d78b1bf11 100644 (file)
@@ -34,7 +34,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-range.h"
 #include "tree-scalar-evolution.h"
 #include "hwint.h"
-#include "symb-execute-all-paths.h"
+#include "crc_verification.h"
 
 class crc_optimization {
  private:
@@ -56,7 +56,7 @@ class crc_optimization {
   gphi *second_phi_for_crc;
 
   /* Phi statement, result maybe data (if exists).  */
-  gphi * data;
+  gphi *data;
 
   /* The loop, which probably calculates CRC.  */
   class loop *crc_loop;
@@ -66,7 +66,10 @@ class crc_optimization {
   /* Function's return value size.  */
   unsigned HOST_WIDE_INT return_size;
 
-  /* Depending on the value, may be forward or reversed CRC.  */
+  /* Depending on the value of is_left_shift,
+     may be forward or reversed CRC.
+     If is_left_shift, then it is bit_forward implementations,
+     otherwise bit_reversed.  */
   bool is_left_shift;
 
   /* Will be true, if crc variable and if condition depend on each other.  */
@@ -76,7 +79,6 @@ class crc_optimization {
      otherwise it may calculate CRC.  */
   bool clean_xor_maybe_crc;
 
-
   void set_initial_values ()
   {
     shift_before_xor = nullptr;
@@ -99,12 +101,12 @@ class crc_optimization {
 
   /* Checks the loop iteration number.
    The loop for CRC calculation may do 8, 16, 24, 32 iterations.  */
-  bool is_loop_of_crc_calculation (class loop *func_loop);
+  bool maybe_crc_iteration_count (class loop *func_loop);
 
   /* Check whether found xor_stmt is for calculating crc.
-   The function fun calculates crc only if there is a shift operation
+   The function crc_fun calculates crc only if there is a shift operation
    in the crc_loop.  */
-  bool xor_calculates_crc (function *fun, class loop *crc_loop,
+  bool xor_calculates_crc (function *crc_fun, class loop *crc_loop,
                           const gimple *stmt);
 
   /* This function goes up through the def-chain of the name,
@@ -115,7 +117,7 @@ class crc_optimization {
    or check_def_stmt_for_if function.  */
   void
   get_dep (tree name,
-          bool (crc_optimization::*continue_to_check_dep) (gimplestmt));
+          bool (crc_optimization::*continue_to_check_dep) (gimple *stmt));
 
 /* Checks whether the def_stmt statement, dependent from xor's operands,
    does shift operation for calculating crc
@@ -123,20 +125,20 @@ class crc_optimization {
    Returns false, if there is an instruction which may not exist
    in the CRC loop.
    Returns true, if the def-chain examination must be continued.  */
-  bool continue_to_check_dep_for_xor (gimplestmt);
+  bool continue_to_check_dep_for_xor (gimple *stmt);
 
 /* Checks whether if's condition and xor-ed variable
    are dependent from the same variable.
    (The crc variable is xor-ed if variable's MSB/LSB is 1).
    Also determines phi instruction's of data and crc
    (for further polynomial extraction).  */
-  bool continue_to_check_dep_for_if (gimplestmt);
+  bool continue_to_check_dep_for_if (gimple *stmt);
 
   /* This function checks that xor is done under the condition
    of MSB/LSB being one.
    Checks that if condition's variable and xor-ed variable
-   depend on same variable and if there is a shift1 in the same block with xor,
-   on the opposite branch must be another shift1 to the same direction.
+   depend on same variable and if there is a shift 1 in the same block with xor,
+   on the opposite branch must be another shift 1 to the same direction.
    xor_bb is the basic block, where xor operation is done.
    pred_bb is the predecessor basic block of the xor_bb,
    it is assumed that the last stmt of pred_bb checks the condition
@@ -168,7 +170,7 @@ class crc_optimization {
 
   /* Get the return value size of the function
      and assign to return_size member.  */
-  void set_return_value_size (function *fun);
+  void set_return_value_size (function *crc_fun);
 
   /* This function checks whether calculated crc value
      (maybe modified) is returned.
@@ -184,7 +186,9 @@ class crc_optimization {
 };
 
 
-/* Set GIMPLE_PHI and GIMPLE statements of the crc loop not visited.  */
+/* TODO use existing code or move the function.
+   Set GIMPLE_PHI and GIMPLE statements of the crc loop not visited.  */
+
 void
 set_loop_statements_not_visited (class loop *loop)
 {
@@ -210,7 +214,10 @@ set_loop_statements_not_visited (class loop *loop)
     }
 }
 
-/* Set GIMPLE_PHI and GIMPLE statements of the function not visited.  */
+
+/* TODO use existing code or move the function.
+   Set GIMPLE_PHI and GIMPLE statements of the function not visited.  */
+
 static void
 set_all_statements_not_visited (function *fun)
 {
@@ -234,6 +241,7 @@ set_all_statements_not_visited (function *fun)
 
 
 /* Prints extracted details of CRC calculation.  */
+
 void
 crc_optimization::print_crc_information ()
 {
@@ -293,10 +301,10 @@ crc_optimization::returned_value_depends_on_crc (tree lhs)
    and assign to return_size member.  */
 
 void
-crc_optimization::set_return_value_size (function *fun)
+crc_optimization::set_return_value_size (function *crc_fun)
 {
   return_size = 0;
-  tree tree_return_value_size = DECL_SIZE (DECL_RESULT (fun->decl));
+  tree tree_return_value_size = DECL_SIZE (DECL_RESULT (crc_fun->decl));
   if (tree_fits_uhwi_p (tree_return_value_size))
     {
       return_size = tree_to_uhwi (tree_return_value_size);
@@ -343,12 +351,12 @@ crc_optimization::find_shift_after_xor (class loop *crc_loop, tree lhs)
          find_shift_after_xor
              (crc_loop, gimple_phi_result (stmt));
        }
-      else if (is_gimple_assign (stmt))
-       if (can_not_be_shift_of_crc (stmt, false))
-         {
-           shift_after_xor = nullptr;
-           return;
-         }
+      else if (is_gimple_assign (stmt)
+              && can_not_be_shift_of_crc (stmt, false))
+       {
+         shift_after_xor = nullptr;
+         return;
+       }
     }
 }
 
@@ -431,6 +439,9 @@ crc_optimization::crc_cond_and_shift (const basic_block &pred_bb,
                                      const basic_block &xor_bb)
 {
   gcond *cond = nullptr;
+  /* Check whether pred_bb contains condition.
+     We will consider only those cases
+     when xor is done immediately under condition.  */
   if (is_a<gcond *> (last_stmt (pred_bb)))
     cond = as_a<gcond *> (last_stmt (pred_bb));
   if (!cond)
@@ -509,6 +520,7 @@ crc_optimization::is_acceptable_statement (const tree_code &stmt_code)
         || TREE_CODE_CLASS (stmt_code) == tcc_unary;
 }
 
+
 /* Checks whether assigment statement does shift operation
    (checks that shift 1 is done),
    if it doesn't - checks whether it is acceptable operation
@@ -547,7 +559,7 @@ crc_optimization::can_not_be_shift_of_crc (gimple *assign_stmt,
              shift_after_xor = assign_stmt;
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file,
-                        "Found shift1 after xor.\n");
+                        "Found <<1 or >>1 after xor.\n");
            }
          return false;
        }
@@ -567,9 +579,9 @@ crc_optimization::can_not_be_shift_of_crc (gimple *assign_stmt,
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file,
-                "\nStmt with following operation "
+                "\nStmt with the following operation "
                 "code %s between xor and shift, "
-                "may not be crc.\n", get_tree_code_name (stmt_code));
+                "may not be CRC.\n", get_tree_code_name (stmt_code));
 
       return true;
     }
@@ -587,7 +599,7 @@ crc_optimization::can_not_be_shift_of_crc (gimple *assign_stmt,
 void
 crc_optimization::get_dep (tree name,
                           bool (crc_optimization::*continue_to_check_dep) (
-                              gimplessa))
+                              gimple *ssa))
 {
   if (!(name && TREE_CODE (name) == SSA_NAME))
     return;
@@ -622,7 +634,7 @@ crc_optimization::get_dep (tree name,
       get_dep (ssa1, continue_to_check_dep);
       get_dep (ssa2, continue_to_check_dep);
     }
-   else if (is_a<gphi *> (stmt) && !bb_loop_header_p (gimple_bb (stmt)))
+  else if (is_a<gphi *> (stmt) && !bb_loop_header_p (gimple_bb (stmt)))
     {
       for (unsigned i = 0; i < gimple_phi_num_args (stmt); i++)
        {
@@ -668,13 +680,13 @@ crc_optimization::continue_to_check_dep_for_xor (gimple *def_stmt)
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file,
-                    "Phi's definition is in loop header.\n");
+                    "Phi's definition is in the loop header.\n");
 
          /* The case when polynomial's value is determined by
             a phi statement.  */
          if (first_phi_for_crc)
            {
-             second_phi_for_crc = as_a <gphi *> (def_stmt);
+             second_phi_for_crc = as_a<gphi *> (def_stmt);
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "Set second phi.\n");
            }
@@ -682,12 +694,12 @@ crc_optimization::continue_to_check_dep_for_xor (gimple *def_stmt)
            {
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "Set first phi.\n");
-             first_phi_for_crc = as_a <gphi *> (def_stmt);
+             first_phi_for_crc = as_a<gphi *> (def_stmt);
            }
          return true;
        }
     }
-    return true;
+  return true;
 }
 
 
@@ -723,7 +735,7 @@ crc_optimization::continue_to_check_dep_for_if (gimple *def_stmt)
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file,
-                      "If condition has dependence "
+                      "The condition of if statement has dependence "
                       "from the same variable as xor.\n"
                       "CRC's phi statement is:\n");
              print_gimple_stmt (dump_file, def_stmt, dump_flags);
@@ -743,7 +755,7 @@ crc_optimization::continue_to_check_dep_for_if (gimple *def_stmt)
              return false;
            }
 
-         data = as_a <gphi *> (def_stmt);
+         data = as_a<gphi *> (def_stmt);
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file,
@@ -757,11 +769,11 @@ crc_optimization::continue_to_check_dep_for_if (gimple *def_stmt)
 
 
 /* Check whether found xor_stmt is for calculating crc.
-   The function fun calculates crc only if there is a shift operation
+   The function crc_fun calculates crc only if there is a shift operation
    in the crc_loop.  */
 
 bool
-crc_optimization::xor_calculates_crc (function *fun, class loop *crc_loop,
+crc_optimization::xor_calculates_crc (function *crc_fun, class loop *crc_loop,
                                      const gimple *xor_stmt)
 {
   tree crc_var = gimple_assign_lhs (xor_stmt);
@@ -770,11 +782,10 @@ crc_optimization::xor_calculates_crc (function *fun, class loop *crc_loop,
   get_dep (crc_var,
           &crc_optimization::continue_to_check_dep_for_xor);
 
-
   if (!clean_xor_maybe_crc)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
-       fprintf (dump_file, "Xor doesn't calculate crc.\n");
+       fprintf (dump_file, "Xor isn't used for CRC calculation.\n");
       return false;
     }
 
@@ -803,21 +814,22 @@ crc_optimization::xor_calculates_crc (function *fun, class loop *crc_loop,
     {
       if (crc_cond_and_shift (single_pred (bb), bb))
        {
-         set_all_statements_not_visited (fun);
+         set_all_statements_not_visited (crc_fun);
          bool crc_is_returned = returned_value_depends_on_crc (crc_var);
          if (dump_file)
            {
              if (crc_is_returned)
                {
                  fprintf (dump_file,
-                          "\nAttention! %s function calculates CRC.\n",
-                          function_name (fun));
+                          "\n%s function maybe calculates CRC "
+                          "and returns it.\n",
+                          function_name (crc_fun));
                }
              else
                {
                  fprintf (dump_file,
-                          "\nFound naive crc implementation in %s.\n",
-                          function_name (fun));
+                          "\n%s function maybe calculates CRC.\n",
+                          function_name (crc_fun));
                }
            }
          return true;
@@ -837,7 +849,7 @@ crc_optimization::xor_calculates_crc (function *fun, class loop *crc_loop,
    The loop for CRC calculation may do 8, 16, 24, 32 iterations.  */
 
 bool
-crc_optimization::is_loop_of_crc_calculation (class loop *func_loop)
+crc_optimization::maybe_crc_iteration_count (class loop *func_loop)
 {
   loop_iteration_number = 0;
   tree n_inters = number_of_latch_executions (func_loop);
@@ -846,6 +858,7 @@ crc_optimization::is_loop_of_crc_calculation (class loop *func_loop)
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file,
                 "Loop iteration number is chrec_dont_know.\n");
+      return false;
 
     }
   else if (tree_fits_uhwi_p (n_inters))
@@ -856,7 +869,8 @@ crc_optimization::is_loop_of_crc_calculation (class loop *func_loop)
                 loop_iteration_number);
 
       if (!(loop_iteration_number == 7 || loop_iteration_number == 15
-           || loop_iteration_number == 23 || loop_iteration_number == 31))
+           || loop_iteration_number == 23 || loop_iteration_number == 31
+           || loop_iteration_number == 63))
        return false;
     }
   return true;
@@ -888,7 +902,7 @@ crc_optimization::function_may_calculate_crc (function *fun)
       if (!loop || loop->inner)
        continue;
 
-      if (!is_loop_of_crc_calculation (loop))
+      if (!maybe_crc_iteration_count (loop))
        continue;
 
       crc_loop = loop;
@@ -925,55 +939,53 @@ crc_optimization::function_may_calculate_crc (function *fun)
   return false;
 }
 
+
 unsigned int
 crc_optimization::execute (function *fun)
 {
   if (function_may_calculate_crc (fun))
-  {
-    crc_symb_execution symb_exec;
-    if (!symb_exec.execute_function (fun))
-      {
-       if (dump_file)
-         fprintf (dump_file, "\nAttention! Not the CRC we want!\n");
-       return 0;
-      }
-
-      crc_symb_execution execute_loop;
-      value * lfsr
-      = execute_loop.extract_poly_and_create_lfsr (crc_loop, first_phi_for_crc,
-                                                  data, is_left_shift);
+    {
+      crc_symbolic_execution symbolically_execute_function;
+      if (!symbolically_execute_function.execute (fun))
+       {
+         if (dump_file)
+           fprintf (dump_file, "\nCRC verification didn't succeed "
+                               "during symbolic execution!\n");
+         return 0;
+       }
 
+      crc_symbolic_execution execute_loop;
+      value *lfsr
+         = execute_loop.extract_poly_and_create_lfsr (crc_loop,
+                                                      first_phi_for_crc,
+                                                      data, is_left_shift);
       if (!lfsr)
        {
-       if (dump_file)
-         fprintf (dump_file, "Couldn't create LFSR!\n");
-       return 0;
+         if (dump_file)
+           fprintf (dump_file, "Couldn't create LFSR!\n");
+         return 0;
        }
-      else
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
        {
-         if (dump_file && (dump_flags & TDF_DETAILS))
-           {
-             fprintf (dump_file, "\nLFSR value is \n");
-             state::print_value (lfsr);
-           }
+         fprintf (dump_file, "\nLFSR value is \n");
+         state::print_value (lfsr);
        }
 
-      if (symb_exec.all_states_match_lfsr (lfsr, is_left_shift))
+      if (all_states_match_lfsr (lfsr, is_left_shift,
+                                symbolically_execute_function
+                                    .get_final_states ()))
        {
          if (dump_file)
-           {
-             fprintf (dump_file, "The function really calculates CRC "
-                                 "and returns it!\n");
-           }
+           fprintf (dump_file, "%s function calculates CRC!\n",
+                    function_name (fun));
        }
       else
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
-           {
-             fprintf (dump_file, "Returned state and LFSR differ.\n");
-           }
+           fprintf (dump_file, "Returned state and LFSR differ.\n");
        }
-  }
+    }
   return 0;
 }
 
index 95e6bd42686b382be3e47b62dc8e2de056f9b737..f2aae1d619ff7dda31de44bc9d94d34d9b4424d2 100644 (file)
@@ -26,7 +26,7 @@ state::state (const state &s)
 
 state::~state ()
 {
-  clear_states ();
+  clear_var_states ();
   clear_conditions ();
 }
 
@@ -164,7 +164,19 @@ state::bulk_add_conditions (const hash_set<bit_expression *> &conds)
 
 
 void
-state::clear_states ()
+state::clear_states (vec<state *> *states)
+{
+  while (!states->is_empty ())
+    {
+      delete states->last ();
+      states->pop ();
+    }
+  states->release ();
+}
+
+
+void
+state::clear_var_states ()
 {
   for (auto iter = var_states.begin (); iter != var_states.end (); ++iter)
     {
index b8311cdb2fcc17c37aca19b177faf7c36361992a..67913e9f934ef85102beefd7c4b62561323bf462 100644 (file)
@@ -226,7 +226,9 @@ class state {
 
   bool add_var_state (tree var, value *state);
 
-  void clear_states ();
+  static void clear_states (vec<state *> *states);
+
+  void clear_var_states ();
 
   void clear_conditions ();
 
index d65763b2b2a8f44f765c4f4dee699c447a0a1a7f..cfa78e049b1140a0a27c238726ba00862891232b 100644 (file)
@@ -48,7 +48,7 @@ uint16_t gen_crc16(const uint8_t *data, uint16_t size) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump "Found naive crc implementation in gen_crc16." "crc"} } */
+/* { dg-final { scan-tree-dump "gen_crc16 function maybe calculates CRC." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 16" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 15" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit forward" "crc"} } */
index 29ee5686e42c766145a15c93314fa36439d7435b..7cf77b856d6b442020430f70dc17ccc936158823 100644 (file)
@@ -17,7 +17,7 @@ u8 crc8(u16 data) {
     return (u8)(data >> 8);
 }
 
-/* { dg-final { scan-tree-dump "Attention! crc8 function calculates CRC." "crc"} } */
+/* { dg-final { scan-tree-dump "crc8 function maybe calculates CRC and returns it." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 8" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit forward" "crc"} } */
index 89d12f866766fd76b1a3347b2a68bc38bc273cf7..8f11345dc956eb01d1a84a3b543b3a28e715c9f9 100644 (file)
@@ -23,5 +23,5 @@ ee_u16 not_crcu8(ee_u8 data, ee_u16 crc) {
     }
     return crc;
 }
-/* { dg-final { scan-tree-dump-times "Attention! crcu8 function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "crcu8 function maybe calculates CRC" 0 "crc"} } */
 
index 66c6743b62a51c6ba96b1b12c93781460ee514eb..09de56b53ab49065fdf7dc0c4d65276ffea675f2 100644 (file)
@@ -23,5 +23,5 @@ notCrc(uint8_t const message[], int nBytes) {
     return (remainder);
 }
 
-/* { dg-final { scan-tree-dump-times "Attention! notCrc function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "notCrc function maybe calculates CRC" 0 "crc"} } */
 
index ee4edde225f8f2800e2e2189722e968b46b84544..0c7fce66dc21ded264480896cd595ab37300968d 100644 (file)
@@ -17,5 +17,5 @@ uint16_t not_crc16_update(uint16_t crc, uint8_t a) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump-times "Attention! not_crc16_update function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "not_crc16_update function maybe calculates CRC" 0 "crc"} } */
 
index ab1cf04c9823ac7555d76e5d7374e1113060ffd7..7dd23995abf6b1d4378fbb72231f8b7b36e4e471 100644 (file)
@@ -14,5 +14,5 @@ uint16_t not_crc(uint16_t crc, uint8_t a) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump-times "Attention! not_crc function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "not_crc function maybe calculates CRC" 0 "crc"} } */
 
index a9f8c84e0ba7094c00ae078652b4fd6b4af74bfe..742922884dc3e00976ecf4e5367b4e4ed4b9e8db 100644 (file)
@@ -21,6 +21,6 @@ uint8_t not_crc(uint8_t *data, size_t len) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump-times "Attention! not_crc function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "not_crc function maybe calculates CRC" 0 "crc"} } */
 
 
index 4e0983acfd3f20af6f63685398bd84c6c306ebaa..5e1a166550f68fb1e0dff7ba78a437d8c2af6187 100644 (file)
@@ -18,6 +18,6 @@ u8 not_crc(u16 data) {
     return (u8)(data >> 8);
 }
 
-/* { dg-final { scan-tree-dump-times "Attention! not_crc function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "not_crc function maybe calculates CRC" 0 "crc"} } */
 
 
index 9f04c0498b7cd7933ab826db7494bc7f295ace95..fd439a798ffe25b46ca130c0d1f8b00d34f70366 100644 (file)
@@ -15,5 +15,5 @@ uint16_t not_crc(uint16_t crc, uint8_t a) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump-times "Attention! not_crc function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "not_crc function maybe calculates CRC" 0 "crc"} } */
 
index b023fc21fa5a99b598c843b6691cdc5b2cda874e..c3cf813fb7861cc6784dd82217280163a3ad7e72 100644 (file)
@@ -16,5 +16,5 @@ int16_t not_crc(int16_t crc, int8_t a) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump-times "Attention! not_crc function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "not_crc function maybe calculates CRC" 0 "crc"} } */
 
index eea073de9243322bff61044f2c857a161ed1567c..a25fb278654cbf954dc03d62f84b03b5f78c779a 100644 (file)
@@ -12,5 +12,5 @@ uint16_t not_crc(uint16_t crc, uint8_t a) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump-times "Attention! not_crc function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "not_crc function maybe calculates CRC" 0 "crc"} } */
 
index e1d342d09d1b6c5642af43bdf6d614abdc8531fc..55d03bdd3eccc5096e67632014296bb90134a0f3 100644 (file)
@@ -21,9 +21,10 @@ unsigned int crc16(unsigned int crcValue, unsigned char newByte) {
     return crcValue;
 }
 
-/* { dg-final { scan-tree-dump "Attention! crc16 function calculates CRC." "crc"} } */
+/* { dg-final { scan-tree-dump "crc16 function maybe calculates CRC and returns it." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 32" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit forward" "crc"} } */
 /* { dg-final { scan-tree-dump "Executing \[a-zA-Z_\]\[a-zA-Z0-9_\]* = \[a-zA-Z_\]\[a-zA-Z0-9_\]* \\\^ \[a-zA-Z0-9_\]+\(\\\(\[a-zA-Z\]\\\)\)?;" "crc" } } */
 /* { dg-final { scan-tree-dump "Executing \[a-zA-Z_\]\[a-zA-Z0-9_\]* = \[a-zA-Z_\]\[a-zA-Z0-9_\]* \(<<|>>\) \[0-9]+;" "crc" } } */
+/* { dg-final { scan-tree-dump "crc16 function calculates CRC!" "crc"} } */
index e9b68976b80b13daf5f06575fa0029520db7ac98..82e1b53541e9af1e49b3460d2385235e575d4c35 100644 (file)
@@ -18,5 +18,5 @@ uint16_t not_crc(uint16_t crc, uint8_t a) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump-times "Attention! not_crc function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "not_crc function maybe calculates CRC" 0 "crc"} } */
 
index c54920af3faca43e0b262666ec670412398ef2f2..c7b496273c9c253d7f8e36318a519171bd5ce127 100644 (file)
@@ -22,4 +22,4 @@ ee_u16 not_crc(ee_u8 data, ee_u16 crc) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump-times "Attention! not_crc function calculates CRC." 0 "crc"} } */
\ No newline at end of file
+/* { dg-final { scan-tree-dump-times "not_crc function maybe calculates CRC" 0 "crc"} } */
\ No newline at end of file
index 153eb6b314061c0b358397bd7e98710f74753349..80a9ebab116263a609be34d3b8ab233711c137a7 100644 (file)
@@ -14,4 +14,4 @@ uint8_t not_crc(uint8_t crc, uint8_t data) {
     }
     return crc;
 }
-/* { dg-final { scan-tree-dump-times "Attention! not_crc function calculates CRC." 0 "crc"} } */
+/* { dg-final { scan-tree-dump-times "not_crc function maybe calculates CRC" 0 "crc"} } */
index a0d1d9c4c27351cb1b16e670a96035fa2518dff4..afc12827b732725ade270cd62e03835c65bd4b63 100644 (file)
@@ -15,7 +15,7 @@ uint16_t crc16(uint16_t crc, uint8_t a, uint16_t polynom) {
   return crc;
 }
 
-/* { dg-final { scan-tree-dump "Attention! crc16 function calculates CRC." "crc"} } */
+/* { dg-final { scan-tree-dump "crc16 function maybe calculates CRC and returns it." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 16" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit reversed" "crc"} } */
index ee015da54002bd2e4f37e869d1b21e0ba7ac8455..6eee036fd578706056af095f83530c3533f4337e 100644 (file)
@@ -51,7 +51,7 @@ uint16_t gen_crc16(const uint8_t *data, uint16_t size) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump "Found naive crc implementation in gen_crc16." "crc"} } */
+/* { dg-final { scan-tree-dump "gen_crc16 function maybe calculates CRC." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 16" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 15" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit forward" "crc"} } */
index 0186d36bb5daede3de31f78b1527ae388805366c..cf5267c464242627b00d2aba81d32d0c6cfbc4a1 100644 (file)
@@ -26,7 +26,7 @@ unsigned short crc16(char *data_p, unsigned short length) {
     return (crc);
 }
 
-/* { dg-final { scan-tree-dump "Attention! crc16 function calculates CRC." "crc"} } */
+/* { dg-final { scan-tree-dump "crc16 function maybe calculates CRC and returns it." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 16" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit reversed" "crc"} } */
index 7cc18f77102da58a6c133b96914215603ee21b00..7cd3d62ea154bcf3419471eb7756df1f2cf01cbc 100644 (file)
@@ -15,9 +15,10 @@ uint16_t crc16_update(uint16_t crc, uint8_t a) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump "Attention! crc16_update function calculates CRC." "crc"} } */
+/* { dg-final { scan-tree-dump "crc16_update function maybe calculates CRC and returns it." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 16" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit reversed" "crc"} } */
 /* { dg-final { scan-tree-dump "Executing \[a-zA-Z_\]\[a-zA-Z0-9_\]* = \[a-zA-Z_\]\[a-zA-Z0-9_\]* \\\^ \[a-zA-Z0-9_\]+\(\\\(\[a-zA-Z\]\\\)\)?;" "crc" } } */
 /* { dg-final { scan-tree-dump "Executing \[a-zA-Z_\]\[a-zA-Z0-9_\]* = \[a-zA-Z_\]\[a-zA-Z0-9_\]* \(<<|>>\) \[0-9]+;" "crc" } } */
+/* { dg-final { scan-tree-dump "crc16_update function calculates CRC!" "crc"} } */
\ No newline at end of file
index 257e70b51823e3ce2f858f95be590dba78a0d5ae..c9009051b3e20c374ee8645622efa7271513978f 100644 (file)
@@ -22,9 +22,10 @@ ee_u16 crcu8(ee_u8 data, ee_u16 crc) {
     }
     return crc;
 }
-/* { dg-final { scan-tree-dump "Attention! crcu8 function calculates CRC." "crc"} } */
+/* { dg-final { scan-tree-dump "crcu8 function maybe calculates CRC and returns it." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 16" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit reversed" "crc"} } */
 /* { dg-final { scan-tree-dump "Executing \[a-zA-Z_\]\[a-zA-Z0-9_\]* = \[a-zA-Z_\]\[a-zA-Z0-9_\]* \\\^ \[a-zA-Z0-9_\]+\(\\\(\[a-zA-Z\]\\\)\)?;" "crc" } } */
 /* { dg-final { scan-tree-dump "Executing \[a-zA-Z_\]\[a-zA-Z0-9_\]* = \[a-zA-Z_\]\[a-zA-Z0-9_\]* \(<<|>>\) \[0-9]+;" "crc" } } */
+/* { dg-final { scan-tree-dump "crcu8 function calculates CRC!" "crc"} } */
\ No newline at end of file
index 9802ab35b02ebdfd8cbc5e4b7d17f0dca5517d1e..cfb40b47b271e285b27d680876c6000feaefda0e 100644 (file)
@@ -26,7 +26,7 @@ crcSlow(uint8_t const message[], int nBytes) {
     return (remainder);
 }
 
-/* { dg-final { scan-tree-dump "Attention! crcSlow function calculates CRC." "crc"} } */
+/* { dg-final { scan-tree-dump "crcSlow function maybe calculates CRC and returns it." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 8" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit forward" "crc"} } */
index f05d0557f097e2334325b1f5eff4858b5329f2f6..d042a0b7b876756695cca385b98ee1a1004a327e 100644 (file)
@@ -15,9 +15,10 @@ uint16_t crc_xmodem_update(uint16_t crc, uint8_t data) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump "Attention! crc_xmodem_update function calculates CRC." "crc"} } */
+/* { dg-final { scan-tree-dump "crc_xmodem_update function maybe calculates CRC and returns it." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 16" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit forward" "crc"} } */
 /* { dg-final { scan-tree-dump "Executing \[a-zA-Z_\]\[a-zA-Z0-9_\]* = \[a-zA-Z_\]\[a-zA-Z0-9_\]* \\\^ \[a-zA-Z0-9_\]+\(\\\(\[a-zA-Z\]\\\)\)?;" "crc" } } */
 /* { dg-final { scan-tree-dump "Executing \[a-zA-Z_\]\[a-zA-Z0-9_\]* = \[a-zA-Z_\]\[a-zA-Z0-9_\]* \(<<|>>\) \[0-9]+;" "crc" } } */
+/* { dg-final { scan-tree-dump "crc_xmodem_update function calculates CRC!" "crc"} } */
\ No newline at end of file
index d04f42e541a27a06c205ff51a20b393cf321f6b6..ec990e1f78df3506c28b024b013eba50fc6c7115 100644 (file)
@@ -15,9 +15,10 @@ uint8_t _crc_ibutton_update(uint8_t crc, uint8_t data) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump "Attention! _crc_ibutton_update function calculates CRC." "crc"} } */
+/* { dg-final { scan-tree-dump "_crc_ibutton_update function maybe calculates CRC and returns it." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 8" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit reversed" "crc"} } */
 /* { dg-final { scan-tree-dump "Executing \[a-zA-Z_\]\[a-zA-Z0-9_\]* = \[a-zA-Z_\]\[a-zA-Z0-9_\]* \\\^ \[a-zA-Z0-9_\]+\(\\\(\[a-zA-Z\]\\\)\)?;" "crc" } } */
 /* { dg-final { scan-tree-dump "Executing \[a-zA-Z_\]\[a-zA-Z0-9_\]* = \[a-zA-Z_\]\[a-zA-Z0-9_\]* \(<<|>>\) \[0-9]+;" "crc" } } */
+/* { dg-final { scan-tree-dump "_crc_ibutton_update function calculates CRC!" "crc"} } */
index 6c644b4ed70e80059f6d6a8aa776dc8e02621bf9..d48e9ce532cf2bd990e7f0cde196610ab9447c29 100644 (file)
@@ -20,7 +20,7 @@ uint8_t gencrc(uint8_t *data, size_t len) {
     return crc;
 }
 
-/* { dg-final { scan-tree-dump "Attention! gencrc function calculates CRC." "crc"} } */
+/* { dg-final { scan-tree-dump "gencrc function maybe calculates CRC and returns it." "crc"} } */
 /* { dg-final { scan-tree-dump "Return size is 8" "crc"} } */
 /* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
 /* { dg-final { scan-tree-dump "Bit forward" "crc"} } */