9.5.8. Automata generation
The most important data generated by new style pipeline hazards recognizer is the deterministic finite state automaton. It now will be generated from data collected in above sections.
expand_automata (continued)
9837 if (!have_error )
9838 {
9839 transform_insn_regexps ();
9840 check_unit_distributions_to_automata ();
9841 }
9842 if (!have_error )
9843 {
9844 generate ();
9845 check_automata_insn_issues ();
9846 }
9.5.8.1. Transform units usage expression
First, in the unit usage expression of define_insn_reservation, it tries to find out any alternatives, and if there is any, the expression will be transformed into the form as: A|B|C|… (that is “|” goes outmost). So when really building automaton, it can easily find out the nondeterministic parts.
5268 static void
5269 transform_insn_regexps (void) in genautomata.c
5270 {
5271 decl_t decl;
5272 int i;
5273
5274 transform_time = create_ticker ();
5275 add_advance_cycle_insn_decl ();
5276 if (progress_flag )
5277 fprintf (stderr , "Reservation transformation...");
5278 for (i = 0; i < description ->decls_num; i++)
5279 {
5280 decl = description ->decls [i];
5281 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl )
5282 DECL_INSN_RESERV (decl)->transformed_regexp
5283 = transform_regexp (copy_insn_regexp
5284 (DECL_INSN_RESERV (decl)->regexp));
5285 }
5286 if (progress_flag )
5287 fprintf (stderr , "done/n");
5288 ticker_off (&transform_time );
5289 }
In the automaton under built, the states are discriminated by available resource in all CPU cycles (in other words the states describe resource occupation in every cycle). The state transition is driven by instruction issue or CPU cycle advancing. To denote the cycle advancing, we need a pseudo insn, that is why add_advance_cycle_insn_decl here. It adds advance_cycle_insn_decl in the instruction set.
3511 static decl_t advance_cycle_insn_decl ;
3512 static void
3513 add_advance_cycle_insn_decl (void) in genautomata.c
3514 {
3515 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3516 advance_cycle_insn_decl ->mode = dm_insn_reserv;
3517 advance_cycle_insn_decl ->pos = no_pos;
3518 DECL_INSN_RESERV (advance_cycle_insn_decl )->regexp = NULL;
3519 DECL_INSN_RESERV (advance_cycle_insn_decl )->name = (char *) "$advance_cycle";
3520 DECL_INSN_RESERV (advance_cycle_insn_decl )->insn_num
3521 = description ->insns_num;
3522 description ->decls [description ->decls_num] = advance_cycle_insn_decl ;
3523 description ->decls_num++;
3524 description ->insns_num++;
3525 num_dfa_decls++;
3526 }
After creating the pseudo insn, we can transform the regexp now. The transformation will strip extra parethensis and regroup elements to make alternatives explicitly if presenting.
5252 static regexp_t
5253 transform_regexp (regexp_t regexp) in genautomata.c
5254 {
5255 regexp = regexp_transform_func (regexp, transform_1 );
5256 do
5257 {
5258 regexp_transformed_p = 0;
5259 regexp = regexp_transform_func (regexp, transform_2 );
5260 regexp = regexp_transform_func (regexp, transform_3 );
5261 }
5262 while (regexp_transformed_p );
5263 return regexp;
5264 }
The transforming service is provided by regexp_transform_func which recurs into the regexp and does transforming from bottom up.
5225 static regexp_t
5226 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp)) in genautomata.c
5227 {
5228 int i;
5229
5230 if (regexp->mode == rm_sequence)
5231 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5232 REGEXP_SEQUENCE (regexp)->regexps [i]
5233 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5234 else if (regexp->mode == rm_allof)
5235 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5236 REGEXP_ALLOF (regexp)->regexps [i]
5237 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5238 else if (regexp->mode == rm_oneof)
5239 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5240 REGEXP_ONEOF (regexp)->regexps [i]
5241 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5242 else if (regexp->mode == rm_repeat)
5243 REGEXP_REPEAT (regexp)->regexp
5244 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5245 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5246 abort ();
5247 return (*func) (regexp);
5248 }
There are 3 ways to transforming regexp . The first method changes form alike: 4 * exp into a sequence of exp of size 4 like: (exp, exp, exp, exp).
4850 static regexp_t
4851 transform_1 (regexp_t regexp) in genautomata.c
4852 {
4853 int i;
4854 int repeat_num;
4855 regexp_t operand;
4856 pos_t pos;
4857
4858 if (regexp->mode == rm_repeat)
4859 {
4860 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4861 if (repeat_num <= 1)
4862 abort ();
4863 operand = REGEXP_REPEAT (regexp)->regexp;
4864 pos = regexp->mode;
4865 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t )
4866 * (repeat_num - 1));
4867 regexp->mode = rm_sequence;
4868 regexp->pos = pos;
4869 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4870 for (i = 0; i < repeat_num; i++)
4871 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4872 regexp_transformed_p = 1;
4873 }
4874 return regexp;
4875 }
In regrexp , expression (A,B,...) is in form of sequence (‘,’ standing for the advancing cycle), (A+B+...) in form allof (‘+’ standing for all presenting of the units), and (A|B|...) form of oneof (‘|’ standing for either presenting of the units). transform_2 will makes following transformations.
...,(A,B,...),C,.. à ...,A,B,...,C,...
...+(A+B+...)+C+... à ...+A+B+...+C+...
...|(A|B|...)|C|... à ...|A|B|...|C|...
To understand transform_2 , keep in mind that this function works on regexp from bottom up as invoked within regexp_transform_func .
4881 static regexp_t
4882 transform_2 (regexp_t regexp) in genautomata.c
4883 {
4884 if (regexp->mode == rm_sequence)
4885 {
4886 regexp_t sequence = NULL;
4887 regexp_t result;
4888 int sequence_index = 0;
4889 int i, j;
4890
4891 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4892 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4893 {
4894 sequence_index = i;
4895 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4896 break ;
4897 }
4898 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4899 {
4900 if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
4901 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4902 abort ();
4903 result = create_node (sizeof (struct regexp)
4904 + sizeof (regexp_t)
4905 * (REGEXP_SEQUENCE (regexp)->regexps_num
4906 + REGEXP_SEQUENCE (sequence)->regexps_num
4907 - 2));
4908 result->mode = rm_sequence;
4909 result->pos = regexp->pos;
4910 REGEXP_SEQUENCE (result)->regexps_num
4911 = (REGEXP_SEQUENCE (regexp)->regexps_num
4912 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4913 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4914 if (i < sequence_index)
4915 REGEXP_SEQUENCE (result)->regexps [i]
4916 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4917 else if (i > sequence_index)
4918 REGEXP_SEQUENCE (result)->regexps
4919 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4920 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4921 else
4922 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4923 REGEXP_SEQUENCE (result)->regexps [i + j]
4924 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4925 regexp_transformed_p = 1;
4926 regexp = result;
4927 }
4928 }
4929 else if (regexp->mode == rm_allof)
4930 {
4931 regexp_t allof = NULL;
4932 regexp_t result;
4933 int allof_index = 0;
4934 int i, j;
4935
4936 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4937 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4938 {
4939 allof_index = i;
4940 allof = REGEXP_ALLOF (regexp)->regexps [i];
4941 break ;
4942 }
4943 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4944 {
4945 if (REGEXP_ALLOF (allof)->regexps_num <= 1
4946 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4947 abort ();
4948 result = create_node (sizeof (struct regexp)
4949 + sizeof (regexp_t)
4950 * (REGEXP_ALLOF (regexp)->regexps_num
4951 + REGEXP_ALLOF (allof)->regexps_num - 2));
4952 result->mode = rm_allof;
4953 result->pos = regexp->pos;
4954 REGEXP_ALLOF (result)->regexps_num
4955 = (REGEXP_ALLOF (regexp)->regexps_num
4956 + REGEXP_ALLOF (allof)->regexps_num - 1);
4957 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4958 if (i < allof_index)
4959 REGEXP_ALLOF (result)->regexps [i]
4960 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4961 else if (i > allof_index)
4962 REGEXP_ALLOF (result)->regexps
4963 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4964 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4965 else
4966 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4967 REGEXP_ALLOF (result)->regexps [i + j]
4968 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4969 regexp_transformed_p = 1;
4970 regexp = result;
4971 }
4972 }
4973 else if (regexp->mode == rm_oneof)
4974 {
4975 regexp_t oneof = NULL;
4976 regexp_t result;
4977 int oneof_index = 0;
4978 int i, j;
4979
4980 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4981 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4982 {
4983 oneof_index = i;
4984 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4985 break ;
4986 }
4987 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4988 {
4989 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4990 || REGEXP_ONEOF (regexp)->regexps_num <= 1)
4991 abort ();
4992 result = create_node (sizeof (struct regexp)
4993 + sizeof (regexp_t )
4994 * (REGEXP_ONEOF (regexp)->regexps_num
4995 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4996 result->mode = rm_oneof;
4997 result->pos = regexp->pos;
4998 REGEXP_ONEOF (result)->regexps_num
4999 = (REGEXP_ONEOF (regexp)->regexps_num
5000 + REGEXP_ONEOF (oneof)->regexps_num - 1);
5001 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5002 if (i < oneof_index)
5003 REGEXP_ONEOF (result)->regexps [i]
5004 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
5005 else if (i > oneof_index)
5006 REGEXP_ONEOF (result)->regexps
5007 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
5008 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
5009 else
5010 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
5011 REGEXP_ONEOF (result)->regexps [i + j]
5012 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
5013 regexp_transformed_p = 1;
5014 regexp = result;
5015 }
5016 }
5017 return regexp;
5018 }
Then transform_3 will makes following transformations:
...,A|B|...,C,... à (...,A,C,...)|(...,B,C,...)|...
...+(A|B|...)+C+... à (...+A+C+...)|(...+B+C+...)|...
...+(A,B,...)+C+... à (...+A+C+...),B,...
...+(A,B,...)+(C,D,...) à (A+C),(B+D),...
Keep in mind that this function works on regexp from bottom up as invoked within regexp_transform_func .
5025 static regexp_t
5026 transform_3 (regexp_t regexp) in genautomata.c
5027 {
5028 if (regexp->mode == rm_sequence)
5029 {
5030 regexp_t oneof = NULL;
5031 int oneof_index = 0;
5032 regexp_t result;
5033 regexp_t sequence;
5034 int i, j;
5035
5036 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5037 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
5038 {
5039 oneof_index = i;
5040 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
5041 break ;
5042 }
5043 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
5044 {
5045 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5046 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
5047 abort ();
5048 result = create_node (sizeof (struct regexp)
5049 + sizeof (regexp_t )
5050 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
5051 result->mode = rm_oneof;
5052 result->pos = regexp->pos;
5053 REGEXP_ONEOF (result)->regexps_num
5054 = REGEXP_ONEOF (oneof)->regexps_num;
5055 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
5056 {
5057 sequence
5058 = create_node (sizeof (struct regexp)
5059 + sizeof (regexp_t )
5060 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
5061 sequence->mode = rm_sequence;
5062 sequence->pos = regexp->pos;
5063 REGEXP_SEQUENCE (sequence)->regexps_num
5064 = REGEXP_SEQUENCE (regexp)->regexps_num;
5065 REGEXP_ONEOF (result)->regexps [i] = sequence;
5066 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
5067 if (j != oneof_index)
5068 REGEXP_SEQUENCE (sequence)->regexps [j]
5069 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
5070 else
5071 REGEXP_SEQUENCE (sequence)->regexps [j]
5072 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
5073 }
5074 regexp_transformed_p = 1;
5075 regexp = result;
5076 }
5077 }
5078 else if (regexp->mode == rm_allof)
5079 {
5080 regexp_t oneof = NULL;
5081 regexp_t seq;
5082 int oneof_index = 0;
5083 int max_seq_length, allof_length;
5084 regexp_t result;
5085 regexp_t allof = NULL;
5086 regexp_t allof_op = NULL;
5087 int i, j;
5088
5089 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5090 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
5091 {
5092 oneof_index = i;
5093 oneof = REGEXP_ALLOF (regexp)->regexps [i];
5094 break ;
5095 }
5096 if (i < REGEXP_ALLOF (regexp)->regexps_num)
5097 {
5098 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5099 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5100 abort ();
5101 result = create_node (sizeof (struct regexp)
5102 + sizeof (regexp_t )
5103 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
5104 result->mode = rm_oneof;
5105 result->pos = regexp->pos;
5106 REGEXP_ONEOF (result)->regexps_num
5107 = REGEXP_ONEOF (oneof)->regexps_num;
5108 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
5109 {
5110 allof
5111 = create_node (sizeof (struct regexp)
5112 + sizeof (regexp_t )
5113 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
5114 allof->mode = rm_allof;
5115 allof->pos = regexp->pos;
5116 REGEXP_ALLOF (allof)->regexps_num
5117 = REGEXP_ALLOF (regexp)->regexps_num;
5118 REGEXP_ONEOF (result)->regexps [i] = allof;
5119 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
5120 if (j != oneof_index)
5121 REGEXP_ALLOF (allof)->regexps [j]
5122 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
5123 else
5124 REGEXP_ALLOF (allof)->regexps [j]
5125 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
5126 }
5127 regexp_transformed_p = 1;
5128 regexp = result;
5129 }
5130 max_seq_length = 0;
5131 if (regexp->mode == rm_allof)
5132 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5133 {
5134 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
5135 {
5136 seq = REGEXP_ALLOF (regexp)->regexps [i];
5137 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
5138 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
5139 }
5140 else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit
5141 && REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_nothing)
5142 {
5143 max_seq_length = 0;
5144 break ;
5145 }
5146 }
5147 if (max_seq_length != 0)
5148 {
5149 if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5150 abort ();
5151 result = create_node (sizeof (struct regexp)
5152 + sizeof (regexp_t ) * (max_seq_length - 1));
5153 result->mode = rm_sequence;
5154 result->pos = regexp->pos;
5155 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5156 for (i = 0; i < max_seq_length; i++)
5157 {
5158 allof_length = 0;
5159 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5160 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5161 && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5162 ->regexps [j])->regexps_num)))
5163 {
5164 allof_op
5165 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5166 ->regexps [i]);
5167 allof_length++;
5168 }
5169 else if (i == 0
5170 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5171 == rm_unit
5172 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
5173 == rm_nothing)))
5174 {
5175 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5176 allof_length++;
5177 }
5178 if (allof_length == 1)
5179 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5180 else
5181 {
5182 allof = create_node (sizeof (struct regexp)
5183 + sizeof (regexp_t)
5184 * (allof_length - 1));
5185 allof->mode = rm_allof;
5186 allof->pos = regexp->pos;
5187 REGEXP_ALLOF (allof)->regexps_num = allof_length;
5188 REGEXP_SEQUENCE (result)->regexps [i] = allof;
5189 allof_length = 0;
5190 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5191 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5192 && (i <
5193 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5194 ->regexps [j])->regexps_num)))
5195 {
5196 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5197 ->regexps [j])
5198 ->regexps [i]);
5199 REGEXP_ALLOF (allof)->regexps [allof_length]
5200 = allof_op;
5201 allof_length++;
5202 }
5203 else if (i == 0
5204 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5205 == rm_unit
5206 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
5207 == rm_nothing)))
5208 {
5209 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5210 REGEXP_ALLOF (allof)->regexps [allof_length]
5211 = allof_op;
5212 allof_length++;
5213 }
5214 }
5215 }
5216 regexp_transformed_p = 1;
5217 regexp = result;
5218 }
5219 }
5220 return regexp;
5221 }
In transform_regexp , it won’t return until no transformation can be made. Return back to expand_automata , then check_unit_distributions_to_automata will take sanity check. Here the only check to be executed based on the assumption that the units in alternatives must belong to the same automaton for every cycle.
5448 static void
5449 check_unit_distributions_to_automata (void) in genautomata.c
5450 {
5451 decl_t decl;
5452 int i;
5453
5454 if (progress_flag )
5455 fprintf (stderr, "Check unit distributions to automata...");
5456 annotation_message_reported_p = FALSE;
5457 for (i = 0; i < description ->decls_num; i++)
5458 {
5459 decl = description ->decls [i];
5460 if (decl->mode == dm_insn_reserv)
5461 check_regexp_units_distribution
5462 (DECL_INSN_RESERV (decl)->name,
5463 DECL_INSN_RESERV (decl)->transformed_regexp);
5464 }
5465 if (progress_flag )
5466 fprintf (stderr, "done/n");
5467 }
5353 static void
5354 check_regexp_units_distribution (const char *insn_reserv_name, in genautomata.c
5355 regexp_t regexp)
5356 {
5357 int i, j, k, cycle;
5358 regexp_t seq, allof, unit;
5359 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
5360
5361 if (regexp == NULL || regexp->mode != rm_oneof)
5362 return ;
5363 /* Store all unit usages in the regexp: */
5364 obstack_init (&unit_usages );
5365 VLA_PTR_CREATE (cycle_alt_unit_usages , 100, "unit usages on cycles");
5366 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5367 {
5368 seq = REGEXP_ONEOF (regexp)->regexps [i];
5369 if (seq->mode == rm_sequence)
5370 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5371 {
5372 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5373 if (allof->mode == rm_allof)
5374 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5375 {
5376 unit = REGEXP_ALLOF (allof)->regexps [k];
5377 if (unit->mode == rm_unit)
5378 store_alt_unit_usage (regexp, unit, j, i);
5379 else if (unit->mode != rm_nothing)
5380 abort ();
5381 }
5382 else if (allof->mode == rm_unit)
5383 store_alt_unit_usage (regexp, allof, j, i);
5384 else if (allof->mode != rm_nothing)
5385 abort ();
5386 }
5387 else if (seq->mode == rm_allof)
5388 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5389 {
5390 unit = REGEXP_ALLOF (seq)->regexps [k];
5391 if (unit->mode == rm_unit)
5392 store_alt_unit_usage (regexp, unit, 0, i);
5393 else if (unit->mode != rm_nothing)
5394 abort ();
5395 }
5396 else if (seq->mode == rm_unit)
5397 store_alt_unit_usage (regexp, seq, 0, i);
5398 else if (seq->mode != rm_nothing)
5399 abort ();
5400 }
5401 /* Check distribution: */
5402 for (i = 0; i < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages ); i++)
5403 {
5404 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5405 for (unit_usage_ptr = VLA_PTR (cycle_alt_unit_usages , i);
5406 unit_usage_ptr != NULL;
5407 unit_usage_ptr = unit_usage_ptr->next)
5408 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5409 {
5410 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5411 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5412 k < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages)
5413 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5414 k++)
5415 {
5416 for (other_unit_usage_ptr = VLA_PTR (cycle_alt_unit_usages , k);
5417 other_unit_usage_ptr != NULL;
5418 other_unit_usage_ptr = other_unit_usage_ptr->next)
5419 if (unit_usage_ptr->unit_decl->automaton_decl
5420 == other_unit_usage_ptr->unit_decl->automaton_decl)
5421 break ;
5422 if (other_unit_usage_ptr == NULL
5423 && VLA_PTR (cycle_alt_unit_usages , k) != NULL)
5424 break ;
5425 }
5426 if (k < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages )
5427 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5428 {
5429 if (!annotation_message_reported_p )
5430 {
5431 fprintf (stderr , "/n");
5432 error ("The following units do not satisfy units-automata distribution rule");
5433 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5434 annotation_message_reported_p = TRUE;
5435 }
5436 error ("Unit %s, reserv. %s, cycle %d",
5437 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5438 cycle);
5439 }
5440 }
5441 }
5442 VLA_PTR_DELETE (cycle_alt_unit_usages );
5443 obstack_free (&unit_usages , NULL);
5444 }
In every invocation, check_regexp_units_distribution checks the alternatives of one define_insn_reservation. Let’s see it closely. Assuming that for one define_insn_reservation, we have unit usage expression as:
(A, B+J, C) | (D, E, F) | (G, H, I)
Note that it must be the simiplied form, as it has passed transformation.
In the FOR loop begins at line 5366, the expression is re-organized in cycle_alt_unit_usages as following.
figure 71 : cycle_alt_unit_usages
Then FOR loop at line 5402 makes sure that units in same cycle belong to the same automaton. Notice that FOR loop at line 5405 only checks two adjacent units of same cycle in cycle_alt_unit_usages .