]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Added LFSR matching v1:
authorMariam Arutunian <mariamarutunian@gmail.com>
Fri, 9 Dec 2022 12:55:18 +0000 (16:55 +0400)
committerJeff Law <jlaw@ventanamicro>
Tue, 21 Mar 2023 15:03:19 +0000 (09:03 -0600)
  - Added functions to check whether LFSR and returned states match (it's not complete).

Changes in Traverse and execute CRC function v7:

  - Pass correct tree to do_mem_ref function

Changes in Sym_exec v8:

  - Added get_first_value () function in state class to get state's first value.

gcc/gimple-crc-optimization.cc
gcc/sym-exec/state.cc
gcc/sym-exec/state.h
gcc/symb-execute-all-paths.cc
gcc/symb-execute-all-paths.h

index dd1595ad261057d279dc06a940d8390c54b76315..12868acd3373358c21443e11d44419d0af0c41e4 100644 (file)
@@ -957,7 +957,22 @@ crc_optimization::execute (function *fun)
              state::print_bits (lfsr);
            }
        }
-       /* TODO: Match LFSR.  */
+
+      if (symb_exec.states_match_lfsr (lfsr))
+       {
+         if (dump_file)
+           {
+             fprintf (dump_file, "The function really calculates CRC "
+                                 "and returns it!\n");
+           }
+       }
+      else
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "Returned state and LFSR differ.\n");
+           }
+       }
   }
   return 0;
 }
index 301f11acef699a4787c8612cab997e3c67fb009f..b32239dae90433f53e54e1c5554a5b9be535d5b4 100644 (file)
@@ -58,6 +58,13 @@ state::get_bits (tree var)
   return var_states.get (var);
 }
 
+/* Get the value of the tree, which is in the beginning of the var_states.  */
+
+vec<value*> *
+state::get_first_value ()
+{
+  return &(*(var_states.begin ())).second;
+}
 
 const hash_set<bit_expression *>&
 state::get_conditions ()
index c032212aa9c4ce37af738ee11b228cf96e25235f..9a4231cfe1d7795d146b54bb9777e887af2b76b3 100644 (file)
@@ -230,6 +230,9 @@ class state {
 
   vec<value*> * get_bits (tree var);
 
+  /* Get the value of the tree, which is in the beginning of the var_states.  */
+  vec<value*> * get_first_value ();
+
   const hash_set<bit_expression *>& get_conditions ();
 
   /* Adds a variable with unknown value to state.  Such variables are
index 07b4b7238c802512f8a7d8adc9c8228a5150d75a..a9db491ee5c14b958064f435f1478c5da8ee9c3e 100644 (file)
@@ -141,7 +141,10 @@ crc_symb_execution::execute_assign_statement (const gassign *gs)
              return true;
            return false;
          case MEM_REF:
-           if (current_state->do_mem_ref (op1, lhs))
+           /* 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:
@@ -682,7 +685,7 @@ bool
 crc_symb_execution::execute_crc_loop (loop *crc_loop, gphi *crc, gphi *data,
                                      bool is_shift_left)
 {
-  if (dump_file)
+  if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "\n\nTrying to calculate the polynomial.\n\n");
 
   states.quick_push (new state);
@@ -786,4 +789,152 @@ crc_symb_execution::extract_poly_and_create_lfsr (loop *crc_loop,
     }
 
   return state::create_lfsr (calculated_crc, polynomial, is_shift_left);
+}
+
+bool
+condition_is_true ()
+{
+  return true;
+}
+
+bool
+condition_is_false ()
+{
+  return true;
+}
+
+
+/* Returns true if the symb_exp is a bit_xor_expression and const_bit equals 1.
+   Otherwise, returns false.  */
+bool
+is_one (value * 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, 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 ();
+
+  size_t diff;
+  if (sym_bit_index > lfsr_bit_index)
+    diff = sym_bit_index - lfsr_bit_index;
+  else
+    diff = lfsr_bit_index - sym_bit_index;
+
+  /* Indexes of the symbolic bit may differ by 0, 8, 16, 24, 32, ...  */
+  return  diff % 8 == 0;
+}
+
+
+/* Returns true if bit is a bit_xor_expression
+   and xor-ed values are valid symbolic bits.
+   Otherwise, returns false.  */
+bool
+is_a_valid_xor (value* bit, size_t index)
+{
+  return is_a <bit_xor_expression *> (bit)
+        && is_a_valid_symb ((as_a <bit_xor_expression *> (bit))->get_left (),
+                            index)
+        && is_a_valid_symb ((as_a <bit_xor_expression *> (bit))->get_right (),
+                            index);
+}
+
+
+/* Returns true if bit is a valid bit_xor_expression with 1.
+   Otherwise, returns false.  */
+bool
+is_a_valid_xor_one (value* bit, size_t index)
+{
+   if (is_a <bit_xor_expression *> (bit))
+     {
+       value * 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, index)
+             || is_a_valid_symb (symb_exp, index);
+     }
+   else
+     return false;
+}
+
+
+/* Returns true if the state matches the LFSR, otherwise - false.  */
+bool
+crc_symb_execution::state_matches_lfsr (const vec<value*> &lfsr,
+                                       const vec<value*> &crc_state)
+{
+  for (size_t i = 0; i < lfsr.length () && crc_state.length (); i++)
+    {
+       if (dump_file && (dump_flags & TDF_DETAILS))
+        fprintf (dump_file, "Checking %lu-th bit.\n", i);
+
+      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)
+               && condition_is_true ())
+         || (is_a_valid_symb (crc_state[i], index) && condition_is_false ()))
+         || ((is_a_valid_xor_one (crc_state[i], index) && condition_is_true ())
+         || (is_a_valid_xor (crc_state[i], index) && condition_is_false ()))))
+           return false;
+       }
+      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)
+               || condition_is_false ()))
+           return false;
+       }
+      else if (is_a <bit *> (lfsr[i]))
+       {
+         if (!is_a <bit*> (crc_state[i]) || as_a <bit*> (lfsr[i])->get_val ()
+             != as_a <bit*> (crc_state[i])->get_val ())
+           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 all states match the LFSR, otherwise - false.  */
+bool
+crc_symb_execution::states_match_lfsr (vec<value*> * lfsr)
+{
+  while (!final_states.is_empty ())
+    {
+      state * final_state = final_states.last ();
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Matching LFSR and following returned state.\n");
+         state::print_bits (final_state->get_first_value ());
+       }
+      if (!state_matches_lfsr (*lfsr, *(final_state->get_first_value ())))
+       return false;
+      final_states.pop ();
+      delete final_state;
+    }
+ return true;
 }
\ No newline at end of file
index 7177a3fc22215157505b9976c29a5d342eeea97d..4d07498d32bac273fed9d1b40785e99d42865eb2 100644 (file)
@@ -94,7 +94,11 @@ class crc_symb_execution {
    to calculate the polynomial.  */
   bool execute_crc_loop (loop *, gphi *, gphi *, bool);
 
+  /* Returns true if the state matches the LFSR, otherwise - false.  */
+  bool state_matches_lfsr (const vec<value*> &, const vec<value*> &);
+
  public:
+
   /* Symbolically execute the function and keep final states.  */
   bool execute_function (function *);
 
@@ -102,6 +106,9 @@ class crc_symb_execution {
      with concrete values.  */
   vec<value*> * extract_poly_and_create_lfsr (loop *, gphi *, gphi *, bool);
 
+  /* Returns true if all states match the LFSR, otherwise - false.  */
+  bool states_match_lfsr (vec<value*> *lfsr);
+
   crc_symb_execution ()
   {
     /* Reserve memory for the vectors of states.  */