2 Copyright (C) 2022-2025 Free Software Foundation, Inc.
3 Contributed by Mariam Arutunian <mariamarutunian@gmail.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* This pass performs CRC optimization. */
24 #include "coretypes.h"
28 #include "tree-pass.h"
30 #include "gimple-iterator.h"
33 #include "tree-scalar-evolution.h"
34 #include "crc-verification.h"
36 class crc_optimization
{
38 /* Record of statements already seen. */
39 bitmap m_visited_stmts
;
41 /* Input CRC of the loop. */
44 /* Input data of the loop. */
47 /* The statement doing shift 1 operation before/after xor operation. */
50 /* Phi statement from the head of the loop for CRC. */
53 /* Phi statement for the data from the head of the loop if exists,
54 otherwise - nullptr. */
57 /* The loop, which probably calculates CRC. */
58 class loop
*m_crc_loop
;
60 /* Polynomial used in CRC calculation. */
61 unsigned HOST_WIDE_INT m_polynomial
;
63 /* Depending on the value of M_IS_BIT_FORWARD, may be forward or reversed CRC.
64 If M_IS_BIT_FORWARD, then it is bit-forward implementation,
65 otherwise bit-reversed. */
66 bool m_is_bit_forward
;
68 /* Sets initial values for CRC analyses. */
69 void set_initial_values ();
71 /* This is the main function that checks whether the given LOOP
72 calculates CRC and extracts details of the CRC calculation.
74 The main idea is to find the innermost loop with 8, 16, 24, 32, 64
75 iterations and xor instruction (xor is the key operation for naive CRC
76 calculation). Then, checks that the variable is shifted by one before/after
78 Xor must be done under the condition of MSB/LSB being 1. */
79 bool loop_may_calculate_crc (class loop
*loop
);
81 /* Symbolically executes the loop and checks that LFSR and resulting states
83 Returns true if it is verified that the loop calculates CRC.
84 Otherwise, return false.
85 OUTPUT_CRC is the phi statement which will hold the calculated CRC value
86 after the loop exit. */
87 bool loop_calculates_crc (gphi
*output_crc
,
88 std::pair
<tree
, value
*> calc_polynom
);
90 /* Returns true if there is only two conditional blocks in the loop
91 (one may be for the CRC bit check and the other for the loop counter).
92 This may filter out some real CRCs, where more than one condition
93 is checked for the CRC calculation. */
94 static bool loop_contains_two_conditional_bb (basic_block
*loop_bbs
,
95 unsigned loop_num_nodes
);
97 /* Checks the FUNC_LOOP loop's iteration number.
98 The loop for CRC calculation may do 8, 16, 24, 32, 64 iterations. */
99 bool satisfies_crc_loop_iteration_count (class loop
*func_loop
);
101 /* This function checks if the XOR_STMT is used for CRC calculation.
102 It verifies the presence of a shift operation in the CRC_FUN function
103 inside the CRC loop. It examines operands of XOR, its dependencies, the
104 relative position of the shift operation, and the existence of a shift
105 operation in the opposite branch of conditional statements. It also
106 checks if XOR is performed when MSB/LSB is one.
107 If these conditions are met, the XOR operation may be part of a CRC
108 calculation. The function returns true if these conditions are fulfilled,
109 otherwise, it returns false. */
110 bool xor_calculates_crc (function
*crc_fun
, const gimple
*xor_stmt
);
112 /* Returns true if we can get definition of the VARIABLE, and the definition
113 it's not outside the loop. Otherwise, returns false. */
114 bool passes_checks_for_def_chain (tree variable
);
116 /* This function goes up through the def-use chains of the parameter NAME.
117 Gathers all the statements within the loop,
118 from which the variable depends on and adds to the USE_DEFS.
119 Returns false, if there is a statement that may not exist in the CRC
120 loop. Otherwise, returns true. */
121 bool set_defs (tree name
, auto_vec
<gimple
*>& use_defs
,
122 bool keep_only_header_phis
);
124 /* Set M_PHI_FOR_CRC and M_PHI_FOR_DATA fields.
125 Returns false if there are more than two (as in CRC calculation only CRC's
126 and data's phi may exist) or no phi statements in STMTS (at least there
128 Otherwise, returns true. */
129 bool set_crc_and_data_phi (auto_vec
<gimple
*>& stmts
);
131 /* Returns true if the variable checked in the condition depends on possible
132 CRC value. Otherwise, returns false. */
133 bool cond_depends_on_crc (auto_vec
<gimple
*>& stmts
);
136 /* Checks that the condition is for checking CRC.
137 Returns true if xor is done under the condition of MSB/LSB being 1, and
138 the condition's variable and xor-ed variable depend on the same variable.
139 Otherwise, returns false.
140 XOR_BB is the basic block, where the xor operation is done.
141 PRED_BB is the predecessor basic block of the XOR_BB, it is assumed that
142 the last stmt of PRED_BB checks the condition under which xor is done. */
143 bool crc_cond (basic_block pred_bb
, basic_block xor_bb
);
145 /* Returns true if xor is done in case the MSB/LSB is 1.
146 Otherwise, returns false.
147 In CRC calculation algorithms CRC is xor-ed with the polynomial only
150 PRED_BB is the block containing the condition for the xor.
151 XOR_BB is the one of the successor blocks of PRED_BB, it is assumed that
152 CRC is xor-ed with the polynomial in XOR_BB.
153 COND is the condition, which is checked to satisfy the CRC condition. */
154 bool is_crc_satisfiable_cond (basic_block pred_bb
, basic_block xor_bb
,
157 /* Checks that the variable used in the condition COND is the assumed CRC
158 (or depends on the assumed CRC).
159 Also sets data member m_phi_for_data if it isn't set and exists. */
160 bool is_crc_checked (gcond
*cond
);
162 /* Returns true if condition COND checks MSB/LSB bit is 1.
163 Otherwise, return false. */
164 static bool cond_true_is_checked_for_bit_one (const gcond
*cond
);
166 /* Returns opposite block of the XOR_BB from PRED_BB's dest blocks. */
167 static basic_block
get_xor_bb_opposite (basic_block pred_bb
,
170 /* Checks whether the pair of xor's shift exists in the opposite
171 basic block (OPPOSITE_BB).
172 If there is a shift and xor in the same block,
173 then in the opposite block must be another shift. */
174 bool exists_shift_for_opp_xor_shift (basic_block opposite_bb
);
176 /* Follow def-use chains of XORED_CRC and return the statement where
177 XORED_CRC is shifted by one bit position. Only PHI statements are
178 allowed between XORED_CRC and the shift in the def-use chain.
180 If no such statement is found, return NULL. */
181 gimple
*find_shift_after_xor (tree xored_crc
);
183 /* Returns the statement which does shift 1 operation.
184 If there is no such statement, returns nullptr.
185 STMTS - are the statements within the loop before xor operation on
186 which possible CRC variable depends. */
187 gimple
*find_shift_before_xor (const auto_vec
<gimple
*> &stmts
);
189 /* Returns true if ASSIGN_STMT does shift with 1.
190 Otherwise, returns false. */
191 bool can_be_crc_shift (gimple
*assign_stmt
);
193 /* Returns true if the operation done in ASSIGN_STMT can occur during CRC
194 calculation. Otherwise, returns false. */
195 bool can_not_be_crc_stmt (gimple
*assign_stmt
);
197 /* Returns true if the statement with STMT_CODE may occur in CRC calculation.
198 Otherwise, returns false. */
199 static bool is_acceptable_stmt_code (const tree_code
&stmt_code
);
201 /* Prints extracted details of CRC calculation. */
202 void dump_crc_information ();
204 /* Returns true if OUTPUT_CRC's result is the input of m_phi_for_crc.
205 Otherwise, returns false. */
206 bool is_output_crc (gphi
*output_crc
);
208 /* Swaps m_phi_for_crc and m_phi_for_data if they are mixed. */
209 void swap_crc_and_data_if_needed (gphi
*output_crc
);
211 /* Validates CRC and data arguments and
212 sets them for potential CRC loop replacement.
214 The function extracts the CRC and data arguments from PHI nodes and
215 performs several checks to ensure that the CRC and data are suitable for
216 replacing the CRC loop with a more efficient implementation.
218 Returns true if the arguments are valid and the loop replacement is possible,
220 bool validate_crc_and_data ();
222 /* Convert polynomial to unsigned HOST_WIDE_INT. */
223 void construct_constant_polynomial (value
*polynomial
);
225 /* Returns phi statement which may hold the calculated CRC. */
226 gphi
*get_output_phi ();
228 /* Attempts to optimize a CRC calculation loop by replacing it with a call to
229 an internal function (IFN_CRC or IFN_CRC_REV).
230 Returns true if replacement succeeded, otherwise false. */
231 bool optimize_crc_loop (gphi
*output_crc
);
234 crc_optimization () : m_visited_stmts (BITMAP_ALLOC (NULL
)),
235 m_crc_loop (nullptr), m_polynomial (0)
237 set_initial_values ();
241 BITMAP_FREE (m_visited_stmts
);
243 unsigned int execute (function
*fun
);
246 /* Prints extracted details of CRC calculation. */
249 crc_optimization::dump_crc_information ()
254 "Loop iteration number is " HOST_WIDE_INT_PRINT_UNSIGNED
".\n",
255 tree_to_uhwi (m_crc_loop
->nb_iterations
));
256 if (m_is_bit_forward
)
257 fprintf (dump_file
, "Bit forward.\n");
259 fprintf (dump_file
, "Bit reversed.\n");
263 /* Goes down by def-use chain (within the CRC loop) and returns the statement
264 where variable (dependent on xor-ed variable) is shifted with 1.
265 Between xor and shift operations only phi statements are allowed.
266 Otherwise, returns nullptr. */
269 crc_optimization::find_shift_after_xor (tree xored_crc
)
271 imm_use_iterator imm_iter
;
274 gcc_assert (TREE_CODE (xored_crc
) == SSA_NAME
);
276 unsigned v
= SSA_NAME_VERSION (xored_crc
);
277 if (bitmap_bit_p (m_visited_stmts
, v
))
279 bitmap_set_bit (m_visited_stmts
, v
);
281 /* Iterate through the immediate uses of the XORED_CRC.
282 If there is a shift return true,
283 if before shift there is other instruction (besides phi) return false. */
284 FOR_EACH_IMM_USE_FAST (use_p
, imm_iter
, xored_crc
)
286 gimple
*stmt
= USE_STMT (use_p
);
287 // Consider only statements within the loop
288 if (!flow_bb_inside_loop_p (m_crc_loop
, gimple_bb (stmt
)))
291 /* If encountered phi statement, check immediate use of its result.
292 Otherwise, if encountered assign statement, check whether it does shift
293 (some other operations are allowed to be between shift and xor). */
294 if (gimple_code (stmt
) == GIMPLE_PHI
)
296 /* Don't continue searching if encountered the loop's beginning. */
297 if (bb_loop_header_p (gimple_bb (stmt
)))
300 return find_shift_after_xor (gimple_phi_result (stmt
));
302 else if (is_gimple_assign (stmt
))
304 /* Check that stmt does shift by 1.
305 There are no other statements between
306 xor and shift, in CRC cases we detect. */
307 if (can_be_crc_shift (stmt
))
311 else if (!is_gimple_debug (stmt
))
317 /* Returns opposite block of the XOR_BB from PRED_BB's dest blocks. */
320 crc_optimization::get_xor_bb_opposite (basic_block pred_bb
, basic_block xor_bb
)
322 /* Check that the predecessor block has exactly two successors. */
323 if (EDGE_COUNT (pred_bb
->succs
) != 2)
326 edge e0
= EDGE_SUCC (pred_bb
, 0);
327 edge e1
= EDGE_SUCC (pred_bb
, 1);
329 /* Ensure neither outgoing edge is marked as complex. */
330 if ((e0
->flags
& EDGE_COMPLEX
)
331 || (e1
->flags
& EDGE_COMPLEX
))
334 /* Check that one of the successors is indeed XOR_BB. */
335 gcc_assert ((e0
->dest
== xor_bb
)
336 || (e1
->dest
== xor_bb
));
338 /* Return the opposite block of XOR_BB. */
339 if (EDGE_SUCC (pred_bb
, 0)->dest
!= xor_bb
)
344 /* Checks whether the pair of xor's shift exists in the opposite
345 basic block (OPPOSITE_BB).
346 If there is a shift and xor in the same block,
347 then in the opposite block must be another shift. */
350 crc_optimization::exists_shift_for_opp_xor_shift (basic_block opposite_bb
)
355 /* Walk through the instructions of given basic block. */
356 for (gimple_stmt_iterator bsi
= gsi_start_nondebug_bb (opposite_bb
);
357 !gsi_end_p (bsi
); gsi_next_nondebug (&bsi
))
359 gimple
*stmt
= gsi_stmt (bsi
);
360 /* Find assignment statement with shift operation.
361 Check that shift's direction is same with the shift done
362 on the path with xor, and it is a shift by one. */
363 if (is_gimple_assign (stmt
))
365 if ((gimple_assign_rhs_code (stmt
)
366 == gimple_assign_rhs_code (m_shift_stmt
))
367 && integer_onep (gimple_assign_rhs2 (stmt
)))
371 /* If there is no shift, return false. */
375 /* Returns true if condition COND checks MSB/LSB bit is 1.
376 Otherwise, return false. */
379 crc_optimization::cond_true_is_checked_for_bit_one (const gcond
*cond
)
384 tree rhs
= gimple_cond_rhs (cond
);
385 enum tree_code code
= gimple_cond_code (cond
);
387 /* If the condition is something == 1 -> return true. */
388 if (code
== EQ_EXPR
&& integer_onep (rhs
))
391 /* If the condition is something != 0 or something < 0 -> return true. */
392 if ((code
== NE_EXPR
|| code
== LT_EXPR
)
393 && integer_zerop (rhs
))
399 /* Returns true if xor is done in case the MSB/LSB is 1.
400 Otherwise, returns false.
401 In CRC calculation algorithms CRC is xor-ed with the polynomial only
404 PRED_BB is the block containing the condition for the xor.
405 XOR_BB is the one of the successor blocks of PRED_BB, it is assumed that CRC
406 is xor-ed with the polynomial in XOR_BB.
407 COND is the condition, which is checked to satisfy the CRC condition. */
410 crc_optimization::is_crc_satisfiable_cond (basic_block pred_bb
,
416 extract_true_false_edges_from_block (pred_bb
, &true_edge
, &false_edge
);
417 bool cond_is_checked_for_bit_one
= cond_true_is_checked_for_bit_one (cond
);
418 /* Check that xor is done in case the MSB/LSB is 1. */
419 if (cond_is_checked_for_bit_one
&& true_edge
->dest
== xor_bb
)
421 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
422 fprintf (dump_file
, "Xor is done on true branch.\n");
424 else if (!cond_is_checked_for_bit_one
&& false_edge
->dest
== xor_bb
)
426 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
427 fprintf (dump_file
, "Xor is done on false branch.\n");
431 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
433 "Xor is done if MSB/LSB is not one, not CRC.\n");
439 /* Checks that the variable used in the condition COND is the assumed CRC
440 (or depends on the assumed CRC).
441 Also sets data member m_phi_for_data if it isn't set and exists. */
444 crc_optimization::is_crc_checked (gcond
*cond
)
446 tree lhs
= gimple_cond_lhs (cond
);
448 /* As conditions are in canonical form, only left part must be an
450 if (TREE_CODE (lhs
) == SSA_NAME
)
452 /* Return whether there is a dependence between if condition's variable
453 and xor-ed variable. Also set phi statement of data if it is not
454 determined earlier and is used in the loop. */
455 auto_vec
<gimple
*> cond_dep_stmts (m_crc_loop
->num_nodes
);
456 bool set_defs_succeeded
= set_defs (lhs
, cond_dep_stmts
, true);
457 bitmap_clear (m_visited_stmts
);
458 if (!set_defs_succeeded
)
460 return cond_depends_on_crc (cond_dep_stmts
);
463 /* Return false if there is no dependence between if condition's variable
464 and xor-ed variable. */
468 /* Checks that the condition is for checking CRC.
469 Returns true if xor is done under the condition of MSB/LSB being 1, and
470 the condition's variable and xor-ed variable depend on the same variable.
471 Otherwise, returns false.
472 XOR_BB is the basic block, where the xor operation is done.
473 PRED_BB is the predecessor basic block of the XOR_BB, it is assumed that
474 the last stmt of PRED_BB checks the condition under which xor is done. */
477 crc_optimization::crc_cond (basic_block pred_bb
, basic_block xor_bb
)
479 /* Check whether PRED_BB contains condition. We will consider only those
480 cases when xor is done immediately under the condition. */
481 gcond
*cond
= safe_dyn_cast
<gcond
*> (gsi_stmt (gsi_last_bb (pred_bb
)));
484 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
485 fprintf (dump_file
, "No condition.\n");
489 /* Check that xor is done in case the MSB/LSB is 1. */
490 if (!is_crc_satisfiable_cond (pred_bb
, xor_bb
, cond
))
493 /* Check that CRC's MSB/LSB is checked in the condition.
494 Set data member if not set and exists. */
495 if (!is_crc_checked (cond
))
497 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
498 fprintf (dump_file
, "The condition is not related to the CRC check.\n");
504 /* Returns true if the statement with STMT_CODE may occur in CRC calculation.
505 Otherwise, returns false. */
508 crc_optimization::is_acceptable_stmt_code (const tree_code
&stmt_code
)
510 return (stmt_code
== BIT_IOR_EXPR
)
511 || (stmt_code
== BIT_AND_EXPR
)
512 || (stmt_code
== BIT_XOR_EXPR
)
513 || (stmt_code
== MINUS_EXPR
)
514 || (stmt_code
== PLUS_EXPR
)
515 || (stmt_code
== RSHIFT_EXPR
)
516 || (stmt_code
== LSHIFT_EXPR
)
517 || (TREE_CODE_CLASS (stmt_code
) == tcc_unary
);
520 /* Returns true if ASSIGN_STMT does shift with 1. Otherwise, returns false. */
523 crc_optimization::can_be_crc_shift (gimple
*assign_stmt
)
525 tree_code stmt_code
= gimple_assign_rhs_code (assign_stmt
);
526 if (stmt_code
== LSHIFT_EXPR
|| stmt_code
== RSHIFT_EXPR
)
528 m_is_bit_forward
= (stmt_code
== LSHIFT_EXPR
);
529 /* Check that shift one is done, keep shift statement. */
530 if (integer_onep (gimple_assign_rhs2 (assign_stmt
)))
534 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
536 "Already there is one shift.\n");
539 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
541 "Found <<1 or >>1.\n");
544 /* This filters out cases, when xor-ed variable is shifted by values
550 /* Returns true if the operation done in ASSIGN_STMT can occur during CRC
551 calculation. Otherwise, returns false. */
554 crc_optimization::can_not_be_crc_stmt (gimple
*assign_stmt
)
556 tree_code stmt_code
= gimple_assign_rhs_code (assign_stmt
);
557 if (!is_acceptable_stmt_code (stmt_code
))
559 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
561 "\nStmt with the following operation "
562 "code %s between xor and shift, "
563 "may not be CRC.\n", get_tree_code_name (stmt_code
));
570 /* Returns true if we can get definition of the VARIABLE, and the definition
571 is not outside the loop. Otherwise, returns false. */
574 crc_optimization::passes_checks_for_def_chain (tree variable
)
576 if (!(variable
&& TREE_CODE (variable
) == SSA_NAME
))
579 /* No definition chain for default defs. */
580 if (SSA_NAME_IS_DEFAULT_DEF (variable
))
583 gimple
*stmt
= SSA_NAME_DEF_STMT (variable
);
588 /* Don't go outside the loop. */
589 if (!flow_bb_inside_loop_p (m_crc_loop
, gimple_bb (stmt
)))
595 /* This function goes up through the def-use chains of the parameter NAME.
596 Gathers all the statements within the loop,
597 from which the variable depends on and adds to the USE_DEFS.
598 Returns false, if there is a statement that may not exist in the CRC
599 loop. Otherwise, returns true. */
602 crc_optimization::set_defs (tree name
, auto_vec
<gimple
*> &use_defs
,
603 bool keep_only_header_phis
= false)
605 if (!passes_checks_for_def_chain (name
))
608 /* Don't consider already visited names. */
609 unsigned v
= SSA_NAME_VERSION (name
);
610 if (bitmap_bit_p (m_visited_stmts
, v
))
612 bitmap_set_bit (m_visited_stmts
, v
);
614 /* In CRC implementations with constant polynomial maximum 12 use_def
615 statements may occur. This limit is based on an analysis of various CRC
616 implementations as well as theoretical possibilities.
617 TODO: Find a better solution. */
618 if (use_defs
.length () > 12)
621 gimple
*stmt
= SSA_NAME_DEF_STMT (name
);
623 /* If it's not specified to keep only header phi's,
624 then keep all statements. */
625 if (!keep_only_header_phis
)
626 use_defs
.safe_push (stmt
);
628 /* If it is an assignment statement,
629 get and check def-use chain for the first and second operands. */
630 if (is_a
<gassign
*> (stmt
))
632 if (can_not_be_crc_stmt (stmt
))
635 tree ssa1
= gimple_assign_rhs1 (stmt
);
636 tree ssa2
= gimple_assign_rhs2 (stmt
);
637 if (!set_defs (ssa1
, use_defs
, keep_only_header_phis
))
639 if (!set_defs (ssa2
, use_defs
, keep_only_header_phis
))
643 /* If it's a phi statement, not declared in loop's header,
644 get and check def-use chain for its values. For the one declared in loop's
645 header just return true and keep it, if keep_only_header_phis is true. */
646 else if (is_a
<gphi
*> (stmt
))
648 if (bb_loop_header_p (gimple_bb (stmt
)))
650 /* If it's specified to keep only header phi's, keep it. */
651 if (keep_only_header_phis
)
652 use_defs
.safe_push (stmt
);
656 for (unsigned i
= 0; i
< gimple_phi_num_args (stmt
); i
++)
658 tree val
= gimple_phi_arg_def (stmt
, i
);
659 if (!set_defs (val
, use_defs
, keep_only_header_phis
))
666 /* Return false for other than assigment and phi statement. */
670 /* Returns the statement which does shift 1 operation.
671 If there is no such statement, returns nullptr.
672 STMTS - are the statements within the loop before xor operation on
673 which possible CRC variable depends. */
676 crc_optimization::find_shift_before_xor (const auto_vec
<gimple
*> &stmts
)
678 for (auto stmt_it
= stmts
.begin (); stmt_it
!= stmts
.end (); stmt_it
++)
680 /* If it is an assignment statement, check that is does shift 1. */
681 if (is_a
<gassign
*> (*stmt_it
))
683 if (can_be_crc_shift (*stmt_it
))
690 /* This function sets M_PHI_FOR_CRC and M_PHI_FOR_DATA fields.
691 At this step phi nodes for CRC and data may be mixed in places.
692 It is fixed later with the "swap_crc_and_data_if_needed" function.
693 The function returns false if there are more than two (as in CRC calculation
694 only CRC's and data's phi may exist) or no phi statements in STMTS (at least
695 there must be CRC's phi).
696 Otherwise, returns true. */
699 crc_optimization::set_crc_and_data_phi (auto_vec
<gimple
*> &stmts
)
701 for (auto stmt_it
= stmts
.begin (); stmt_it
!= stmts
.end (); stmt_it
++)
703 if (is_a
<gphi
*> (*stmt_it
) && bb_loop_header_p (gimple_bb (*stmt_it
)))
706 m_phi_for_crc
= as_a
<gphi
*> (*stmt_it
);
707 else if (!m_phi_for_data
)
708 m_phi_for_data
= as_a
<gphi
*> (*stmt_it
);
711 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
712 fprintf (dump_file
, "Xor-ed variable depends on more than 2 "
718 return m_phi_for_crc
;
721 /* Returns true if the variable checked in the condition depends on possible
722 CRC value. Otherwise, returns false. */
725 crc_optimization::cond_depends_on_crc (auto_vec
<gimple
*>& stmts
)
727 bool con_depends_on_crc
= false;
729 /* The condition may depend maximum on data and CRC phi's. */
730 if (stmts
.length () > 2)
733 for (auto stmt_it
= stmts
.begin (); stmt_it
!= stmts
.end (); stmt_it
++)
735 if (is_a
<gphi
*> (*stmt_it
) && bb_loop_header_p (gimple_bb (*stmt_it
)))
737 /* Check whether variable checked in the condition depends on
739 Here don't stop the check, to set data if needed. */
740 if (m_phi_for_crc
== (*stmt_it
))
741 con_depends_on_crc
= true;
742 else if (m_phi_for_data
&& m_phi_for_data
== (*stmt_it
))
744 /* If M_PHI_FOR_DATA isn't determined, the phi statement maybe for the
745 data. Just set it. */
746 else if (!m_phi_for_data
)
747 m_phi_for_data
= as_a
<gphi
*> (*stmt_it
);
750 return con_depends_on_crc
;
753 /* Sets initial values for the CRC analysis.
754 This function is used multiple times during the analyses. */
757 crc_optimization::set_initial_values ()
760 m_data_arg
= nullptr;
761 m_shift_stmt
= nullptr;
762 m_phi_for_crc
= nullptr;
763 m_phi_for_data
= nullptr;
764 m_is_bit_forward
= false;
767 /* This function checks if the XOR_STMT is used for CRC calculation.
768 It verifies the presence of a shift operation in the CRC_FUN function inside
769 the CRC loop. It examines operands of XOR, its dependencies, the relative
770 position of the shift operation, and the existence of a shift operation in
771 the opposite branch of conditional statements. It also checks if XOR is
772 performed when MSB/LSB is one.
773 If these conditions are met, the XOR operation may be part of a CRC
774 calculation. The function returns true if these conditions are fulfilled,
775 otherwise, it returns false. */
778 crc_optimization::xor_calculates_crc (function
*crc_fun
,
779 const gimple
*xor_stmt
)
781 tree crc_var
= gimple_assign_lhs (xor_stmt
);
782 set_initial_values ();
783 tree ssa1
= gimple_assign_rhs1 (xor_stmt
);
784 tree ssa2
= gimple_assign_rhs2 (xor_stmt
);
785 if (TREE_CODE (ssa2
) != INTEGER_CST
)
787 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
788 fprintf (dump_file
, "Second operand of the "
789 "xor statement isn't an integer constant.\n");
793 /* Get the statements within the loop on which xor-ed variable depends. */
794 auto_vec
<gimple
*> xor_dep_stmts (m_crc_loop
->num_nodes
);
795 bool set_defs_succeeded
= set_defs (ssa1
, xor_dep_stmts
);
796 bitmap_clear (m_visited_stmts
);
797 if (!set_defs_succeeded
)
799 xor_dep_stmts
.release ();
803 m_shift_stmt
= find_shift_before_xor (xor_dep_stmts
);
805 if (!set_crc_and_data_phi (xor_dep_stmts
))
807 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
808 fprintf (dump_file
, "Xor isn't used for CRC calculation.\n");
812 /* Check the case when shift is done after xor. */
815 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
816 fprintf (dump_file
, "No shift before xor, trying to find after xor.\n");
818 m_shift_stmt
= find_shift_after_xor (crc_var
);
819 bitmap_clear (m_visited_stmts
);
824 /* Get the basic block where xor operation is done. */
825 basic_block xor_bb
= gimple_bb (xor_stmt
);
827 /* Get the predecessor basic block of xor's block. */
828 if (!single_pred_p (xor_bb
))
830 basic_block block_of_condition
= single_pred (xor_bb
);
833 /* If the found shift operation is in the same block as the xor operation,
834 verify whether another shift exists in the opposite branch of the
835 conditional statements. */
836 if (m_shift_stmt
&& gimple_bb (m_shift_stmt
) == xor_bb
)
838 basic_block opposite_block
= get_xor_bb_opposite (block_of_condition
,
840 if (!exists_shift_for_opp_xor_shift (opposite_block
))
842 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
844 "Opposite block doesn't contain shift's pair.\n");
849 /* Check that xor is done if MSB/LSB is one.
850 If all checks succeed, then it may be a CRC. */
851 if (crc_cond (block_of_condition
, xor_bb
))
855 "\n%s function maybe contains CRC calculation.\n",
856 function_name (crc_fun
));
863 /* Returns true if there is only two conditional blocks in the loop,
864 one may be for the CRC bit check and the other for the loop counter.
865 This may filter out some real CRCs, where more than one condition
866 is checked for the CRC calculation and branch-less CRCs. */
869 crc_optimization::loop_contains_two_conditional_bb (basic_block
*loop_bbs
,
870 unsigned loop_num_nodes
)
872 unsigned conditional_bb_count
= 0;
873 /* Iterate through the loop until the conditional branches count
875 for (unsigned i
= 0; i
< loop_num_nodes
&& conditional_bb_count
<= 2; i
++)
877 basic_block bb
= loop_bbs
[i
];
878 if (!single_succ_p (bb
))
879 conditional_bb_count
++;
881 return conditional_bb_count
== 2;
884 /* Checks the FUNC_LOOP loop's iteration number.
885 The loop for CRC calculation may do 8, 16, 24, 32, 64 iterations. */
888 crc_optimization::satisfies_crc_loop_iteration_count (class loop
*func_loop
)
890 /* Calculate the number of times the latch of the loop is executed.
891 The function sets NB_ITERATIONS field of the loop. */
892 number_of_latch_executions (func_loop
);
893 tree n_inters
= func_loop
->nb_iterations
;
894 if (n_inters
== NULL_TREE
|| n_inters
== chrec_dont_know
)
896 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
898 "Loop iteration number is chrec_dont_know.\n");
902 else if (tree_fits_uhwi_p (n_inters
))
904 unsigned HOST_WIDE_INT
905 loop_iteration_number
= tree_to_uhwi (n_inters
);
906 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
907 fprintf (dump_file
, "Loop iteration number is "
908 HOST_WIDE_INT_PRINT_UNSIGNED
".\n", loop_iteration_number
);
910 if ((loop_iteration_number
== 7 || loop_iteration_number
== 15
911 || loop_iteration_number
== 23 || loop_iteration_number
== 31
912 || loop_iteration_number
== 63))
915 if (stderr
&& (dump_flags
& TDF_DETAILS
))
916 fprintf (dump_file
, "Loop iteration number isn't a constant.\n");
920 /* This is the main function that checks whether the given LOOP
921 calculates CRC and extracts details of the CRC calculation.
923 The main idea is to find the innermost loop with 8, 16, 24, 32, 64
924 iterations and xor instruction (xor is the key operation for naive CRC
925 calculation). Then, checks that the variable is shifted by one before/after
927 Xor must be done under the condition of MSB/LSB being 1. */
930 crc_optimization::loop_may_calculate_crc (class loop
*loop
)
932 /* Only examine innermost loops. */
933 if (!loop
|| loop
->inner
)
936 if (!satisfies_crc_loop_iteration_count (loop
))
940 basic_block
*loop_bbs
= get_loop_body_in_dom_order (m_crc_loop
);
942 /* Filter out the cases, which don't have exactly two conditions in the loop.
943 One for the CRC bit check, the other for the loop counter. */
944 if (!loop_contains_two_conditional_bb (loop_bbs
, m_crc_loop
->num_nodes
))
946 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
948 "The number of conditional "
949 "branches in the loop isn't 2.\n");
954 unsigned short checked_xor_count
= 0;
955 /* Walk bbs of the loop. */
956 for (unsigned int i
= 0; i
< m_crc_loop
->num_nodes
; i
++)
958 basic_block bb
= loop_bbs
[i
];
959 /* Walk instructions of the bb. */
960 for (gimple_stmt_iterator bsi
= gsi_start_nondebug_bb (bb
);
961 !gsi_end_p (bsi
); gsi_next_nondebug (&bsi
))
963 gimple
*stmt
= gsi_stmt (bsi
);
964 /* If there is an xor instruction,
965 check that it is calculating CRC. */
966 if (is_gimple_assign (stmt
)
967 && gimple_assign_rhs_code (stmt
) == BIT_XOR_EXPR
)
969 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
972 "checking whether it is for CRC calculation.\n");
974 if (xor_calculates_crc (cfun
, stmt
))
976 dump_crc_information ();
981 if (++checked_xor_count
== 2)
993 /* Symbolically executes the loop and checks that LFSR and resulting states
995 Returns true if it is verified that the loop calculates CRC.
996 Otherwise, return false.
997 OUTPUT_CRC is the phi statement which will hold the calculated CRC value
998 after the loop exit. */
1001 crc_optimization::loop_calculates_crc (gphi
*output_crc
,
1002 std::pair
<tree
, value
*> calc_polynom
)
1004 /* Create LFSR state using extracted polynomial. */
1005 value
* lfsr
= state::create_lfsr (calc_polynom
.first
, calc_polynom
.second
,
1009 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1010 fprintf (dump_file
, "Couldn't create LFSR!\n");
1014 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1016 fprintf (dump_file
, "\nLFSR value is \n");
1017 state::print_value (lfsr
);
1020 /* Execute the loop with symbolic values
1021 (symbolic value is assigned to the variable when its value isn't known)
1022 to keep states, for further comparison. */
1024 crc_symbolic_execution
loop_executor (m_crc_loop
, output_crc
);
1025 while (!loop_executor
.is_last_iteration ())
1027 if (!loop_executor
.symb_execute_crc_loop ())
1030 fprintf (dump_file
, "\nCRC verification didn't succeed "
1031 "during symbolic execution!\n");
1036 /* Check whether LFSR and obtained states are same. */
1037 tree calculated_crc
= PHI_ARG_DEF_FROM_EDGE (output_crc
,
1038 single_exit (m_crc_loop
));
1039 if (!all_states_match_lfsr (lfsr
, m_is_bit_forward
, calculated_crc
,
1040 loop_executor
.get_final_states ()))
1042 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1043 fprintf (dump_file
, "Returned state and LFSR differ.\n");
1052 /* Returns true if OUTPUT_CRC's result is the input of M_PHI_FOR_CRC.
1053 Otherwise, returns false. */
1056 crc_optimization::is_output_crc (gphi
*output_crc
)
1059 = PHI_ARG_DEF_FROM_EDGE (output_crc
, single_exit (m_crc_loop
));
1061 = PHI_ARG_DEF_FROM_EDGE (m_phi_for_crc
, loop_latch_edge (m_crc_loop
));
1062 if (crc_of_exit
== crc_of_latch
)
1064 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1066 fprintf (dump_file
, "Output CRC is ");
1067 print_gimple_expr (dump_file
, (gimple
*) output_crc
, dump_flags
);
1068 fprintf (dump_file
, "\n");
1074 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1075 fprintf (dump_file
, "Output CRC and determined input CRC "
1081 /* Swaps M_PHI_FOR_CRC and M_PHI_FOR_DATA if they are mixed. */
1084 crc_optimization::swap_crc_and_data_if_needed (gphi
*output_crc
)
1087 = PHI_ARG_DEF_FROM_EDGE (output_crc
, single_exit (m_crc_loop
));
1088 edge crc_loop_latch
= loop_latch_edge (m_crc_loop
);
1089 if (crc_of_exit
!= PHI_ARG_DEF_FROM_EDGE (m_phi_for_crc
, crc_loop_latch
))
1092 && crc_of_exit
== PHI_ARG_DEF_FROM_EDGE (m_phi_for_data
,
1095 std::swap (m_phi_for_crc
, m_phi_for_data
);
1100 /* Validates CRC and data arguments and
1101 sets them for potential CRC loop replacement.
1103 The function extracts the CRC and data arguments from PHI nodes and
1104 performs several checks to ensure that the CRC and data are suitable for
1105 replacing the CRC loop with a more efficient implementation.
1107 Returns true if the arguments are valid and the loop replacement is possible,
1110 bool crc_optimization::validate_crc_and_data ()
1112 /* Set m_crc_arg and check if fits in word_mode. */
1113 gcc_assert (m_phi_for_crc
);
1114 m_crc_arg
= PHI_ARG_DEF_FROM_EDGE (m_phi_for_crc
,
1115 loop_preheader_edge (m_crc_loop
));
1116 gcc_assert (m_crc_arg
);
1118 unsigned HOST_WIDE_INT
1119 data_size
= tree_to_uhwi (m_crc_loop
->nb_iterations
) + 1;
1120 /* We don't support the case where data is larger than the CRC. */
1121 if (TYPE_PRECISION (TREE_TYPE (m_crc_arg
)) < data_size
)
1124 /* Set m_data_arg if a PHI node for data exists,
1125 and check its size against loop iterations.
1126 This is the case when data and CRC are XOR-ed in the loop. */
1129 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1131 "Data and CRC are xor-ed in the for loop. Initializing data "
1132 "with its value.\n");
1133 m_data_arg
= PHI_ARG_DEF_FROM_EDGE (m_phi_for_data
,
1134 loop_preheader_edge (m_crc_loop
));
1135 gcc_assert (m_data_arg
);
1136 if (TYPE_PRECISION (TREE_TYPE (m_data_arg
)) != data_size
)
1138 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1140 "Loop iteration number and data's size differ.\n");
1148 /* Convert polynomial to unsigned HOST_WIDE_INT. */
1151 crc_optimization::construct_constant_polynomial (value
*polynomial
)
1154 for (unsigned i
= 0; i
< (*polynomial
).length (); i
++)
1156 value_bit
*const_bit
;
1157 if (m_is_bit_forward
)
1158 const_bit
= (*polynomial
)[(*polynomial
).length () - 1 - i
];
1160 const_bit
= (*polynomial
)[i
];
1162 m_polynomial
^= (as_a
<bit
*> (const_bit
))->get_val () ? 1 : 0;
1166 /* Returns phi statement which may hold the calculated CRC. */
1169 crc_optimization::get_output_phi ()
1171 edge loop_exit
= single_exit (m_crc_loop
);
1174 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1175 fprintf (dump_file
, "The loop doesn't have single exit.\n");
1178 basic_block bb
= loop_exit
->dest
;
1179 gphi
*output_crc
= nullptr;
1182 /* We are only interested in cases when there is only one phi at the
1183 loop exit, and that phi can potentially represent the CRC.
1184 If there are other phis present, it indicates that additional values are
1185 being calculated within the loop that are used outside it. */
1186 for (gphi_iterator gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
);
1189 tree phi_result
= gimple_phi_result (gsi
.phi ());
1191 /* Don't consider virtual operands. */
1192 if (!virtual_operand_p (phi_result
))
1196 output_crc
= gsi
.phi ();
1201 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1202 fprintf (dump_file
, "There is more than one output phi.\n");
1210 if (gimple_phi_num_args (output_crc
) == 1)
1214 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1215 fprintf (dump_file
, "Couldn't determine output CRC.\n");
1219 /* Attempts to optimize a CRC calculation loop by replacing it with a call to
1220 an internal function (IFN_CRC or IFN_CRC_REV).
1221 Returns true if replacement succeeded, otherwise false. */
1224 crc_optimization::optimize_crc_loop (gphi
*output_crc
)
1229 fprintf (dump_file
, "Couldn't determine output CRC.\n");
1235 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1237 "Data and CRC are xor-ed before for loop. Initializing data "
1239 /* Create a new variable for the data.
1240 Determine the data's size with the loop iteration count. */
1241 unsigned HOST_WIDE_INT
1242 data_size
= tree_to_uhwi (m_crc_loop
->nb_iterations
) + 1;
1243 tree type
= build_nonstandard_integer_type (data_size
, 1);
1244 /* For the CRC calculation, it doesn't matter CRC is calculated for the
1245 (CRC^data, 0) or (CRC, data). */
1246 m_data_arg
= build_int_cstu (type
, 0);
1249 /* Build tree node for the polynomial from its constant value. */
1250 tree polynomial_arg
= build_int_cstu (TREE_TYPE (m_crc_arg
), m_polynomial
);
1251 gcc_assert (polynomial_arg
);
1254 if (m_is_bit_forward
)
1259 tree phi_result
= gimple_phi_result (output_crc
);
1261 loc
= EXPR_LOCATION (phi_result
);
1263 /* Add IFN call and write the return value in the phi_result. */
1265 = gimple_build_call_internal (ifn
, 3,
1270 gimple_call_set_lhs (call
, phi_result
);
1271 gimple_set_location (call
, loc
);
1272 gimple_stmt_iterator si
= gsi_start_bb (output_crc
->bb
);
1273 gsi_insert_before (&si
, call
, GSI_SAME_STMT
);
1275 /* Remove phi statement, which was holding CRC result. */
1276 gimple_stmt_iterator tmp_gsi
= gsi_for_stmt (output_crc
);
1277 remove_phi_node (&tmp_gsi
, false);
1279 /* Alter the exit condition of the loop to always exit. */
1280 gcond
* loop_exit_cond
= get_loop_exit_condition (m_crc_loop
);
1281 gimple_cond_make_false (loop_exit_cond
);
1282 update_stmt (loop_exit_cond
);
1287 crc_optimization::execute (function
*fun
)
1289 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1290 fprintf (dump_file
, "\nExamining %s function.\n",
1291 function_name (fun
));
1293 if (number_of_loops (fun
) <= 1)
1296 /* Get loops of the function. */
1297 auto loop_list
= loops_list (fun
, LI_ONLY_INNERMOST
);
1298 for (auto loop
: loop_list
)
1300 /* Perform initial checks to filter out non-CRCs. */
1301 if (loop_may_calculate_crc (loop
))
1303 /* Get the phi which will hold the calculated CRC. */
1304 gphi
*output_crc
= get_output_phi ();
1308 swap_crc_and_data_if_needed (output_crc
);
1309 if (!is_output_crc (output_crc
))
1311 if (!validate_crc_and_data ())
1314 edge loop_latch
= loop_latch_edge (m_crc_loop
);
1315 tree calced_crc
= PHI_ARG_DEF_FROM_EDGE (m_phi_for_crc
, loop_latch
);
1316 crc_symbolic_execution
execute_loop (m_crc_loop
, nullptr);
1317 /* Execute the loop assigning specific values to CRC and data
1318 for extracting the polynomial. */
1319 std::pair
<tree
, value
*>
1320 calc_polynom
= execute_loop
.extract_polynomial (m_phi_for_crc
,
1325 value
*polynom_value
= calc_polynom
.second
;
1326 /* Stop analysis if we couldn't get the polynomial's value. */
1330 /* Stop analysis in case optimize_size is specified
1331 and table-based would be generated. This check is only needed for
1332 TARGET_CRC case, as polynomial's value isn't known in the
1334 construct_constant_polynomial (polynom_value
);
1336 if (!loop_calculates_crc (output_crc
, calc_polynom
))
1340 fprintf (dump_file
, "The loop with %d header BB index "
1341 "calculates CRC!\n", m_crc_loop
->header
->index
);
1343 if (!optimize_crc_loop (output_crc
))
1346 fprintf (dump_file
, "Couldn't generate faster CRC code.\n");
1356 const pass_data pass_data_crc_optimization
1358 GIMPLE_PASS
, /* type */
1360 OPTGROUP_NONE
, /* optinfo_flags */
1361 TV_GIMPLE_CRC_OPTIMIZATION
, /* tv_id */
1362 (PROP_cfg
| PROP_ssa
), /* properties_required */
1363 0, /* properties_provided */
1364 0, /* properties_destroyed */
1365 0, /* todo_flags_start */
1366 0, /* todo_flags_finish */
1369 class pass_crc_optimization
: public gimple_opt_pass
{
1371 pass_crc_optimization (gcc::context
*ctxt
)
1372 : gimple_opt_pass (pass_data_crc_optimization
, ctxt
)
1375 /* opt_pass methods: */
1376 virtual bool gate (function
*)
1378 return flag_optimize_crc
;
1381 virtual unsigned int execute (function
*);
1383 }; // class pass_crc_optimization
1386 pass_crc_optimization::execute (function
*fun
)
1388 return crc_optimization ().execute (fun
);
1394 make_pass_crc_optimization (gcc::context
*ctxt
)
1396 return new pass_crc_optimization (ctxt
);