PandA-2024.02
IR_lowering_exec.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
36 #include "config_HAVE_ASSERTS.hpp" // for HAVE_ASSERTS
37 #include "config_HAVE_FROM_DISCREPANCY_BUILT.hpp" // for HAVE_FROM_DISCRE...
38 
39 #include "Discrepancy.hpp" // for Discrepancy
40 #include "IR_lowering.hpp" // for IR_lowering, blo...
41 #include "Parameter.hpp" // for Parameter, OPT_d...
42 #include "application_manager.hpp" // for application_manager
43 #include "custom_map.hpp" // for map, _Rb_tree_it...
44 #include "dbgPrintHelper.hpp" // for INDENT_DBG_MEX
45 #include "design_flow_step.hpp" // for ParameterConstRef
46 #include "exceptions.hpp" // for THROW_ASSERT
47 #include "frontend_flow_step.hpp" // for application_mana...
48 #include "function_behavior.hpp" // for FunctionBehavior
49 #include "function_frontend_flow_step.hpp" // for FunctionBehaviorRef
50 #include "math_function.hpp" // for resize_to_1_8_16...
51 #include "refcount.hpp" // for GetPointer
52 #include "string_manipulation.hpp" // for STR
53 #include "tree_basic_block.hpp" // for bloc
54 #include "tree_common.hpp" // for addr_expr_K, mem...
55 #include "tree_helper.hpp" // for tree_helper
56 #include "tree_manager.hpp" // for tree_manager
57 #include "tree_manipulation.hpp" // for tree_nodeRef
58 #include "tree_node.hpp" // for gimple_assign
59 #include "tree_reindex.hpp"
60 #include <algorithm> // for max, min
61 #include <cstring> // for memset, size_t
62 #include <iterator> // for next
63 #include <string> // for operator+, alloc...
64 #include <utility> // for pair
65 #include <vector> // for vector
66 
69 static unsigned long long int invert_mod2n(unsigned long long int x, unsigned long long n)
70 {
71  /* Solve x*y == 1 (mod 2^n), where x is odd. Return y. */
72 
73  /* The algorithm notes that the choice y = x satisfies
74  x*y == 1 mod 2^3, since x is assumed odd.
75  Each iteration doubles the number of bits of significance in y. */
76 
77  unsigned long long int mask;
78  auto y = x;
79  auto nbit = 3ull;
80 
81  mask = (n == sizeof(long long int) * 8 ? ~static_cast<unsigned long long int>(0) :
82  (static_cast<unsigned long long int>(1) << n) - 1);
83 
84  while(nbit < n)
85  {
86  y = y * (2 - x * y) & mask; /* Modulo 2^N */
87  nbit *= 2;
88  }
89  return y;
90 }
91 
92 #define LOWPART(x) (static_cast<unsigned long long int>(x) & ((1ULL << 32) - 1))
93 #define HIGHPART(x) (static_cast<unsigned long long int>(x) >> 32)
94 #define BASE (1LL << 32)
95 
96 /* Unpack a two-word integer into 4 words.
97  LOW and HI are the integer, as two `HOST_WIDE_INT' pieces.
98  WORDS points to the array of HOST_WIDE_INTs. */
99 static void encode(long long int* words, unsigned long long int low, long long int hi)
100 {
101  words[0] = static_cast<long long int>(LOWPART(low));
102  words[1] = static_cast<long long int>(HIGHPART(low));
103  words[2] = static_cast<long long int>(LOWPART(hi));
104  words[3] = static_cast<long long int>(HIGHPART(hi));
105 }
106 
107 /* Pack an array of 4 words into a two-word integer.
108  WORDS points to the array of words.
109  The integer is stored into *LOW and *HI as two `HOST_WIDE_INT' pieces. */
110 static void decode(long long int* words, unsigned long long int* low, long long int* hi)
111 {
112  *low = static_cast<unsigned long long int>(words[0] + words[1] * BASE);
113  *hi = words[2] + words[3] * BASE;
114 }
115 
116 /* Divide doubleword integer LNUM, HNUM by doubleword integer LDEN, HDEN
117  for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM).
118  CODE is a tree code for a kind of division, one of
119  TRUNC_DIV_EXPR, FLOOR_DIV_EXPR, CEIL_DIV_EXPR, ROUND_DIV_EXPR
120  or EXACT_DIV_EXPR
121  It controls how the quotient is rounded to an integer.
122  Return nonzero if the operation overflows.
123  UNS nonzero says do unsigned division. */
125  /* num == numerator == dividend */
126  unsigned long long int lnum_orig, long long int hnum_orig,
127  /* den == denominator == divisor */
128  unsigned long long int lden_orig, unsigned long long int* lquo, long long int* hquo)
129 {
130  long long int num[4 + 1]; /* extra element for scaling. */
131  long long int den[4], quo[4];
132  int i, j;
133  unsigned long long int work;
134  unsigned long long int carry = 0;
135  unsigned long long int lnum = lnum_orig;
136  long long int hnum = hnum_orig;
137  unsigned long long int lden = lden_orig;
138  int overflow = 0;
139 
140  if(lden == 0)
141  {
142  overflow = 1, lden = 1;
143  }
144 
145  if(hnum == 0)
146  { /* single precision */
147  *hquo = 0;
148  /* This unsigned division rounds toward zero. */
149  *lquo = lnum / lden;
150  goto finish_up;
151  }
152 
153  if(hnum == 0)
154  { /* trivial case: dividend < divisor */
155  *hquo = 0;
156  *lquo = 0;
157 
158  goto finish_up;
159  }
160 
161  memset(quo, 0, sizeof quo);
162 
163  memset(num, 0, sizeof num); /* to zero 9th element */
164  memset(den, 0, sizeof den);
165 
166  encode(num, lnum, hnum);
167  encode(den, lden, 0);
168 
169  /* Special code for when the divisor < BASE. */
170  if(lden < static_cast<unsigned long long int>(BASE))
171  {
172  /* hnum != 0 already checked. */
173  for(i = 4 - 1; i >= 0; i--)
174  {
175  work = static_cast<unsigned long long int>(num[i]) + carry * BASE;
176  quo[i] = static_cast<long long int>(work / lden);
177  carry = work % lden;
178  }
179  }
180  else
181  {
182  /* Full double precision division,
183  with thanks to Don Knuth's "Seminumerical Algorithms". */
184  int num_hi_sig, den_hi_sig;
185  unsigned long long int quo_est, scale;
186 
187  /* Find the highest nonzero divisor digit. */
188  for(i = 4 - 1;; i--)
189  {
190  if(den[i] != 0)
191  {
192  den_hi_sig = i;
193  break;
194  }
195  }
196 
197  /* Insure that the first digit of the divisor is at least BASE/2.
198  This is required by the quotient digit estimation algorithm. */
199 
200  scale = static_cast<unsigned long long int>(BASE / (den[den_hi_sig] + 1));
201  if(scale > 1)
202  { /* scale divisor and dividend */
203  carry = 0;
204  for(i = 0; i <= 4 - 1; i++)
205  {
206  work = (static_cast<unsigned long long int>(num[i]) * scale) + carry;
207  num[i] = LOWPART(work);
208  carry = HIGHPART(work);
209  }
210 
211  num[4] = static_cast<long long int>(carry);
212  carry = 0;
213  for(i = 0; i <= 4 - 1; i++)
214  {
215  work = (static_cast<unsigned long long int>(den[i]) * scale) + carry;
216  den[i] = LOWPART(work);
217  carry = HIGHPART(work);
218  if(den[i] != 0)
219  {
220  den_hi_sig = i;
221  }
222  }
223  }
224 
225  num_hi_sig = 4;
226 
227  /* Main loop */
228  for(i = num_hi_sig - den_hi_sig - 1; i >= 0; i--)
229  {
230  /* Guess the next quotient digit, quo_est, by dividing the first
231  two remaining dividend digits by the high order quotient digit.
232  quo_est is never low and is at most 2 high. */
233  unsigned long long int tmp;
234 
235  num_hi_sig = i + den_hi_sig + 1;
236  work = static_cast<unsigned long long int>(num[num_hi_sig]) * BASE +
237  static_cast<unsigned long long int>(num[num_hi_sig - 1]);
238  if(num[num_hi_sig] != den[den_hi_sig])
239  {
240  quo_est = work / static_cast<unsigned long long int>(den[den_hi_sig]);
241  }
242  else
243  {
244  quo_est = BASE - 1;
245  }
246 
247  /* Refine quo_est so it's usually correct, and at most one high. */
248  tmp = work - quo_est * static_cast<unsigned long long int>(den[den_hi_sig]);
249  if(tmp < BASE && (static_cast<unsigned long long int>(den[den_hi_sig - 1]) * quo_est >
250  (tmp * BASE + static_cast<unsigned long long int>(num[num_hi_sig - 2]))))
251  {
252  quo_est--;
253  }
254 
255  /* Try QUO_EST as the quotient digit, by multiplying the
256  divisor by QUO_EST and subtracting from the remaining dividend.
257  Keep in mind that QUO_EST is the I - 1st digit. */
258 
259  carry = 0;
260  for(j = 0; j <= den_hi_sig; j++)
261  {
262  work = quo_est * static_cast<unsigned long long int>(den[j]) + carry;
263  carry = HIGHPART(work);
264  work = static_cast<unsigned long long int>(num[i + j]) - LOWPART(work);
265  num[i + j] = LOWPART(work);
266  carry += HIGHPART(work) != 0;
267  }
268 
269  /* If quo_est was high by one, then num[i] went negative and
270  we need to correct things. */
271  if(num[num_hi_sig] < static_cast<long long int>(carry))
272  {
273  quo_est--;
274  carry = 0; /* add divisor back in */
275  for(j = 0; j <= den_hi_sig; j++)
276  {
277  work = static_cast<unsigned long long int>(num[i + j]) + static_cast<unsigned long long int>(den[j]) +
278  carry;
279  carry = HIGHPART(work);
280  num[i + j] = LOWPART(work);
281  }
282 
283  num[num_hi_sig] = num[num_hi_sig] + static_cast<long long int>(carry);
284  }
285 
286  /* Store the quotient digit. */
287  quo[i] = static_cast<long long int>(quo_est);
288  }
289  }
290 
291  decode(quo, lquo, hquo);
292 
293 finish_up:
294 
295  return overflow;
296 }
297 
298 /* Choose a minimal N + 1 bit approximation to 1/D that can be used to
299  replace division by D, and put the least significant N bits of the result
300  in *MULTIPLIER_PTR and return the most significant bit.
301 
302  The width of operations is N (should be <= HOST_BITS_PER_WIDE_INT), the
303  needed precision is in PRECISION (should be <= N).
304 
305  PRECISION should be as small as possible so this function can choose
306  multiplier more freely.
307 
308  The rounded-up logarithm of D is placed in *lgup_ptr. A shift count that
309  is to be used for a final right shift is placed in *POST_SHIFT_PTR.
310 
311  Using this function, x/D will be equal to (x * m) >> (*POST_SHIFT_PTR),
312  where m is the full HOST_BITS_PER_WIDE_INT + 1 bit multiplier. */
313 static unsigned long long int choose_multiplier(unsigned long long int d, int n, int precision,
314  unsigned long long int* multiplier_ptr, int* post_shift_ptr,
315  int* lgup_ptr)
316 {
317  long long int mhigh_hi, mlow_hi;
318  unsigned long long int mhigh_lo, mlow_lo;
319  int lgup, post_shift;
320  int pow, pow2;
321  unsigned long long int nl;
322  long long int nh;
323 
324  /* lgup = ceil(log2(divisor)); */
325  lgup = static_cast<int>(ceil_log2(d));
326 
327  THROW_ASSERT(lgup <= n, "unexpected condition");
328 
329  pow = n + lgup;
330  pow2 = n + lgup - precision;
331 
332  /* We could handle this with some effort, but this case is much
333  better handled directly with a scc insn, so rely on caller using
334  that. */
335  THROW_ASSERT(pow != 128, "unexpected condition");
336 
337  /* mlow = 2^(N + lgup)/d */
338  if(pow >= 64)
339  {
340  nh = 1LL << (pow - 64);
341  nl = 0;
342  }
343  else
344  {
345  nh = 0;
346  nl = 1ULL << pow;
347  }
348 
349  div_and_round_double_cprop(nl, nh, d, &mlow_lo, &mlow_hi);
350 
351  /* mhigh = (2^(N + lgup) + 2^(N + lgup - precision))/d */
352  if(pow2 >= 64)
353  {
354  nh |= 1LL << (pow2 - 64);
355  }
356  else
357  {
358  nl |= 1ULL << pow2;
359  }
360 
361  div_and_round_double_cprop(nl, nh, d, &mhigh_lo, &mhigh_hi);
362 
363  THROW_ASSERT(!mhigh_hi || static_cast<unsigned long long int>(nh) - d < d, "unexpected condition");
364  THROW_ASSERT(mhigh_hi <= 1 && mlow_hi <= 1, "unexpected condition");
365  /* Assert that mlow < mhigh. */
366  THROW_ASSERT(mlow_hi < mhigh_hi || (mlow_hi == mhigh_hi && mlow_lo < mhigh_lo), "unexpected condition");
367 
368  /* If precision == N, then mlow, mhigh exceed 2^N
369  (but they do not exceed 2^(N+1)). */
370 
371  /* Reduce to lowest terms. */
372  for(post_shift = lgup; post_shift > 0; post_shift--)
373  {
374  unsigned long long int ml_lo =
375  static_cast<unsigned long long int>((static_cast<unsigned long long int>(mlow_hi)) << (64 - 1)) |
376  (mlow_lo >> 1);
377  unsigned long long int mh_lo =
378  static_cast<unsigned long long int>((static_cast<unsigned long long int>(mhigh_hi)) << (64 - 1)) |
379  (mhigh_lo >> 1);
380  if(ml_lo >= mh_lo)
381  {
382  break;
383  }
384 
385  mlow_hi = 0;
386  mlow_lo = ml_lo;
387  mhigh_hi = 0;
388  mhigh_lo = mh_lo;
389  }
390 
391  *post_shift_ptr = post_shift;
392  *lgup_ptr = lgup;
393  if(n < 64)
394  {
395  unsigned long long int mask = (1ULL << n) - 1;
396  *multiplier_ptr = mhigh_lo & mask;
397  return mhigh_lo >= mask;
398  }
399  else
400  {
401  *multiplier_ptr = mhigh_lo;
402  return static_cast<unsigned long long int>(mhigh_hi);
403  }
404 }
405 
406 void IR_lowering::division_by_a_constant(const std::pair<unsigned int, blocRef>& block,
407  std::list<tree_nodeRef>::const_iterator& it_los, gimple_assign* ga,
408  const tree_nodeRef& op1, enum kind code1, bool& restart_analysis,
409  const std::string& srcp_default, const std::string& step_name)
410 {
412  const auto op0 = GetPointerS<const binary_expr>(GET_CONST_NODE(ga->op1))->op0;
413  const auto type_expr = GetPointerS<const binary_expr>(GET_CONST_NODE(ga->op1))->type;
414 
415  const auto unsignedp = tree_helper::IsUnsignedIntegerType(type_expr);
418  "");
419  const auto ext_op1 = static_cast<long long>(tree_helper::GetConstValue(op1));
420  const auto rem_flag = code1 == trunc_mod_expr_K;
421 
422  if(!AppM->ApplyNewTransformation())
423  {
424  return;
425  }
427  if(ext_op1 == 1)
428  {
429  tree_nodeRef new_op1;
430  if(rem_flag)
431  {
432  new_op1 = TM->CreateUniqueIntegerCst(0, type_expr);
433  }
434  else
435  {
436  new_op1 = op0;
437  }
438  ga->op1 = new_op1;
439  restart_analysis = true;
440  }
441  else if(!unsignedp && ext_op1 == -1)
442  {
443  tree_nodeRef new_op1;
444  if(rem_flag)
445  {
446  new_op1 = TM->CreateUniqueIntegerCst(0, type_expr);
447  }
448  else
449  {
450  new_op1 = tree_man->create_unary_operation(type_expr, op0, srcp_default, negate_expr_K);
451  }
452  ga->op1 = new_op1;
453  restart_analysis = true;
454  }
455  else
456  {
457  const auto op1_is_pow2 =
458  ((EXACT_POWER_OF_2_OR_ZERO_P(ext_op1) || (!unsignedp && EXACT_POWER_OF_2_OR_ZERO_P(-ext_op1))));
459  // long long int last_div_const = ! rem_flag ? ext_op1 : 0;
460 
461  if(code1 == exact_div_expr_K && op1_is_pow2)
462  {
463  code1 = trunc_div_expr_K;
464  }
465 
466  if(ext_op1 != 0)
467  {
468  switch(code1)
469  {
470  case trunc_div_expr_K:
471  case trunc_mod_expr_K:
472  {
473  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Trunc_div or trunc_mod");
474  if(unsignedp)
475  {
477  int pre_shift;
478  auto d = static_cast<unsigned long long int>(ext_op1);
480  {
481  pre_shift = static_cast<int>(floor_log2(d));
482  tree_nodeRef new_op1;
483  if(rem_flag)
484  {
485  const auto mask =
486  TM->CreateUniqueIntegerCst((static_cast<long long int>(1) << pre_shift) - 1, type_expr);
487  new_op1 = tree_man->create_binary_operation(type_expr, op0, mask, srcp_default, bit_and_expr_K);
488  }
489  else
490  {
491  const auto shift = TM->CreateUniqueIntegerCst(pre_shift, type_expr);
492  new_op1 = tree_man->create_binary_operation(type_expr, op0, shift, srcp_default, rshift_expr_K);
493  }
494  ga->op1 = new_op1;
495  restart_analysis = true;
496  }
497  else
498  {
499  const auto data_bitsize = static_cast<int>(tree_helper::Size(tree_helper::CGetType(type_expr)));
500  if(d < (1ull << (data_bitsize - 1)))
501  {
502  unsigned long long int mh, ml;
503  int post_shift;
504  int dummy;
505  const auto previous_precision = data_bitsize;
506  int precision;
507  if(code1 == trunc_mod_expr_K)
508  {
509  precision =
510  std::min(data_bitsize,
511  static_cast<int>(std::max(tree_helper::Size(ga->op0), tree_helper::Size(op0)) +
512  1ULL + ceil_log2(d)));
513  }
514  else
515  {
516  precision = std::min(data_bitsize,
517  static_cast<int>(tree_helper::Size(ga->op0) + 1ULL + ceil_log2(d)));
518  }
520  "---correct rounding: precision=" + STR(data_bitsize) +
521  " vs precision=" + STR(precision));
522  if(previous_precision > precision)
523  {
525  "-->Decreased precision keeping correct rounding to value " + STR(precision) +
526  ". Gained " + STR(previous_precision - precision) + " bits.");
528  }
531  mh = choose_multiplier(d, data_bitsize, precision, &ml, &post_shift, &dummy);
533  "---ml = " + STR(ml) + " mh =" + STR(mh));
534  /* If the suggested multiplier is more than SIZE bits,
535  we can do better for even divisors, using an
536  initial right shift. */
537  if(mh != 0 && (d & 1) == 0)
538  {
539  pre_shift = static_cast<int>(floor_log2(d & -d));
540  mh = choose_multiplier(d >> pre_shift, data_bitsize, precision - pre_shift, &ml, &post_shift,
541  &dummy);
542  THROW_ASSERT(!mh, "unexpected condition");
543  }
544  else
545  {
546  pre_shift = 0;
547  }
548  tree_nodeRef quotient_expr;
549  if(mh != 0)
550  {
551  THROW_ASSERT(post_shift - 1 < 64, "fail1");
552 
553  tree_nodeRef t1_ga_var = expand_mult_highpart(op0, ml, type_expr, data_bitsize, it_los,
554  block.second, srcp_default);
555  THROW_ASSERT(t1_ga_var, "fail1");
556 
557  const auto t2_expr =
558  tree_man->create_binary_operation(type_expr, op0, t1_ga_var, srcp_default, minus_expr_K);
559  const auto t2_ga = tree_man->CreateGimpleAssign(type_expr, tree_nodeRef(), tree_nodeRef(),
560  t2_expr, function_id, srcp_default);
561  block.second->PushBefore(t2_ga, *it_los, AppM);
562  const auto t2_ga_var = GetPointer<gimple_assign>(GET_NODE(t2_ga))->op0;
563 
564  const auto const1_node = TM->CreateUniqueIntegerCst(1, type_expr);
565  const auto t3_expr = tree_man->create_binary_operation(type_expr, t2_ga_var, const1_node,
566  srcp_default, rshift_expr_K);
567  const auto t3_ga = tree_man->CreateGimpleAssign(type_expr, tree_nodeRef(), tree_nodeRef(),
568  t3_expr, function_id, srcp_default);
569  block.second->PushBefore(t3_ga, *it_los, AppM);
570  const auto t3_ga_var = GetPointer<gimple_assign>(GET_NODE(t3_ga))->op0;
571 
572  const auto t4_expr = tree_man->create_binary_operation(type_expr, t1_ga_var, t3_ga_var,
573  srcp_default, plus_expr_K);
574  const auto t4_ga = tree_man->CreateGimpleAssign(type_expr, tree_nodeRef(), tree_nodeRef(),
575  t4_expr, function_id, srcp_default);
576  block.second->PushBefore(t4_ga, *it_los, AppM);
577  const auto t4_ga_var = GetPointer<gimple_assign>(GET_NODE(t4_ga))->op0;
578 
579  THROW_ASSERT(post_shift > 0, "unexpected condition");
580 
581  if(post_shift > 1)
582  {
583  const auto post_shift_minusone_node =
584  TM->CreateUniqueIntegerCst(post_shift - 1, type_expr);
585  quotient_expr = tree_man->create_binary_operation(
586  type_expr, t4_ga_var, post_shift_minusone_node, srcp_default, rshift_expr_K);
587  }
588  else
589  {
590  quotient_expr = t4_ga_var;
591  }
592  }
593  else
594  {
595  THROW_ASSERT(pre_shift < data_bitsize && post_shift < data_bitsize, "fail1");
596  tree_nodeRef t1_ga_var;
597  if(pre_shift != 0)
598  {
599  const auto pre_shift_node = TM->CreateUniqueIntegerCst(pre_shift, type_expr);
600  const auto t1_expr = tree_man->create_binary_operation(type_expr, op0, pre_shift_node,
601  srcp_default, rshift_expr_K);
602  const auto t1_ga = tree_man->CreateGimpleAssign(type_expr, tree_nodeRef(), tree_nodeRef(),
603  t1_expr, function_id, srcp_default);
604  block.second->PushBefore(t1_ga, *it_los, AppM);
605  t1_ga_var = GetPointer<gimple_assign>(GET_NODE(t1_ga))->op0;
606  }
607  else
608  {
609  t1_ga_var = op0;
610  }
611 
612  const auto t2_ga_var = expand_mult_highpart(t1_ga_var, ml, type_expr, data_bitsize, it_los,
613  block.second, srcp_default);
614 
615  if(post_shift != 0)
616  {
617  const auto post_shift_node = TM->CreateUniqueIntegerCst(post_shift, type_expr);
618  quotient_expr = tree_man->create_binary_operation(type_expr, t2_ga_var, post_shift_node,
619  srcp_default, rshift_expr_K);
620  }
621  else
622  {
623  quotient_expr = t2_ga_var;
624  }
625  }
626  AppM->RegisterTransformation(step_name, *it_los);
627  if(rem_flag)
628  {
629  const auto quotient_ga = tree_man->CreateGimpleAssign(
630  type_expr, tree_nodeRef(), tree_nodeRef(), quotient_expr, function_id, srcp_default);
631  block.second->PushBefore(quotient_ga, *it_los, AppM);
632  const auto quotient_ga_var = GetPointer<gimple_assign>(GET_NODE(quotient_ga))->op0;
633  const auto mul_expr = tree_man->create_binary_operation(type_expr, quotient_ga_var, op1,
634  srcp_default, mult_expr_K);
635  const auto mul_ga = tree_man->CreateGimpleAssign(type_expr, tree_nodeRef(), tree_nodeRef(),
636  mul_expr, function_id, srcp_default);
637  block.second->PushBefore(mul_ga, *it_los, AppM);
638  const auto mul_ga_var = GetPointerS<gimple_assign>(GET_NODE(mul_ga))->op0;
640  tree_nodeRef sub_expr;
641  if(AppM->ApplyNewTransformation() &&
642  static_cast<unsigned long long>(data_bitsize) > tree_helper::Size(ga->op0))
643  {
644  const auto masklow = (integer_cst_t(1) << tree_helper::Size(ga->op0)) - 1;
645  const auto Constmasklow = TM->CreateUniqueIntegerCst(masklow, type_expr);
646  const auto temp_op0_expr = tree_man->create_binary_operation(
647  type_expr, op0, Constmasklow, srcp_default, bit_and_expr_K);
648  const auto temp_op0_ga = tree_man->CreateGimpleAssign(
649  type_expr, tree_nodeRef(), tree_nodeRef(), temp_op0_expr, function_id, srcp_default);
650  block.second->PushBefore(temp_op0_ga, *it_los, AppM);
651  const auto temp_op0_ga_var = GetPointer<gimple_assign>(GET_NODE(temp_op0_ga))->op0;
652  const auto temp_op1_expr = tree_man->create_binary_operation(
653  type_expr, mul_ga_var, Constmasklow, srcp_default, bit_and_expr_K);
654  const auto temp_op1_ga = tree_man->CreateGimpleAssign(
655  type_expr, tree_nodeRef(), tree_nodeRef(), temp_op1_expr, function_id, srcp_default);
656  block.second->PushBefore(temp_op1_ga, *it_los, AppM);
657  const auto temp_op1_ga_var = GetPointerS<gimple_assign>(GET_NODE(temp_op1_ga))->op0;
658  const auto temp_sub_expr = tree_man->create_binary_operation(
659  type_expr, temp_op0_ga_var, temp_op1_ga_var, srcp_default, minus_expr_K);
660  const auto temp_sub_expr_ga = tree_man->CreateGimpleAssign(
661  type_expr, tree_nodeRef(), tree_nodeRef(), temp_sub_expr, function_id, srcp_default);
662  AppM->RegisterTransformation(step_name, temp_sub_expr_ga);
663  block.second->PushBefore(temp_sub_expr_ga, *it_los, AppM);
664  const auto temp_sub_expr_ga_var =
665  GetPointerS<gimple_assign>(GET_NODE(temp_sub_expr_ga))->op0;
666  sub_expr = tree_man->create_binary_operation(type_expr, temp_sub_expr_ga_var,
667  Constmasklow, srcp_default, bit_and_expr_K);
668  }
669  else
670  {
671  sub_expr = tree_man->create_binary_operation(type_expr, op0, mul_ga_var, srcp_default,
672  minus_expr_K);
673  }
674  ga->op1 = sub_expr;
675  }
676  else
677  {
678  ga->op1 = quotient_expr;
679  }
680  restart_analysis = true;
681  }
682  }
683  }
684  else
685  {
687  tree_nodeRef new_op1;
688  auto d = ext_op1;
689  unsigned long long abs_d;
690 
691  /* Since d might be INT_MIN, we have to cast to
692  unsigned long long before negating to avoid
693  undefined signed overflow. */
694  abs_d = (d >= 0 ? static_cast<unsigned long long int>(d) : static_cast<unsigned long long int>(-d));
695 
696  /* n rem d = n rem -d */
697  if(rem_flag && d < 0)
698  {
699  d = static_cast<long long int>(abs_d);
700  }
701 
702  const auto size = tree_helper::Size(type_expr);
703  if(abs_d == (1ull << (size - 1)))
704  {
705  if(AppM->ApplyNewTransformation())
706  {
707  const auto bt = tree_man->GetBooleanType();
708  const auto quotient_expr =
709  tree_man->create_binary_operation(bt, op0, op1, srcp_default, eq_expr_K);
710  const auto quotient_ga = tree_man->CreateGimpleAssign(bt, TM->CreateUniqueIntegerCst(0, bt),
711  TM->CreateUniqueIntegerCst(1, bt),
712  quotient_expr, function_id, srcp_default);
713  block.second->PushBefore(quotient_ga, *it_los, AppM);
714  const auto quotient_ga_var = GetPointerS<gimple_assign>(GET_NODE(quotient_ga))->op0;
715  const auto quotient_nop_expr =
716  tree_man->create_unary_operation(type_expr, quotient_ga_var, srcp_default, nop_expr_K);
717  if(rem_flag)
718  {
719  const auto quotient_nop = tree_man->CreateGimpleAssign(
720  type_expr, TM->CreateUniqueIntegerCst(0, type_expr),
721  TM->CreateUniqueIntegerCst(1, type_expr), quotient_nop_expr, function_id, srcp_default);
722  block.second->PushBefore(quotient_nop, *it_los, AppM);
723  const auto quotient_nop_var = GetPointerS<gimple_assign>(GET_NODE(quotient_nop))->op0;
724  const auto mul_expr = tree_man->create_binary_operation(type_expr, quotient_nop_var, op1,
725  srcp_default, mult_expr_K);
726  const auto mul_ga = tree_man->CreateGimpleAssign(type_expr, nullptr, nullptr, mul_expr,
727  function_id, srcp_default);
728  block.second->PushBefore(mul_ga, *it_los, AppM);
729  const auto mul_ga_var = GetPointerS<gimple_assign>(GET_NODE(mul_ga))->op0;
730  const auto sub_expr = tree_man->create_binary_operation(type_expr, op0, mul_ga_var,
731  srcp_default, minus_expr_K);
732  ga->op1 = sub_expr;
733  }
734  else
735  {
736  ga->op1 = quotient_nop_expr;
737  }
738  AppM->RegisterTransformation(step_name, *it_los);
739  restart_analysis = true;
740  }
741  }
742  else if(EXACT_POWER_OF_2_OR_ZERO_P(abs_d))
743  {
744  if(AppM->ApplyNewTransformation())
745  {
746  if(rem_flag)
747  {
748  new_op1 = expand_smod_pow2(op0, abs_d, *it_los, block.second, type_expr, srcp_default);
749  ga->op1 = new_op1;
750  }
751  else
752  {
753  new_op1 = expand_sdiv_pow2(op0, abs_d, *it_los, block.second, type_expr, srcp_default);
755  if(d < 0)
756  {
757  tree_nodeRef sdiv_pow2_ga = tree_man->CreateGimpleAssign(
758  type_expr, tree_nodeRef(), tree_nodeRef(), new_op1, function_id, srcp_default);
759  block.second->PushBefore(sdiv_pow2_ga, *it_los, AppM);
760  tree_nodeRef sdiv_pow2_ga_var = GetPointer<gimple_assign>(GET_NODE(sdiv_pow2_ga))->op0;
761  new_op1 = tree_man->create_unary_operation(type_expr, sdiv_pow2_ga_var, srcp_default,
762  negate_expr_K);
763  }
764  ga->op1 = new_op1;
765  }
766  AppM->RegisterTransformation(step_name, *it_los);
767  restart_analysis = true;
768  }
769  }
770  else
771  {
772  const auto data_bitsize = static_cast<int>(tree_helper::Size(type_expr));
773  if(AppM->ApplyNewTransformation() && data_bitsize <= 64)
774  {
775  unsigned long long int ml;
776  int post_shift;
777  int lgup;
778  choose_multiplier(abs_d, data_bitsize, data_bitsize - 1, &ml, &post_shift, &lgup);
779  tree_nodeRef quotient_expr;
780  THROW_ASSERT(post_shift < 64 && size - 1 < 64, "unexpected condition");
781  if(ml < (1ULL << (data_bitsize - 1)))
782  {
783  tree_nodeRef t1_ga_var = expand_mult_highpart(op0, ml, type_expr, data_bitsize, it_los,
784  block.second, srcp_default);
785  THROW_ASSERT(t1_ga_var, "fail1");
786 
787  tree_nodeRef t2_ga_var;
788  if(post_shift != 0)
789  {
790  tree_nodeRef post_shift_node =
791  TM->CreateUniqueIntegerCst(static_cast<long long int>(post_shift), type_expr);
792 
794  type_expr, t1_ga_var, post_shift_node, srcp_default, rshift_expr_K);
796  type_expr, tree_nodeRef(), tree_nodeRef(), t2_expr, function_id, srcp_default);
797  block.second->PushBefore(t2_ga, *it_los, AppM);
798  t2_ga_var = GetPointer<gimple_assign>(GET_NODE(t2_ga))->op0;
799  }
800  else
801  {
802  t2_ga_var = t1_ga_var;
803  }
804 
805  tree_nodeRef data_bitsize_minusone_node =
806  TM->CreateUniqueIntegerCst(static_cast<long long int>(data_bitsize - 1), type_expr);
808  type_expr, op0, data_bitsize_minusone_node, srcp_default, rshift_expr_K);
810  t3_expr, function_id, srcp_default);
811  block.second->PushBefore(t3_ga, *it_los, AppM);
812  tree_nodeRef t3_ga_var = GetPointer<gimple_assign>(GET_NODE(t3_ga))->op0;
813 
814  if(d < 0)
815  {
816  quotient_expr = tree_man->create_binary_operation(type_expr, t3_ga_var, t2_ga_var,
817  srcp_default, minus_expr_K);
818  }
819  else
820  {
821  quotient_expr = tree_man->create_binary_operation(type_expr, t2_ga_var, t3_ga_var,
822  srcp_default, minus_expr_K);
823  }
824  }
825  else
826  {
827  ml |= (~0ULL) << (data_bitsize - 1);
828  tree_nodeRef t1_ga_var = expand_mult_highpart(op0, ml, type_expr, data_bitsize, it_los,
829  block.second, srcp_default);
830  THROW_ASSERT(t1_ga_var, "fail1");
831  tree_nodeRef t2_expr =
832  tree_man->create_binary_operation(type_expr, t1_ga_var, op0, srcp_default, plus_expr_K);
834  t2_expr, function_id, srcp_default);
835  block.second->PushBefore(t2_ga, *it_los, AppM);
836  tree_nodeRef t2_ga_var = GetPointer<gimple_assign>(GET_NODE(t2_ga))->op0;
837 
838  tree_nodeRef post_shift_node =
839  TM->CreateUniqueIntegerCst(static_cast<long long int>(post_shift), type_expr);
840 
842  type_expr, t2_ga_var, post_shift_node, srcp_default, rshift_expr_K);
844  t3_expr, function_id, srcp_default);
845  block.second->PushBefore(t3_ga, *it_los, AppM);
846  tree_nodeRef t3_ga_var = GetPointer<gimple_assign>(GET_NODE(t3_ga))->op0;
847 
848  tree_nodeRef data_bitsize_minusone_node =
849  TM->CreateUniqueIntegerCst(static_cast<long long int>(data_bitsize - 1), type_expr);
851  type_expr, op0, data_bitsize_minusone_node, srcp_default, rshift_expr_K);
853  t4_expr, function_id, srcp_default);
854  block.second->PushBefore(t4_ga, *it_los, AppM);
855  tree_nodeRef t4_ga_var = GetPointer<gimple_assign>(GET_NODE(t4_ga))->op0;
856 
857  if(d < 0)
858  {
859  quotient_expr = tree_man->create_binary_operation(type_expr, t4_ga_var, t3_ga_var,
860  srcp_default, minus_expr_K);
861  }
862  else
863  {
864  quotient_expr = tree_man->create_binary_operation(type_expr, t3_ga_var, t4_ga_var,
865  srcp_default, minus_expr_K);
866  }
867  }
868  if(rem_flag)
869  {
871  type_expr, tree_nodeRef(), tree_nodeRef(), quotient_expr, function_id, srcp_default);
872  block.second->PushBefore(quotient_ga, *it_los, AppM);
873  tree_nodeRef quotient_ga_var = GetPointer<gimple_assign>(GET_NODE(quotient_ga))->op0;
874  tree_nodeRef mul_expr = tree_man->create_binary_operation(type_expr, quotient_ga_var, op1,
875  srcp_default, mult_expr_K);
877  mul_expr, function_id, srcp_default);
878  block.second->PushBefore(mul_ga, *it_los, AppM);
879  tree_nodeRef mul_ga_var = GetPointer<gimple_assign>(GET_NODE(mul_ga))->op0;
880  tree_nodeRef sub_expr = tree_man->create_binary_operation(type_expr, op0, mul_ga_var,
881  srcp_default, minus_expr_K);
882  ga->op1 = sub_expr;
883  }
884  else
885  {
886  ga->op1 = quotient_expr;
887  }
888  AppM->RegisterTransformation(step_name, *it_los);
889  restart_analysis = true;
890  }
891  }
892  }
893  break;
894  }
895  case exact_div_expr_K:
896  {
897  int pre_shift;
898  long long int d = ext_op1;
899  unsigned long long int ml;
900  auto size = tree_helper::Size(tree_helper::CGetType(type_expr));
901 
902  pre_shift = static_cast<int>(floor_log2(static_cast<unsigned long long int>(d & -d)));
903  ml = invert_mod2n(static_cast<unsigned long long int>(d >> pre_shift), size);
904  tree_nodeRef pre_shift_node = TM->CreateUniqueIntegerCst(pre_shift, type_expr);
905  tree_nodeRef ml_node = TM->CreateUniqueIntegerCst(static_cast<long long int>(ml), type_expr);
906  tree_nodeRef t1_expr =
907  tree_man->create_binary_operation(type_expr, op0, pre_shift_node, srcp_default, rshift_expr_K);
908  tree_nodeRef t1_ga = tree_man->CreateGimpleAssign(type_expr, tree_nodeRef(), tree_nodeRef(), t1_expr,
909  function_id, srcp_default);
910  block.second->PushBefore(t1_ga, *it_los, AppM);
911  tree_nodeRef t1_ga_var = GetPointer<gimple_assign>(GET_NODE(t1_ga))->op0;
912  tree_nodeRef quotient_expr =
913  tree_man->create_binary_operation(type_expr, t1_ga_var, ml_node, srcp_default, mult_expr_K);
914 
915  ga->op1 = quotient_expr;
916  AppM->RegisterTransformation(step_name, *it_los);
917  restart_analysis = true;
918  break;
919  }
920  case assert_expr_K:
921  case bit_and_expr_K:
922  case bit_ior_expr_K:
923  case bit_xor_expr_K:
924  case catch_expr_K:
925  case ceil_div_expr_K:
926  case ceil_mod_expr_K:
927  case complex_expr_K:
928  case compound_expr_K:
929  case eh_filter_expr_K:
930  case eq_expr_K:
931  case fdesc_expr_K:
932  case floor_div_expr_K:
933  case floor_mod_expr_K:
934  case ge_expr_K:
935  case gt_expr_K:
936  case goto_subroutine_K:
937  case in_expr_K:
938  case init_expr_K:
939  case le_expr_K:
940  case lrotate_expr_K:
941  case lshift_expr_K:
942  case lt_expr_K:
943  case max_expr_K:
944  case mem_ref_K:
945  case min_expr_K:
946  case minus_expr_K:
947  case modify_expr_K:
948  case mult_expr_K:
949  case mult_highpart_expr_K:
950  case ne_expr_K:
951  case ordered_expr_K:
952  case plus_expr_K:
953  case pointer_plus_expr_K:
954  case postdecrement_expr_K:
955  case postincrement_expr_K:
956  case predecrement_expr_K:
957  case preincrement_expr_K:
958  case range_expr_K:
959  case rdiv_expr_K:
960  case frem_expr_K:
961  case round_div_expr_K:
962  case round_mod_expr_K:
963  case rrotate_expr_K:
964  case rshift_expr_K:
965  case set_le_expr_K:
966  case truth_and_expr_K:
967  case truth_andif_expr_K:
968  case truth_or_expr_K:
969  case truth_orif_expr_K:
970  case truth_xor_expr_K:
971  case try_catch_expr_K:
972  case try_finally_K:
973  case uneq_expr_K:
974  case ltgt_expr_K:
975  case lut_expr_K:
976  case unge_expr_K:
977  case ungt_expr_K:
978  case unle_expr_K:
979  case unlt_expr_K:
980  case unordered_expr_K:
981  case widen_sum_expr_K:
982  case widen_mult_expr_K:
983  case with_size_expr_K:
984  case vec_lshift_expr_K:
985  case vec_rshift_expr_K:
986  case widen_mult_hi_expr_K:
987  case widen_mult_lo_expr_K:
988  case vec_pack_trunc_expr_K:
989  case vec_pack_sat_expr_K:
990  case vec_pack_fix_trunc_expr_K:
991  case vec_extracteven_expr_K:
992  case vec_extractodd_expr_K:
993  case vec_interleavehigh_expr_K:
994  case vec_interleavelow_expr_K:
995  case binfo_K:
996  case block_K:
997  case call_expr_K:
998  case aggr_init_expr_K:
999  case case_label_expr_K:
1000  case constructor_K:
1001  case identifier_node_K:
1002  case ssa_name_K:
1003  case statement_list_K:
1004  case target_expr_K:
1005  case target_mem_ref_K:
1006  case target_mem_ref461_K:
1007  case tree_list_K:
1008  case tree_vec_K:
1009  case error_mark_K:
1010  case extract_bit_expr_K:
1011  case sat_plus_expr_K:
1012  case sat_minus_expr_K:
1013  case extractvalue_expr_K:
1014  case extractelement_expr_K:
1015  case CASE_CPP_NODES:
1016  case CASE_CST_NODES:
1017  case CASE_DECL_NODES:
1018  case CASE_FAKE_NODES:
1019  case CASE_GIMPLE_NODES:
1020  case CASE_PRAGMA_NODES:
1023  case CASE_TYPE_NODES:
1024  case CASE_UNARY_EXPRESSION:
1025  default:
1026  {
1027  THROW_ERROR("not yet supported code: " + GET_NODE(ga->op1)->get_kind_text());
1028  break;
1029  }
1030  }
1031  }
1032  }
1033 }
1034 
1036 {
1037  const auto tn = TM->GetTreeNode(function_id);
1038  auto* fd = GetPointer<function_decl>(tn);
1039  THROW_ASSERT(fd && fd->body, "Node is not a function or it hasn't a body");
1040  auto* sl = GetPointer<statement_list>(GET_NODE(fd->body));
1041  THROW_ASSERT(sl, "Body is not a statement_list");
1043  for(const auto& block : sl->list_of_bloc)
1044  {
1045  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining PHI of BB" + STR(block.first));
1046  for(const auto& phi : block.second->CGetPhiList())
1047  {
1048  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---phi operation");
1050  const auto pn = GetPointerS<gimple_phi>(GET_NODE(phi));
1051  const auto srcp_default = pn->include_name + ":" + STR(pn->line_number) + ":" + STR(pn->column_number);
1052 
1053  bool is_virtual = pn->virtual_flag;
1054  if(!is_virtual)
1055  {
1056  gimple_phi::DefEdgeList to_be_replaced;
1057  for(const auto& def_edge : pn->CGetDefEdgesList())
1058  {
1059  THROW_ASSERT(tree_helper::IsSameType(pn->res, def_edge.first), "required a conversion");
1060  const auto def_kind = GET_NODE(def_edge.first)->get_kind();
1061  if(def_kind == addr_expr_K || def_kind == view_convert_expr_K || def_kind == nop_expr_K ||
1062  def_kind == pointer_plus_expr_K || def_kind == minus_expr_K || def_kind == constructor_K)
1063  {
1064  to_be_replaced.push_back(def_edge);
1065  }
1066  }
1067  for(const auto& def_edge : to_be_replaced)
1068  {
1069  const auto ue = GetPointer<unary_expr>(GET_NODE(def_edge.first));
1070  tree_nodeRef op_ga;
1071  if(ue)
1072  {
1073  const auto ue_expr = tree_man->create_unary_operation(
1074  ue->type, ue->op, srcp_default,
1075  GET_NODE(def_edge.first)->get_kind());
1076  op_ga = tree_man->CreateGimpleAssign(ue->type, tree_nodeRef(), tree_nodeRef(), ue_expr, function_id,
1077  srcp_default);
1078  }
1079  else
1080  {
1081  auto op_node = GET_NODE(def_edge.first);
1082  const auto en_type = GetPointer<expr_node>(op_node) ? GetPointerS<expr_node>(op_node)->type :
1083  GetPointer<constructor>(op_node)->type;
1084  op_ga = tree_man->CreateGimpleAssign(en_type, tree_nodeRef(), tree_nodeRef(), def_edge.first,
1085  function_id, srcp_default);
1086  }
1088  "---adding statement " + GET_NODE(op_ga)->ToString());
1089  const auto ue_vd = GetPointerS<gimple_assign>(GET_NODE(op_ga))->op0;
1090  const auto pred_block = sl->list_of_bloc.at(def_edge.second);
1091  if(pred_block->CGetStmtList().empty())
1092  {
1093  pred_block->PushBack(op_ga, AppM);
1094  }
1095  else
1096  {
1097  const auto last_statement = pred_block->CGetStmtList().back();
1098  const auto last_stmt_kind = GET_NODE(last_statement)->get_kind();
1099  if(last_stmt_kind == gimple_cond_K || last_stmt_kind == gimple_multi_way_if_K ||
1100  last_stmt_kind == gimple_return_K || last_stmt_kind == gimple_switch_K ||
1101  last_stmt_kind == gimple_goto_K)
1102  {
1103  pred_block->PushBefore(op_ga, last_statement, AppM);
1104  }
1105  else
1106  {
1107  pred_block->PushAfter(op_ga, last_statement, AppM);
1108  GetPointerS<ssa_name>(GET_NODE(ue_vd))->SetDefStmt(op_ga);
1109  }
1110  }
1111  pn->ReplaceDefEdge(TM, def_edge, gimple_phi::DefEdge(ue_vd, def_edge.second));
1112  }
1113  }
1114  }
1115  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined PHI of BB" + STR(block.first));
1116  }
1117 
1119  for(const auto& block : sl->list_of_bloc)
1120  {
1121  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining BB" + STR(block.first));
1122  const auto& list_of_stmt = block.second->CGetStmtList();
1123  bool restart_analysis;
1124  do
1125  {
1126  restart_analysis = false;
1127  auto it_los_end = list_of_stmt.end();
1128  auto it_los = list_of_stmt.begin();
1129  TreeNodeSet bitfield_vuses;
1130  TreeNodeSet bitfield_vdefs;
1131  while(it_los != it_los_end)
1132  {
1133  if(GetPointer<gimple_node>(GET_NODE(*it_los)) && GetPointerS<gimple_node>(GET_NODE(*it_los))->vdef)
1134  {
1135  bitfield_vuses.insert(GetPointer<gimple_node>(GET_NODE(*it_los))->vdef);
1136  }
1137  if(GetPointer<gimple_node>(GET_NODE(*it_los)) &&
1138  (GetPointerS<gimple_node>(GET_NODE(*it_los))->vdef ||
1139  !GetPointerS<gimple_node>(GET_NODE(*it_los))->vuses.empty()))
1140  {
1141  for(const auto& vd : bitfield_vdefs)
1142  {
1143  GetPointer<gimple_node>(GET_NODE(*it_los))->AddVuse(vd);
1144  }
1145  }
1146 
1147  const auto srcp_default = [&]() -> std::string {
1148  const auto gn = GetPointer<gimple_node>(GET_NODE(*it_los));
1149  if(gn)
1150  {
1151  return gn->include_name + ":" + STR(gn->line_number) + ":" + STR(gn->column_number);
1152  }
1153  return "";
1154  }();
1155 
1156  const auto extract_expr = [&](tree_nodeRef& op, bool set_temp_addr) {
1157  auto op_node = GET_NODE(op);
1158  const auto en_type = GetPointer<expr_node>(op_node) ? GetPointerS<expr_node>(op_node)->type :
1159  GetPointer<constructor>(op_node)->type;
1160  const auto new_ga =
1161  tree_man->CreateGimpleAssign(en_type, tree_nodeRef(), tree_nodeRef(), op, function_id, srcp_default);
1162  const auto ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
1163  op = ssa_vd;
1164  if(set_temp_addr)
1165  {
1166  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
1167  }
1168  block.second->PushBefore(new_ga, *it_los, AppM);
1170  "---adding statement " + GET_NODE(new_ga)->ToString());
1171  restart_analysis = true;
1172  };
1173  const auto extract_unary_expr = [&](tree_nodeRef& op, bool duplicate, bool set_temp_addr) {
1174  if(duplicate)
1175  {
1176  auto* ue = GetPointer<unary_expr>(GET_NODE(op));
1177  op = tree_man->create_unary_operation(ue->type, ue->op, srcp_default, ue->get_kind());
1178  }
1179  extract_expr(op, set_temp_addr);
1180  };
1181  const auto type_cast = [&](tree_nodeRef& op, const tree_nodeConstRef& type) {
1182  const auto nop =
1184  const auto nop_ssa = GetPointerS<const gimple_assign>(GET_CONST_NODE(nop))->op0;
1185  op = nop_ssa;
1186  block.second->PushBefore(nop, *it_los, AppM);
1188  "---adding statement " + GET_NODE(nop)->ToString());
1189  restart_analysis = true;
1190  };
1191 
1193  "-->Examining statement " + GET_NODE(*it_los)->ToString());
1194  if(GET_NODE(*it_los)->get_kind() == gimple_assign_K)
1195  {
1196  auto* ga = GetPointer<gimple_assign>(GET_NODE(*it_los));
1198  "---Left part is " + GET_CONST_NODE(ga->op0)->get_kind_text() + " - Right part is " +
1199  GET_CONST_NODE(ga->op1)->get_kind_text());
1200  const auto code0 = GET_NODE(ga->op0)->get_kind();
1201  const auto code1 = GET_NODE(ga->op1)->get_kind();
1202 
1203  if(ga->clobber)
1204  {
1207  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Init or clobber assignment");
1208  it_los++;
1209  continue;
1210  }
1211 
1212  if(GetPointer<unary_expr>(GET_NODE(ga->op1)) &&
1213  GET_NODE(ga->op1)->get_kind() != addr_expr_K)
1214  {
1215  auto ue = GetPointer<unary_expr>(GET_NODE(ga->op1));
1216  if(GetPointer<unary_expr>(GET_NODE(ue->op)))
1217  {
1218  extract_unary_expr(ue->op,
1219  GET_NODE(ue->op)->get_kind() == addr_expr_K ||
1220  GET_NODE(ue->op)->get_kind() == nop_expr_K,
1221  ga->temporary_address || code1 == mem_ref_K);
1222  }
1223  // if(GetPointer<binary_expr>(GET_NODE(ue->op)))
1224  // {
1225  // extract_binary_expr(ue->op, ga->temporary_address || code1 == mem_ref_K);
1226  // }
1227  }
1228  if(GetPointer<binary_expr>(GET_NODE(ga->op1)))
1229  {
1230  auto be = GetPointer<binary_expr>(GET_NODE(ga->op1));
1231  if(GetPointer<unary_expr>(GET_NODE(be->op0)))
1232  {
1233  extract_unary_expr(be->op0,
1234  GET_NODE(be->op0)->get_kind() == addr_expr_K ||
1235  GET_NODE(be->op0)->get_kind() == nop_expr_K,
1236  ga->temporary_address || code1 == mem_ref_K);
1237  }
1238  if(GetPointer<unary_expr>(GET_NODE(be->op1)))
1239  {
1240  extract_unary_expr(be->op1,
1241  GET_NODE(be->op0)->get_kind() == addr_expr_K ||
1242  GET_NODE(be->op0)->get_kind() == nop_expr_K,
1243  false);
1244  }
1245  if(GetPointer<binary_expr>(GET_NODE(be->op0)) || GetPointer<constructor>(GET_NODE(be->op0)))
1246  {
1247  extract_expr(be->op0, ga->temporary_address || code1 == mem_ref_K);
1248  }
1249  if(GetPointer<binary_expr>(GET_NODE(be->op1)) || GetPointer<constructor>(GET_NODE(be->op1)))
1250  {
1251  extract_expr(be->op1, false);
1252  }
1253  const auto be_kind = be->get_kind();
1254  if(be_kind == bit_and_expr_K || be_kind == bit_ior_expr_K || be_kind == bit_xor_expr_K ||
1255  be_kind == plus_expr_K || be_kind == minus_expr_K || be_kind == mult_expr_K ||
1256  be_kind == trunc_div_expr_K || be_kind == trunc_mod_expr_K || be_kind == sat_plus_expr_K ||
1257  be_kind == sat_minus_expr_K)
1258  {
1259  if(!tree_helper::IsSameType(be->op0, be->type))
1260  {
1261  type_cast(be->op0, be->type);
1262  }
1263  if(!tree_helper::IsSameType(be->op1, be->type))
1264  {
1265  type_cast(be->op1, be->type);
1266  }
1267  }
1268  }
1269  if(GetPointer<ternary_expr>(GET_NODE(ga->op1)))
1270  {
1271  auto op1_kind = GET_NODE(ga->op1)->get_kind();
1272  if(op1_kind != component_ref_K && op1_kind != bit_field_ref_K)
1273  {
1274  auto te = GetPointer<ternary_expr>(GET_NODE(ga->op1));
1275  if(GetPointer<unary_expr>(GET_NODE(te->op0)) || GetPointer<binary_expr>(GET_NODE(te->op0)) ||
1276  GetPointer<constructor>(GET_NODE(te->op0)))
1277  {
1278  extract_expr(te->op0, false);
1279  }
1280  if(GetPointer<unary_expr>(GET_NODE(te->op1)) || GetPointer<binary_expr>(GET_NODE(te->op1)) ||
1281  GetPointer<constructor>(GET_NODE(te->op1)))
1282  {
1283  extract_expr(te->op1, false);
1284  }
1285  if(te->op2 &&
1286  (GetPointer<unary_expr>(GET_NODE(te->op2)) || GetPointer<binary_expr>(GET_NODE(te->op2)) ||
1287  GetPointer<constructor>(GET_NODE(te->op2))))
1288  {
1289  extract_expr(te->op2, false);
1290  }
1291  }
1292  }
1293 
1294  if(GetPointer<binary_expr>(GET_NODE(ga->op0)))
1295  {
1296  auto be = GetPointer<binary_expr>(GET_NODE(ga->op0));
1297  if(GetPointer<unary_expr>(GET_NODE(be->op0)))
1298  {
1299  // BEAWARE: not exactly as previuos revision, check commit history in case of issues
1300  extract_unary_expr(be->op0, GET_NODE(be->op0)->get_kind() == addr_expr_K, code0 == mem_ref_K);
1301  }
1302  if(GetPointer<binary_expr>(GET_NODE(be->op0)))
1303  {
1304  extract_expr(be->op0, code0 == mem_ref_K);
1305  }
1306  if(GetPointer<unary_expr>(GET_NODE(be->op1)) || GetPointer<binary_expr>(GET_NODE(be->op1)))
1307  {
1308  extract_expr(be->op1, false);
1309  }
1310  }
1311  const auto manage_realpart = [&](const tree_nodeRef op, tree_nodeRef type) -> tree_nodeRef {
1312  auto* rpe = GetPointer<realpart_expr>(GET_NODE(op));
1313  auto type_index = tree_helper::get_type_index(TM, GET_INDEX_NODE(rpe->op));
1314  const auto op_type = TM->GetTreeReindex(type_index);
1315  auto size_complex = tree_helper::Size(op_type);
1316  auto align = size_complex / 2;
1317  const auto pt = tree_man->GetPointerType(op_type, align);
1318 
1319  const auto ae_cr = tree_man->create_unary_operation(pt, rpe->op, srcp_default, addr_expr_K);
1320  const auto ae_cr_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae_cr,
1321  function_id, srcp_default);
1322  const auto ae_cr_vd = GetPointer<gimple_assign>(GET_NODE(ae_cr_ga))->op0;
1323  GetPointer<gimple_assign>(GET_NODE(ae_cr_ga))->temporary_address = ga->temporary_address;
1324  block.second->PushBefore(ae_cr_ga, *it_los, AppM);
1326  "---adding statement " + GET_NODE(ae_cr_ga)->ToString());
1327  auto ssa_vd = ae_cr_vd;
1328  if(type)
1329  {
1330  const auto ga_nop =
1332  THROW_ASSERT(ga_nop, "unexpected pattern");
1333  tree_nodeRef ga_nop_vd = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
1334  block.second->PushBefore(ga_nop, *it_los, AppM);
1336  "---adding statement " + GET_NODE(ga_nop)->ToString());
1337  ssa_vd = ga_nop_vd;
1338  }
1339  else
1340  {
1341  type = pt;
1342  }
1344  return tree_man->create_binary_operation(rpe->type, ssa_vd, offset, srcp_default, mem_ref_K);
1345  };
1346  const auto manage_imagpart = [&](const tree_nodeRef op, tree_nodeRef type) -> tree_nodeRef {
1347  auto* ipe = GetPointer<imagpart_expr>(GET_NODE(op));
1348  auto type_index = tree_helper::get_type_index(TM, GET_INDEX_NODE(ipe->op));
1349  tree_nodeRef op_type = TM->GetTreeReindex(type_index);
1350  auto size_complex = tree_helper::Size(op_type);
1351  auto align = size_complex / 2;
1352  tree_nodeRef pt = tree_man->GetPointerType(op_type, align);
1353 
1354  tree_nodeRef ae_cr = tree_man->create_unary_operation(pt, ipe->op, srcp_default, addr_expr_K);
1356  function_id, srcp_default);
1357  tree_nodeRef ae_cr_vd = GetPointer<gimple_assign>(GET_NODE(ae_cr_ga))->op0;
1358  GetPointer<gimple_assign>(GET_NODE(ae_cr_ga))->temporary_address = ga->temporary_address;
1359  block.second->PushBefore(ae_cr_ga, *it_los, AppM);
1361  "---adding statement " + GET_NODE(ae_cr_ga)->ToString());
1362  auto ssa_vd = ae_cr_vd;
1363  if(type)
1364  {
1365  const auto ga_nop =
1367  THROW_ASSERT(ga_nop, "unexpected pattern");
1368  tree_nodeRef ga_nop_vd = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
1369  block.second->PushBefore(ga_nop, *it_los, AppM);
1371  "---adding statement " + GET_NODE(ga_nop)->ToString());
1372  ssa_vd = ga_nop_vd;
1373  }
1374  else
1375  {
1376  type = pt;
1377  }
1378  auto offset_value = tree_helper::Size(tree_helper::CGetType(ipe->op)) / 16;
1379  tree_nodeRef offset = TM->CreateUniqueIntegerCst(static_cast<long long>(offset_value), type);
1380  return tree_man->create_binary_operation(ipe->type, ssa_vd, offset, srcp_default, mem_ref_K);
1381  };
1382  if(code1 == array_ref_K)
1383  {
1385  "---expand array_ref 1 " + STR(GET_INDEX_NODE(ga->op1)));
1386  auto* AR = GetPointer<array_ref>(GET_NODE(ga->op1));
1387  ga->op1 = array_ref_lowering(AR, srcp_default, block, it_los, true);
1388  restart_analysis = true;
1389  }
1390  else if(code1 == ssa_name_K && code0 == ssa_name_K)
1391  {
1395  {
1396  auto ssa0 = GetPointerS<ssa_name>(GET_NODE(ga->op0));
1397  const auto ga_nop =
1398  tree_man->CreateNopExpr(ga->op1, ssa0->type, ssa0->min, ssa0->max, function_id);
1400  "---adding statement " + GET_NODE(ga_nop)->ToString());
1401  const auto nop_vd = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
1402  block.second->PushBefore(ga_nop, *it_los, AppM);
1403  ga->op1 = nop_vd;
1404  restart_analysis = true;
1405  }
1406  }
1407  else if(code1 == addr_expr_K)
1408  {
1409  auto addr_exprNormalize = [&] {
1410  auto* ae = GetPointer<addr_expr>(GET_NODE(ga->op1));
1412  "---Op of addr expr is " + GET_CONST_NODE(ae->op)->get_kind_text());
1413  enum kind ae_code = GET_NODE(ae->op)->get_kind();
1414  if(ae_code == mem_ref_K)
1415  {
1417  auto* MR = GetPointer<mem_ref>(GET_NODE(ae->op));
1418  const auto mem_op0_kind = GET_NODE(MR->op0)->get_kind();
1419  if(mem_op0_kind == addr_expr_K || mem_op0_kind == pointer_plus_expr_K ||
1420  mem_op0_kind == view_convert_expr_K)
1421  {
1422  // BEAWARE: it is ok to use this function even with binary_expr provided that duplicate =
1423  // false in those cases
1424  extract_unary_expr(MR->op0, mem_op0_kind == addr_expr_K, ga->temporary_address);
1425  }
1426 
1427  tree_nodeRef op1 = MR->op1;
1428  const auto op1_val = tree_helper::GetConstValue(op1);
1429  if(mem_op0_kind == integer_cst_K && op1_val == 0)
1430  {
1431  ga->op1 = MR->op0;
1432  }
1433  else if(ga->temporary_address)
1434  {
1435  if(op1_val != 0)
1436  {
1437  const auto offset = TM->CreateUniqueIntegerCst(op1_val, tree_man->GetSizeType());
1438  const auto mr = tree_man->create_binary_operation(ae->type, MR->op0, offset, srcp_default,
1439  pointer_plus_expr_K);
1440  ga->op1 = mr;
1441  }
1442  else
1443  {
1444  ga->op1 = MR->op0;
1445  }
1446  }
1447  else
1448  {
1449  if(op1_val != 0)
1450  {
1451  const auto offset = TM->CreateUniqueIntegerCst(op1_val, tree_man->GetSizeType());
1452  const auto mr = tree_man->create_binary_operation(ae->type, MR->op0, offset, srcp_default,
1453  pointer_plus_expr_K);
1454  const auto pp_ga = tree_man->CreateGimpleAssign(ae->type, tree_nodeRef(), tree_nodeRef(),
1455  mr, function_id, srcp_default);
1457  "---adding statement " + GET_NODE(pp_ga)->ToString());
1458  GetPointer<gimple_assign>(GET_NODE(pp_ga))->temporary_address = true;
1459  const auto pp_vd = GetPointer<gimple_assign>(GET_NODE(pp_ga))->op0;
1460  block.second->PushBefore(pp_ga, *it_los, AppM);
1461  MR->op0 = pp_vd;
1462  MR->op1 = TM->CreateUniqueIntegerCst(0, ae->type);
1463  }
1464  else
1465  {
1466  auto type_index = tree_helper::get_type_index(TM, GET_INDEX_NODE(MR->op0));
1467  if(type_index != GET_INDEX_NODE(ae->type))
1468  {
1469  const auto ga_nop = tree_man->CreateNopExpr(MR->op0, ae->type, tree_nodeRef(),
1472  "---adding statement " + GET_NODE(ga_nop)->ToString());
1473  const auto nop_vd = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
1474  block.second->PushBefore(ga_nop, *it_los, AppM);
1475  ga->op1 = nop_vd;
1476  }
1477  else
1478  {
1479  ga->op1 = MR->op0;
1480  }
1481  }
1482  }
1483  restart_analysis = true;
1484  }
1485  else if(ae_code == array_ref_K)
1486  {
1487  auto* AR = GetPointer<array_ref>(GET_NODE(ae->op));
1488  ae->op = array_ref_lowering(AR, srcp_default, block, it_los, ga->temporary_address);
1489  restart_analysis = true;
1490  }
1491  else if(ae_code == target_mem_ref461_K)
1492  {
1493  auto* tmr = GetPointer<target_mem_ref461>(GET_NODE(ae->op));
1495  expand_target_mem_ref(tmr, *it_los, block.second, srcp_default, ga->temporary_address);
1496  const auto pt =
1497  tree_man->GetPointerType(tmr->type, GetPointer<type_node>(GET_NODE(ae->type))->algn);
1498  const auto zero_offset = TM->CreateUniqueIntegerCst(0, pt);
1499  const auto mr = tree_man->create_binary_operation(tmr->type, tmr->base, zero_offset,
1500  srcp_default, mem_ref_K);
1501  ae->op = mr;
1502  restart_analysis = true;
1503  }
1504  else if(ae_code == component_ref_K)
1505  {
1506  auto* cr = GetPointer<component_ref>(GET_NODE(ae->op));
1507  auto* field_d = GetPointer<field_decl>(GET_NODE(cr->op1));
1508  THROW_ASSERT(field_d, "expected an field_decl but got something of different");
1509  const auto pt =
1510  tree_man->GetPointerType(cr->type, GetPointer<type_node>(GET_NODE(ae->type))->algn);
1511  const auto ae_cr = tree_man->create_unary_operation(pt, cr->op0, srcp_default, addr_expr_K);
1512  const auto ae_cr_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae_cr,
1513  function_id, srcp_default);
1514  const auto ae_cr_vd = GetPointer<gimple_assign>(GET_NODE(ae_cr_ga))->op0;
1515  GetPointer<gimple_assign>(GET_NODE(ae_cr_ga))->temporary_address = ga->temporary_address;
1516  block.second->PushBefore(ae_cr_ga, *it_los, AppM);
1518  "---adding statement " + GET_NODE(ae_cr_ga)->ToString());
1519 
1520  const auto op1_val = tree_helper::GetConstValue(field_d->bpos);
1521  const auto offset = TM->CreateUniqueIntegerCst(op1_val / 8, tree_man->GetSizeType());
1522  const auto pp =
1523  tree_man->create_binary_operation(pt, ae_cr_vd, offset, srcp_default, pointer_plus_expr_K);
1524  const auto pp_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), pp,
1525  function_id, srcp_default);
1526  GetPointer<gimple_assign>(GET_NODE(pp_ga))->temporary_address = ga->temporary_address;
1527  const auto ssa_vd = GetPointer<gimple_assign>(GET_NODE(pp_ga))->op0;
1528  block.second->PushBefore(pp_ga, *it_los, AppM);
1530  "---adding statement " + GET_NODE(pp_ga)->ToString());
1531  const auto zero_offset = TM->CreateUniqueIntegerCst(0, pt);
1532  const auto mr =
1533  tree_man->create_binary_operation(cr->type, ssa_vd, zero_offset, srcp_default, mem_ref_K);
1534  ae->op = mr;
1535  restart_analysis = true;
1536  }
1537  else if(ae_code == bit_field_ref_K)
1538  {
1539  auto* bfr = GetPointer<bit_field_ref>(GET_NODE(ae->op));
1540  const auto pt =
1541  tree_man->GetPointerType(bfr->type, GetPointer<type_node>(GET_NODE(ae->type))->algn);
1542  const auto ae_cr = tree_man->create_unary_operation(pt, bfr->op0, srcp_default, addr_expr_K);
1543  const auto ae_cr_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae_cr,
1544  function_id, srcp_default);
1545  const auto ae_cr_vd = GetPointer<gimple_assign>(GET_NODE(ae_cr_ga))->op0;
1546  GetPointer<gimple_assign>(GET_NODE(ae_cr_ga))->temporary_address = ga->temporary_address;
1547  block.second->PushBefore(ae_cr_ga, *it_los, AppM);
1549  "---adding statement " + GET_NODE(ae_cr_ga)->ToString());
1550 
1551  const auto op1_val = tree_helper::GetConstValue(bfr->op2);
1552  const auto offset = TM->CreateUniqueIntegerCst(op1_val / 8, tree_man->GetSizeType());
1553  const auto pp =
1554  tree_man->create_binary_operation(pt, ae_cr_vd, offset, srcp_default, pointer_plus_expr_K);
1555  const auto pp_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), pp,
1556  function_id, srcp_default);
1557  GetPointer<gimple_assign>(GET_NODE(pp_ga))->temporary_address = ga->temporary_address;
1558  const auto ssa_vd = GetPointer<gimple_assign>(GET_NODE(pp_ga))->op0;
1559  block.second->PushBefore(pp_ga, *it_los, AppM);
1561  "---adding statement " + GET_NODE(pp_ga)->ToString());
1562  const auto zero_offset = TM->CreateUniqueIntegerCst(0, pt);
1563  const auto mr =
1564  tree_man->create_binary_operation(bfr->type, ssa_vd, zero_offset, srcp_default, mem_ref_K);
1565  ae->op = mr;
1566  restart_analysis = true;
1567  }
1568  else if(ae_code == indirect_ref_K)
1569  {
1570  auto* ir = GetPointerS<indirect_ref>(GET_NODE(ae->op));
1571  const auto type = ir->type;
1572  const auto pt = tree_man->GetPointerType(type, GetPointer<type_node>(GET_NODE(ae->type))->algn);
1573  const auto offset = TM->CreateUniqueIntegerCst(0, pt);
1574  const auto mr =
1575  tree_man->create_binary_operation(type, ir->op, offset, srcp_default, mem_ref_K);
1576  ae->op = mr;
1577  restart_analysis = true;
1578  }
1579  else if(ae_code == realpart_expr_K)
1580  {
1581  ae->op = manage_realpart(ae->op, ae->type);
1582  restart_analysis = true;
1583  }
1584  else if(ae_code == imagpart_expr_K)
1585  {
1586  ae->op = manage_imagpart(ae->op, ae->type);
1587  restart_analysis = true;
1588  }
1589  else if(ae_code == var_decl_K || ae_code == parm_decl_K || ae_code == function_decl_K ||
1590  ae_code == string_cst_K)
1591  {
1592  if(code0 == ssa_name_K && ae_code != function_decl_K && ae_code != parm_decl_K)
1593  {
1594  auto ssa_var = GetPointerS<const ssa_name>(GET_NODE(ga->op0));
1595  if(ssa_var->use_set->variables.empty())
1596  {
1597  ssa_var->use_set->Add(ae->op);
1598  }
1599  }
1600  }
1601  else
1602  {
1603  THROW_ERROR("not supported " + GET_NODE(ae->op)->get_kind_text());
1604  }
1605 
1607 #if 1
1608  auto* pt_ae = GetPointerS<pointer_type>(GET_NODE(ae->type));
1609  auto ptd_index = GET_INDEX_CONST_NODE(pt_ae->ptd);
1610  const auto op_type_node = tree_helper::CGetType(ae->op);
1611  const auto op_type_id = op_type_node->index;
1612  if(op_type_id != ptd_index)
1613  {
1614  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Fix missing cast");
1615  const auto ae_new_node = tree_man->CreateAddrExpr(GET_NODE(ae->op), srcp_default);
1616  auto* ae_new = GetPointer<addr_expr>(GET_NODE(ae_new_node));
1617  const auto a_ga = tree_man->CreateGimpleAssign(ae_new->type, tree_nodeRef(), tree_nodeRef(),
1618  ae_new_node, function_id, srcp_default);
1619  GetPointer<gimple_assign>(GET_NODE(a_ga))->temporary_address = ga->temporary_address;
1620  block.second->PushBefore(a_ga, *it_los, AppM);
1622  "---adding statement " + GET_NODE(a_ga)->ToString());
1623  const auto nop_ae = tree_man->create_unary_operation(
1624  ae->type, GetPointer<gimple_assign>(GET_NODE(a_ga))->op0, srcp_default, nop_expr_K);
1625  ga->op1 = nop_ae;
1626  ga->temporary_address = true;
1627  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---modified statement " + STR(ga));
1628  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Fixed missing cast");
1629  restart_analysis = true;
1630  }
1631 #endif
1632  };
1633  addr_exprNormalize();
1634  }
1635  else if(code1 == realpart_expr_K)
1636  {
1637  auto* rpe = GetPointer<realpart_expr>(GET_NODE(ga->op1));
1638  if(GET_NODE(rpe->op)->get_kind() != ssa_name_K)
1639  {
1640  ga->op1 = manage_realpart(ga->op1, tree_nodeRef());
1641  restart_analysis = true;
1642  }
1643  }
1644  else if(code1 == imagpart_expr_K)
1645  {
1646  auto* ipe = GetPointer<imagpart_expr>(GET_NODE(ga->op1));
1647  if(GET_NODE(ipe->op)->get_kind() != ssa_name_K)
1648  {
1649  ga->op1 = manage_imagpart(ga->op1, tree_nodeRef());
1650  restart_analysis = true;
1651  }
1652  }
1653  else if(code1 == target_mem_ref461_K)
1654  {
1655  auto target_mem_ref1 = [&] {
1656  auto* tmr = GetPointer<target_mem_ref461>(GET_NODE(ga->op1));
1658  const auto type = tmr->type;
1659 
1660  const auto pt = tree_man->GetPointerType(type, 8);
1661  const auto ae = tree_man->create_unary_operation(pt, ga->op1, srcp_default, addr_expr_K);
1662  const auto new_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae,
1663  function_id, srcp_default);
1664  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
1665 
1666  const auto ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
1667 
1668  const auto offset = TM->CreateUniqueIntegerCst(0, pt);
1669  const auto mr = tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
1670 
1671  ga->op1 = mr;
1672  block.second->PushBefore(new_ga, *it_los, AppM);
1674  "---adding statement " + GET_NODE(new_ga)->ToString());
1675  restart_analysis = true;
1676  };
1677  target_mem_ref1();
1678  }
1679  else if(code1 == mem_ref_K)
1680  {
1681  auto mem_ref1 = [&] {
1683  "---expand mem_ref 1 " + STR(GET_INDEX_NODE(ga->op1)));
1684  auto* MR = GetPointer<mem_ref>(GET_NODE(ga->op1));
1685  const auto mem_op0_kind = GET_NODE(MR->op0)->get_kind();
1686  if(mem_op0_kind == addr_expr_K || mem_op0_kind == pointer_plus_expr_K ||
1687  mem_op0_kind == view_convert_expr_K)
1688  {
1689  // BEAWARE: it is ok to use this function even with binary_expr provided that duplicate = false
1690  // in those cases
1691  extract_unary_expr(MR->op0, mem_op0_kind == addr_expr_K, true);
1692  }
1693 
1694  tree_nodeRef op1 = MR->op1;
1695  const auto op1_val = tree_helper::GetConstValue(op1);
1696  if(op1_val != 0)
1697  {
1698  const auto type = MR->type;
1699 
1701  auto obj_size = static_cast<long long>(tree_helper::Size(tree_helper::CGetType(ga->op1)));
1702  auto bram_size = std::max(8ll, obj_size / 2ll);
1703  if(((op1_val * 8) % bram_size) != 0)
1704  {
1705  function_behavior->set_unaligned_accesses(true);
1706  }
1707 
1708  const auto pt = tree_man->GetPointerType(type, 8);
1709  const auto ae = tree_man->create_unary_operation(pt, ga->op1, srcp_default, addr_expr_K);
1710  const auto new_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae,
1711  function_id, srcp_default);
1712  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
1713  const auto ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
1714 
1715  const auto offset = TM->CreateUniqueIntegerCst(0, pt);
1716  const auto mr =
1717  tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
1718 
1719  ga->op1 = mr;
1720  block.second->PushBefore(new_ga, *it_los, AppM);
1722  "---adding statement " + GET_NODE(new_ga)->ToString());
1723  restart_analysis = true;
1724  }
1725  };
1726  mem_ref1();
1727  }
1728  else if(code1 == eq_expr_K or code1 == ne_expr_K or code1 == gt_expr_K or code1 == lt_expr_K or
1729  code1 == ge_expr_K or code1 == le_expr_K)
1730  {
1731  auto rel_expr1 = [&] {
1732  const auto lhs_type = tree_helper::CGetType(ga->op0);
1733  if(code0 == ssa_name_K && !tree_helper::IsBooleanType(lhs_type) &&
1734  !(tree_helper::IsVectorType(lhs_type) &&
1736  {
1737  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Fix lhs to be bool");
1738  // fix the left hand side to be a bool
1739  const auto new_left_type = [&]() -> tree_nodeRef {
1740  if(!tree_helper::IsVectorType(ga->op0))
1741  {
1742  return tree_man->GetBooleanType();
1743  }
1744  const auto element_type = tree_helper::CGetElements(lhs_type);
1745  const auto element_size = tree_helper::Size(element_type);
1746  const auto vector_size = tree_helper::Size(lhs_type);
1747  const auto num_elements = vector_size / element_size;
1748  return tree_man->CreateVectorBooleanType(num_elements);
1749  }();
1750  GetPointer<binary_expr>(GET_NODE(ga->op1))->type = new_left_type;
1751  const auto lt_ga = tree_man->CreateGimpleAssign(new_left_type, nullptr, nullptr, ga->op1,
1752  function_id, srcp_default);
1753  block.second->PushBefore(lt_ga, *it_los, AppM);
1755  "---adding statement " + GET_NODE(lt_ga)->ToString());
1756  const auto type_node = tree_helper::CGetType(ga->op0);
1757  const auto nop_e = tree_man->create_unary_operation(
1758  type_node, GetPointer<const gimple_assign>(GET_CONST_NODE(lt_ga))->op0, srcp_default,
1759  nop_expr_K);
1760  ga->op1 = nop_e;
1761  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---modified statement " + STR(ga));
1762  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Fixed lhs to be bool");
1763  restart_analysis = true;
1764  }
1765  };
1766  rel_expr1();
1767  }
1768  else if(code1 == truth_not_expr_K)
1769  {
1770  auto tn_expr1 = [&] {
1771  const auto lhs = GET_NODE(ga->op1);
1772  auto* e = GetPointer<truth_not_expr>(lhs);
1773  const auto bt = tree_man->GetBooleanType();
1774  e->type = bt;
1775  if(!tree_helper::IsBooleanType(e->op))
1776  {
1777  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Fix first operand to be bool");
1778  const auto operand_type = tree_helper::CGetType(e->op);
1779  const auto zero_value = TM->CreateUniqueIntegerCst(0, operand_type);
1780  const auto not_zero =
1781  tree_man->create_binary_operation(bt, e->op, zero_value, srcp_default, ne_expr_K);
1782  const auto not_zero_ga = tree_man->CreateGimpleAssign(bt, TM->CreateUniqueIntegerCst(0, bt),
1783  TM->CreateUniqueIntegerCst(1, bt),
1784  not_zero, function_id, srcp_default);
1786  "---adding statement " + GET_NODE(not_zero_ga)->ToString());
1787  block.second->PushBefore(not_zero_ga, *it_los, AppM);
1788  e->op = GetPointer<gimple_assign>(GET_NODE(not_zero_ga))->op0;
1789  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---modified statement " + STR(ga));
1790  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Fixed first operand to be bool");
1791  restart_analysis = true;
1792  }
1793  if(code0 == ssa_name_K && !tree_helper::IsBooleanType(ga->op0))
1794  {
1795  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Fix lhs to be bool");
1796  // fix the left hand side to be a bool
1797  const auto lt_ga = tree_man->CreateGimpleAssign(bt, TM->CreateUniqueIntegerCst(0, bt),
1798  TM->CreateUniqueIntegerCst(1, bt), ga->op1,
1799  function_id, srcp_default);
1800  block.second->PushBefore(lt_ga, *it_los, AppM);
1802  "---adding statement " + GET_NODE(lt_ga)->ToString());
1803  const auto type_node = tree_helper::CGetType(ga->op0);
1804  const auto nop_e = tree_man->create_unary_operation(
1805  type_node, GetPointer<const gimple_assign>(GET_CONST_NODE(lt_ga))->op0, srcp_default,
1806  nop_expr_K);
1807  ga->op1 = nop_e;
1808  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---modified statement " + STR(ga));
1809  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Fixed lhs to be bool");
1810  restart_analysis = true;
1811  }
1812  };
1813  tn_expr1();
1814  }
1815  else if(code1 == truth_and_expr_K or code1 == truth_andif_expr_K or code1 == truth_or_expr_K or
1816  code1 == truth_orif_expr_K or code1 == truth_xor_expr_K)
1817  {
1818  auto tn_expr1 = [&] {
1819  const auto lhs = GET_NODE(ga->op1);
1820  auto* e = GetPointer<binary_expr>(lhs);
1821  const auto bt = tree_man->GetBooleanType();
1822  e->type = bt;
1823  if(!tree_helper::IsBooleanType(e->op0))
1824  {
1825  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Fix first operand to be bool");
1826  const auto operand_type = tree_helper::CGetType(e->op0);
1827  const auto zero_value = TM->CreateUniqueIntegerCst(0, operand_type);
1828  const auto not_zero =
1829  tree_man->create_binary_operation(bt, e->op0, zero_value, srcp_default, ne_expr_K);
1830  const auto not_zero_ga = tree_man->CreateGimpleAssign(bt, TM->CreateUniqueIntegerCst(0, bt),
1831  TM->CreateUniqueIntegerCst(1, bt),
1832  not_zero, function_id, srcp_default);
1834  "---adding statement " + GET_NODE(not_zero_ga)->ToString());
1835  block.second->PushBefore(not_zero_ga, *it_los, AppM);
1836  e->op0 = GetPointer<gimple_assign>(GET_NODE(not_zero_ga))->op0;
1837  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---modified statement " + STR(ga));
1838  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Fixed first operand to be bool");
1839  restart_analysis = true;
1840  }
1841  if(!tree_helper::IsBooleanType(e->op1))
1842  {
1843  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Fix second operand to be bool");
1844  const auto operand_type = tree_helper::CGetType(e->op1);
1845  const auto zero_value = TM->CreateUniqueIntegerCst(0, operand_type);
1846  const auto not_zero =
1847  tree_man->create_binary_operation(bt, e->op1, zero_value, srcp_default, ne_expr_K);
1848  const auto not_zero_ga = tree_man->CreateGimpleAssign(bt, TM->CreateUniqueIntegerCst(0, bt),
1849  TM->CreateUniqueIntegerCst(1, bt),
1850  not_zero, function_id, srcp_default);
1852  "---adding statement " + GET_NODE(not_zero_ga)->ToString());
1853  block.second->PushBefore(not_zero_ga, *it_los, AppM);
1854  e->op1 = GetPointer<gimple_assign>(GET_NODE(not_zero_ga))->op0;
1855  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---modified statement " + STR(ga));
1856  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Fixed second operand to be bool");
1857  restart_analysis = true;
1858  }
1859  if(code0 == ssa_name_K && !tree_helper::IsBooleanType(ga->op0))
1860  {
1861  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Fix lhs to be bool");
1862  // fix the left hand side to be a bool
1863  const auto lt_ga = tree_man->CreateGimpleAssign(bt, TM->CreateUniqueIntegerCst(0, bt),
1864  TM->CreateUniqueIntegerCst(1, bt), ga->op1,
1865  function_id, srcp_default);
1866  block.second->PushBefore(lt_ga, *it_los, AppM);
1868  "---adding statement " + GET_NODE(lt_ga)->ToString());
1869  const auto type_node = tree_helper::CGetType(ga->op0);
1870  const auto nop_e = tree_man->create_unary_operation(
1871  type_node, GetPointer<const gimple_assign>(GET_CONST_NODE(lt_ga))->op0, srcp_default,
1872  nop_expr_K);
1873  ga->op1 = nop_e;
1874  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---modified statement " + STR(ga));
1875  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Fixed lhs to be bool");
1876  restart_analysis = true;
1877  }
1878  };
1879  tn_expr1();
1880  }
1881  else if(code1 == call_expr_K || code1 == aggr_init_expr_K)
1882  {
1883  auto* ce = GetPointer<call_expr>(GET_NODE(ga->op1));
1884  for(auto& arg : ce->args)
1885  {
1886  if(GetPointer<unary_expr>(GET_NODE(arg)) || GetPointer<binary_expr>(GET_NODE(arg)))
1887  {
1888  extract_unary_expr(arg, GET_NODE(arg)->get_kind() == addr_expr_K, false);
1889  }
1890  }
1891  }
1892  else if(code1 == pointer_plus_expr_K)
1893  {
1894  auto pp_expr1 = [&] {
1895  auto* ppe = GetPointer<pointer_plus_expr>(GET_NODE(ga->op1));
1896  THROW_ASSERT(ppe->op0 && ppe->op1, "expected two parameters");
1897  if(GetPointer<addr_expr>(GET_NODE(ppe->op0)))
1898  {
1899  extract_expr(ppe->op0, ga->temporary_address);
1900  }
1901  else if(GetPointer<pointer_plus_expr>(GET_NODE(ppe->op0)))
1902  {
1903  extract_expr(ppe->op0, ga->temporary_address);
1904  }
1905  else if(GetPointer<mult_expr>(GET_NODE(ppe->op1)))
1906  {
1907  extract_expr(ppe->op1, false);
1908  }
1909  else if(GetPointer<var_decl>(GET_NODE(ppe->op0)))
1910  {
1911  auto* vd = GetPointer<var_decl>(GET_NODE(ppe->op0));
1912  const auto type = vd->type;
1913  const auto pt = tree_man->GetPointerType(type, GetPointer<type_node>(GET_NODE(type))->algn);
1914  const auto ae = tree_man->create_unary_operation(pt, ppe->op0, srcp_default, addr_expr_K);
1915  const auto new_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae,
1916  function_id, srcp_default);
1917  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
1918  const auto ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
1919  ppe->op0 = ssa_vd;
1920  block.second->PushBefore(new_ga, *it_los, AppM);
1922  "---adding statement " + GET_NODE(new_ga)->ToString());
1923  restart_analysis = true;
1924  }
1925  else if(GetPointer<ssa_name>(GET_NODE(ppe->op0)) && GetPointer<integer_cst>(GET_NODE(ppe->op1)))
1926  {
1927  auto temp_def = GET_NODE(GetPointer<const ssa_name>(GET_NODE(ppe->op0))->CGetDefStmt());
1928  if(temp_def->get_kind() == gimple_assign_K)
1929  {
1930  const auto prev_ga = GetPointer<const gimple_assign>(temp_def);
1931  if(GET_NODE(prev_ga->op1)->get_kind() == pointer_plus_expr_K)
1932  {
1933  const auto prev_ppe = GetPointer<const pointer_plus_expr>(GET_NODE(prev_ga->op1));
1934  if(GetPointer<ssa_name>(GET_NODE(prev_ppe->op0)) &&
1935  GetPointer<integer_cst>(GET_NODE(prev_ppe->op1)))
1936  {
1937  const auto prev_val = tree_helper::GetConstValue(prev_ppe->op1);
1938  const auto curr_val = tree_helper::GetConstValue(ppe->op1);
1939  ppe->op1 =
1940  TM->CreateUniqueIntegerCst(prev_val + curr_val, tree_helper::CGetType(ppe->op1));
1941  ppe->op0 = prev_ppe->op0;
1942  restart_analysis = true;
1943  }
1944  }
1945  }
1946  }
1947  else if(GetPointer<ssa_name>(GET_NODE(ppe->op0)))
1948  {
1949  auto temp_def = GET_NODE(GetPointer<const ssa_name>(GET_NODE(ppe->op0))->CGetDefStmt());
1950  if(temp_def->get_kind() == gimple_assign_K)
1951  {
1952  const auto prev_ga = GetPointer<const gimple_assign>(temp_def);
1953  if(GET_NODE(prev_ga->op1)->get_kind() == addr_expr_K)
1954  {
1955  auto* prev_ae = GetPointer<addr_expr>(GET_NODE(prev_ga->op1));
1956  enum kind prev_ae_code = GET_NODE(prev_ae->op)->get_kind();
1957  if(prev_ae_code == mem_ref_K)
1958  {
1959  auto* prev_MR = GetPointer<mem_ref>(GET_NODE(prev_ae->op));
1960  const auto prev_op1_val = tree_helper::GetConstValue(prev_MR->op1);
1961  if(prev_op1_val == 0)
1962  {
1963  if(GET_NODE(prev_MR->op0)->get_kind() == ssa_name_K)
1964  {
1965  ppe->op0 = prev_MR->op0;
1966  restart_analysis = true;
1967  }
1968  }
1969  }
1970  }
1971  }
1972  }
1973  };
1974  pp_expr1();
1975  }
1976  else if(code1 == component_ref_K)
1977  {
1978  auto cr_expr1 = [&] {
1979  const auto cr = GetPointer<component_ref>(GET_NODE(ga->op1));
1980  const auto field_d = GetPointer<field_decl>(GET_NODE(cr->op1));
1982  if(field_d->is_bitfield())
1983  {
1984  THROW_ASSERT(tree_helper::GetConstValue(field_d->bpos) >= 0, "");
1985  const auto op1_val = static_cast<unsigned long long>(tree_helper::GetConstValue(field_d->bpos));
1986  const auto right_shift_val = op1_val % 8;
1987  if(GET_NODE(cr->type)->get_kind() == boolean_type_K)
1988  {
1989  type = tree_man->GetCustomIntegerType(std::max(8ull, ceil_pow2(1 + right_shift_val)), true);
1990  }
1991  else
1992  {
1993  const auto it = GetPointer<integer_type>(GET_NODE(cr->type));
1994  THROW_ASSERT(it, "unexpected pattern");
1995  type = tree_man->GetCustomIntegerType(std::max(8ull, ceil_pow2(it->prec + right_shift_val)),
1996  it->unsigned_flag);
1997  }
1998  }
1999  else
2000  {
2001  type = cr->type;
2002  }
2003  THROW_ASSERT(type, "unexpected condition");
2004  const auto pt = tree_man->GetPointerType(type, 8);
2005  THROW_ASSERT(pt, "unexpected condition");
2006  const auto ae = tree_man->create_unary_operation(pt, ga->op1, srcp_default, addr_expr_K);
2007  const auto new_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae,
2008  function_id, srcp_default);
2009  GetPointerS<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
2010 
2011  const auto ssa_vd = GetPointerS<gimple_assign>(GET_NODE(new_ga))->op0;
2012  block.second->PushBefore(new_ga, *it_los, AppM);
2014  "---adding statement " + GET_NODE(new_ga)->ToString());
2015 
2016  if(field_d->packed_flag)
2017  {
2018  function_behavior->set_packed_vars(true);
2019  }
2020  const auto offset = TM->CreateUniqueIntegerCst(0, pt);
2021  const auto mr = tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
2022  if(field_d->is_bitfield())
2023  {
2024  const auto op1_val = static_cast<long long>(tree_helper::GetConstValue(field_d->bpos));
2025  const auto right_shift_val = op1_val % 8;
2026  const auto size_tp = tree_helper::Size(type);
2027  const auto size_field_decl = tree_helper::Size(cr->op1);
2028 
2029  if(right_shift_val == 0 and size_field_decl == size_tp)
2030  {
2031  ga->op1 = mr;
2032  }
2033  else
2034  {
2035  const auto mr_dup =
2036  tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
2037  const auto mr_ga = tree_man->CreateGimpleAssign(type, tree_nodeRef(), tree_nodeRef(), mr_dup,
2038  function_id, srcp_default);
2039  GetPointerS<gimple_assign>(GET_NODE(mr_ga))->memuse = ga->memuse;
2040  GetPointerS<gimple_assign>(GET_NODE(mr_ga))->vuses = ga->vuses;
2041  GetPointerS<gimple_assign>(GET_NODE(mr_ga))->vovers = ga->vovers;
2042  ga->memuse = tree_nodeRef();
2043  ga->vuses.clear();
2044  ga->vovers.clear();
2045  block.second->PushBefore(mr_ga, *it_los, AppM);
2047  "---adding statement " + GET_NODE(mr_ga)->ToString());
2048  const auto mr_vd = GetPointerS<gimple_assign>(GET_NODE(mr_ga))->op0;
2049 #if HAVE_FROM_DISCREPANCY_BUILT
2050  /*
2051  * for discrepancy analysis, the ssa assigned loading
2052  * the bitfield must not be checked, because it has
2053  * not been resized yet and it may also load
2054  * inconsistent stuff from other bitfields nearby
2055  */
2056  if(parameters->isOption(OPT_discrepancy) && parameters->getOption<bool>(OPT_discrepancy) &&
2057  (!parameters->isOption(OPT_discrepancy_force) ||
2058  !parameters->getOption<bool>(OPT_discrepancy_force)))
2059  {
2061  "---skip discrepancy of ssa " + GET_NODE(mr_vd)->ToString() +
2062  " assigned in new stmt: " + GET_NODE(mr_ga)->ToString());
2063  AppM->RDiscr->ssa_to_skip.insert(GET_NODE(mr_vd));
2064  }
2065 #endif
2066  if(right_shift_val)
2067  {
2068  const auto rshift_value = TM->CreateUniqueIntegerCst(right_shift_val, type);
2069  const auto rsh_node = tree_man->create_binary_operation(type, mr_vd, rshift_value,
2070  srcp_default, rshift_expr_K);
2071  if(size_field_decl == size_tp)
2072  {
2073  ga->op1 = rsh_node;
2074  }
2075  else
2076  {
2077  const auto rsh_ga = tree_man->CreateGimpleAssign(type, tree_nodeRef(), tree_nodeRef(),
2078  rsh_node, function_id, srcp_default);
2079  const auto rsh_vd = GetPointerS<gimple_assign>(GET_NODE(rsh_ga))->op0;
2080  block.second->PushBefore(rsh_ga, *it_los, AppM);
2082  "---adding statement " + GET_NODE(rsh_ga)->ToString());
2083 #if HAVE_FROM_DISCREPANCY_BUILT
2084  /*
2085  * for discrepancy analysis, the ssa assigned loading
2086  * the bitfield must not be checked, because it has
2087  * not been resized yet and it may also load
2088  * inconsistent stuff from other bitfields nearby
2089  */
2090  if(parameters->isOption(OPT_discrepancy) &&
2091  parameters->getOption<bool>(OPT_discrepancy) &&
2092  (!parameters->isOption(OPT_discrepancy_force) ||
2093  !parameters->getOption<bool>(OPT_discrepancy_force)))
2094  {
2096  "---skip discrepancy of ssa " + GET_NODE(rsh_vd)->ToString() +
2097  " assigned in new stmt: " + GET_NODE(rsh_ga)->ToString());
2098  AppM->RDiscr->ssa_to_skip.insert(GET_NODE(rsh_vd));
2099  }
2100 #endif
2101  const auto and_mask_value =
2102  TM->CreateUniqueIntegerCst((integer_cst_t(1) << size_field_decl) - 1, type);
2103  ga->op1 = tree_man->create_binary_operation(type, rsh_vd, and_mask_value, srcp_default,
2104  bit_and_expr_K);
2105  }
2106  }
2107  else
2108  {
2109  const auto and_mask_value =
2110  TM->CreateUniqueIntegerCst((integer_cst_t(1) << size_field_decl) - 1, type);
2111  ga->op1 = tree_man->create_binary_operation(type, mr_vd, and_mask_value, srcp_default,
2112  bit_and_expr_K);
2113  }
2114  }
2115  }
2116  else
2117  {
2118  ga->op1 = mr;
2119  }
2120  restart_analysis = true;
2121  };
2122  cr_expr1();
2123  }
2124  else if(code1 == vec_cond_expr_K)
2125  {
2126  auto vc_expr1 = [&] {
2127  const auto vce = GetPointerS<vec_cond_expr>(GET_NODE(ga->op1));
2128  THROW_ASSERT(vce->op1 && vce->op2, "expected three parameters");
2129  if(GetPointer<binary_expr>(GET_NODE(vce->op0)))
2130  {
2131  const auto be = GetPointerS<binary_expr>(GET_NODE(vce->op0));
2132  THROW_ASSERT(be->get_kind() == le_expr_K or be->get_kind() == eq_expr_K or
2133  be->get_kind() == ne_expr_K or be->get_kind() == gt_expr_K or
2134  be->get_kind() == lt_expr_K or be->get_kind() == ge_expr_K,
2135  be->get_kind_text());
2136  const auto new_ga = tree_man->CreateGimpleAssign(be->type, tree_nodeRef(), tree_nodeRef(),
2137  vce->op0, function_id, srcp_default);
2138  const auto ssa_vd = GetPointerS<gimple_assign>(GET_NODE(new_ga))->op0;
2139 
2140  vce->op0 = ssa_vd;
2141  block.second->PushBefore(new_ga, *it_los, AppM);
2143  "---adding statement " + GET_NODE(new_ga)->ToString());
2144  restart_analysis = true;
2145  }
2146  };
2147  vc_expr1();
2148  }
2149  else if(code1 == view_convert_expr_K || code1 == nop_expr_K)
2150  {
2151  auto vcne_expr1 = [&] {
2152  auto* ue = GetPointer<unary_expr>(GET_NODE(ga->op1));
2153  if(GET_NODE(ue->op)->get_kind() == var_decl_K)
2154  {
2155  auto vc = GetPointer<view_convert_expr>(GET_NODE(ga->op1));
2156  tree_nodeRef pt =
2157  tree_man->GetPointerType(vc->type, GetPointer<type_node>(GET_NODE(vc->type))->algn);
2158  tree_nodeRef ae = tree_man->create_unary_operation(pt, ue->op, srcp_default, addr_expr_K);
2160  function_id, srcp_default);
2161  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
2162  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
2164  tree_nodeRef mr =
2165  tree_man->create_binary_operation(vc->type, ssa_vd, offset, srcp_default, mem_ref_K);
2166  ga->op1 = mr;
2167  block.second->PushBefore(new_ga, *it_los, AppM);
2169  "---adding statement " + GET_NODE(new_ga)->ToString());
2170  restart_analysis = true;
2171  }
2172  else if(GET_NODE(ue->op)->get_kind() != ssa_name_K && !GetPointer<cst_node>(GET_NODE(ue->op)))
2173  {
2174  auto type_index = tree_helper::get_type_index(TM, GET_INDEX_NODE(ue->op));
2175  tree_nodeRef op_type = TM->GetTreeReindex(type_index);
2177  ue->op, function_id, srcp_default);
2178  tree_nodeRef op_vd = GetPointer<gimple_assign>(GET_NODE(op_ga))->op0;
2179  if(ga->temporary_address)
2180  {
2181  GetPointer<gimple_assign>(GET_NODE(op_ga))->temporary_address = true;
2182  }
2183  block.second->PushBefore(op_ga, *it_los, AppM);
2185  "---adding statement " + GET_NODE(op_ga)->ToString());
2186  ue->op = op_vd;
2187  restart_analysis = true;
2188  }
2189  };
2190  vcne_expr1();
2191  }
2192  else if(code1 == cond_expr_K)
2193  {
2194  auto ce_expr1 = [&] {
2195  auto* ce = GetPointer<cond_expr>(GET_NODE(ga->op1));
2196  THROW_ASSERT(ce->op1 && ce->op2, "expected three parameters");
2197  if(GetPointer<binary_expr>(GET_NODE(ce->op0)))
2198  {
2199 #if HAVE_ASSERTS
2200  auto* be = GetPointer<binary_expr>(GET_NODE(ce->op0));
2201  THROW_ASSERT(be->get_kind() == le_expr_K or be->get_kind() == eq_expr_K or
2202  be->get_kind() == ne_expr_K or be->get_kind() == gt_expr_K or
2203  be->get_kind() == lt_expr_K or be->get_kind() == ge_expr_K,
2204  be->get_kind_text());
2205 #endif
2206  auto bt = tree_man->GetBooleanType();
2208  TM->CreateUniqueIntegerCst(1, bt), ce->op0,
2209  function_id, srcp_default);
2210  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
2211 
2212  ce->op0 = ssa_vd;
2213  block.second->PushBefore(new_ga, *it_los, AppM);
2215  "---adding statement " + GET_NODE(new_ga)->ToString());
2216  restart_analysis = true;
2217  }
2218  else if(!tree_helper::IsBooleanType(ce->op0))
2219  {
2220  const auto bt = tree_man->GetBooleanType();
2221  const auto ga_nop = tree_man->CreateNopExpr(ce->op0, bt, TM->CreateUniqueIntegerCst(0, bt),
2224  "---adding statement " + GET_NODE(ga_nop)->ToString());
2225  block.second->PushBefore(ga_nop, *it_los, AppM);
2226  ce->op0 = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
2227  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---modified statement " + STR(ga));
2228  restart_analysis = true;
2229  }
2230  };
2231  ce_expr1();
2232  }
2233  else if(code1 == indirect_ref_K)
2234  {
2235  auto* ir = GetPointer<indirect_ref>(GET_NODE(ga->op1));
2236  tree_nodeRef type = ir->type;
2238  tree_nodeRef mr = tree_man->create_binary_operation(type, ir->op, offset, srcp_default, mem_ref_K);
2239  ga->op1 = mr;
2240  restart_analysis = true;
2241  }
2242  else if(code1 == misaligned_indirect_ref_K)
2243  {
2244  auto* MIR = GetPointer<misaligned_indirect_ref>(GET_NODE(ga->op1));
2245  tree_nodeRef type = MIR->type;
2246  tree_nodeRef pt = tree_man->GetPointerType(type, 8);
2248  tree_nodeRef mr = tree_man->create_binary_operation(type, MIR->op, offset, srcp_default, mem_ref_K);
2249  ga->op1 = mr;
2250  restart_analysis = true;
2251  }
2252  else if(code1 == var_decl_K && !ga->init_assignment)
2253  {
2254  auto vd_expr1 = [&] {
2255  auto* vd = GetPointer<var_decl>(GET_NODE(ga->op1));
2256  tree_nodeRef type = vd->type;
2257  tree_nodeRef pt = tree_man->GetPointerType(type, GetPointer<type_node>(GET_NODE(type))->algn);
2258  tree_nodeRef ae = tree_man->create_unary_operation(pt, ga->op1, srcp_default, addr_expr_K);
2260  function_id, srcp_default);
2261  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
2262  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
2263  auto ssa_var_decl = GetPointer<ssa_name>(GET_NODE(ssa_vd));
2264  ssa_var_decl->use_set->Add(ga->op1);
2266  tree_nodeRef mr = tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
2267 
2268  ga->op1 = mr;
2269  block.second->PushBefore(new_ga, *it_los, AppM);
2271  "---adding statement " + GET_NODE(new_ga)->ToString());
2272  restart_analysis = true;
2273  };
2274  vd_expr1();
2275  }
2276  else if(reached_max_transformation_limit(*it_los))
2277  {
2279  "---Reached max cfg transformations (" + GET_CONST_NODE(ga->op1)->get_kind_text() +
2280  ")");
2281  }
2282  else
2283  {
2284  if(code1 == bit_field_ref_K)
2285  {
2286  auto bfe_expr1 = [&] {
2287  auto* bfr = GetPointer<bit_field_ref>(GET_NODE(ga->op1));
2288  if(GET_NODE(bfr->op0)->get_kind() != ssa_name_K)
2289  {
2290  THROW_ASSERT(tree_helper::GetConstValue(bfr->op2) >= 0, "");
2291  const auto op1_val = static_cast<unsigned int>(tree_helper::GetConstValue(bfr->op2));
2292  const auto right_shift_val = op1_val % 8;
2294  if(GET_NODE(bfr->type)->get_kind() == boolean_type_K)
2295  {
2296  type = tree_man->GetCustomIntegerType(std::max(8u, ceil_pow2(1 + right_shift_val)), true);
2297  }
2298  else
2299  {
2300  const auto it = GetPointer<integer_type>(GET_NODE(bfr->type));
2301  THROW_ASSERT(it, "unexpected pattern");
2302  type = tree_man->GetCustomIntegerType(std::max(8u, ceil_pow2(it->prec + right_shift_val)),
2303  it->unsigned_flag);
2304  }
2305  tree_nodeRef pt = tree_man->GetPointerType(type, 8);
2306  tree_nodeRef ae = tree_man->create_unary_operation(pt, ga->op1, srcp_default, addr_expr_K);
2308  function_id, srcp_default);
2309  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
2310 
2311  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
2312  block.second->PushBefore(new_ga, *it_los, AppM);
2314  "---adding statement " + GET_NODE(new_ga)->ToString());
2315  AppM->RegisterTransformation(GetName(), new_ga);
2316  const auto offset = TM->CreateUniqueIntegerCst(0, pt);
2317  const auto mr =
2318  tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
2319  const auto size_tp = tree_helper::Size(type);
2320  THROW_ASSERT(tree_helper::GetConstValue(bfr->op1) >= 0, "");
2321  const auto size_field_decl =
2322  static_cast<unsigned long long>(tree_helper::GetConstValue(bfr->op1));
2323  if(right_shift_val == 0 && size_field_decl == size_tp)
2324  {
2325  ga->op1 = mr;
2326  }
2327  else
2328  {
2329  tree_nodeRef mr_dup =
2330  tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
2332  mr_dup, function_id, srcp_default);
2333  tree_nodeRef mr_vd = GetPointer<gimple_assign>(GET_NODE(mr_ga))->op0;
2334  GetPointer<gimple_assign>(GET_NODE(mr_ga))->memuse = ga->memuse;
2335  GetPointer<gimple_assign>(GET_NODE(mr_ga))->vuses = ga->vuses;
2336  GetPointer<gimple_assign>(GET_NODE(mr_ga))->vovers = ga->vovers;
2337  ga->memuse = tree_nodeRef();
2338  ga->vuses.clear();
2339  ga->vovers.clear();
2340  block.second->PushBefore(mr_ga, *it_los, AppM);
2342  "---adding statement " + GET_NODE(mr_ga)->ToString());
2343 #if HAVE_FROM_DISCREPANCY_BUILT
2344  /*
2345  * for discrepancy analysis, the ssa assigned loading
2346  * the bitfield must not be checked, because it has
2347  * not been resized yet and it may also load
2348  * inconsistent stuff from other bitfields nearby
2349  */
2350  if(parameters->isOption(OPT_discrepancy) and
2351  parameters->getOption<bool>(OPT_discrepancy) and
2352  (not parameters->isOption(OPT_discrepancy_force) or
2353  not parameters->getOption<bool>(OPT_discrepancy_force)))
2354  {
2356  "---skip discrepancy of ssa " + GET_NODE(mr_vd)->ToString() +
2357  " assigned in new stmt: " + GET_NODE(mr_ga)->ToString());
2358  AppM->RDiscr->ssa_to_skip.insert(GET_NODE(mr_vd));
2359  }
2360 #endif
2361  if(right_shift_val)
2362  {
2363  tree_nodeRef rshift_value = TM->CreateUniqueIntegerCst(right_shift_val, type);
2364  tree_nodeRef rsh_node = tree_man->create_binary_operation(type, mr_vd, rshift_value,
2365  srcp_default, rshift_expr_K);
2366  if(size_field_decl == size_tp)
2367  {
2368  ga->op1 = rsh_node;
2369  }
2370  else
2371  {
2373  type, tree_nodeRef(), tree_nodeRef(), rsh_node, function_id, srcp_default);
2374  tree_nodeRef rsh_vd = GetPointer<gimple_assign>(GET_NODE(rsh_ga))->op0;
2375  block.second->PushBefore(rsh_ga, *it_los, AppM);
2377  "---adding statement " + GET_NODE(rsh_ga)->ToString());
2378 #if HAVE_FROM_DISCREPANCY_BUILT
2379  /*
2380  * for discrepancy analysis, the ssa assigned loading
2381  * the bitfield must not be checked, because it has
2382  * not been resized yet and it may also load
2383  * inconsistent stuff from other bitfields nearby
2384  */
2385  if(parameters->isOption(OPT_discrepancy) and
2386  parameters->getOption<bool>(OPT_discrepancy) and
2387  (not parameters->isOption(OPT_discrepancy_force) or
2388  not parameters->getOption<bool>(OPT_discrepancy_force)))
2389  {
2391  "---skip discrepancy of ssa " + GET_NODE(rsh_vd)->ToString() +
2392  " assigned in new stmt: " + GET_NODE(rsh_ga)->ToString());
2393  AppM->RDiscr->ssa_to_skip.insert(GET_NODE(rsh_vd));
2394  }
2395 #endif
2396  tree_nodeRef and_mask_value = TM->CreateUniqueIntegerCst(
2397  static_cast<long long int>((1ULL << size_field_decl) - 1), type);
2398  ga->op1 = tree_man->create_binary_operation(type, rsh_vd, and_mask_value,
2399  srcp_default, bit_and_expr_K);
2400  }
2401  }
2402  else
2403  {
2404  tree_nodeRef and_mask_value = TM->CreateUniqueIntegerCst(
2405  static_cast<long long int>((1ULL << size_field_decl) - 1), type);
2406  ga->op1 = tree_man->create_binary_operation(type, mr_vd, and_mask_value, srcp_default,
2407  bit_and_expr_K);
2408  }
2409  }
2410  restart_analysis = true;
2411  }
2412  else
2413  {
2414  const auto type_node = tree_helper::CGetType(bfr->op0);
2415  bool is_scalar = tree_helper::IsRealType(type_node) ||
2418  if(is_scalar)
2419  {
2420  auto data_size = tree_helper::Size(type_node);
2421  const auto type_vc =
2422  tree_man->GetCustomIntegerType(std::max(8ull, ceil_pow2(data_size)), true);
2423  const auto vc_expr = tree_man->create_unary_operation(type_vc, bfr->op0, srcp_default,
2424  view_convert_expr_K);
2425  const auto vc_ga = tree_man->CreateGimpleAssign(type_vc, tree_nodeRef(), tree_nodeRef(),
2426  vc_expr, function_id, srcp_default);
2427  block.second->PushBefore(vc_ga, *it_los, AppM);
2428  const auto vc_ga_var = GetPointer<gimple_assign>(GET_NODE(vc_ga))->op0;
2429  THROW_ASSERT(tree_helper::GetConstValue(bfr->op1) >= 0, "");
2430  const auto sel_size =
2431  static_cast<unsigned long long>(tree_helper::GetConstValue(bfr->op1));
2432  const auto vc_shift_expr = tree_man->create_binary_operation(type_vc, vc_ga_var, bfr->op2,
2433  srcp_default, rshift_expr_K);
2434  const auto vc_shift_ga = tree_man->CreateGimpleAssign(
2435  type_vc, tree_nodeRef(), tree_nodeRef(), vc_shift_expr, function_id, srcp_default);
2436  block.second->PushBefore(vc_shift_ga, *it_los, AppM);
2437  const auto vc_shift_ga_var = GetPointer<gimple_assign>(GET_NODE(vc_shift_ga))->op0;
2438  const auto sel_type =
2439  tree_man->GetCustomIntegerType(std::max(8ull, ceil_pow2(sel_size)), true);
2440  const auto vc_nop_expr =
2441  tree_man->create_unary_operation(sel_type, vc_shift_ga_var, srcp_default, nop_expr_K);
2442  const auto vc_nop_ga = tree_man->CreateGimpleAssign(
2443  sel_type, tree_nodeRef(), tree_nodeRef(), vc_nop_expr, function_id, srcp_default);
2444  block.second->PushBefore(vc_nop_ga, *it_los, AppM);
2445  const auto vc_nop_ga_var = GetPointer<gimple_assign>(GET_NODE(vc_nop_ga))->op0;
2446  const auto fvc_expr = tree_man->create_unary_operation(bfr->type, vc_nop_ga_var,
2447  srcp_default, view_convert_expr_K);
2448  ga->op1 = fvc_expr;
2449  restart_analysis = true;
2450  }
2451  }
2452  };
2453  bfe_expr1();
2454  }
2455  else if(code1 == trunc_div_expr_K || code1 == trunc_mod_expr_K || code1 == exact_div_expr_K)
2456  {
2457  auto be = GetPointer<binary_expr>(GET_NODE(ga->op1));
2458  tree_nodeRef op1 = be->op1;
2459  if(GetPointer<cst_node>(GET_NODE(op1)))
2460  {
2461  division_by_a_constant(block, it_los, ga, op1, code1, restart_analysis, srcp_default,
2462  GetName());
2463  }
2464  }
2465  else if(code1 == mult_expr_K)
2466  {
2467  auto me_expr1 = [&] {
2469  "-->Expanding mult_expr " + STR(GET_INDEX_NODE(ga->op1)));
2470  tree_nodeRef op1 = GetPointer<binary_expr>(GET_NODE(ga->op1))->op1;
2471  if(GetPointer<integer_cst>(GET_NODE(op1)))
2472  {
2473  auto* cn = GetPointer<integer_cst>(GET_NODE(op1));
2474  tree_nodeRef op0 = GetPointer<binary_expr>(GET_NODE(ga->op1))->op0;
2475  tree_nodeRef type_expr = GetPointer<binary_expr>(GET_NODE(ga->op1))->type;
2476 
2477  if(cn)
2478  {
2479  auto prev_index = GET_INDEX_NODE(ga->op1);
2480  ga->op1 = expand_MC(op0, cn, ga->op1, *it_los, block.second, type_expr, srcp_default);
2481  restart_analysis = restart_analysis || (prev_index != GET_INDEX_NODE(ga->op1));
2482  if(prev_index != GET_INDEX_NODE(ga->op1))
2483  {
2484  AppM->RegisterTransformation(GetName(), *it_los);
2485  }
2486  }
2487  }
2490  if(not reached_max_transformation_limit(*it_los) and
2491  GET_NODE(ga->op1)->get_kind() == mult_expr_K)
2492  {
2493  tree_nodeRef type_expr = GetPointer<binary_expr>(GET_NODE(ga->op1))->type;
2494 
2495  bool realp = tree_helper::is_real(TM, GET_INDEX_NODE(type_expr));
2496  if(!realp)
2497  {
2499  auto dw_out = tree_helper::Size(ga->op0);
2500  auto data_bitsize_out = ceil_pow2(dw_out);
2502  "---data_bitsize_out " + STR(data_bitsize_out) + " <- " + STR(dw_out) +
2503  "\n");
2504  auto dw_in0 = tree_helper::Size(GetPointer<binary_expr>(GET_NODE(ga->op1))->op0);
2505  auto data_bitsize_in0 = ceil_pow2(dw_in0);
2507  "---data_bitsize_in0 " + STR(data_bitsize_in0) + " <- " + STR(dw_in0) +
2508  "\n");
2509  auto dw_in1 = tree_helper::Size(GetPointer<binary_expr>(GET_NODE(ga->op1))->op1);
2510  auto data_bitsize_in1 = ceil_pow2(dw_in1);
2512  "---data_bitsize_in1 " + STR(data_bitsize_in1) + " <- " + STR(dw_in1) +
2513  "\n");
2514  if(std::max(data_bitsize_in0, data_bitsize_in1) * 2 == data_bitsize_out)
2515  {
2516  auto type_index = tree_helper::get_type_index(TM, GET_INDEX_NODE(ga->op0));
2517  tree_nodeRef op0_type = TM->GetTreeReindex(type_index);
2518  ga->op1 = tree_man->create_binary_operation(
2519  op0_type, GetPointer<binary_expr>(GET_NODE(ga->op1))->op0,
2520  GetPointer<binary_expr>(GET_NODE(ga->op1))->op1, srcp_default, widen_mult_expr_K);
2521  restart_analysis = true;
2522  AppM->RegisterTransformation(GetName(), *it_los);
2523  }
2524  }
2525  }
2527  };
2528  me_expr1();
2529  }
2530  else if(code1 == widen_mult_expr_K)
2531  {
2532  auto wme_expr1 = [&] {
2533  const auto be = GetPointer<binary_expr>(GET_NODE(ga->op1));
2534  tree_nodeRef op1 = be->op1;
2535  if(GetPointer<cst_node>(GET_NODE(op1)) && !GetPointer<vector_cst>(GET_NODE(op1)))
2536  {
2538  "-->Expanding widen_mult_expr " + STR(GET_INDEX_NODE(ga->op1)));
2539  auto* cn = GetPointer<cst_node>(GET_NODE(op1));
2540  tree_nodeRef op0 = GetPointer<binary_expr>(GET_NODE(ga->op1))->op0;
2541  tree_nodeRef type_expr = GetPointer<binary_expr>(GET_NODE(ga->op1))->type;
2542 
2543  bool realp = tree_helper::IsRealType(type_expr);
2544  if(!realp)
2545  {
2546  auto prev_index = GET_INDEX_NODE(ga->op1);
2547  ga->op1 = expand_MC(op0, static_cast<integer_cst*>(cn), ga->op1, *it_los, block.second,
2548  type_expr, srcp_default);
2549  restart_analysis = restart_analysis || (prev_index != GET_INDEX_NODE(ga->op1));
2550  if(prev_index != GET_INDEX_NODE(ga->op1))
2551  {
2552  AppM->RegisterTransformation(GetName(), *it_los);
2553  }
2554  }
2556  }
2557  else
2558  {
2559  if(tree_helper::IsUnsignedIntegerType(be->type) !=
2561  {
2563  "Conversion from unsigned to signed is required for first input of " +
2564  STR(ga->op1->index));
2565  const auto ga_nop = tree_man->CreateNopExpr(
2568  if(ga_nop)
2569  {
2570  be->op0 = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
2571  AppM->RegisterTransformation(GetName(), ga_nop);
2572  block.second->PushBefore(ga_nop, *it_los, AppM);
2573  restart_analysis = true;
2574  }
2575  else
2576  {
2577 #ifndef NDEBUG
2578  THROW_UNREACHABLE("Conversion of " + be->op0->ToString() + " cannot be created");
2579 #else
2580  THROW_WARNING("Implicit type conversion for first input of " + ga->ToString());
2581 #endif
2582  }
2583  }
2584  if(tree_helper::IsUnsignedIntegerType(be->type) !=
2586  {
2588  "Conversion from unsigned to signed is required for first input of " +
2589  STR(ga->op1->index));
2590  const auto ga_nop = tree_man->CreateNopExpr(
2593  if(ga_nop)
2594  {
2595  be->op1 = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
2596  block.second->PushBefore(ga_nop, *it_los, AppM);
2597  AppM->RegisterTransformation(GetName(), ga_nop);
2598  restart_analysis = true;
2599  }
2600  else
2601  {
2602 #ifndef NDEBUG
2603  THROW_UNREACHABLE("Conversion of " + be->op1->ToString() + " cannot be created");
2604 #else
2605  THROW_WARNING("Implicit type conversion for first input of " + ga->ToString());
2606 #endif
2607  }
2608  }
2609  }
2610  };
2611  wme_expr1();
2612  }
2613  else if(code1 == lt_expr_K)
2614  {
2615  auto lt_expr1 = [&] {
2617  "-->Expanding lt_expr " + STR(GET_INDEX_NODE(ga->op1)));
2618  auto be = GetPointer<binary_expr>(GET_NODE(ga->op1));
2619  tree_nodeRef op0 = be->op0;
2620  bool intp = tree_helper::is_int(TM, GET_INDEX_NODE(op0));
2621  if(intp)
2622  {
2623  tree_nodeRef op1 = be->op1;
2624  if(GetPointer<integer_cst>(GET_NODE(op1)))
2625  {
2626  if(tree_helper::GetConstValue(op1) == 0)
2627  {
2628  auto type_index = tree_helper::get_type_index(TM, GET_INDEX_NODE(op0));
2629  tree_nodeRef op0_type = TM->GetTreeReindex(type_index);
2630  tree_nodeRef right_shift_value = TM->CreateUniqueIntegerCst(
2631  static_cast<long long>(tree_helper::Size(op0) - 1), op0_type);
2633  op0_type, op0, right_shift_value, srcp_default, rshift_expr_K);
2635  op0_type, tree_nodeRef(), tree_nodeRef(), rshift1, function_id, srcp_default);
2636  block.second->PushBefore(rshift1_ga, *it_los, AppM);
2638  "---adding statement " + GET_NODE(rshift1_ga)->ToString());
2639  tree_nodeRef rshift1_ga_var = GetPointer<gimple_assign>(GET_NODE(rshift1_ga))->op0;
2640  tree_nodeRef bitwise_mask_value = TM->CreateUniqueIntegerCst(1, op0_type);
2641  tree_nodeRef bitwise_masked = tree_man->create_binary_operation(
2642  op0_type, rshift1_ga_var, bitwise_mask_value, srcp_default, bit_and_expr_K);
2643  tree_nodeRef bitwise_masked_ga =
2645  bitwise_masked, function_id, srcp_default);
2646  block.second->PushBefore(bitwise_masked_ga, *it_los, AppM);
2648  "---adding statement " + GET_NODE(bitwise_masked_ga)->ToString());
2649  tree_nodeRef bitwise_masked_var =
2650  GetPointer<gimple_assign>(GET_NODE(bitwise_masked_ga))->op0;
2651  tree_nodeRef ne = tree_man->create_unary_operation(be->type, bitwise_masked_var,
2652  srcp_default, nop_expr_K);
2654  be->type, tree_nodeRef(), tree_nodeRef(), ne, function_id, srcp_default);
2655  block.second->PushBefore(ga_nop, *it_los, AppM);
2657  "---adding statement " + GET_NODE(ga_nop)->ToString());
2658  AppM->RegisterTransformation(GetName(), ga_nop);
2659  ga->op1 = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
2660  restart_analysis = true;
2661  }
2662  else
2663  {
2664  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Not expanded");
2665  }
2666  }
2667  else
2668  {
2669  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Not expanded");
2670  }
2671  }
2672  else
2673  {
2674  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Not expanded");
2675  }
2676  };
2677  lt_expr1();
2678  }
2679  else if(code1 == ge_expr_K)
2680  {
2681  auto ge_expr1 = [&] {
2683  "-->Expanding ge_expr " + STR(GET_INDEX_NODE(ga->op1)));
2684  tree_nodeRef op0 = GetPointer<binary_expr>(GET_NODE(ga->op1))->op0;
2685  bool intp = tree_helper::is_int(TM, GET_INDEX_NODE(op0));
2686  if(intp)
2687  {
2688  tree_nodeRef op1 = GetPointer<binary_expr>(GET_NODE(ga->op1))->op1;
2689  if(GetPointer<integer_cst>(GET_NODE(op1)))
2690  {
2691  const auto op1_value = tree_helper::GetConstValue(op1);
2692  if(op1_value == 0)
2693  {
2694  auto type_index = tree_helper::get_type_index(TM, GET_INDEX_NODE(op0));
2695  tree_nodeRef op0_type = TM->GetTreeReindex(type_index);
2696  tree_nodeRef right_shift_value = TM->CreateUniqueIntegerCst(
2697  static_cast<long long>(tree_helper::Size(op0) - 1), op0_type);
2699  op0_type, op0, right_shift_value, srcp_default, rshift_expr_K);
2701  op0_type, tree_nodeRef(), tree_nodeRef(), rshift1, function_id, srcp_default);
2702  block.second->PushBefore(rshift1_ga, *it_los, AppM);
2704  "---adding statement " + GET_NODE(rshift1_ga)->ToString());
2705  tree_nodeRef rshift1_ga_var = GetPointer<gimple_assign>(GET_NODE(rshift1_ga))->op0;
2706  tree_nodeRef bitwise_mask_value = TM->CreateUniqueIntegerCst(1, op0_type);
2707  tree_nodeRef bitwise_masked = tree_man->create_binary_operation(
2708  op0_type, rshift1_ga_var, bitwise_mask_value, srcp_default, bit_and_expr_K);
2709  tree_nodeRef bitwise_masked_ga =
2711  bitwise_masked, function_id, srcp_default);
2712  block.second->PushBefore(bitwise_masked_ga, *it_los, AppM);
2714  "---adding statement " + GET_NODE(bitwise_masked_ga)->ToString());
2715  tree_nodeRef bitwise_masked_var =
2716  GetPointer<gimple_assign>(GET_NODE(bitwise_masked_ga))->op0;
2717  tree_nodeRef ne =
2718  tree_man->create_unary_operation(GetPointer<binary_expr>(GET_NODE(ga->op1))->type,
2719  bitwise_masked_var, srcp_default, nop_expr_K);
2721  GetPointer<binary_expr>(GET_NODE(ga->op1))->type, tree_nodeRef(), tree_nodeRef(),
2722  ne, function_id, srcp_default);
2723  block.second->PushBefore(ga_nop, *it_los, AppM);
2725  "---adding statement " + GET_NODE(ga_nop)->ToString());
2726  tree_nodeRef ga_nop_var = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
2727  auto booleanType = tree_man->GetBooleanType();
2729  booleanType, ga_nop_var, srcp_default, truth_not_expr_K);
2730  ga->op1 = not_masked;
2731  restart_analysis = true;
2732  }
2733  else
2734  {
2735  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Not expanded");
2736  }
2737  }
2738  else
2739  {
2740  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Not expanded");
2741  }
2742  }
2743  else
2744  {
2745  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Not expanded");
2746  }
2747  };
2748  ge_expr1();
2749  }
2750  else if(code1 == plus_expr_K)
2751  {
2752  auto pe_expr1 = [&] {
2754  "-->Expanding plus_expr " + STR(GET_INDEX_NODE(ga->op1)));
2755  tree_nodeRef bop0 = GetPointer<binary_expr>(GET_NODE(ga->op1))->op0;
2756  tree_nodeRef bop1 = GetPointer<binary_expr>(GET_NODE(ga->op1))->op1;
2759  {
2760  auto ssa0 = GetPointerS<ssa_name>(GET_NODE(ga->op0));
2761  const auto ga_nop =
2762  tree_man->CreateNopExpr(bop0, ssa0->type, ssa0->min, ssa0->max, function_id);
2764  "---adding statement " + GET_NODE(ga_nop)->ToString());
2765  const auto nop_vd = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
2766  block.second->PushBefore(ga_nop, *it_los, AppM);
2767  GetPointer<binary_expr>(GET_NODE(ga->op1))->op0 = bop1 = nop_vd;
2768  restart_analysis = true;
2769  }
2772  {
2773  auto ssa0 = GetPointerS<ssa_name>(GET_NODE(ga->op0));
2774  const auto ga_nop =
2775  tree_man->CreateNopExpr(bop1, ssa0->type, ssa0->min, ssa0->max, function_id);
2777  "---adding statement " + GET_NODE(ga_nop)->ToString());
2778  const auto nop_vd = GetPointer<gimple_assign>(GET_NODE(ga_nop))->op0;
2779  block.second->PushBefore(ga_nop, *it_los, AppM);
2780  GetPointer<binary_expr>(GET_NODE(ga->op1))->op1 = bop1 = nop_vd;
2781  restart_analysis = true;
2782  }
2784  if(intp)
2785  {
2786  if(GET_INDEX_NODE(bop0) == GET_INDEX_NODE(bop1))
2787  {
2788  tree_nodeRef type = GetPointer<binary_expr>(GET_NODE(ga->op1))->type;
2789  tree_nodeRef left_shift_value = TM->CreateUniqueIntegerCst(1, type);
2790  tree_nodeRef left1 = tree_man->create_binary_operation(type, bop0, left_shift_value,
2791  srcp_default, lshift_expr_K);
2792  ga->op1 = left1;
2793  restart_analysis = true;
2795  }
2796  else
2797  {
2799  }
2800  }
2801  else
2802  {
2804  }
2805  };
2806  pe_expr1();
2807  }
2808  else if(code1 == parm_decl_K)
2809  {
2810  auto* pd = GetPointer<parm_decl>(GET_NODE(ga->op1));
2811  tree_nodeRef type = pd->type;
2812  tree_nodeRef pt = tree_man->GetPointerType(type, 8);
2813  tree_nodeRef ae = tree_man->create_unary_operation(pt, ga->op1, srcp_default, addr_expr_K);
2815  function_id, srcp_default);
2816  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
2817  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
2818 
2820  tree_nodeRef mr = tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
2821 
2822  ga->op1 = mr;
2823  block.second->PushBefore(new_ga, *it_los, AppM);
2825  "---adding statement " + GET_NODE(new_ga)->ToString());
2826  AppM->RegisterTransformation(GetName(), new_ga);
2827  restart_analysis = true;
2828  }
2829  }
2830 
2831  if(code0 == array_ref_K)
2832  {
2834  "---expand array_ref 2 " + STR(GET_INDEX_NODE(ga->op0)));
2835  auto* AR = GetPointer<array_ref>(GET_NODE(ga->op0));
2836  ga->op0 = array_ref_lowering(AR, srcp_default, block, it_los, true);
2837  restart_analysis = true;
2838  }
2839  else if(code0 == mem_ref_K)
2840  {
2841  auto mem_ref0 = [&] {
2843  "---expand mem_ref 2 " + STR(GET_INDEX_NODE(ga->op0)));
2844  auto* MR = GetPointer<mem_ref>(GET_NODE(ga->op0));
2845  const auto mem_op0_kind = GET_NODE(MR->op0)->get_kind();
2846  if(mem_op0_kind == addr_expr_K || mem_op0_kind == pointer_plus_expr_K ||
2847  mem_op0_kind == view_convert_expr_K)
2848  {
2849  extract_unary_expr(MR->op0, mem_op0_kind == addr_expr_K, true);
2850  }
2851 
2852  tree_nodeRef op1 = MR->op1;
2853  const auto op1_val = tree_helper::GetConstValue(op1);
2854  if(op1_val != 0)
2855  {
2856  tree_nodeRef type = MR->type;
2857 
2859  auto obj_size = tree_helper::Size(tree_helper::CGetType(ga->op0));
2860  auto bram_size = std::max(8ull, obj_size / 2);
2863  bool implicit_memset = GET_NODE(ga->op1)->get_kind() == constructor_K &&
2864  GetPointer<constructor>(GET_NODE(ga->op1)) &&
2865  GetPointer<constructor>(GET_NODE(ga->op1))->list_of_idx_valu.size() == 0;
2866  if(implicit_memset)
2867  {
2868  auto var = tree_helper::get_base_index(TM, GET_INDEX_NODE(MR->op0));
2869  implicit_memset = var != 0;
2870  if(implicit_memset)
2871  {
2872  auto type_index = tree_helper::get_type_index(TM, var);
2873  const auto type_node = TM->get_tree_node_const(type_index);
2874  implicit_memset = type_node->get_kind() == array_type_K;
2875  }
2876  }
2877  if(!implicit_memset && ((((op1_val * 8)) % static_cast<long long>(bram_size)) != 0))
2878  {
2879  function_behavior->set_unaligned_accesses(true);
2880  }
2881 
2882  const auto pt = tree_man->GetPointerType(type, 8);
2883  const auto ae = tree_man->create_unary_operation(pt, ga->op0, srcp_default, addr_expr_K);
2884  const auto new_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae,
2885  function_id, srcp_default);
2886  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
2887  const auto ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
2888 
2889  const auto offset = TM->CreateUniqueIntegerCst(0, pt);
2890  const auto mr =
2891  tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
2892 
2893  ga->op0 = mr;
2894  block.second->PushBefore(new_ga, *it_los, AppM);
2896  "---adding statement " + GET_NODE(new_ga)->ToString());
2897  restart_analysis = true;
2898  }
2899  const auto op1_type = tree_helper::CGetType(ga->op1);
2900  auto view_convert_pattern = GET_CONST_NODE(op1_type)->get_kind() == record_type_K &&
2901  GET_NODE(ga->op1)->get_kind() == view_convert_expr_K;
2902  if(!view_convert_pattern && GET_NODE(ga->op1)->get_kind() != ssa_name_K &&
2903  !GetPointer<cst_node>(GET_NODE(ga->op1)) && GET_NODE(ga->op1)->get_kind() != mem_ref_K &&
2904  GET_NODE(ga->op1)->get_kind() != constructor_K)
2905  {
2906  auto type_index = tree_helper::get_type_index(TM, GET_INDEX_NODE(ga->op1));
2907  const auto op_type = TM->GetTreeReindex(type_index);
2908  const auto op_ga = tree_man->CreateGimpleAssign(op_type, tree_nodeRef(), tree_nodeRef(),
2909  ga->op1, function_id, srcp_default);
2910  const auto op_vd = GetPointer<gimple_assign>(GET_NODE(op_ga))->op0;
2911  block.second->PushBefore(op_ga, *it_los, AppM);
2913  "---adding statement " + GET_NODE(op_ga)->ToString());
2914  ga->op1 = op_vd;
2915  restart_analysis = true;
2916  }
2917  };
2918  mem_ref0();
2919  }
2920  else if(code0 == component_ref_K)
2921  {
2922  auto component_ref0 = [&] {
2923  auto* cr = GetPointer<component_ref>(GET_NODE(ga->op0));
2924  auto* field_d = GetPointer<field_decl>(GET_NODE(cr->op1));
2926  if(field_d->is_bitfield())
2927  {
2928  THROW_ASSERT(tree_helper::GetConstValue(field_d->bpos) >= 0, "");
2929  auto op1_val = static_cast<unsigned long long>(tree_helper::GetConstValue(field_d->bpos));
2930  auto right_shift_val = op1_val % 8;
2931  if(GET_NODE(cr->type)->get_kind() == boolean_type_K)
2932  {
2933  type = tree_man->GetCustomIntegerType(std::max(8ull, ceil_pow2(1 + right_shift_val)), true);
2934  }
2935  else
2936  {
2937  auto* it = GetPointer<integer_type>(GET_NODE(cr->type));
2938  THROW_ASSERT(it, "unexpected pattern");
2939  type = tree_man->GetCustomIntegerType(std::max(8ull, ceil_pow2(it->prec + right_shift_val)),
2940  it->unsigned_flag);
2941  }
2942  }
2943  else
2944  {
2945  type = cr->type;
2946  }
2947  const auto pt = tree_man->GetPointerType(type, 8);
2948  const auto ae = tree_man->create_unary_operation(pt, ga->op0, srcp_default, addr_expr_K);
2949  const auto new_ga = tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae,
2950  function_id, srcp_default);
2951  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
2952 
2953  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
2954  block.second->PushBefore(new_ga, *it_los, AppM);
2956  "---adding statement " + GET_NODE(new_ga)->ToString());
2957 
2958  if(field_d->packed_flag)
2959  {
2960  function_behavior->set_packed_vars(true);
2961  }
2962 
2964  tree_nodeRef mr = tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
2965  if(field_d->is_bitfield())
2966  {
2967  THROW_ASSERT(tree_helper::GetConstValue(field_d->bpos) >= 0, "");
2968  auto op1_val = static_cast<unsigned int>(tree_helper::GetConstValue(field_d->bpos));
2969  auto right_shift_val = op1_val % 8;
2970  auto size_tp = tree_helper::Size(type);
2971  auto size_field_decl = tree_helper::Size(cr->op1);
2972 
2973  if(right_shift_val == 0 and size_field_decl == size_tp)
2974  {
2975  ga->op0 = mr;
2976  }
2977  else
2978  {
2979  tree_nodeRef mr_dup =
2980  tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
2982  mr_dup, function_id, srcp_default);
2983  tree_nodeRef load_vd = GetPointer<gimple_assign>(GET_NODE(load_ga))->op0;
2984  GetPointer<gimple_assign>(GET_NODE(load_ga))->memuse = ga->memuse;
2985  GetPointer<gimple_assign>(GET_NODE(load_ga))->vuses = ga->vuses;
2986  for(const auto& vd : bitfield_vuses)
2987  {
2988  GetPointer<gimple_assign>(GET_NODE(load_ga))->AddVuse(vd);
2989  }
2990  THROW_ASSERT(ga->vdef, "unexpected condition");
2991  bitfield_vdefs.insert(ga->vdef);
2992  block.second->PushBefore(load_ga, *it_los, AppM);
2994  "---adding statement " + GET_NODE(load_ga)->ToString());
2995 
2996  tree_nodeRef load_var;
2997  if(size_field_decl != size_tp)
2998  {
2999 #if HAVE_FROM_DISCREPANCY_BUILT
3000  /*
3001  * for discrepancy analysis, the ssa assigned loading
3002  * the bitfield must not be checked, because it has
3003  * not been resized yet and it may also load
3004  * inconsistent stuff from other bitfields nearby
3005  */
3006  if(parameters->isOption(OPT_discrepancy) and
3007  parameters->getOption<bool>(OPT_discrepancy) and
3008  (not parameters->isOption(OPT_discrepancy_force) or
3009  not parameters->getOption<bool>(OPT_discrepancy_force)))
3010  {
3012  "---skip discrepancy of ssa " + GET_NODE(load_vd)->ToString() +
3013  " assigned in new stmt: " + GET_NODE(load_ga)->ToString());
3014  AppM->RDiscr->ssa_to_skip.insert(GET_NODE(load_vd));
3015  }
3016 #endif
3017  tree_nodeRef nmask_value = TM->CreateUniqueIntegerCst(
3018  static_cast<long long int>(~(((1ULL << size_field_decl) - 1) << right_shift_val)),
3019  type);
3020  tree_nodeRef nmask_node = tree_man->create_binary_operation(type, load_vd, nmask_value,
3021  srcp_default, bit_and_expr_K);
3023  type, tree_nodeRef(), tree_nodeRef(), nmask_node, function_id, srcp_default);
3024  block.second->PushBefore(nmask_ga, *it_los, AppM);
3026  "---adding statement " + GET_NODE(nmask_ga)->ToString());
3027  load_var = GetPointer<gimple_assign>(GET_NODE(nmask_ga))->op0;
3028 #if HAVE_FROM_DISCREPANCY_BUILT
3029  /*
3030  * for discrepancy analysis, the ssa assigned loading
3031  * the bitfield must not be checked, because it has
3032  * not been resized yet and it may also load
3033  * inconsistent stuff from other bitfields nearby
3034  */
3035  if(parameters->isOption(OPT_discrepancy) and
3036  parameters->getOption<bool>(OPT_discrepancy) and
3037  (not parameters->isOption(OPT_discrepancy_force) or
3038  not parameters->getOption<bool>(OPT_discrepancy_force)))
3039  {
3041  "---skip discrepancy of ssa " + GET_NODE(load_var)->ToString() +
3042  " assigned in new stmt: " + GET_NODE(nmask_ga)->ToString());
3043  AppM->RDiscr->ssa_to_skip.insert(GET_NODE(load_var));
3044  }
3045 #endif
3046  }
3047  else
3048  {
3049  THROW_ASSERT(right_shift_val == 0, "unexpected pattern");
3050  load_var = load_vd;
3051  }
3052  tree_nodeRef written_var;
3053  if(size_field_decl != size_tp)
3054  {
3055  tree_nodeRef and_mask_value = TM->CreateUniqueIntegerCst(
3056  static_cast<long long int>((1ULL << size_field_decl) - 1), type);
3058  type, ga->op1, and_mask_value, srcp_default, bit_and_expr_K);
3059  tree_nodeRef and_mask_ga = tree_man->CreateGimpleAssign(
3060  type, tree_nodeRef(), tree_nodeRef(), and_mask_node, function_id, srcp_default);
3061  block.second->PushBefore(and_mask_ga, *it_los, AppM);
3063  "---adding statement " + GET_NODE(and_mask_ga)->ToString());
3064  written_var = GetPointer<gimple_assign>(GET_NODE(and_mask_ga))->op0;
3065  }
3066  else
3067  {
3068  written_var = ga->op1;
3069  }
3070  tree_nodeRef lshifted_var;
3071  if(right_shift_val)
3072  {
3073  tree_nodeRef lsh_value = TM->CreateUniqueIntegerCst(right_shift_val, type);
3074  tree_nodeRef lsh_node = tree_man->create_binary_operation(type, written_var, lsh_value,
3075  srcp_default, lshift_expr_K);
3077  lsh_node, function_id, srcp_default);
3078  block.second->PushBefore(lsh_ga, *it_los, AppM);
3080  "---adding statement " + GET_NODE(lsh_ga)->ToString());
3081  lshifted_var = GetPointer<gimple_assign>(GET_NODE(lsh_ga))->op0;
3082  }
3083  else
3084  {
3085  lshifted_var = written_var;
3086  }
3087 
3088  tree_nodeRef res_node = tree_man->create_binary_operation(type, lshifted_var, load_var,
3089  srcp_default, bit_ior_expr_K);
3091  res_node, function_id, srcp_default);
3092  block.second->PushBefore(res_ga, *it_los, AppM);
3094  "---adding statement " + GET_NODE(res_ga)->ToString());
3095  tree_nodeRef res_vd = GetPointer<gimple_assign>(GET_NODE(res_ga))->op0;
3096  ga->op1 = res_vd;
3097  ga->op0 = mr;
3098 #if HAVE_FROM_DISCREPANCY_BUILT
3099  /*
3100  * for discrepancy analysis, the ssa assigned loading
3101  * the bitfield must not be checked, because it has
3102  * not been resized yet and it may also load
3103  * inconsistent stuff from other bitfields nearby
3104  */
3105  if(size_field_decl != size_tp and parameters->isOption(OPT_discrepancy) and
3106  parameters->getOption<bool>(OPT_discrepancy) and
3107  (not parameters->isOption(OPT_discrepancy_force) or
3108  not parameters->getOption<bool>(OPT_discrepancy_force)))
3109  {
3111  "---skip discrepancy of ssa " + GET_NODE(res_vd)->ToString() +
3112  " assigned in new stmt: " + GET_NODE(res_ga)->ToString());
3113  AppM->RDiscr->ssa_to_skip.insert(GET_NODE(res_vd));
3114  }
3115 #endif
3116  }
3117  }
3118  else
3119  {
3120  ga->op0 = mr;
3121  }
3122  restart_analysis = true;
3123  };
3124  component_ref0();
3125  }
3126  else if(code0 == target_mem_ref461_K)
3127  {
3128  auto tmr0 = [&] {
3130  "---expand target_mem_ref 2 " + STR(GET_INDEX_NODE(ga->op0)));
3131 
3132  auto* tmr = GetPointer<target_mem_ref461>(GET_NODE(ga->op0));
3134  tree_nodeRef type = tmr->type;
3135 
3136  tree_nodeRef pt = tree_man->GetPointerType(type, 8);
3137  tree_nodeRef ae = tree_man->create_unary_operation(pt, ga->op0, srcp_default, addr_expr_K);
3139  function_id, srcp_default);
3140  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
3141  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
3142 
3144  tree_nodeRef mr = tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
3145 
3146  ga->op0 = mr;
3147  block.second->PushBefore(new_ga, *it_los, AppM);
3149  "---adding statement " + GET_NODE(new_ga)->ToString());
3150  restart_analysis = true;
3151  };
3152  tmr0();
3153  }
3154  else if(code0 == var_decl_K && !ga->init_assignment)
3155  {
3156  auto* vd = GetPointer<var_decl>(GET_NODE(ga->op0));
3157  tree_nodeRef type = vd->type;
3158  // std::cerr << "algn" << GetPointer<type_node>(GET_NODE(type))->algn << "\n";
3159  tree_nodeRef pt = tree_man->GetPointerType(type, GetPointer<type_node>(GET_NODE(type))->algn);
3160  tree_nodeRef ae = tree_man->create_unary_operation(pt, ga->op0, srcp_default, addr_expr_K);
3161  tree_nodeRef new_ga =
3162  tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae, function_id, srcp_default);
3163  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
3164  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
3165  auto ssa_var_decl = GetPointer<ssa_name>(GET_NODE(ssa_vd));
3166  ssa_var_decl->use_set->Add(ga->op0);
3168  tree_nodeRef mr = tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
3169 
3170  ga->op0 = mr;
3171  block.second->PushBefore(new_ga, *it_los, AppM);
3173  "---adding statement " + GET_NODE(new_ga)->ToString());
3174  restart_analysis = true;
3175 
3176  // {
3177  // /// check if volatile attribute is missing
3178  // /// it may happen with gcc v4.8 or greater
3179  // if(vd->scpe && GET_NODE(vd->scpe)->get_kind() != translation_unit_decl_K &&
3180  // !vd->static_flag && !tree_helper::is_volatile(TM,GET_INDEX_NODE(ga->op1)) &&
3181  // GET_NODE(vd->type)->get_kind() != array_type_K &&
3182  // GET_NODE(vd->type)->get_kind() != record_type_K &&
3183  // GET_NODE(vd->type)->get_kind() != union_type_K)
3184  // {
3185  // /// w.r.t. bambu this kind of non-ssa variable is equivalent to a static
3186  // local variable vd->static_flag = true;
3187  // }
3188  // }
3189  }
3190  else if(code0 == indirect_ref_K)
3191  {
3192  auto* ir = GetPointer<indirect_ref>(GET_NODE(ga->op0));
3193  tree_nodeRef type = ir->type;
3195  tree_nodeRef mr = tree_man->create_binary_operation(type, ir->op, offset, srcp_default, mem_ref_K);
3196  ga->op0 = mr;
3197  restart_analysis = true;
3198  }
3199  else if(code0 == misaligned_indirect_ref_K)
3200  {
3201  auto* MIR = GetPointer<misaligned_indirect_ref>(GET_NODE(ga->op0));
3202  function_behavior->set_unaligned_accesses(true);
3203  tree_nodeRef type = MIR->type;
3204  tree_nodeRef pt = tree_man->GetPointerType(type, 8);
3206  tree_nodeRef mr = tree_man->create_binary_operation(type, MIR->op, offset, srcp_default, mem_ref_K);
3207  ga->op0 = mr;
3208  restart_analysis = true;
3209  }
3210  else if(code0 == realpart_expr_K)
3211  {
3212  ga->op0 = manage_realpart(ga->op0, tree_nodeRef());
3213  restart_analysis = true;
3214  }
3215  else if(code0 == imagpart_expr_K)
3216  {
3217  ga->op0 = manage_imagpart(ga->op0, tree_nodeRef());
3218  restart_analysis = true;
3219  }
3220  else if(reached_max_transformation_limit(*it_los))
3221  {
3222  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Reached max cfg transformations");
3224  "<--Examined statement " + GET_NODE(*it_los)->ToString());
3225  it_los++;
3226  continue;
3227  }
3228  if(code0 == bit_field_ref_K)
3229  {
3230  auto bit_field_ref0 = [&] {
3231  auto* bfr = GetPointer<bit_field_ref>(GET_NODE(ga->op0));
3232  THROW_ASSERT(GET_NODE(bfr->op0)->get_kind() != ssa_name_K, "unexpected pattern");
3233  THROW_ASSERT(tree_helper::GetConstValue(bfr->op2) >= 0, "");
3234  auto op1_val = static_cast<unsigned int>(tree_helper::GetConstValue(bfr->op2));
3235  auto right_shift_val = op1_val % 8;
3237  if(GET_NODE(bfr->type)->get_kind() == boolean_type_K)
3238  {
3239  type = tree_man->GetCustomIntegerType(std::max(8u, ceil_pow2(1 + right_shift_val)), true);
3240  }
3241  else
3242  {
3243  auto* it = GetPointer<integer_type>(GET_NODE(bfr->type));
3244  THROW_ASSERT(it, "unexpected pattern");
3245  type = tree_man->GetCustomIntegerType(std::max(8u, ceil_pow2(it->prec + right_shift_val)),
3246  it->unsigned_flag);
3247  }
3248  tree_nodeRef pt = tree_man->GetPointerType(type, 8);
3249  tree_nodeRef ae = tree_man->create_unary_operation(pt, ga->op0, srcp_default, addr_expr_K);
3251  function_id, srcp_default);
3252  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
3253 
3254  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
3255  block.second->PushBefore(new_ga, *it_los, AppM);
3257  "---adding statement " + GET_NODE(new_ga)->ToString());
3258  AppM->RegisterTransformation(GetName(), new_ga);
3259 
3261  tree_nodeRef mr = tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
3262 
3263  auto size_tp = tree_helper::Size(type);
3264  auto size_field_decl = tree_helper::Size(bfr->op1);
3265 
3266  if(right_shift_val == 0 and size_field_decl == size_tp)
3267  {
3268  ga->op0 = mr;
3269  }
3270  else
3271  {
3272  tree_nodeRef mr_dup =
3273  tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
3275  mr_dup, function_id, srcp_default);
3276  tree_nodeRef load_vd = GetPointer<gimple_assign>(GET_NODE(load_ga))->op0;
3277  GetPointer<gimple_assign>(GET_NODE(load_ga))->memuse = ga->memuse;
3278  GetPointer<gimple_assign>(GET_NODE(load_ga))->vuses = ga->vuses;
3279  for(const auto& vd : bitfield_vuses)
3280  {
3281  GetPointer<gimple_assign>(GET_NODE(load_ga))->AddVuse(vd);
3282  }
3283  THROW_ASSERT(ga->vdef, "unexpected condition");
3284  bitfield_vdefs.insert(ga->vdef);
3285  block.second->PushBefore(load_ga, *it_los, AppM);
3287  "---adding statement " + GET_NODE(load_ga)->ToString());
3288 
3289  tree_nodeRef load_var;
3290  if(size_field_decl != size_tp)
3291  {
3292 #if HAVE_FROM_DISCREPANCY_BUILT
3293  /*
3294  * for discrepancy analysis, the ssa assigned loading
3295  * the bitfield must not be checked, because it has
3296  * not been resized yet and it may also load
3297  * inconsistent stuff from other bitfields nearby
3298  */
3299  if(parameters->isOption(OPT_discrepancy) and parameters->getOption<bool>(OPT_discrepancy) and
3300  (not parameters->isOption(OPT_discrepancy_force) or
3301  not parameters->getOption<bool>(OPT_discrepancy_force)))
3302  {
3304  "---skip discrepancy of ssa " + GET_NODE(load_vd)->ToString() +
3305  " assigned in new stmt: " + GET_NODE(load_ga)->ToString());
3306  AppM->RDiscr->ssa_to_skip.insert(GET_NODE(load_vd));
3307  }
3308 #endif
3309  tree_nodeRef nmask_value = TM->CreateUniqueIntegerCst(
3310  static_cast<long long int>(~(((1ULL << size_field_decl) - 1) << right_shift_val)), type);
3311  tree_nodeRef nmask_node = tree_man->create_binary_operation(type, load_vd, nmask_value,
3312  srcp_default, bit_and_expr_K);
3314  nmask_node, function_id, srcp_default);
3315  block.second->PushBefore(nmask_ga, *it_los, AppM);
3317  "---adding statement " + GET_NODE(nmask_ga)->ToString());
3318  load_var = GetPointer<gimple_assign>(GET_NODE(nmask_ga))->op0;
3319 #if HAVE_FROM_DISCREPANCY_BUILT
3320  /*
3321  * for discrepancy analysis, the ssa assigned loading
3322  * the bitfield must not be checked, because it has
3323  * not been resized yet and it may also load
3324  * inconsistent stuff from other bitfields nearby
3325  */
3326  if(parameters->isOption(OPT_discrepancy) and parameters->getOption<bool>(OPT_discrepancy) and
3327  (not parameters->isOption(OPT_discrepancy_force) or
3328  not parameters->getOption<bool>(OPT_discrepancy_force)))
3329  {
3331  "---skip discrepancy of ssa " + GET_NODE(load_var)->ToString() +
3332  " assigned in new stmt: " + GET_NODE(nmask_ga)->ToString());
3333  AppM->RDiscr->ssa_to_skip.insert(GET_NODE(load_var));
3334  }
3335 #endif
3336  }
3337  else
3338  {
3339  THROW_ASSERT(right_shift_val == 0, "unexpected pattern");
3340  load_var = load_vd;
3341  }
3342  tree_nodeRef written_var;
3343  if(size_field_decl != size_tp)
3344  {
3345  tree_nodeRef and_mask_value = TM->CreateUniqueIntegerCst(
3346  static_cast<long long int>((1ULL << size_field_decl) - 1), type);
3347  tree_nodeRef and_mask_node = tree_man->create_binary_operation(type, ga->op1, and_mask_value,
3348  srcp_default, bit_and_expr_K);
3349  tree_nodeRef and_mask_ga = tree_man->CreateGimpleAssign(
3350  type, tree_nodeRef(), tree_nodeRef(), and_mask_node, function_id, srcp_default);
3351  block.second->PushBefore(and_mask_ga, *it_los, AppM);
3353  "---adding statement " + GET_NODE(and_mask_ga)->ToString());
3354  written_var = GetPointer<gimple_assign>(GET_NODE(and_mask_ga))->op0;
3355  }
3356  else
3357  {
3358  written_var = ga->op1;
3359  }
3360  tree_nodeRef lshifted_var;
3361  if(right_shift_val)
3362  {
3363  tree_nodeRef lsh_value = TM->CreateUniqueIntegerCst(right_shift_val, type);
3364  tree_nodeRef lsh_node = tree_man->create_binary_operation(type, written_var, lsh_value,
3365  srcp_default, lshift_expr_K);
3367  lsh_node, function_id, srcp_default);
3368  block.second->PushBefore(lsh_ga, *it_los, AppM);
3370  "---adding statement " + GET_NODE(lsh_ga)->ToString());
3371  lshifted_var = GetPointer<gimple_assign>(GET_NODE(lsh_ga))->op0;
3372  }
3373  else
3374  {
3375  lshifted_var = written_var;
3376  }
3377 
3378  tree_nodeRef res_node = tree_man->create_binary_operation(type, lshifted_var, load_var,
3379  srcp_default, bit_ior_expr_K);
3381  res_node, function_id, srcp_default);
3382  block.second->PushBefore(res_ga, *it_los, AppM);
3384  "---adding statement " + GET_NODE(res_ga)->ToString());
3385  tree_nodeRef res_vd = GetPointer<gimple_assign>(GET_NODE(res_ga))->op0;
3386  ga->op1 = res_vd;
3387  ga->op0 = mr;
3388 #if HAVE_FROM_DISCREPANCY_BUILT
3389  /*
3390  * for discrepancy analysis, the ssa assigned loading
3391  * the bitfield must not be checked, because it has
3392  * not been resized yet and it may also load
3393  * inconsistent stuff from other bitfields nearby
3394  */
3395  if(size_field_decl != size_tp and parameters->isOption(OPT_discrepancy) and
3396  parameters->getOption<bool>(OPT_discrepancy) and
3397  (not parameters->isOption(OPT_discrepancy_force) or
3398  not parameters->getOption<bool>(OPT_discrepancy_force)))
3399  {
3401  "---skip discrepancy of ssa " + GET_NODE(res_vd)->ToString() +
3402  " assigned in new stmt: " + GET_NODE(res_ga)->ToString());
3403  AppM->RDiscr->ssa_to_skip.insert(GET_NODE(res_vd));
3404  }
3405 #endif
3406  }
3407  restart_analysis = true;
3408  };
3409  bit_field_ref0();
3410  }
3411  else if(code0 == parm_decl_K)
3412  {
3413  auto* pd = GetPointer<parm_decl>(GET_NODE(ga->op0));
3414  tree_nodeRef type = pd->type;
3415  tree_nodeRef pt = tree_man->GetPointerType(type, 8);
3416  tree_nodeRef ae = tree_man->create_unary_operation(pt, ga->op0, srcp_default, addr_expr_K);
3417  tree_nodeRef new_ga =
3418  tree_man->CreateGimpleAssign(pt, tree_nodeRef(), tree_nodeRef(), ae, function_id, srcp_default);
3419  GetPointer<gimple_assign>(GET_NODE(new_ga))->temporary_address = true;
3420  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
3421 
3423  tree_nodeRef mr = tree_man->create_binary_operation(type, ssa_vd, offset, srcp_default, mem_ref_K);
3424 
3425  ga->op0 = mr;
3426  block.second->PushBefore(new_ga, *it_los, AppM);
3428  "---adding statement " + GET_NODE(new_ga)->ToString());
3429  AppM->RegisterTransformation(GetName(), new_ga);
3430  restart_analysis = true;
3431  }
3432  else if(code0 == result_decl_K && code1 == ssa_name_K)
3433  {
3434  const auto type_node = tree_helper::CGetType(ga->op1);
3435  if(GET_CONST_NODE(type_node)->get_kind() == complex_type_K ||
3436  GET_CONST_NODE(type_node)->get_kind() == vector_type_K)
3437  {
3438  auto it_los_next = std::next(it_los);
3439  if(it_los_next != it_los_end && GET_NODE(*it_los_next)->get_kind() == gimple_return_K)
3440  {
3441  auto* gr = GetPointer<gimple_return>(GET_NODE(*it_los_next));
3442  gr->op = ga->op1;
3443  block.second->RemoveStmt(*it_los, AppM);
3444  it_los = list_of_stmt.begin();
3445  it_los_end = list_of_stmt.end();
3446  bitfield_vuses.clear();
3447  bitfield_vdefs.clear();
3448  }
3449  }
3450  }
3451  else if(code0 == result_decl_K)
3452  {
3453  auto type_index = tree_helper::get_type_index(TM, GET_INDEX_NODE(ga->op0));
3454  tree_nodeRef op_type = TM->GetTreeReindex(type_index);
3455  tree_nodeRef new_ga = tree_man->CreateGimpleAssign(op_type, tree_nodeRef(), tree_nodeRef(), ga->op1,
3456  function_id, srcp_default);
3457  tree_nodeRef ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
3458  ga->op1 = ssa_vd;
3459  block.second->PushBefore(new_ga, *it_los, AppM);
3460  AppM->RegisterTransformation(GetName(), new_ga);
3461  restart_analysis = true;
3462  }
3463  }
3464  else if(GET_NODE(*it_los)->get_kind() == gimple_cond_K)
3465  {
3467  {
3468  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Reached max cfg transformations");
3470  "<--Examined statement " + GET_NODE(*it_los)->ToString());
3471  it_los++;
3472  continue;
3473  }
3474  auto gc0 = [&] {
3475  auto* gc = GetPointer<gimple_cond>(GET_NODE(*it_los));
3477  if(GetPointer<binary_expr>(GET_NODE(gc->op0)))
3478  {
3479  auto be = GetPointer<binary_expr>(GET_NODE(gc->op0));
3480  const auto be_kind = be->get_kind();
3481  if(be_kind == eq_expr_K || be_kind == ne_expr_K || be_kind == lt_expr_K || be_kind == le_expr_K ||
3482  be_kind == gt_expr_K || be_kind == ge_expr_K || be_kind == ltgt_expr_K ||
3483  be_kind == truth_and_expr_K || be_kind == truth_andif_expr_K || be_kind == truth_or_expr_K ||
3484  be_kind == truth_orif_expr_K || be_kind == truth_xor_expr_K)
3485  {
3486  be->type = tree_man->GetBooleanType();
3487  }
3488  bool changed = false;
3489  if(GET_NODE(be->op0)->get_kind() == addr_expr_K)
3490  {
3491  extract_unary_expr(be->op0, true, false);
3492  }
3493  if(GET_NODE(be->op1)->get_kind() == addr_expr_K)
3494  {
3495  extract_unary_expr(be->op1, true, false);
3496  }
3497  if(GetPointer<unary_expr>(GET_NODE(be->op0)) || GetPointer<binary_expr>(GET_NODE(be->op0)) ||
3498  GetPointer<ternary_expr>(GET_NODE(be->op0)))
3499  {
3501  if(GetPointer<unary_expr>(GET_NODE(be->op0)))
3502  {
3503  type = GetPointer<unary_expr>(GET_NODE(be->op0))->type;
3504  }
3505  else if(GetPointer<binary_expr>(GET_NODE(be->op0)))
3506  {
3507  type = GetPointer<binary_expr>(GET_NODE(be->op0))->type;
3508  }
3509  else if(GetPointer<ternary_expr>(GET_NODE(be->op0)))
3510  {
3511  type = GetPointer<ternary_expr>(GET_NODE(be->op0))->type;
3512  }
3513  else
3514  {
3515  THROW_ERROR("not managed condition");
3516  }
3517 
3518  const auto new_ga =
3519  tree_man->CreateGimpleAssign(type, nullptr, nullptr, be->op0, function_id, srcp_default);
3520  const auto ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
3521  be->op0 = ssa_vd;
3522  block.second->PushBefore(new_ga, *it_los, AppM);
3524  "---adding statement " + GET_NODE(new_ga)->ToString());
3525  changed = true;
3526  }
3527  if(GetPointer<unary_expr>(GET_NODE(be->op1)) || GetPointer<binary_expr>(GET_NODE(be->op1)) ||
3528  GetPointer<ternary_expr>(GET_NODE(be->op1)))
3529  {
3531  if(GetPointer<unary_expr>(GET_NODE(be->op1)))
3532  {
3533  type = GetPointer<unary_expr>(GET_NODE(be->op1))->type;
3534  }
3535  else if(GetPointer<binary_expr>(GET_NODE(be->op1)))
3536  {
3537  type = GetPointer<binary_expr>(GET_NODE(be->op1))->type;
3538  }
3539  else if(GetPointer<ternary_expr>(GET_NODE(be->op1)))
3540  {
3541  type = GetPointer<ternary_expr>(GET_NODE(be->op1))->type;
3542  }
3543  else
3544  {
3545  THROW_ERROR("not managed condition");
3546  }
3547  const auto new_ga =
3548  tree_man->CreateGimpleAssign(type, nullptr, nullptr, be->op1, function_id, srcp_default);
3549  const auto ssa_vd = GetPointer<gimple_assign>(GET_NODE(new_ga))->op0;
3550  be->op1 = ssa_vd;
3551  block.second->PushBefore(new_ga, *it_los, AppM);
3553  "---adding statement " + GET_NODE(new_ga)->ToString());
3554  changed = true;
3555  }
3556  if(changed)
3557  {
3558  restart_analysis = true;
3559  }
3560  }
3561  else if(tree_helper::Size(gc->op0) != 1)
3562  {
3563  const auto bt = tree_man->GetBooleanType();
3564  const auto ne = tree_man->create_unary_operation(bt, gc->op0, srcp_default, nop_expr_K);
3565  const auto nga =
3567  TM->CreateUniqueIntegerCst(1, bt), ne, function_id, srcp_default);
3568  const auto n_vd = GetPointer<gimple_assign>(GET_NODE(nga))->op0;
3569  block.second->PushBefore(nga, *it_los, AppM);
3570  gc->op0 = n_vd;
3572  "---adding statement " + GET_NODE(nga)->ToString());
3573  restart_analysis = true;
3574  }
3576  if(GET_NODE(gc->op0)->get_kind() == lt_expr_K || GET_NODE(gc->op0)->get_kind() == ge_expr_K)
3577  {
3578  const auto le = GetPointer<binary_expr>(GET_NODE(gc->op0));
3580  {
3581  if(GET_NODE(le->op1)->get_kind() == integer_cst_K)
3582  {
3583  if(tree_helper::GetConstValue(le->op1) == 0)
3584  {
3585  const auto cond_op_ga = tree_man->CreateGimpleAssign(le->type, nullptr, nullptr, gc->op0,
3586  function_id, srcp_default);
3587  block.second->PushBefore(cond_op_ga, *it_los, AppM);
3588  const auto cond_ga_var = GetPointerS<gimple_assign>(GET_NODE(cond_op_ga))->op0;
3589  AppM->RegisterTransformation(GetName(), cond_op_ga);
3590  gc->op0 = cond_ga_var;
3591  restart_analysis = true;
3592  }
3593  }
3594  }
3595  }
3596  };
3597  gc0();
3598  }
3599  else if(GET_NODE(*it_los)->get_kind() == gimple_call_K)
3600  {
3601  auto* gc = GetPointer<gimple_call>(GET_NODE(*it_los));
3602  for(auto& arg : gc->args)
3603  {
3604  if(GetPointer<unary_expr>(GET_NODE(arg)) ||
3605  GetPointer<binary_expr>(GET_NODE(arg)))
3606  {
3607  extract_unary_expr(arg, GET_NODE(arg)->get_kind() == addr_expr_K, false);
3608  }
3609  }
3610  }
3611  else if(GET_NODE(*it_los)->get_kind() == gimple_return_K)
3612  {
3613  auto* gr = GetPointer<gimple_return>(GET_NODE(*it_los));
3614  if(gr->op)
3615  {
3616  if(GetPointer<unary_expr>(GET_NODE(gr->op)) || GetPointer<binary_expr>(GET_NODE(gr->op)))
3617  {
3618  extract_expr(gr->op, false);
3619  }
3620  }
3621  else
3622  {
3623  const auto ret_type = tree_helper::GetFunctionReturnType(tn);
3624  if(ret_type)
3625  {
3627  "Control reaches end of non-void function, '" +
3628  tree_helper::print_function_name(TM, fd) + "' will return zero");
3629  gr->op = TM->CreateUniqueIntegerCst(0LL, ret_type);
3630  }
3631  }
3632  }
3634  "<--Examined statement " + GET_NODE(*it_los)->ToString());
3635  it_los++;
3636  }
3637  } while(restart_analysis);
3638 
3639  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined BB" + STR(block.first));
3640  }
3641  function_behavior->UpdateBBVersion();
3643 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
static bool IsSameType(const tree_nodeConstRef &tn0, const tree_nodeConstRef &tn1)
Given two nodes tells if they have same base type (const is not considered: const double == double) ...
T floor_log2(T x)
Given X, an unsigned number, return the largest int Y such that 2**Y <= X. If X is 0...
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
bool reached_max_transformation_limit(const tree_nodeRef &stmt)
check if the max transformation limit has been reached
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
File containing functions and utilities to support the printing of debug messagges.
static bool is_int(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of integer type.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
static bool IsConstant(const tree_nodeConstRef &node)
Return if a tree node is a constant object.
tree_nodeRef op1
The second operand of the binary expression.
Definition: tree_node.hpp:3024
Definition of the class representing a generic C application.
const int output_level
The output level.
#define CASE_DECL_NODES
NOTE that cast_expr is a unary expression but it could not be included in the CASE_UNARY_EXPRESSION b...
Definition: tree_node.hpp:672
std::string GetName() const override
Return the name of this design step.
static bool is_real(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of real type.
static unsigned long long int invert_mod2n(unsigned long long int x, unsigned long long n)
Compute the inverse of X mod 2**n, i.e., find Y such that X * Y is congruent to 1 (mod 2**N)...
tree_nodeRef CreateUnsigned(const tree_nodeConstRef &signed_type) const
Create an unsigned integer type starting from signed type.
mathematical utility function not provided by standard libraries
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
tree_nodeRef GetSizeType() const
create a sizetype builtin type in case it has not already been created, otherwise it returns the one ...
static unsigned long long int align(unsigned long long int address, unsigned long long int alignment)
STL includes.
Definition: memory.cpp:81
static tree_nodeConstRef CGetElements(const tree_nodeConstRef &type)
Given an array or a vector return the element type.
std::list< DefEdge > DefEdgeList
The type of the def edge list.
Definition: tree_node.hpp:3753
exceptions managed by PandA
tree_nodeRef create_binary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op0, const tree_nodeRef &op1, const std::string &srcp, enum kind operation_kind) const
Function used to create a binary expression.
tree_nodeRef op0
The first operand of the binary expression.
Definition: tree_node.hpp:3021
#define LOWPART(x)
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:361
#define min(x, y)
static std::string print_function_name(const tree_managerConstRef &TM, const function_decl *fd)
Return the name of the function in a string.
This class contains the base representation for a generic frontend flow step which works on a single ...
tree_nodeRef expand_MC(const tree_nodeRef &op0, const integer_cst *ic_node, const tree_nodeRef &old_target, const tree_nodeRef &stmt, const blocRef &block, const tree_nodeRef &type_expr, const std::string &srcp_default)
Data structure describing a basic block at tree level.
static unsigned int get_type_index(const tree_managerConstRef &TM, const unsigned int index, long long int &vec_size, bool &is_a_pointer, bool &is_a_function)
Return the treenode index of the type of index.
#define OUTPUT_LEVEL_MINIMUM
minimum debugging print is performed.
tree_nodeRef CreateAddrExpr(const tree_nodeConstRef &tn, const std::string &srcp) const
Create an addr_expr.
redefinition of map to manage ordered/unordered structures
tree_nodeRef create_unary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op, const std::string &srcp, enum kind operation_kind) const
EXPRESSION_TREE_NODES.
#define HIGHPART(x)
tree_nodeRef CreateGimpleAssign(const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, const tree_nodeRef &op, unsigned int function_decl_nid, const std::string &srcp) const
Create gimple assignment.
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define THROW_WARNING(str_expr)
helper function used to throw a warning in a standard way: though it uses PRINT_DBG_MEX, the debug level used is such that the message is always printed
Definition: exceptions.hpp:300
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define max
Definition: backprop.h:17
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
static bool IsUnsignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of unsigned integer type.
const tree_nodeRef get_tree_node_const(unsigned int i) const
Return the reference to the i-th tree_node Constant version of get_tree_node.
static bool IsSignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of integer type.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
#define EXACT_POWER_OF_2_OR_ZERO_P(x)
Test whether a value is zero of a power of two.
T ceil_log2(T x)
Return the smallest n such that 2**n >= X.
static int div_and_round_double_cprop(unsigned long long int lnum_orig, long long int hnum_orig, unsigned long long int lden_orig, unsigned long long int *lquo, long long int *hquo)
static void decode(long long int *words, unsigned long long int *low, long long int *hi)
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
Base class for step of design flow.
tree_nodeRef CreateVectorBooleanType(const unsigned long long number_of_elements) const
Create a vector bool type.
tree_nodeRef GetPointerType(const tree_nodeConstRef &ptd, unsigned long long algn=0) const
Function that creates a pointer type if it is not already present, otherwise it returns the one that ...
static bool IsBooleanType(const tree_nodeConstRef &type)
Return true if the treenode is of bool type.
APInt integer_cst_t
Definition: panda_types.hpp:47
This struct specifies the gimple_assign node (GCC 4.3 tree node).
Definition: tree_node.hpp:3015
#define CASE_QUATERNARY_EXPRESSION
This macro collects all case labels for quaternary_expr objects.
Definition: tree_node.hpp:574
tree_managerRef TM
The tree manager.
Definition: IR_lowering.hpp:88
#define CASE_UNARY_EXPRESSION
This macro collects all case labels for unary_expr objects.
Definition: tree_node.hpp:371
This C++ header file contains common macros for the tree structure.
void division_by_a_constant(const std::pair< unsigned int, blocRef > &block, std::list< tree_nodeRef >::const_iterator &it_los, gimple_assign *ga, const tree_nodeRef &op1, enum kind code1, bool &restart_analysis, const std::string &srcp_default, const std::string &step_name)
#define BASE
tree_nodeRef CreateUniqueIntegerCst(integer_cst_t value, const tree_nodeConstRef &type)
memoization of integer constants
kind
std::pair< tree_nodeRef, unsigned int > DefEdge
The type of the def edge.
Definition: tree_node.hpp:3750
tree_nodeRef GetTreeReindex(const unsigned int i)
Return a tree_reindex wrapping the i-th tree_node.
static bool IsVectorType(const tree_nodeConstRef &type)
Return true if the treenode is a vector.
unsigned offset[NUM_VERTICES+1]
Definition: graph.h:3
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
static void encode(long long int *words, unsigned long long int low, long long int hi)
refcount< const tree_node > tree_nodeConstRef
Definition: tree_node.hpp:213
This class contains the base representation for a generic frontend flow step.
tree_nodeRef expand_smod_pow2(const tree_nodeRef &op0, unsigned long long int d, const tree_nodeRef &stmt, const blocRef &block, const tree_nodeRef &type, const std::string &srcp_default)
Expand signed modulus of OP0 by a power of two D in mode MODE.
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
bool expand_target_mem_ref(target_mem_ref461 *tmr, const tree_nodeRef &stmt, const blocRef &block, const std::string &srcp_default, bool temp_addr)
tree_nodeRef GetBooleanType() const
Function that creates a boolean type if it is not already present, otherwise it returns the one that ...
This struct specifies the block node.
Definition: tree_node.hpp:1820
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
Definition: tree_node.hpp:581
This file collects some utility functions.
tree_nodeRef GetTreeNode(const unsigned int index) const
Return the index-th tree_node (modifiable version)
tree_manipulationRef tree_man
The IR manipulation.
Definition: IR_lowering.hpp:91
tree_nodeRef GetCustomIntegerType(unsigned long long prec, bool unsigned_p) const
create an integer type starting from a given prec
Template definition of refcount.
const unsigned int function_id
The index of the function to be analyzed.
#define CASE_CST_NODES
This macro collects all case labels for cast nodes.
Definition: tree_node.hpp:689
const application_managerRef AppM
The application manager.
struct definition of the type node structures.
Definition: tree_node.hpp:1318
Class specification of the tree_reindex support class.
tree_nodeRef expand_mult_highpart(const tree_nodeRef &op0, unsigned long long int ml, const tree_nodeRef &type_expr, int data_bitsize, const std::list< tree_nodeRef >::const_iterator it_los, const blocRef &block, const std::string &srcp_default)
#define CASE_FAKE_NODES
This macro collects all case labels for fake or empty nodes.
Definition: tree_node.hpp:635
Decompose some complex gimple statements into set of simple operations.
tree_nodeRef expand_sdiv_pow2(const tree_nodeRef &op0, unsigned long long int d, const tree_nodeRef &stmt, const blocRef &block, const tree_nodeRef &type, const std::string &srcp_default)
Expand signed division of OP0 by a power of two D in mode MODE.
tree_nodeRef array_ref_lowering(array_ref *AR, const std::string &srcp_default, std::pair< unsigned int, blocRef > block, std::list< tree_nodeRef >::const_iterator it_los, bool temp_addr)
tree_nodeRef CreateNopExpr(const tree_nodeConstRef &operand, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, unsigned int function_decl_nid) const
Create a nop_expr to perform a conversion.
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
static unsigned long long int choose_multiplier(unsigned long long int d, int n, int precision, unsigned long long int *multiplier_ptr, int *post_shift_ptr, int *lgup_ptr)
this class is used to manage the command-line or XML options.
#define CASE_CPP_NODES
This macro collects all case labels for cpp nodes.
Definition: tree_node.hpp:644
static unsigned int get_base_index(const tree_managerConstRef &TM, const unsigned int index)
Retrun the base address of a memory access.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
Definition: tree_node.hpp:212
x
Return the smallest n such that 2^n >= _x.
#define CASE_GIMPLE_NODES
This macro collects all cases labels for gimple nodes.
Definition: tree_node.hpp:700
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
#define OUTPUT_LEVEL_VERBOSE
verbose debugging print is performed.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
DesignFlowStep_Status InternalExec() override
traverse the data structure to simplify and make more homogeneous as possible.
static tree_nodeConstRef GetFunctionReturnType(const tree_nodeConstRef &function, bool void_as_null=true)
Return the return type of a function.
#define CASE_TERNARY_EXPRESSION
This macro collects all case labels for ternary_expr objects.
Definition: tree_node.hpp:550
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
static bool IsRealType(const tree_nodeConstRef &type)
Return true if the treenode is of real type.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
int sl
Definition: adpcm.c:105
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
Definition: tree_node.hpp:610
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:52 for PandA-2024.02 by doxygen 1.8.13