PandA-2024.02
Bit_Value_opt.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  */
33 
45 // Header include
46 #include "Bit_Value_opt.hpp"
47 
48 #include "Range.hpp"
49 #include "bit_lattice.hpp"
50 
52 #include "config_HAVE_FROM_DISCREPANCY_BUILT.hpp"
53 
54 // Behavior include
55 #include "application_manager.hpp"
56 #include "behavioral_helper.hpp"
57 #include "call_graph.hpp"
58 #include "call_graph_manager.hpp"
59 #include "function_behavior.hpp"
60 
62 #include "Discrepancy.hpp"
63 
64 // Parameter include
65 #include "Parameter.hpp"
66 
68 #include "design_flow_graph.hpp"
69 #include "design_flow_manager.hpp"
71 
72 // STD include
73 #include <boost/range/adaptor/reversed.hpp>
74 #include <cmath>
75 #include <fstream>
76 #include <string>
77 
78 // Tree include
79 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
80 #include "ext_tree_node.hpp"
81 #include "hls_device.hpp"
82 #include "hls_manager.hpp"
83 #include "math_function.hpp" // for ceil_pow2
84 #include "string_manipulation.hpp" // for GET_CLASS
85 #include "tree_basic_block.hpp"
86 #include "tree_helper.hpp"
87 #include "tree_manager.hpp"
88 #include "tree_manipulation.hpp"
89 #include "tree_node.hpp"
90 #include "tree_reindex.hpp"
91 #include "utility.hpp"
92 
93 #define DEBUG_CALLSITE (__FILE__ + std::string(":") + STR(__LINE__))
94 
96  unsigned int _function_id, const DesignFlowManagerConstRef _design_flow_manager)
97  : FunctionFrontendFlowStep(_AppM, _function_id, BIT_VALUE_OPT, _design_flow_manager, _parameters), modified(false)
98 {
99  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
100 }
101 
103 
106 {
108  switch(relationship_type)
109  {
111  {
112  if(!parameters->getOption<int>(OPT_gcc_openmp_simd))
113  {
114  relationships.insert(std::make_pair(BIT_VALUE, SAME_FUNCTION));
115  if(parameters->isOption(OPT_bitvalue_ipa) && parameters->getOption<bool>(OPT_bitvalue_ipa))
116  {
117  relationships.insert(std::make_pair(BIT_VALUE_IPA, WHOLE_APPLICATION));
118  }
119  }
120  relationships.insert(std::make_pair(BIT_VALUE_OPT, CALLED_FUNCTIONS));
121  relationships.insert(std::make_pair(PARM2SSA, SAME_FUNCTION));
122  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
123  break;
124  }
126  {
127  break;
128  }
130  {
132  {
133  if(!parameters->getOption<int>(OPT_gcc_openmp_simd))
134  {
135  relationships.insert(std::make_pair(BIT_VALUE, SAME_FUNCTION));
136  }
137  }
138  break;
139  }
140  default:
141  THROW_UNREACHABLE("");
142  }
143  return relationships;
144 }
145 
147 {
149 }
150 
152 {
153  if(parameters->IsParameter("bitvalue-opt") && !parameters->GetParameter<unsigned int>("bitvalue-opt"))
154  {
156  }
157  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " --------- BIT_VALUE_OPT ----------");
158  const auto TM = AppM->get_tree_manager();
159  const auto IRman = tree_manipulationRef(new tree_manipulation(TM, parameters, AppM));
160 
161  const auto tn = TM->CGetTreeNode(function_id);
162  // tree_nodeRef Scpe = TM->GetTreeReindex(function_id);
163  const auto fd = GetPointerS<const function_decl>(tn);
164  THROW_ASSERT(fd && fd->body, "Node is not a function or it hasn't a body");
165  modified = false;
166  optimize(fd, TM, IRman);
167  modified ? function_behavior->UpdateBBVersion() : 0;
169 }
170 
172 {
173  if(tree_helper::IsRealType(op_ssa->type))
174  {
175  return;
176  }
177  const auto nbit = op_ssa->bit_values.size();
178  THROW_ASSERT(!op_ssa->bit_values.empty(), "unexpected condition");
179  const auto nbitType = BitLatticeManipulator::Size(op_ssa->type);
180  if(nbit != nbitType)
181  {
182  const bool isSigned = tree_helper::IsSignedIntegerType(op_ssa->type);
183  if(isSigned)
184  {
185  RangeRef constraintRange(
186  new Range(Regular, static_cast<Range::bw_t>(nbitType), -(1ll << (nbit - 1)), (1ll << (nbit - 1)) - 1));
187  if(op_ssa->range)
188  {
189  if(op_ssa->range->getSpan() < constraintRange->getSpan())
190  {
191  return;
192  }
193  }
194  else
195  {
196  op_ssa->range = constraintRange;
197  }
198  op_ssa->min = TM->CreateUniqueIntegerCst(-(1ll << (nbit - 1)), op_ssa->type);
199  op_ssa->max = TM->CreateUniqueIntegerCst((1ll << (nbit - 1)) - 1, op_ssa->type);
200  }
201  else
202  {
203  RangeRef constraintRange(new Range(Regular, static_cast<Range::bw_t>(nbitType), 0, (1ll << nbit) - 1));
204  if(op_ssa->range)
205  {
206  if(op_ssa->range->getSpan() < constraintRange->getSpan())
207  {
208  return;
209  }
210  }
211  else
212  {
213  op_ssa->range = constraintRange;
214  }
215  op_ssa->min = TM->CreateUniqueIntegerCst(0, op_ssa->type);
216  op_ssa->max = TM->CreateUniqueIntegerCst((1ll << nbit) - 1, op_ssa->type);
217  }
218  // std::cerr<<"var " << op_ssa->ToString()<<" ";
219  // std::cerr << "min " <<op_ssa->min->ToString() << " max " <<op_ssa->max->ToString()<<"\n";
220  // std::cerr << "nbit "<< nbit << " nbitType " << nbitType <<"\n";
221  }
222 }
223 
224 static integer_cst_t convert_bitvalue_to_integer_cst(const std::string& bit_values, tree_managerRef TM,
225  unsigned int var_id)
226 {
227  integer_cst_t const_value = 0;
228  size_t index_val = 0;
229  for(auto current_el : boost::adaptors::reverse(bit_values))
230  {
231  if(current_el == '1')
232  {
233  const_value |= integer_cst_t(1) << index_val;
234  }
235  ++index_val;
236  }
238  const auto is_signed = tree_helper::is_int(TM, var_id);
239  if(is_signed && bit_values[0] == '1')
240  {
241  const_value |= integer_cst_t(-1) << index_val;
242  THROW_ASSERT(const_value < 0, "");
243  }
244  return const_value;
245 }
246 
247 static bool is_bit_values_constant(const std::string& bit_values)
248 {
249  bool is_constant = bit_values.size() != 0;
250  for(auto current_el : bit_values)
251  {
252  if(current_el == 'U')
253  {
254  is_constant = false;
255  break;
256  }
257  }
258  return is_constant;
259 }
260 
262  const std::string
263 #if HAVE_ASSERTS
264  callSiteString
265 #endif
266 )
267 {
268  THROW_ASSERT(tree_helper::Size(old_val) >= tree_helper::Size(new_val),
269  "unexpected case " + STR(old_val) + " " + STR(new_val) + " old-bw=" + STR(tree_helper::Size(old_val)) +
270  " new-bw=" + STR(tree_helper::Size(new_val)) + " from " + callSiteString);
271  const auto StmtUses = ssa->CGetUseStmts();
272  for(const auto& use : StmtUses)
273  {
274  if(!AppM->ApplyNewTransformation())
275  {
276  break;
277  }
278  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---replace var usage before: " + use.first->ToString());
279  TM->ReplaceTreeNode(use.first, old_val, new_val);
280  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---replace var usage after: " + use.first->ToString());
281  modified = true;
282  AppM->RegisterTransformation(GetName(), use.first);
283  }
284 }
285 
287 {
288  THROW_ASSERT(GetPointer<const HLS_manager>(AppM)->get_HLS_device(), "unexpected condition");
289  const auto hls_d = GetPointerS<const HLS_manager>(AppM)->get_HLS_device();
290  THROW_ASSERT(hls_d->has_parameter("max_lut_size"), "unexpected condition");
291  const auto max_lut_size = hls_d->get_parameter<size_t>("max_lut_size");
292 
294  for(const auto& parm_decl_node : fd->list_of_args)
295  {
296  const unsigned int p_decl_id = AppM->getSSAFromParm(function_id, GET_INDEX_CONST_NODE(parm_decl_node));
297  if(tree_helper::is_real(TM, p_decl_id) || tree_helper::is_a_complex(TM, p_decl_id))
298  {
300  "---Parameter not supported " + TM->get_tree_node_const(p_decl_id)->ToString());
301  continue;
302  }
303  if(AppM->ApplyNewTransformation())
304  {
305  const auto parm_type = tree_helper::CGetType(parm_decl_node);
306  const auto parmssa = TM->CGetTreeNode(p_decl_id);
307  const auto p = GetPointer<const ssa_name>(parmssa);
308  THROW_ASSERT(!p->bit_values.empty(), "unexpected condition");
309  const auto is_constant = is_bit_values_constant(p->bit_values);
310  if(is_constant)
311  {
312  const auto ull_value = convert_bitvalue_to_integer_cst(p->bit_values, TM, p_decl_id);
313  const auto val = TM->CreateUniqueIntegerCst(ull_value, parm_type);
314  propagateValue(p, TM, TM->CGetTreeReindex(p_decl_id), val, DEBUG_CALLSITE);
315  }
316  }
317  }
318  auto sl = GetPointerS<statement_list>(GET_NODE(fd->body));
319  THROW_ASSERT(sl, "Body is not a statement_list");
320  for(const auto& bb_pair : sl->list_of_bloc)
321  {
322  const auto B = bb_pair.second;
323  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining BB" + STR(B->number));
324  const auto list_of_stmt = B->CGetStmtList();
325  for(const auto& stmt : list_of_stmt)
326  {
327  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining statement " + GET_NODE(stmt)->ToString());
328  if(!AppM->ApplyNewTransformation())
329  {
331  "<--Skipped because reached limit of CFG transformations");
332  break;
333  }
334  if(GetPointerS<gimple_node>(GET_NODE(stmt))->keep)
335  {
337  "<--Skipped because the statement has been annotated with the keep tag");
338  continue;
339  }
340  if(GET_NODE(stmt)->get_kind() == gimple_assign_K)
341  {
342  auto ga = GetPointerS<gimple_assign>(GET_NODE(stmt));
343  unsigned int output_uid = GET_INDEX_CONST_NODE(ga->op0);
344  auto ssa = GetPointer<ssa_name>(GET_NODE(ga->op0));
345  if(ssa && !ssa->bit_values.empty() && !ssa->CGetUseStmts().empty())
346  {
347  auto condPropageValue = [&](tree_nodeRef val, std::string debug_callsite) {
348  auto bw_op1 = tree_helper::Size(val);
349  auto bw_op0 = tree_helper::Size(ga->op0);
350  if(bw_op1 <= bw_op0)
351  {
352  propagateValue(ssa, TM, ga->op0, val, debug_callsite);
353  }
354  else
355  {
356  const auto srcp = ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
357  const auto& val_type = ssa->type;
358  const auto val_type_bw = tree_helper::Size(ssa->type);
359  const auto shift_offset =
360  TM->CreateUniqueIntegerCst(static_cast<long long>(val_type_bw - bw_op0), val_type);
361  const auto shl_expr =
362  IRman->create_binary_operation(val_type, val, shift_offset, srcp, lshift_expr_K);
363  const auto shl =
364  IRman->CreateGimpleAssign(val_type, nullptr, nullptr, shl_expr, function_id, srcp);
365  const auto svar = GetPointerS<const gimple_assign>(GET_CONST_NODE(shl))->op0;
367  B->PushBefore(shl, stmt, AppM);
368  const auto shr_expr =
369  IRman->create_binary_operation(val_type, svar, shift_offset, srcp, rshift_expr_K);
370  const auto op0_ga =
371  IRman->CreateGimpleAssign(ssa->type, ssa->min, ssa->max, shr_expr, function_id, srcp);
373  B->PushBefore(op0_ga, stmt, AppM);
374  auto op0_ga_var = GetPointerS<gimple_assign>(GET_CONST_NODE(op0_ga))->op0;
375  auto op0_ga_varSSA = GetPointerS<ssa_name>(GET_CONST_NODE(op0_ga_var));
376  op0_ga_varSSA->bit_values = ssa->bit_values;
377  constrainSSA(op0_ga_varSSA, TM);
378  propagateValue(ssa, TM, ga->op0, op0_ga_var, DEBUG_CALLSITE);
379  }
380  };
381  if(tree_helper::is_real(TM, output_uid))
382  {
383  auto real_BVO = [&] {
384  if(GET_NODE(ga->op1)->get_kind() == cond_expr_K)
385  {
386  const auto me = GetPointerS<cond_expr>(GET_NODE(ga->op1));
387  const auto op0 = GET_NODE(me->op1);
388  const auto op1 = GET_NODE(me->op2);
389  const auto condition = GET_NODE(me->op0);
390  if(op0 == op1)
391  {
392  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Cond expr with equal operands");
393  propagateValue(ssa, TM, ga->op0, me->op1, DEBUG_CALLSITE);
394  }
395  else if(GET_CONST_NODE(me->op0)->get_kind() == integer_cst_K)
396  {
398  "---Cond expr with constant condition");
399  const auto new_val = tree_helper::GetConstValue(me->op0) ? me->op1 : me->op2;
400  propagateValue(ssa, TM, ga->op0, new_val, DEBUG_CALLSITE);
401  }
402  else
403  {
404  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---nothing more can be done");
405  }
406  }
407  else if(GetPointer<cst_node>(GET_NODE(ga->op1)))
408  {
409  propagateValue(ssa, TM, ga->op0, ga->op1, DEBUG_CALLSITE);
410  }
411  else if(GetPointer<ssa_name>(GET_NODE(ga->op1)))
412  {
413  propagateValue(ssa, TM, ga->op0, ga->op1, DEBUG_CALLSITE);
414  }
415  else if(GET_NODE(ga->op1)->get_kind() == view_convert_expr_K)
416  {
417  auto vce = GetPointerS<view_convert_expr>(GET_NODE(ga->op1));
418  if(GetPointer<cst_node>(GET_NODE(vce->op)))
419  {
420  if(GET_NODE(vce->op)->get_kind() == integer_cst_K)
421  {
422  const auto cst_val = tree_helper::GetConstValue(vce->op);
423  auto bitwidth_op = BitLatticeManipulator::Size(vce->type);
424  tree_nodeRef val;
425  if(bitwidth_op == 32)
426  {
427  union
428  {
429  float dest;
430  int source;
431  } __conv_union = {};
432  __conv_union.source = static_cast<int>(cst_val);
433  val = TM->CreateUniqueRealCst(static_cast<long double>(__conv_union.dest), vce->type);
434  }
435  else if(bitwidth_op == 64)
436  {
437  union
438  {
439  double dest;
440  long long int source;
441  } __conv_union = {};
442  __conv_union.source = static_cast<long long int>(cst_val);
443  val = TM->CreateUniqueRealCst(static_cast<long double>(__conv_union.dest), vce->type);
444  }
445  else
446  {
447  THROW_ERROR("not supported floating point bitwidth");
448  }
449  propagateValue(ssa, TM, ga->op0, val, DEBUG_CALLSITE);
450  }
451  }
452  }
453  else
454  {
456  "---real variables not considered: " + STR(GET_INDEX_CONST_NODE(ga->op0)));
457  }
459  "<--Examined statement " + GET_NODE(stmt)->ToString());
460  };
461  real_BVO();
462  continue;
463  }
464  if(tree_helper::is_a_complex(TM, output_uid))
465  {
467  "---complex variables not considered: " + STR(GET_INDEX_CONST_NODE(ga->op0)));
469  "<--Examined statement " + GET_NODE(stmt)->ToString());
470  continue;
471  }
472  if(tree_helper::is_a_vector(TM, output_uid))
473  {
475  "---vector variables not considered: " + STR(GET_INDEX_CONST_NODE(ga->op0)));
477  "<--Examined statement " + GET_NODE(stmt)->ToString());
478  continue;
479  }
480  if((GetPointer<integer_cst>(GET_NODE(ga->op1)) || GetPointer<real_cst>(GET_NODE(ga->op1))) &&
482  {
484  "---constant pointer value assignments not considered: " +
485  STR(GET_INDEX_CONST_NODE(ga->op0)));
487  "<--Examined statement " + GET_NODE(stmt)->ToString());
488  continue;
489  }
490  if(GetPointer<call_expr>(GET_NODE(ga->op1)) and ga->vdef)
491  {
493  "---calls with side effects cannot be optimized" + STR(GET_INDEX_CONST_NODE(ga->op1)));
495  "<--Examined statement " + GET_NODE(stmt)->ToString());
496  continue;
497  }
498  if(GetPointer<addr_expr>(GET_NODE(ga->op1)))
499  {
501  "---addr_expr cannot be optimized" + STR(GET_INDEX_CONST_NODE(ga->op1)));
503  "<--Examined statement " + GET_NODE(stmt)->ToString());
504  continue;
505  }
506  auto ga_BVO = [&] {
507  const auto ga_op_type = tree_helper::CGetType(ga->op0);
508  const auto Scpe = TM->GetTreeReindex(function_id);
509  const auto& bit_values = ssa->bit_values;
510  auto is_constant = is_bit_values_constant(bit_values) && !tree_helper::IsPointerType(ga->op1);
511  auto rel_expr_BVO = [&] {
512  auto* me = GetPointer<binary_expr>(GET_NODE(ga->op1));
513  const auto op0 = GET_CONST_NODE(me->op0);
514  const auto op1 = GET_CONST_NODE(me->op1);
515 
516  std::string s0, s1;
517  const auto is_op0_ssa = GetPointer<const ssa_name>(op0);
518  const auto is_op1_ssa = GetPointer<const ssa_name>(op1);
519  if(is_op0_ssa)
520  {
521  s0 = GetPointerS<const ssa_name>(op0)->bit_values;
522  if(s0.empty())
523  {
525  "---Skipped because bitvalue of op0 is empty");
526  return;
527  }
528  }
529  else
530  {
531  THROW_ASSERT(op0->get_kind() == integer_cst_K, "unexpected condition");
532  }
533  if(is_op1_ssa)
534  {
535  s1 = GetPointerS<const ssa_name>(op1)->bit_values;
536  if(s1.empty())
537  {
539  "---Skipped because bitvalue of op1 is empty");
540  return;
541  }
542  }
543  else
544  {
545  THROW_ASSERT(op1->get_kind() == integer_cst_K, "unexpected condition");
546  }
547  if(!is_op0_ssa && !is_op1_ssa)
548  {
549  return;
550  }
551 
552  unsigned int trailing_zero = 0;
553  if(!is_op0_ssa)
554  {
555  const auto uvalue = tree_helper::GetConstValue(me->op0, false);
556  s0 = convert_to_binary(uvalue, BitLatticeManipulator::Size(me->op0));
557  }
558  if(!is_op1_ssa)
559  {
560  const auto uvalue = tree_helper::GetConstValue(me->op1, false);
561  s1 = convert_to_binary(uvalue, BitLatticeManipulator::Size(me->op1));
562  }
563 
564  for(auto s0it = s0.rbegin(), s1it = s1.rbegin(), s0end = s0.rend(), s1end = s1.rend();
565  s0it != s0end && s1it != s1end; ++s0it, ++s1it)
566  {
567  if((*s0it == *s1it && (*s1it == '0' || *s1it == '1')) || *s0it == 'X' || *s1it == 'X')
568  {
569  ++trailing_zero;
570  }
571  else
572  {
573  break;
574  }
575  }
576  auto min_size = std::min(s0.size(), s1.size());
577  if(trailing_zero < min_size && trailing_zero)
578  {
580  "-->Bit Value Opt: " + std::string(GET_NODE(ga->op1)->get_kind_text()) +
581  " optimized, nbits = " + STR(trailing_zero));
583  modified = true;
584  AppM->RegisterTransformation(GetName(), stmt);
585  const auto srcp_default =
586  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
587  const auto op0_op_type = tree_helper::CGetType(op0);
588  const auto op1_op_type = tree_helper::CGetType(op1);
589 
590  if(is_op0_ssa)
591  {
592  const auto op0_const_node =
593  TM->CreateUniqueIntegerCst(static_cast<long long int>(trailing_zero), op0_op_type);
594  const auto op0_expr = IRman->create_binary_operation(op0_op_type, me->op0, op0_const_node,
595  srcp_default, rshift_expr_K);
596  const auto op0_ga = IRman->CreateGimpleAssign(op0_op_type, nullptr, nullptr, op0_expr,
597  function_id, srcp_default);
599  B->PushBefore(op0_ga, stmt, AppM);
600  const auto op0_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(op0_ga))->op0;
601  TM->ReplaceTreeNode(stmt, me->op0, op0_ga_var);
603  auto op0_ssa = GetPointer<ssa_name>(GET_NODE(op0_ga_var));
604  THROW_ASSERT(s0.size() - trailing_zero > 0, "unexpected condition");
605  op0_ssa->bit_values = s0.substr(0, s0.size() - trailing_zero);
606  constrainSSA(op0_ssa, TM);
607  }
608  else
609  {
610  const auto cst_val =
612  TM->ReplaceTreeNode(stmt, me->op0,
613  TM->CreateUniqueIntegerCst(cst_val >> trailing_zero, op0_op_type));
614  }
615  if(is_op1_ssa)
616  {
617  const auto op1_const_node =
618  TM->CreateUniqueIntegerCst(static_cast<long long int>(trailing_zero), op1_op_type);
619  const auto op1_expr = IRman->create_binary_operation(op1_op_type, me->op1, op1_const_node,
620  srcp_default, rshift_expr_K);
621  const auto op1_ga = IRman->CreateGimpleAssign(op1_op_type, nullptr, nullptr, op1_expr,
622  function_id, srcp_default);
624  B->PushBefore(op1_ga, stmt, AppM);
625  const auto op1_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(op1_ga))->op0;
626  TM->ReplaceTreeNode(stmt, me->op1, op1_ga_var);
628  const auto op1_ssa = GetPointer<ssa_name>(GET_NODE(op1_ga_var));
629  THROW_ASSERT(s1.size() - trailing_zero > 0, "unexpected condition");
630  op1_ssa->bit_values = s1.substr(0, s1.size() - trailing_zero);
631  constrainSSA(op1_ssa, TM);
632  }
633  else
634  {
635  const auto cst_val =
637  TM->ReplaceTreeNode(stmt, me->op1,
638  TM->CreateUniqueIntegerCst(cst_val >> trailing_zero, op1_op_type));
639  }
640  }
641  };
642 
643  if(is_constant)
644  {
645  auto c_BVO = [&] {
647  "---Left part is constant " + bit_values);
648  tree_nodeRef val;
649  if(GET_CONST_NODE(ga->op1)->get_kind() == integer_cst_K &&
650  tree_helper::Size(ga->op1) <= bit_values.size())
651  {
652  val = ga->op1;
653  }
654  else
655  {
656  const auto const_value = convert_bitvalue_to_integer_cst(bit_values, TM, output_uid);
657  val = TM->CreateUniqueIntegerCst(const_value, ga_op_type);
658  }
659  if(AppM->ApplyNewTransformation())
660  {
661  if(GET_CONST_NODE(ga->op0)->get_kind() == ssa_name_K && ga->predicate)
662  {
663  if(GET_CONST_NODE(ga->predicate)->get_kind() != integer_cst_K ||
664  tree_helper::GetConstValue(ga->predicate) != 0)
665  {
666  const auto bt = IRman->GetBooleanType();
667  const auto zeroval = TM->CreateUniqueIntegerCst(static_cast<long long int>(0), bt);
668  TM->ReplaceTreeNode(stmt, ga->predicate, zeroval);
670  "---zero predicated statement: " + stmt->ToString());
671  modified = true;
672  AppM->RegisterTransformation(GetName(), stmt);
673  }
674  }
675  }
676  condPropageValue(val, DEBUG_CALLSITE);
677  };
678  c_BVO();
679  }
680  else if(GetPointer<const cst_node>(GET_CONST_NODE(ga->op1)))
681  {
682  propagateValue(ssa, TM, ga->op0, ga->op1, DEBUG_CALLSITE);
683  }
684  else if(GET_CONST_NODE(ga->op1)->get_kind() == ssa_name_K)
685  {
686  auto ssa_name_BVO = [&] {
687  if(!ssa->bit_values.empty() && ssa->bit_values.at(0) == '0' && ssa->bit_values.size() <= 64)
688  {
689  const auto srcp_default =
690  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
691  const auto bit_mask_constant_node =
692  TM->CreateUniqueIntegerCst((1LL << (ssa->bit_values.size() - 1)) - 1, ssa->type);
693  const auto band_expr = IRman->create_binary_operation(
694  ssa->type, ga->op1, bit_mask_constant_node, srcp_default, bit_and_expr_K);
696  "---replace ssa usage before: " + stmt->ToString());
697  TM->ReplaceTreeNode(stmt, ga->op1, band_expr);
699  "---replace ssa usage after: " + stmt->ToString());
700  modified = true;
701  ga->keep = true;
702  }
703  else
704  {
705  auto bw_op1 = tree_helper::Size(ga->op1);
706  auto bw_op0 = tree_helper::Size(ga->op0);
707 
708  if(bw_op1 <= bw_op0)
709  {
710  propagateValue(ssa, TM, ga->op0, ga->op1, DEBUG_CALLSITE);
711  }
712  }
713  };
714  ssa_name_BVO();
715  }
716  else if(GET_CONST_NODE(ga->op1)->get_kind() == mult_expr_K ||
717  GET_CONST_NODE(ga->op1)->get_kind() == widen_mult_expr_K)
718  {
719  auto mult_expr_BVO = [&] {
720  const auto me = GetPointer<const binary_expr>(GET_CONST_NODE(ga->op1));
721  const auto op0 = GET_CONST_NODE(me->op0);
722  const auto op1 = GET_CONST_NODE(me->op1);
723  bool squareP = GET_INDEX_CONST_NODE(me->op0) == GET_INDEX_CONST_NODE(me->op1);
724  const auto data_bitsize_in0 = ceil_pow2(BitLatticeManipulator::Size(op0));
725  const auto data_bitsize_in1 = ceil_pow2(BitLatticeManipulator::Size(op1));
726  const auto isSigned = tree_helper::is_int(TM, GET_INDEX_CONST_NODE(ga_op_type));
727  if(!isSigned && GET_CONST_NODE(ga->op1)->get_kind() == mult_expr_K &&
728  (data_bitsize_in0 == 1 || data_bitsize_in1 == 1))
729  {
730  modified = true;
731  AppM->RegisterTransformation(GetName(), stmt);
732  const auto constNE0 = TM->CreateUniqueIntegerCst(0LL, ga_op_type);
733  const auto srcp_default =
734  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
735  const auto bt = IRman->GetBooleanType();
736  const auto cond_op0 = IRman->create_binary_operation(
737  bt, data_bitsize_in0 == 1 ? me->op0 : me->op1, constNE0, srcp_default, ne_expr_K);
738  const auto op0_ga = IRman->CreateGimpleAssign(bt, TM->CreateUniqueIntegerCst(0LL, bt),
739  TM->CreateUniqueIntegerCst(1LL, bt), cond_op0,
740  function_id, srcp_default);
742  B->PushBefore(op0_ga, stmt, AppM);
743  const auto op0_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(op0_ga))->op0;
744  const auto const0 = TM->CreateUniqueIntegerCst(0LL, ga_op_type);
745  const auto cond_op = IRman->create_ternary_operation(
746  ga_op_type, op0_ga_var, data_bitsize_in1 == 1 ? me->op0 : me->op1, const0, srcp_default,
747  cond_expr_K);
748  THROW_ASSERT(tree_helper::CGetType(GetPointer<const gimple_assign>(stmt)->op0)->index ==
749  GET_INDEX_CONST_NODE(ga_op_type),
750  "");
752  "---Replacing " + STR(ga->op1) + " with " + STR(cond_op) + " in " +
753  STR(stmt));
754  TM->ReplaceTreeNode(stmt, ga->op1, cond_op);
756  "---replace expression with a cond_expr: " + stmt->ToString());
757  }
758  else
759  {
760  unsigned int trailing_zero_op0 = 0;
761  unsigned int trailing_zero_op1 = 0;
762  std::string bit_values_op0;
763  std::string bit_values_op1;
764  bool is_op0_ssa = op0->get_kind() == ssa_name_K;
765  bool is_op1_ssa = op1->get_kind() == ssa_name_K;
766  if(is_op0_ssa)
767  {
768  bit_values_op0 = GetPointer<const ssa_name>(op0)->bit_values;
769  if(bit_values_op0.empty())
770  {
772  "---Skipped because bitvalue of op0 is empty");
773  return;
774  }
775  for(auto current_el : boost::adaptors::reverse(bit_values_op0))
776  {
777  if(current_el == '0' || current_el == 'X')
778  {
779  ++trailing_zero_op0;
780  }
781  else
782  {
783  break;
784  }
785  }
786  }
787  else
788  {
789  THROW_ASSERT(op0->get_kind() == integer_cst_K, "unexpected case");
790  const auto cst_val = tree_helper::GetConstValue(op0, false);
791  bit_values_op0 = convert_to_binary(cst_val, tree_helper::Size(op0));
792  for(unsigned int index = 0; index < bit_values_op0.size() && cst_val != 0; ++index)
793  {
794  if(cst_val & (integer_cst_t(1) << index))
795  {
796  break;
797  }
798  else
799  {
800  ++trailing_zero_op0;
801  }
802  }
803  }
804  if(is_op1_ssa)
805  {
806  bit_values_op1 = GetPointer<const ssa_name>(op1)->bit_values;
807  if(bit_values_op1.empty())
808  {
810  "---Skipped because bitvalue of op1 is empty");
811  return;
812  }
813  for(auto current_el : boost::adaptors::reverse(bit_values_op1))
814  {
815  if(current_el == '0' || current_el == 'X')
816  {
817  ++trailing_zero_op1;
818  }
819  else
820  {
821  break;
822  }
823  }
824  }
825  else
826  {
827  THROW_ASSERT(op1->get_kind() == integer_cst_K, "unexpected case");
828  const auto cst_val = tree_helper::GetConstValue(op1, false);
829  bit_values_op1 = convert_to_binary(cst_val, tree_helper::Size(op1));
830  for(unsigned int index = 0; index < bit_values_op1.size() && cst_val != 0; ++index)
831  {
832  if(cst_val & (integer_cst_t(1) << index))
833  {
834  break;
835  }
836  else
837  {
838  ++trailing_zero_op1;
839  }
840  }
841  }
842  if(trailing_zero_op0 != 0 || trailing_zero_op1 != 0)
843  {
844  modified = true;
845  AppM->RegisterTransformation(GetName(), stmt);
847  "-->Bit Value Opt: mult_expr/widen_mult_expr optimized, nbits = " +
848  STR(trailing_zero_op0 + trailing_zero_op1));
850  const auto srcp_default =
851  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
852  if(trailing_zero_op0 != 0)
853  {
854  const auto op0_type = tree_helper::CGetType(op0);
855  const auto op0_const_node = TM->CreateUniqueIntegerCst(
856  static_cast<long long int>(trailing_zero_op0), op0_type);
857  const auto op0_expr = IRman->create_binary_operation(op0_type, me->op0, op0_const_node,
858  srcp_default, rshift_expr_K);
859  const auto op0_ga = IRman->CreateGimpleAssign(op0_type, nullptr, nullptr, op0_expr,
860  function_id, srcp_default);
862  B->PushBefore(op0_ga, stmt, AppM);
863  const auto op0_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(op0_ga))->op0;
864  TM->ReplaceTreeNode(stmt, me->op0, op0_ga_var);
866  if(is_op0_ssa)
867  {
868  auto op0_ssa = GetPointer<ssa_name>(GET_NODE(op0_ga_var));
869  THROW_ASSERT(bit_values_op0.size() - trailing_zero_op0 > 0, "unexpected condition");
870  op0_ssa->bit_values =
871  bit_values_op0.substr(0, bit_values_op0.size() - trailing_zero_op0);
872  constrainSSA(op0_ssa, TM);
873  }
874  }
875  if(trailing_zero_op1 != 0 && !squareP)
876  {
877  const auto op1_type = tree_helper::CGetType(op1);
878  const auto op1_const_node = TM->CreateUniqueIntegerCst(
879  static_cast<long long int>(trailing_zero_op1), op1_type);
880  const auto op1_expr = IRman->create_binary_operation(op1_type, me->op1, op1_const_node,
881  srcp_default, rshift_expr_K);
882  const auto op1_ga = IRman->CreateGimpleAssign(op1_type, tree_nodeRef(), tree_nodeRef(),
883  op1_expr, function_id, srcp_default);
885  B->PushBefore(op1_ga, stmt, AppM);
886  const auto op1_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(op1_ga))->op0;
887  TM->ReplaceTreeNode(stmt, me->op1, op1_ga_var);
889  if(is_op1_ssa)
890  {
891  auto* op1_ssa = GetPointer<ssa_name>(GET_NODE(op1_ga_var));
892  THROW_ASSERT(bit_values_op1.size() - trailing_zero_op1 > 0, "unexpected condition");
893  op1_ssa->bit_values =
894  bit_values_op1.substr(0, bit_values_op1.size() - trailing_zero_op1);
895  constrainSSA(op1_ssa, TM);
896  }
897  }
898 
899  const auto ssa_vd = IRman->create_ssa_name(nullptr, ga_op_type, nullptr, nullptr);
900  auto sn = GetPointer<ssa_name>(GET_NODE(ssa_vd));
902  THROW_ASSERT(ssa->bit_values.size() - trailing_zero_op0 - trailing_zero_op1 > 0,
903  "unexpected condition");
904  sn->bit_values = ssa->bit_values.substr(0, ssa->bit_values.size() - trailing_zero_op0 -
905  trailing_zero_op1);
906  constrainSSA(sn, TM);
907  const auto op_const_node =
908  TM->CreateUniqueIntegerCst((trailing_zero_op0 + trailing_zero_op1), ga_op_type);
909  const auto op_expr = IRman->create_binary_operation(ga_op_type, ssa_vd, op_const_node,
910  srcp_default, lshift_expr_K);
911  const auto curr_ga = IRman->CreateGimpleAssign(ga_op_type, ssa->min, ssa->max, op_expr,
912  function_id, srcp_default);
913  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(curr_ga));
914  TM->ReplaceTreeNode(
915  curr_ga, GetPointer<const gimple_assign>(GET_CONST_NODE(curr_ga))->op0, ga->op0);
916  TM->ReplaceTreeNode(stmt, ga->op0, ssa_vd);
917  B->PushAfter(curr_ga, stmt, AppM);
919  }
920  }
921  };
922  mult_expr_BVO();
923  }
924  else if(GET_CONST_NODE(ga->op1)->get_kind() == plus_expr_K ||
925  GET_CONST_NODE(ga->op1)->get_kind() == minus_expr_K)
926  {
927  auto plus_minus_BVO = [&] {
928  const auto me = GetPointer<const binary_expr>(GET_CONST_NODE(ga->op1));
929  bool identicalP = GET_INDEX_CONST_NODE(me->op0) == GET_INDEX_CONST_NODE(me->op1);
930  if(identicalP)
931  {
932  if(GET_CONST_NODE(ga->op1)->get_kind() == minus_expr_K)
933  {
934  TM->ReplaceTreeNode(stmt, ga->op1, TM->CreateUniqueIntegerCst(0LL, ga_op_type));
936  "---Statement transformed in " + GET_NODE(stmt)->ToString());
937  modified = true;
938  AppM->RegisterTransformation(GetName(), stmt);
939  }
940  else
941  {
942  const auto op_const_node =
943  TM->CreateUniqueIntegerCst(static_cast<long long int>(1), ga_op_type);
944  const auto srcp_default =
945  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
946  const auto op_expr = IRman->create_binary_operation(ga_op_type, me->op0, op_const_node,
947  srcp_default, lshift_expr_K);
948  TM->ReplaceTreeNode(stmt, ga->op1, op_expr);
950  "---Statement transformed in " + GET_NODE(stmt)->ToString());
951  modified = true;
952  AppM->RegisterTransformation(GetName(), stmt);
953  }
954  return;
955  }
956  const auto op0 = GET_CONST_NODE(me->op0);
957  const auto op1 = GET_CONST_NODE(me->op1);
958  bool is_op0_ssa = op0->get_kind() == ssa_name_K;
959  bool is_op1_ssa = op1->get_kind() == ssa_name_K;
960  std::string bit_values_op0;
961  std::string bit_values_op1;
962 
964  "Var_uid: " +
965  AppM->CGetFunctionBehavior(function_id)
966  ->CGetBehavioralHelper()
967  ->PrintVariable(output_uid) +
968  " bitstring: " + bit_values);
969  unsigned int trailing_zero_op0 = 0;
970  unsigned int trailing_zero_op1 = 0;
971  bool is_op0_null = false;
972  bool is_op1_null = false;
973 
974  if(GET_CONST_NODE(ga->op1)->get_kind() == plus_expr_K)
975  {
976  if(is_op0_ssa)
977  {
978  bit_values_op0 = GetPointerS<const ssa_name>(op0)->bit_values;
979  if(bit_values_op0.empty())
980  {
982  "---Skipped because bitvalue of op0 is empty");
983  return;
984  }
986  "Var_uid: " +
987  AppM->CGetFunctionBehavior(function_id)
988  ->CGetBehavioralHelper()
989  ->PrintVariable(GET_INDEX_CONST_NODE(me->op0)) +
990  " bitstring: " + bit_values_op0);
991  for(const auto& current_el : boost::adaptors::reverse(bit_values_op0))
992  {
993  if(current_el == '0' || current_el == 'X')
994  {
995  ++trailing_zero_op0;
996  }
997  else
998  {
999  break;
1000  }
1001  }
1002  if(bit_values_op0.find_first_not_of("0X") == std::string::npos ||
1003  trailing_zero_op0 >= bit_values.size())
1004  {
1005  is_op0_null = true;
1006  }
1007  }
1008  else
1009  {
1010  THROW_ASSERT(op0->get_kind() == integer_cst_K, "unexpected case");
1011  const auto cst_val = tree_helper::GetConstValue(op0, false);
1012  bit_values_op0 = convert_to_binary(cst_val, tree_helper::Size(op0));
1013  if(cst_val == 0)
1014  {
1015  is_op0_null = true;
1016  }
1017  else
1018  {
1019  for(unsigned int index = 0; index < bit_values_op0.size(); ++index)
1020  {
1021  if(cst_val & (integer_cst_t(1) << index))
1022  {
1023  break;
1024  }
1025  else
1026  {
1027  ++trailing_zero_op0;
1028  }
1029  }
1030  if(trailing_zero_op0 >= bit_values.size())
1031  {
1032  is_op1_null = true;
1033  }
1034  }
1035  }
1036  }
1037  else
1038  {
1039  if(is_op0_ssa)
1040  {
1041  bit_values_op0 = GetPointerS<const ssa_name>(op0)->bit_values;
1042  if(bit_values_op0.empty())
1043  {
1045  "---Skipped because bitvalue of op0 is empty");
1046  return;
1047  }
1048  }
1049  }
1050 
1051  if(is_op1_ssa)
1052  {
1053  bit_values_op1 = GetPointerS<const ssa_name>(op1)->bit_values;
1054  if(bit_values_op1.empty())
1055  {
1057  "---Skipped because bitvalue of op1 is empty");
1058  return;
1059  }
1061  "Var_uid: " +
1062  AppM->CGetFunctionBehavior(function_id)
1063  ->CGetBehavioralHelper()
1064  ->PrintVariable(GET_INDEX_CONST_NODE(me->op1)) +
1065  " bitstring: " + bit_values_op1);
1066  for(const auto& current_el : boost::adaptors::reverse(bit_values_op1))
1067  {
1068  if(current_el == '0' || current_el == 'X')
1069  {
1070  ++trailing_zero_op1;
1071  }
1072  else
1073  {
1074  break;
1075  }
1076  }
1077  if(bit_values_op1.find_first_not_of("0X") == std::string::npos ||
1078  trailing_zero_op1 >= bit_values.size())
1079  {
1080  is_op1_null = true;
1081  }
1082  }
1083  else
1084  {
1085  THROW_ASSERT(op1->get_kind() == integer_cst_K, "unexpected case");
1086  const auto cst_val = tree_helper::GetConstValue(op1, false);
1087  bit_values_op1 = convert_to_binary(cst_val, tree_helper::Size(op1));
1088  if(cst_val == 0)
1089  {
1090  is_op1_null = true;
1091  }
1092  else
1093  {
1094  for(unsigned int index = 0; index < bit_values_op1.size(); ++index)
1095  {
1096  if(cst_val & (integer_cst_t(1) << index))
1097  {
1098  break;
1099  }
1100  else
1101  {
1102  ++trailing_zero_op1;
1103  }
1104  }
1105  if(trailing_zero_op1 >= bit_values.size())
1106  {
1107  is_op1_null = true;
1108  }
1109  }
1110  }
1111 
1113  "---Trailing zeros op0=" + STR(trailing_zero_op0) +
1114  ", trailing zeros op1=" + STR(trailing_zero_op1));
1115  if(is_op0_null)
1116  {
1117  condPropageValue(me->op1, DEBUG_CALLSITE);
1118  }
1119  else if(is_op1_null)
1120  {
1121  condPropageValue(me->op0, DEBUG_CALLSITE);
1122  }
1123  else if(trailing_zero_op0 != 0 || trailing_zero_op1 != 0)
1124  {
1125  modified = true;
1126  AppM->RegisterTransformation(GetName(), stmt);
1127  const auto srcp_default =
1128  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
1129  const auto is_first_max = trailing_zero_op0 > trailing_zero_op1;
1130 
1131  auto shift_const = is_first_max ? trailing_zero_op0 : trailing_zero_op1;
1132 
1134  "---Bit Value Opt: " +
1135  (GET_CONST_NODE(ga->op1)->get_kind() == plus_expr_K ?
1136  std::string("plus_expr") :
1137  std::string("minus_expr")) +
1138  " optimized, nbits = " + STR(shift_const));
1139  const auto shift_constant_node =
1140  TM->CreateUniqueIntegerCst(static_cast<long long int>(shift_const), ga_op_type);
1141  const auto op0_type = tree_helper::CGetType(op0);
1142  const auto op1_type = tree_helper::CGetType(op1);
1143  const auto b_node = is_first_max ? me->op1 : me->op0;
1144  const auto b_type = is_first_max ? op1_type : op0_type;
1145 
1146  if(!is_op0_ssa)
1147  {
1148  const auto cst_val =
1150  if(ssa->bit_values.size() <= shift_const)
1151  {
1152  is_op0_null = true;
1153  }
1154  else
1155  {
1156  if((cst_val >> shift_const) == 0)
1157  {
1158  is_op0_null = GET_CONST_NODE(ga->op1)->get_kind() == plus_expr_K; // TODO: true?
1159  }
1160  TM->ReplaceTreeNode(stmt, me->op0,
1161  TM->CreateUniqueIntegerCst(cst_val >> shift_const, op0_type));
1162  }
1163  }
1164  else
1165  {
1166  std::string resulting_bit_values;
1167 
1168  if((bit_values_op0.size() - shift_const) > 0)
1169  {
1170  resulting_bit_values = bit_values_op0.substr(0, bit_values_op0.size() - shift_const);
1171  }
1172  else if(tree_helper::IsSignedIntegerType(op0_type))
1173  {
1174  resulting_bit_values = bit_values_op0.substr(0, 1);
1175  }
1176  else
1177  {
1178  resulting_bit_values = "0";
1179  }
1180 
1181  if(resulting_bit_values.find_first_not_of("0X") == std::string::npos &&
1182  GET_CONST_NODE(ga->op1)->get_kind() == plus_expr_K)
1183  {
1184  is_op0_null = true;
1185  }
1186  else
1187  {
1188  const auto op0_expr = IRman->create_binary_operation(
1189  op0_type, me->op0, shift_constant_node, srcp_default, rshift_expr_K);
1190  const auto op0_ga = IRman->CreateGimpleAssign(op0_type, nullptr, nullptr, op0_expr,
1191  function_id, srcp_default);
1192  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(op0_ga));
1193  B->PushBefore(op0_ga, stmt, AppM);
1194  const auto op0_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(op0_ga))->op0;
1196  "---Replacing " + me->op0->ToString() + " with " +
1197  op0_ga_var->ToString() + " in " + stmt->ToString());
1198  TM->ReplaceTreeNode(stmt, me->op0, op0_ga_var);
1199 #if HAVE_FROM_DISCREPANCY_BUILT
1200  /*
1201  * for discrepancy analysis, the ssa assigned by this
1202  * bitshift must not be checked if it was applied to
1203  * a variable marked as address.
1204  */
1205  if(parameters->isOption(OPT_discrepancy) and
1206  parameters->getOption<bool>(OPT_discrepancy))
1207  {
1208  AppM->RDiscr->ssa_to_skip_if_address.insert(GET_NODE(op0_ga_var));
1209  }
1210 #endif
1211  auto op0_ssa = GetPointer<ssa_name>(GET_NODE(op0_ga_var));
1213  THROW_ASSERT(resulting_bit_values.size() > 0, "unexpected condition");
1214  op0_ssa->bit_values = resulting_bit_values;
1215  constrainSSA(op0_ssa, TM);
1217  "Var_uid: " +
1218  AppM->CGetFunctionBehavior(function_id)
1219  ->CGetBehavioralHelper()
1220  ->PrintVariable(GET_INDEX_CONST_NODE(op0_ga_var)) +
1221  " bitstring: " + STR(op0_ssa->bit_values));
1222  }
1223  }
1224 
1225  if(!is_op1_ssa)
1226  {
1227  const auto cst_val =
1229  if(ssa->bit_values.size() <= shift_const)
1230  {
1231  is_op1_null = true;
1232  }
1233  else
1234  {
1235  if((cst_val >> shift_const) == 0)
1236  {
1237  is_op1_null = true;
1238  }
1239  TM->ReplaceTreeNode(stmt, me->op1,
1240  TM->CreateUniqueIntegerCst(cst_val >> shift_const, op1_type));
1241  }
1242  }
1243  else
1244  {
1245  std::string resulting_bit_values;
1246 
1247  if((bit_values_op1.size() - shift_const) > 0)
1248  {
1249  resulting_bit_values = bit_values_op1.substr(0, bit_values_op1.size() - shift_const);
1250  }
1251  else if(tree_helper::IsSignedIntegerType(op1_type))
1252  {
1253  resulting_bit_values = bit_values_op1.substr(0, 1);
1254  }
1255  else
1256  {
1257  resulting_bit_values = "0";
1258  }
1259 
1260  if(resulting_bit_values.find_first_not_of("0X") == std::string::npos)
1261  {
1262  is_op1_null = true;
1263  }
1264  else
1265  {
1266  const auto op1_expr = IRman->create_binary_operation(
1267  op1_type, me->op1, shift_constant_node, srcp_default, rshift_expr_K);
1268  const auto op1_ga = IRman->CreateGimpleAssign(op1_type, nullptr, nullptr, op1_expr,
1269  function_id, srcp_default);
1270  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(op1_ga));
1271  B->PushBefore(op1_ga, stmt, AppM);
1272  const auto op1_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(op1_ga))->op0;
1274  "---Replacing " + me->op1->ToString() + " with " +
1275  op1_ga_var->ToString() + " in " + stmt->ToString());
1276  TM->ReplaceTreeNode(stmt, me->op1, op1_ga_var);
1277 #if HAVE_FROM_DISCREPANCY_BUILT
1278  /*
1279  * for discrepancy analysis, the ssa assigned by this
1280  * bitshift must not be checked if it was applied to
1281  * a variable marked as address.
1282  */
1283  if(parameters->isOption(OPT_discrepancy) and
1284  parameters->getOption<bool>(OPT_discrepancy))
1285  {
1286  AppM->RDiscr->ssa_to_skip_if_address.insert(GET_NODE(op1_ga_var));
1287  }
1288 #endif
1289  auto* op1_ssa = GetPointer<ssa_name>(GET_NODE(op1_ga_var));
1291  THROW_ASSERT(resulting_bit_values.size() > 0, "unexpected condition");
1292  op1_ssa->bit_values = resulting_bit_values;
1293  constrainSSA(op1_ssa, TM);
1295  "Var_uid: " +
1296  AppM->CGetFunctionBehavior(function_id)
1297  ->CGetBehavioralHelper()
1298  ->PrintVariable(GET_INDEX_CONST_NODE(op1_ga_var)) +
1299  " bitstring: " + STR(op1_ssa->bit_values));
1300  }
1301  }
1302 
1303  tree_nodeRef curr_ga;
1304  if(is_op0_null)
1305  {
1306  curr_ga = IRman->CreateGimpleAssign(op1_type, nullptr, nullptr, me->op1, function_id,
1307  srcp_default);
1308  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(curr_ga));
1309  }
1310  else if(is_op1_null)
1311  {
1312  curr_ga = IRman->CreateGimpleAssign(op1_type, nullptr, nullptr, me->op0, function_id,
1313  srcp_default);
1314  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(curr_ga));
1315  }
1316  else
1317  {
1318  curr_ga = IRman->CreateGimpleAssign(op1_type, nullptr, nullptr, ga->op1, function_id,
1319  srcp_default);
1320  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(curr_ga));
1321  }
1322  B->PushBefore(curr_ga, stmt, AppM);
1323  const auto curr_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(curr_ga))->op0;
1324 #if HAVE_FROM_DISCREPANCY_BUILT
1325  /*
1326  * for discrepancy analysis, the ssa assigned by this
1327  * bitshift must not be checked if it was applied to
1328  * a variable marked as address.
1329  */
1330  if(parameters->isOption(OPT_discrepancy) and parameters->getOption<bool>(OPT_discrepancy))
1331  {
1332  AppM->RDiscr->ssa_to_skip_if_address.insert(GET_NODE(curr_ga_var));
1333  }
1334 #endif
1335  auto op_ssa = GetPointer<ssa_name>(GET_NODE(curr_ga_var));
1337  THROW_ASSERT(ssa->bit_values.size() - shift_const > 0, "unexpected condition");
1338  op_ssa->bit_values = ssa->bit_values.substr(0, ssa->bit_values.size() - shift_const);
1339  constrainSSA(op_ssa, TM);
1341  "Var_uid: " +
1342  AppM->CGetFunctionBehavior(function_id)
1343  ->CGetBehavioralHelper()
1344  ->PrintVariable(GET_INDEX_CONST_NODE(curr_ga_var)) +
1345  " bitstring: " + STR(op_ssa->bit_values));
1346 
1347  const auto op_expr = IRman->create_binary_operation(
1348  ga_op_type, curr_ga_var, shift_constant_node, srcp_default, lshift_expr_K);
1349  const auto lshift_ga = IRman->CreateGimpleAssign(ga_op_type, nullptr, nullptr, op_expr,
1350  function_id, srcp_default);
1351  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(lshift_ga));
1352  B->PushBefore(lshift_ga, stmt, AppM);
1353  const auto lshift_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(lshift_ga))->op0;
1355  auto lshift_ssa = GetPointer<ssa_name>(GET_NODE(lshift_ga_var));
1356  THROW_ASSERT(ssa->bit_values.size() - shift_const > 0, "unexpected condition");
1357  lshift_ssa->bit_values = ssa->bit_values.substr(0, ssa->bit_values.size() - shift_const);
1358  while(lshift_ssa->bit_values.size() < ssa->bit_values.size())
1359  {
1360  lshift_ssa->bit_values.push_back('0');
1361  }
1362  constrainSSA(lshift_ssa, TM);
1364  "Var_uid: " +
1365  AppM->CGetFunctionBehavior(function_id)
1366  ->CGetBehavioralHelper()
1367  ->PrintVariable(GET_INDEX_CONST_NODE(lshift_ga_var)) +
1368  " bitstring: " + STR(lshift_ssa->bit_values));
1369 
1370  bool do_final_or = false;
1371  unsigned int n_iter = 0;
1372  for(const auto& cur_bit : boost::adaptors::reverse(ssa->bit_values))
1373  {
1374  if(cur_bit == '1' || cur_bit == 'U')
1375  {
1376  do_final_or = true;
1377  break;
1378  }
1379  n_iter++;
1380  if(n_iter == shift_const)
1381  {
1382  break;
1383  }
1384  }
1385 
1386  if(do_final_or)
1387  {
1388 #if HAVE_FROM_DISCREPANCY_BUILT
1389  /*
1390  * for discrepancy analysis, the ssa assigned by this
1391  * bitshift must not be checked if it was applied to
1392  * a variable marked as address.
1393  */
1394  if(parameters->isOption(OPT_discrepancy) and parameters->getOption<bool>(OPT_discrepancy))
1395  {
1396  AppM->RDiscr->ssa_to_skip_if_address.insert(GET_NODE(lshift_ga_var));
1397  }
1398 #endif
1399  if(GetPointer<const integer_cst>(GET_CONST_NODE(b_node)))
1400  {
1401  const auto cst_val = tree_helper::GetConstValue(b_node, false);
1402  const auto b_node_val = TM->CreateUniqueIntegerCst(
1403  cst_val & ((integer_cst_t(1) << shift_const) - 1), b_type);
1404  TM->ReplaceTreeNode(stmt, ga->op1,
1405  IRman->create_ternary_operation(
1406  ga_op_type, lshift_ga_var, b_node_val, shift_constant_node,
1407  srcp_default, bit_ior_concat_expr_K));
1408  }
1409  else
1410  {
1411  const auto bit_mask_constant_node = TM->CreateUniqueIntegerCst(
1412  static_cast<long long int>((1ULL << shift_const) - 1), b_type);
1413  const auto band_expr = IRman->create_binary_operation(
1414  b_type, b_node, bit_mask_constant_node, srcp_default, bit_and_expr_K);
1415  const auto band_ga = IRman->CreateGimpleAssign(b_type, nullptr, nullptr, band_expr,
1416  function_id, srcp_default);
1417  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(band_ga));
1418  B->PushBefore(band_ga, stmt, AppM);
1419  const auto band_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(band_ga))->op0;
1420 #if HAVE_FROM_DISCREPANCY_BUILT
1421  /*
1422  * for discrepancy analysis, the ssa assigned by this
1423  * bitshift must not be checked if it was applied to
1424  * a variable marked as address.
1425  */
1426  if(parameters->isOption(OPT_discrepancy) and
1427  parameters->getOption<bool>(OPT_discrepancy))
1428  {
1429  AppM->RDiscr->ssa_to_skip_if_address.insert(GET_NODE(band_ga_var));
1430  }
1431 #endif
1432  auto band_ssa = GetPointer<ssa_name>(GET_NODE(band_ga_var));
1434  for(const auto& cur_bit : boost::adaptors::reverse(ssa->bit_values))
1435  {
1436  band_ssa->bit_values = cur_bit + band_ssa->bit_values;
1437  if(band_ssa->bit_values.size() == shift_const)
1438  {
1439  break;
1440  }
1441  }
1442  band_ssa->bit_values = "0" + band_ssa->bit_values;
1443  constrainSSA(band_ssa, TM);
1445  "Var_uid: " +
1446  AppM->CGetFunctionBehavior(function_id)
1447  ->CGetBehavioralHelper()
1448  ->PrintVariable(GET_INDEX_CONST_NODE(band_ga_var)) +
1449  " bitstring: " + STR(band_ssa->bit_values));
1450 
1451  const auto res_expr = IRman->create_ternary_operation(
1452  ga_op_type, lshift_ga_var, band_ga_var, shift_constant_node, srcp_default,
1453  bit_ior_concat_expr_K);
1454  TM->ReplaceTreeNode(stmt, ga->op1, res_expr);
1455  }
1456  }
1457  else
1458  {
1459  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Final or not performed: ");
1460  TM->ReplaceTreeNode(stmt, ga->op1, lshift_ga_var);
1461  }
1463  }
1464  else if(GET_CONST_NODE(ga->op1)->get_kind() == minus_expr_K &&
1465  op0->get_kind() == integer_cst_K && tree_helper::GetConstValue(op0) == 0)
1466  {
1467  if(!parameters->isOption(OPT_use_ALUs) || !parameters->getOption<bool>(OPT_use_ALUs))
1468  {
1469  const auto srcp_default =
1470  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
1471  const auto res_expr =
1472  IRman->create_unary_operation(ga_op_type, me->op1, srcp_default, negate_expr_K);
1473  TM->ReplaceTreeNode(stmt, ga->op1, res_expr);
1474  modified = true;
1475  AppM->RegisterTransformation(GetName(), stmt);
1476  }
1477  }
1478  };
1479  plus_minus_BVO();
1480  }
1481  else if(GET_CONST_NODE(ga->op1)->get_kind() == eq_expr_K ||
1482  GET_CONST_NODE(ga->op1)->get_kind() == ne_expr_K)
1483  {
1484  auto eq_ne_expr_BVO = [&] {
1485  const auto me = GetPointer<const binary_expr>(GET_CONST_NODE(ga->op1));
1486  const auto& op0 = me->op0;
1487  const auto& op1 = me->op1;
1489  {
1490  // TODO: adapt existing operations to real type (zero sign bug to be considered)
1491  return;
1492  }
1493  const auto op0_size = BitLatticeManipulator::Size(op0);
1494  bool is_op1_zero = false;
1495  if(GetPointer<const integer_cst>(GET_CONST_NODE(op1)))
1496  {
1497  if(tree_helper::GetConstValue(op1) == 0)
1498  {
1499  is_op1_zero = true;
1500  }
1501  }
1502 
1503  if(op0->index == op1->index)
1504  {
1505  const auto const_value = GET_CONST_NODE(ga->op1)->get_kind() == eq_expr_K ? 1LL : 0LL;
1506  const auto val = TM->CreateUniqueIntegerCst(const_value, ga_op_type);
1507  propagateValue(ssa, TM, ga->op0, val, DEBUG_CALLSITE);
1508  }
1509  else if(is_op1_zero && GET_CONST_NODE(ga->op1)->get_kind() == ne_expr_K && op0_size == 1)
1510  {
1511  const auto op0_op_type = tree_helper::CGetType(op0);
1512  const auto data_bitsize = BitLatticeManipulator::Size(op0_op_type);
1513  if(data_bitsize == 1)
1514  {
1515  propagateValue(ssa, TM, ga->op0, me->op0, DEBUG_CALLSITE);
1516  if(!ssa->CGetUseStmts().empty())
1517  {
1518  if(AppM->ApplyNewTransformation())
1519  {
1520  const auto srcp_default =
1521  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
1522  const auto nop_expr_node =
1523  IRman->create_unary_operation(ga_op_type, me->op0, srcp_default, nop_expr_K);
1524  TM->ReplaceTreeNode(stmt, ga->op1, nop_expr_node);
1525  modified = true;
1526  AppM->RegisterTransformation(GetName(), stmt);
1527  }
1528  }
1529  }
1530  else
1531  {
1532  const auto srcp_default =
1533  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
1534  const auto one_const_node = TM->CreateUniqueIntegerCst(1, op0_op_type);
1535  const auto bitwise_masked = IRman->create_binary_operation(
1536  op0_op_type, me->op0, one_const_node, srcp_default, bit_and_expr_K);
1537  const auto op0_ga =
1538  IRman->CreateGimpleAssign(op0_op_type, TM->CreateUniqueIntegerCst(0, op0_op_type),
1539  TM->CreateUniqueIntegerCst(1LL, op0_op_type),
1540  bitwise_masked, function_id, srcp_default);
1541  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(op0_ga));
1542  B->PushBefore(op0_ga, stmt, AppM);
1543  const auto op0_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(op0_ga))->op0;
1544 
1545  const auto ga_nop = IRman->CreateNopExpr(op0_ga_var, ga_op_type, tree_nodeRef(),
1546  tree_nodeRef(), function_id);
1547  B->PushBefore(ga_nop, stmt, AppM);
1548  modified = true;
1549  AppM->RegisterTransformation(GetName(), ga_nop);
1550  const auto nop_ga_var = GetPointer<const gimple_assign>(GET_CONST_NODE(ga_nop))->op0;
1551  TM->ReplaceTreeNode(stmt, ga->op1, nop_ga_var);
1552  }
1553  }
1554  else
1555  {
1556  rel_expr_BVO();
1557  }
1558  };
1559  eq_ne_expr_BVO();
1560  }
1561  else if(GET_CONST_NODE(ga->op1)->get_kind() == lt_expr_K ||
1562  GET_CONST_NODE(ga->op1)->get_kind() == gt_expr_K ||
1563  GET_CONST_NODE(ga->op1)->get_kind() == le_expr_K ||
1564  GET_CONST_NODE(ga->op1)->get_kind() == ge_expr_K)
1565  {
1566  rel_expr_BVO();
1567  }
1568  else if(GET_CONST_NODE(ga->op1)->get_kind() == bit_and_expr_K ||
1569  GET_CONST_NODE(ga->op1)->get_kind() == bit_xor_expr_K)
1570  {
1571  auto bit_expr_BVO = [&] {
1572  const auto me = GetPointer<const binary_expr>(GET_CONST_NODE(ga->op1));
1573  const auto& op0 = me->op0;
1574  const auto& op1 = me->op1;
1575  const auto expr_kind = GET_CONST_NODE(ga->op1)->get_kind();
1576 
1577  std::string s0, s1;
1578  bool is_op0_ssa = GetPointer<const ssa_name>(GET_CONST_NODE(op0));
1579  bool is_op1_ssa = GetPointer<const ssa_name>(GET_CONST_NODE(op1));
1580  if(is_op0_ssa)
1581  {
1582  s0 = GetPointer<const ssa_name>(GET_CONST_NODE(op0))->bit_values;
1583  if(s0.empty())
1584  {
1586  "---Skipped because bitvalue of s0 is empty");
1587  return;
1588  }
1590  }
1591  else
1592  {
1593  THROW_ASSERT(GET_CONST_NODE(op0)->get_kind() == integer_cst_K, "unexpected case");
1594  }
1595  if(is_op1_ssa)
1596  {
1597  s1 = GetPointer<const ssa_name>(GET_CONST_NODE(op1))->bit_values;
1598  if(s1.empty())
1599  {
1601  "---Skipped because bitvalue of s1 is empty");
1602  return;
1603  }
1605  }
1606  else
1607  {
1608  THROW_ASSERT(GET_CONST_NODE(op1)->get_kind() == integer_cst_K, "unexpected case");
1609  }
1610 
1611  unsigned int trailing_zero = 0;
1612  bool is_zero0 = s0.find_first_not_of("0X") == std::string::npos;
1613  if(!is_op0_ssa)
1614  {
1615  const auto uvalue = tree_helper::GetConstValue(op0, false);
1616  is_zero0 = uvalue == 0;
1618  }
1619  bool is_zero1 = s1.find_first_not_of("0X") == std::string::npos;
1620  if(!is_op1_ssa)
1621  {
1622  const auto uvalue = tree_helper::GetConstValue(op1, false);
1623  is_zero1 = uvalue == 0;
1625  }
1626  if(is_zero0 || is_zero1)
1627  {
1628  if(GET_CONST_NODE(ga->op1)->get_kind() == bit_and_expr_K)
1629  {
1631  "---replace bit_and_expr usage before: " + stmt->ToString());
1632  const auto zero_node = TM->CreateUniqueIntegerCst(0LL, tree_helper::CGetType(op0));
1633  propagateValue(ssa, TM, ga->op0, zero_node, DEBUG_CALLSITE);
1634  }
1635  else
1636  {
1637  // bit_xor_expr_K
1639  "---replace bit_xor_expr usage before: " + stmt->ToString());
1640  const auto val = is_zero0 ? op1 : op0;
1641  condPropageValue(val, DEBUG_CALLSITE);
1642  }
1643  }
1644  else
1645  {
1646  for(auto s0it = s0.rbegin(), s1it = s1.rbegin(), s0end = s0.rend(), s1end = s1.rend();
1647  s0it != s0end && s1it != s1end; ++s0it, ++s1it)
1648  {
1649  if((expr_kind == bit_and_expr_K && (*s0it == '0' || *s1it == '0')) || *s0it == 'X' ||
1650  *s1it == 'X')
1651  {
1652  ++trailing_zero;
1653  }
1654  else
1655  {
1656  break;
1657  }
1658  }
1659  auto min_size = std::min(s0.size(), s1.size());
1660  if(trailing_zero < min_size && trailing_zero)
1661  {
1663  "---Bit Value Opt: " + std::string(GET_NODE(ga->op1)->get_kind_text()) +
1664  " optimized, nbits = " + STR(trailing_zero));
1665  modified = true;
1666  AppM->RegisterTransformation(GetName(), stmt);
1667  const auto srcp_default =
1668  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
1669  const auto op0_op_type = tree_helper::CGetType(op0);
1670  const auto op1_op_type = tree_helper::CGetType(op1);
1671 
1672  if(is_op0_ssa)
1673  {
1674  const auto op0_const_node = TM->CreateUniqueIntegerCst(trailing_zero, op0_op_type);
1675  const auto op0_expr = IRman->create_binary_operation(op0_op_type, op0, op0_const_node,
1676  srcp_default, rshift_expr_K);
1677  const auto op0_ga = IRman->CreateGimpleAssign(op0_op_type, nullptr, nullptr, op0_expr,
1678  function_id, srcp_default);
1679  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(op0_ga));
1680  B->PushBefore(op0_ga, stmt, AppM);
1681  const auto op0_ga_var = GetPointerS<const gimple_assign>(GET_CONST_NODE(op0_ga))->op0;
1682  TM->ReplaceTreeNode(stmt, op0, op0_ga_var);
1684  auto op0_ssa = GetPointerS<ssa_name>(GET_NODE(op0_ga_var));
1685  THROW_ASSERT(s0.size() - trailing_zero > 0, "unexpected condition");
1686  op0_ssa->bit_values = s0.substr(0, s0.size() - trailing_zero);
1687  constrainSSA(op0_ssa, TM);
1688  }
1689  else
1690  {
1691  const auto cst_val =
1693  TM->ReplaceTreeNode(stmt, op0,
1694  TM->CreateUniqueIntegerCst(cst_val >> trailing_zero, op0_op_type));
1695  }
1696  if(is_op1_ssa)
1697  {
1698  const auto op1_const_node =
1699  TM->CreateUniqueIntegerCst(static_cast<long long int>(trailing_zero), op1_op_type);
1700  const auto op1_expr = IRman->create_binary_operation(op1_op_type, op1, op1_const_node,
1701  srcp_default, rshift_expr_K);
1702  const auto op1_ga = IRman->CreateGimpleAssign(op1_op_type, nullptr, nullptr, op1_expr,
1703  function_id, srcp_default);
1704  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(op1_ga));
1705  B->PushBefore(op1_ga, stmt, AppM);
1706  const auto op1_ga_var = GetPointerS<const gimple_assign>(GET_CONST_NODE(op1_ga))->op0;
1707  TM->ReplaceTreeNode(stmt, op1, op1_ga_var);
1709  auto op1_ssa = GetPointerS<ssa_name>(GET_NODE(op1_ga_var));
1710  THROW_ASSERT(s1.size() - trailing_zero > 0, "unexpected condition");
1711  op1_ssa->bit_values = s1.substr(0, s1.size() - trailing_zero);
1712  constrainSSA(op1_ssa, TM);
1713  }
1714  else
1715  {
1716  const auto cst_val =
1718  TM->ReplaceTreeNode(stmt, op1,
1719  TM->CreateUniqueIntegerCst(cst_val >> trailing_zero, op1_op_type));
1720  }
1721 
1722  const auto ssa_vd = IRman->create_ssa_name(nullptr, ga_op_type, nullptr, nullptr);
1723  auto sn = GetPointerS<ssa_name>(GET_NODE(ssa_vd));
1725  THROW_ASSERT(ssa->bit_values.size() - trailing_zero > 0, "unexpected condition");
1726  sn->bit_values = ssa->bit_values.substr(0, ssa->bit_values.size() - trailing_zero);
1727  constrainSSA(sn, TM);
1728  const auto op_const_node =
1729  TM->CreateUniqueIntegerCst(static_cast<long long int>(trailing_zero), ga_op_type);
1730  const auto op_expr = IRman->create_binary_operation(ga_op_type, ssa_vd, op_const_node,
1731  srcp_default, lshift_expr_K);
1732  const auto curr_ga = IRman->CreateGimpleAssign(ga_op_type, ssa->min, ssa->max, op_expr,
1733  function_id, srcp_default);
1734  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(curr_ga));
1735  TM->ReplaceTreeNode(
1736  curr_ga, GetPointer<const gimple_assign>(GET_CONST_NODE(curr_ga))->op0, ga->op0);
1737  TM->ReplaceTreeNode(stmt, ga->op0, ssa_vd);
1738  B->PushAfter(curr_ga, stmt, AppM);
1740  }
1741  }
1742  };
1743  bit_expr_BVO();
1744  }
1745  else if(GET_CONST_NODE(ga->op1)->get_kind() == cond_expr_K)
1746  {
1747  auto cond_expr_BVO = [&] {
1748  const auto me = GetPointer<const cond_expr>(GET_CONST_NODE(ga->op1));
1749  if(!tree_helper::IsBooleanType(me->op0))
1750  {
1752  const auto cond_op0_ssa = GetPointer<const ssa_name>(GET_CONST_NODE(me->op0));
1753  if(cond_op0_ssa)
1754  {
1755  const auto defStmt = GET_CONST_NODE(cond_op0_ssa->CGetDefStmt());
1756  if(defStmt->get_kind() == gimple_assign_K)
1757  {
1758  const auto prev_ga = GetPointer<const gimple_assign>(defStmt);
1759  const auto prev_code1 = GET_CONST_NODE(prev_ga->op1)->get_kind();
1760  if(prev_code1 == nop_expr_K)
1761  {
1762  const auto ne = GetPointer<const nop_expr>(GET_CONST_NODE(prev_ga->op1));
1763  if(tree_helper::IsBooleanType(ne->op))
1764  {
1766  "---replace cond_expr condition before: " + stmt->ToString());
1767  TM->ReplaceTreeNode(stmt, me->op0, ne->op);
1769  "---replace cond_expr condition after: " + stmt->ToString());
1770  modified = true;
1771  AppM->RegisterTransformation(GetName(), stmt);
1772  }
1773  }
1774  }
1775  }
1776  }
1777  if(!AppM->ApplyNewTransformation())
1778  {
1780  "---Skipped because reached limit of cfg transformations");
1781  return;
1782  }
1783  const auto& op0 = me->op1;
1784  const auto& op1 = me->op2;
1785  const auto condition = GET_CONST_NODE(me->op0);
1787  {
1788  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Cond expr with equal operands");
1789  condPropageValue(me->op1, DEBUG_CALLSITE);
1790  }
1791  else if(condition->get_kind() == integer_cst_K)
1792  {
1794  "---Cond expr with constant condition");
1795  const auto val = tree_helper::GetConstValue(me->op0, false) ? me->op1 : me->op2;
1796 
1797  condPropageValue(val, DEBUG_CALLSITE);
1798  }
1799  else
1800  {
1801  THROW_ASSERT(op0 != op1, "unexpected condition");
1802  std::string s0, s1;
1803  bool is_op0_ssa = GetPointer<const ssa_name>(GET_CONST_NODE(op0));
1804  bool is_op1_ssa = GetPointer<const ssa_name>(GET_CONST_NODE(op1));
1805  unsigned long long s0_precision = 0;
1806  bool is_s0_null = false;
1807  bool is_s0_one = false;
1808  if(is_op0_ssa)
1809  {
1810  s0 = GetPointerS<const ssa_name>(GET_CONST_NODE(op0))->bit_values;
1811  if(s0.empty())
1812  {
1814  "---Skipped because so is empty");
1815  return;
1816  }
1817  s0_precision = static_cast<unsigned int>(s0.size());
1818  is_s0_null = s0.find_first_not_of("0X") == std::string::npos;
1819  is_s0_one = s0 == "1" || s0 == "01";
1820  }
1821  else
1822  {
1823  THROW_ASSERT(GET_CONST_NODE(op0)->get_kind() == integer_cst_K, "unexpected condition");
1824  const auto uvalue = tree_helper::GetConstValue(op0, false);
1825  s0_precision =
1827  s0 = convert_to_binary(uvalue, s0_precision);
1828  is_s0_null = uvalue == 0;
1829  is_s0_one = uvalue == 1;
1830  }
1831  unsigned long long s1_precision = 0;
1832  bool is_s1_null = false;
1833  bool is_s1_one = false;
1834  if(is_op1_ssa)
1835  {
1836  s1 = GetPointerS<const ssa_name>(GET_CONST_NODE(op1))->bit_values;
1837  if(s1.empty())
1838  {
1840  "---Skipped because s1 is empty");
1841  return;
1842  }
1843  s1_precision = static_cast<unsigned int>(s1.size());
1844  is_s1_null = s1.find_first_not_of("0X") == std::string::npos;
1845  is_s1_one = s1 == "1" || s1 == "01";
1846  }
1847  else
1848  {
1849  THROW_ASSERT(GET_CONST_NODE(op1)->get_kind() == integer_cst_K, "unexpected condition");
1850  const auto uvalue = tree_helper::GetConstValue(op1, false);
1851  s1_precision =
1853  s1 = convert_to_binary(uvalue, s1_precision);
1854  is_s1_null = uvalue == 0;
1855  is_s1_one = uvalue == 1;
1856  }
1857 
1858  unsigned long long minimum_precision = std::min(s0_precision, s1_precision);
1859  unsigned int trailing_eq = 0;
1861  "---Bit_value strings are " + s0 + " and " + s1);
1862  for(unsigned int index = 0; index < (minimum_precision - 1); ++index)
1863  {
1864  if((s0[s0.size() - index - 1] == '0' || s0[s0.size() - index - 1] == 'X') &&
1865  (s1[s1.size() - index - 1] == '0' || s1[s1.size() - index - 1] == 'X'))
1866  {
1867  ++trailing_eq;
1868  }
1869  else
1870  {
1871  break;
1872  }
1873  }
1874  if(trailing_eq)
1875  {
1877  "---Bit Value Opt: cond_expr optimized, nbits = " + STR(trailing_eq));
1878  modified = true;
1879  const auto srcp_default =
1880  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
1881  const auto op0_op_type = tree_helper::CGetType(op0);
1882  const auto op1_op_type = tree_helper::CGetType(op1);
1883 
1884  if(is_op0_ssa)
1885  {
1886  const auto op0_const_node =
1887  TM->CreateUniqueIntegerCst(static_cast<long long int>(trailing_eq), op0_op_type);
1888  const auto op0_expr = IRman->create_binary_operation(
1889  op0_op_type, me->op1, op0_const_node, srcp_default, rshift_expr_K);
1890  const auto op0_ga = IRman->CreateGimpleAssign(op0_op_type, nullptr, nullptr, op0_expr,
1891  function_id, srcp_default);
1892  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(op0_ga));
1893  B->PushBefore(op0_ga, stmt, AppM);
1894  const auto op0_ga_var = GetPointerS<const gimple_assign>(GET_CONST_NODE(op0_ga))->op0;
1895  TM->ReplaceTreeNode(stmt, me->op1, op0_ga_var);
1897  auto op0_ssa = GetPointerS<ssa_name>(GET_NODE(op0_ga_var));
1898  THROW_ASSERT(s0.size() - trailing_eq > 0, "unexpected condition");
1899  op0_ssa->bit_values = s0.substr(0, s0.size() - trailing_eq);
1900  constrainSSA(op0_ssa, TM);
1901  }
1902  else
1903  {
1904  const auto cst_val =
1906  TM->ReplaceTreeNode(stmt, me->op1,
1907  TM->CreateUniqueIntegerCst(cst_val >> trailing_eq, op0_op_type));
1908  }
1909  if(is_op1_ssa)
1910  {
1911  const auto op1_const_node =
1912  TM->CreateUniqueIntegerCst(static_cast<long long int>(trailing_eq), op1_op_type);
1913  const auto op1_expr = IRman->create_binary_operation(
1914  op1_op_type, me->op2, op1_const_node, srcp_default, rshift_expr_K);
1915  const auto op1_ga = IRman->CreateGimpleAssign(
1916  op1_op_type, tree_nodeRef(), tree_nodeRef(), op1_expr, function_id, srcp_default);
1917  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(op1_ga));
1918  B->PushBefore(op1_ga, stmt, AppM);
1919  const auto op1_ga_var = GetPointerS<const gimple_assign>(GET_CONST_NODE(op1_ga))->op0;
1920  TM->ReplaceTreeNode(stmt, me->op2, op1_ga_var);
1922  auto op1_ssa = GetPointerS<ssa_name>(GET_NODE(op1_ga_var));
1923  THROW_ASSERT(s1.size() - trailing_eq > 0, "unexpected condition");
1924  op1_ssa->bit_values = s1.substr(0, s1.size() - trailing_eq);
1925  constrainSSA(op1_ssa, TM);
1926  }
1927  else
1928  {
1929  const auto cst_val =
1931  TM->ReplaceTreeNode(stmt, me->op2,
1932  TM->CreateUniqueIntegerCst(cst_val >> trailing_eq, op1_op_type));
1933  }
1934  const auto ssa_vd = IRman->create_ssa_name(nullptr, ga_op_type, nullptr, nullptr);
1935  auto* sn = GetPointer<ssa_name>(GET_NODE(ssa_vd));
1937  if(ssa->bit_values.size())
1938  {
1939  THROW_ASSERT(ssa->bit_values.size() - trailing_eq > 0, "unexpected condition");
1940  sn->bit_values = ssa->bit_values.substr(0, ssa->bit_values.size() - trailing_eq);
1941  constrainSSA(sn, TM);
1942  }
1943  const auto op_const_node =
1944  TM->CreateUniqueIntegerCst(static_cast<long long int>(trailing_eq), ga_op_type);
1945  const auto op_expr = IRman->create_binary_operation(ga_op_type, ssa_vd, op_const_node,
1946  srcp_default, lshift_expr_K);
1947  const auto curr_ga = IRman->CreateGimpleAssign(ga_op_type, ssa->min, ssa->max, op_expr,
1948  function_id, srcp_default);
1949  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created " + STR(curr_ga));
1950  TM->ReplaceTreeNode(
1951  curr_ga, GetPointer<const gimple_assign>(GET_CONST_NODE(curr_ga))->op0, ga->op0);
1952  TM->ReplaceTreeNode(stmt, ga->op0, ssa_vd);
1953  B->PushAfter(curr_ga, stmt, AppM);
1954  modified = true;
1955  AppM->RegisterTransformation(GetName(), stmt);
1956  }
1957  else if(is_s0_one && is_s1_null)
1958  {
1960  "---Cond expr with true and false");
1961  tree_nodeRef cond_var;
1962  if(tree_helper::IsBooleanType(ssa->type))
1963  {
1964  cond_var = me->op0;
1965  }
1966  else
1967  {
1968  const auto ga_nop =
1969  IRman->CreateNopExpr(me->op0, ssa->type, ssa->min, ssa->max, function_id);
1970  B->PushBefore(ga_nop, stmt, AppM);
1971  modified = true;
1972  AppM->RegisterTransformation(GetName(), ga_nop);
1973  cond_var = GetPointer<const gimple_assign>(GET_CONST_NODE(ga_nop))->op0;
1974  }
1975  condPropageValue(cond_var, DEBUG_CALLSITE);
1976  }
1977  else if(is_s0_null && is_s1_one)
1978  {
1980  "---Cond expr with false and true");
1983  const auto new_ssa = IRman->CreateNotExpr(me->op0, blocRef(), function_id);
1984  const auto new_stmt = GetPointer<const ssa_name>(GET_CONST_NODE(new_ssa))->CGetDefStmt();
1985  B->PushBefore(new_stmt, stmt, AppM);
1986  tree_nodeRef cond_var;
1987  if(tree_helper::IsBooleanType(ssa->type))
1988  {
1989  cond_var = new_ssa;
1990  }
1991  else
1992  {
1993  const auto ga_nop =
1994  IRman->CreateNopExpr(new_ssa, ssa->type, ssa->min, ssa->max, function_id);
1995  B->PushBefore(ga_nop, stmt, AppM);
1996  cond_var = GetPointer<const gimple_assign>(GET_CONST_NODE(ga_nop))->op0;
1997  }
1998  condPropageValue(cond_var, DEBUG_CALLSITE);
1999  }
2000  }
2001  };
2002  cond_expr_BVO();
2003  }
2004  else if(GET_CONST_NODE(ga->op1)->get_kind() == bit_ior_expr_K)
2005  {
2006  auto bit_ior_expr_BVO = [&] {
2007  const auto bie = GetPointer<const bit_ior_expr>(GET_CONST_NODE(ga->op1));
2008  if(GET_CONST_NODE(bie->op0)->get_kind() == integer_cst_K ||
2009  GET_CONST_NODE(bie->op1)->get_kind() == integer_cst_K)
2010  {
2011  tree_nodeRef val;
2012  if(GET_CONST_NODE(bie->op0)->get_kind() == integer_cst_K)
2013  {
2014  const auto cst_val = tree_helper::GetConstValue(bie->op0);
2015  if(cst_val == 0)
2016  {
2017  val = bie->op1;
2018  }
2019  }
2020  else
2021  {
2022  const auto cst_val = tree_helper::GetConstValue(bie->op1);
2023  if(cst_val == 0)
2024  {
2025  val = bie->op0;
2026  }
2027  }
2028  if(val)
2029  {
2030  condPropageValue(val, DEBUG_CALLSITE);
2031  }
2032  }
2033  };
2034  bit_ior_expr_BVO();
2035  }
2036  else if(GET_CONST_NODE(ga->op1)->get_kind() == pointer_plus_expr_K)
2037  {
2038  auto pointer_plus_expr_BVO = [&] {
2039  const auto ppe = GetPointer<const pointer_plus_expr>(GET_CONST_NODE(ga->op1));
2040  if(GET_CONST_NODE(ppe->op1)->get_kind() == integer_cst_K)
2041  {
2042  const auto cst_val = tree_helper::GetConstValue(ppe->op1);
2043  if(cst_val == 0)
2044  {
2045  condPropageValue(ppe->op0, DEBUG_CALLSITE);
2046  }
2047  else if(GetPointer<const ssa_name>(GET_CONST_NODE(ppe->op0)))
2048  {
2049  const auto temp_def =
2050  GET_CONST_NODE(GetPointer<const ssa_name>(GET_CONST_NODE(ppe->op0))->CGetDefStmt());
2051  if(temp_def->get_kind() == gimple_assign_K)
2052  {
2053  const auto prev_ga = GetPointer<const gimple_assign>(temp_def);
2054  if(GET_CONST_NODE(prev_ga->op1)->get_kind() == pointer_plus_expr_K)
2055  {
2056  const auto prev_ppe =
2057  GetPointer<const pointer_plus_expr>(GET_CONST_NODE(prev_ga->op1));
2058  if(GetPointer<const ssa_name>(GET_CONST_NODE(prev_ppe->op0)) &&
2059  GetPointer<const integer_cst>(GET_CONST_NODE(prev_ppe->op1)))
2060  {
2061  const auto prev_val = tree_helper::GetConstValue(prev_ppe->op1);
2062  const auto new_offset = TM->CreateUniqueIntegerCst(
2063  (prev_val + cst_val), tree_helper::CGetType(ppe->op1));
2065  "---replace constant usage before: " + stmt->ToString());
2066  TM->ReplaceTreeNode(stmt, ppe->op1, new_offset);
2067  TM->ReplaceTreeNode(stmt, ppe->op0, prev_ppe->op0);
2069  "---replace constant usage after: " + stmt->ToString());
2070  modified = true;
2071  AppM->RegisterTransformation(GetName(), stmt);
2072  }
2073  }
2074  }
2075  }
2076  }
2077  };
2078  pointer_plus_expr_BVO();
2079  }
2080  else if(GET_CONST_NODE(ga->op1)->get_kind() == addr_expr_K)
2081  {
2082  auto addr_expr_BVO = [&] {
2083  const auto ae = GetPointer<const addr_expr>(GET_CONST_NODE(ga->op1));
2084  const auto ae_code = GET_CONST_NODE(ae->op)->get_kind();
2085  if(ae_code == mem_ref_K)
2086  {
2087  const auto MR = GetPointer<const mem_ref>(GET_CONST_NODE(ae->op));
2088  const auto op1_val = tree_helper::GetConstValue(MR->op1);
2089  if(op1_val == 0 && GET_CONST_NODE(MR->op0)->get_kind() == ssa_name_K)
2090  {
2091  const auto temp_def =
2092  GET_NODE(GetPointer<const ssa_name>(GET_CONST_NODE(MR->op0))->CGetDefStmt());
2093  if(temp_def->get_kind() == gimple_assign_K)
2094  {
2095  const auto prev_ga = GetPointer<const gimple_assign>(temp_def);
2096  if(GET_CONST_NODE(prev_ga->op1)->get_kind() == addr_expr_K)
2097  {
2098  condPropageValue(prev_ga->op0, DEBUG_CALLSITE);
2099  }
2100  }
2101  }
2102  else if(op1_val == 0 && GET_CONST_NODE(MR->op0)->get_kind() == integer_cst_K)
2103  {
2105  "---replace constant usage before: " + stmt->ToString());
2106  TM->ReplaceTreeNode(stmt, ga->op1, MR->op0);
2107  modified = true;
2109  "---replace constant usage after: " + stmt->ToString());
2110  }
2111  }
2112  };
2113  addr_expr_BVO();
2114  }
2115  else if(GET_NODE(ga->op1)->get_kind() == extract_bit_expr_K)
2116  {
2117  auto extract_bit_expr_BVO = [&] {
2118  const auto srcp_default =
2119  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
2120  const auto ebe = GetPointer<const extract_bit_expr>(GET_CONST_NODE(ga->op1));
2121  THROW_ASSERT(GET_CONST_NODE(ebe->op1)->get_kind() == integer_cst_K, "unexpected condition");
2122  const auto pos_value = tree_helper::GetConstValue(ebe->op1);
2123  THROW_ASSERT(pos_value >= 0, "");
2124  const auto ebe_op0_ssa = GetPointer<const ssa_name>(GET_CONST_NODE(ebe->op0));
2125  if(ebe_op0_ssa)
2126  {
2127  if(static_cast<integer_cst_t>(BitLatticeManipulator::Size(ebe->op0)) <= pos_value)
2128  {
2129  const auto right_id = GET_INDEX_CONST_NODE(ebe->op0);
2130  const bool right_signed = tree_helper::is_int(TM, right_id);
2131  if(right_signed)
2132  {
2134  "---replace extract_bit_expr usage before: " + stmt->ToString());
2135  const auto new_pos = TM->CreateUniqueIntegerCst(
2136  static_cast<integer_cst_t>(BitLatticeManipulator::Size(ebe->op0) - 1),
2137  tree_helper::CGetType(ebe->op1));
2138  const auto eb_op = IRman->create_extract_bit_expr(ebe->op0, new_pos, srcp_default);
2139  const auto eb_ga = IRman->CreateGimpleAssign(
2140  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2141  TM->CreateUniqueIntegerCst(1LL, ebe->type), eb_op, function_id, srcp_default);
2142  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga));
2143  B->PushBefore(eb_ga, stmt, AppM);
2144  const auto bit_mask_constant_node = TM->CreateUniqueIntegerCst(1, ebe->type);
2145  const auto masking = IRman->create_binary_operation(
2146  ebe->type, GetPointer<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0,
2147  bit_mask_constant_node, srcp_default, truth_and_expr_K);
2148  TM->ReplaceTreeNode(
2149  stmt, ga->op1,
2150  masking);
2152  "---replace extract_bit_expr usage after: " + stmt->ToString());
2153  modified = true;
2154  AppM->RegisterTransformation(GetName(), stmt);
2155  }
2156  else
2157  {
2159  "---replace extract_bit_expr usage before: " + stmt->ToString());
2160  const auto zero_node = TM->CreateUniqueIntegerCst(0LL, ebe->type);
2161  propagateValue(ssa, TM, ga->op0, zero_node, DEBUG_CALLSITE);
2162  }
2163  }
2164  else if(tree_helper::IsBooleanType(ebe->op0))
2165  {
2166  propagateValue(ssa, TM, ga->op0, ebe->op0, DEBUG_CALLSITE);
2167  }
2168  else
2169  {
2170  auto defStmt = GET_CONST_NODE(ebe_op0_ssa->CGetDefStmt());
2171  if(defStmt->get_kind() == gimple_assign_K)
2172  {
2173  const auto prev_ga = GetPointer<const gimple_assign>(defStmt);
2174  auto prev_code1 = GET_CONST_NODE(prev_ga->op1)->get_kind();
2175  if(prev_code1 == nop_expr_K || prev_code1 == convert_expr_K)
2176  {
2177  auto ne = GetPointer<const unary_expr>(GET_CONST_NODE(prev_ga->op1));
2178  if(tree_helper::IsBooleanType(ne->op))
2179  {
2180  if(pos_value == 0)
2181  {
2183  "---replace extract_bit_expr usage before: " +
2184  stmt->ToString());
2185  const auto bit_mask_constant_node =
2186  TM->CreateUniqueIntegerCst(1LL, ebe->type);
2187  const auto masking =
2188  IRman->create_binary_operation(ebe->type, ne->op, bit_mask_constant_node,
2189  srcp_default, truth_and_expr_K);
2190  TM->ReplaceTreeNode(
2191  stmt, ga->op1,
2192  masking);
2194  "---replace extract_bit_expr usage after: " +
2195  stmt->ToString());
2196  modified = true;
2197  AppM->RegisterTransformation(GetName(), stmt);
2198  }
2199  else
2200  {
2201  const auto zero_node = TM->CreateUniqueIntegerCst(0LL, ebe->type);
2202  propagateValue(ssa, TM, ga->op0, zero_node, DEBUG_CALLSITE);
2203  }
2204  }
2205  else
2206  {
2207  const auto neType_node = tree_helper::CGetType(ne->op);
2208  if(GET_CONST_NODE(neType_node)->get_kind() == integer_type_K)
2209  {
2210  if(static_cast<integer_cst_t>(BitLatticeManipulator::Size(ne->op)) >
2211  pos_value)
2212  {
2214  "---replace extract_bit_expr usage before: " +
2215  stmt->ToString());
2216  const auto eb_op =
2217  IRman->create_extract_bit_expr(ne->op, ebe->op1, srcp_default);
2218  const auto eb_ga = IRman->CreateGimpleAssign(
2219  ebe->type, TM->CreateUniqueIntegerCst(0LL, ebe->type),
2220  TM->CreateUniqueIntegerCst(1LL, ebe->type), eb_op, function_id,
2221  srcp_default);
2223  "---Created " + STR(eb_ga));
2224  B->PushBefore(eb_ga, stmt, AppM);
2225  const auto bit_mask_constant_node =
2226  TM->CreateUniqueIntegerCst(1LL, ebe->type);
2227  const auto masking = IRman->create_binary_operation(
2228  ebe->type, GetPointer<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0,
2229  bit_mask_constant_node, srcp_default, truth_and_expr_K);
2230  TM->ReplaceTreeNode(stmt, ga->op1,
2231  masking);
2234  "---replace extract_bit_expr usage after: " +
2235  stmt->ToString());
2236  modified = true;
2237  AppM->RegisterTransformation(GetName(), stmt);
2238  }
2239  else
2240  {
2241  const bool right_signed = tree_helper::IsSignedIntegerType(ne->op);
2242  if(right_signed)
2243  {
2245  "---replace extract_bit_expr usage before: " +
2246  stmt->ToString());
2247  const auto new_pos = TM->CreateUniqueIntegerCst(
2248  static_cast<integer_cst_t>(BitLatticeManipulator::Size(ne->op) - 1),
2249  tree_helper::CGetType(ebe->op1));
2250  const auto eb_op =
2251  IRman->create_extract_bit_expr(ne->op, new_pos, srcp_default);
2252  const auto eb_ga = IRman->CreateGimpleAssign(
2253  ebe->type, TM->CreateUniqueIntegerCst(0LL, ebe->type),
2254  TM->CreateUniqueIntegerCst(1LL, ebe->type), eb_op, function_id,
2255  srcp_default);
2257  "---Created " + STR(eb_ga));
2258  B->PushBefore(eb_ga, stmt, AppM);
2259  const auto bit_mask_constant_node =
2260  TM->CreateUniqueIntegerCst(1LL, ebe->type);
2261  const auto masking = IRman->create_binary_operation(
2262  ebe->type,
2263  GetPointer<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0,
2264  bit_mask_constant_node, srcp_default, truth_and_expr_K);
2265  TM->ReplaceTreeNode(stmt, ga->op1,
2266  masking);
2269  "---replace extract_bit_expr usage after: " +
2270  stmt->ToString());
2271  modified = true;
2272  AppM->RegisterTransformation(GetName(), stmt);
2273  }
2274  else
2275  {
2277  "---replace extract_bit_expr usage before: " +
2278  stmt->ToString());
2279  const auto zero_node = TM->CreateUniqueIntegerCst(0LL, ebe->type);
2280  propagateValue(ssa, TM, ga->op0, zero_node, DEBUG_CALLSITE);
2281  }
2282  }
2283  }
2284  }
2285  }
2286  else if(prev_code1 == bit_and_expr_K)
2287  {
2288  const auto bae = GetPointerS<const bit_and_expr>(GET_CONST_NODE(prev_ga->op1));
2289  if(GET_CONST_NODE(bae->op0)->get_kind() == integer_cst_K ||
2290  GET_CONST_NODE(bae->op1)->get_kind() == integer_cst_K)
2291  {
2292  auto bae_op0 = bae->op0;
2293  auto bae_op1 = bae->op1;
2294  if(GET_CONST_NODE(bae->op0)->get_kind() == integer_cst_K)
2295  {
2296  std::swap(bae_op0, bae_op1);
2297  }
2298  const auto bae_mask_value = tree_helper::GetConstValue(bae_op1);
2299  const auto masked_value = (bae_mask_value & (integer_cst_t(1) << pos_value));
2300  if(masked_value && GET_CONST_NODE(bae_op0)->get_kind() != integer_cst_K)
2301  {
2303  "---replace extract_bit_expr usage before: " +
2304  stmt->ToString());
2305  const auto eb_op =
2306  IRman->create_extract_bit_expr(bae_op0, ebe->op1, srcp_default);
2307  const auto eb_ga = IRman->CreateGimpleAssign(
2308  ebe->type, TM->CreateUniqueIntegerCst(0LL, ebe->type),
2309  TM->CreateUniqueIntegerCst(1LL, ebe->type), eb_op, function_id,
2310  srcp_default);
2312  "---Created " + STR(eb_ga));
2313  B->PushBefore(eb_ga, stmt, AppM);
2314  const auto bit_mask_constant_node = TM->CreateUniqueIntegerCst(1, ebe->type);
2315  const auto masking = IRman->create_binary_operation(
2316  ebe->type, GetPointer<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0,
2317  bit_mask_constant_node, srcp_default, truth_and_expr_K);
2318  TM->ReplaceTreeNode(
2319  stmt, ga->op1,
2320  masking);
2322  "---replace extract_bit_expr usage after: " +
2323  stmt->ToString());
2324  modified = true;
2325  AppM->RegisterTransformation(GetName(), stmt);
2326  }
2327  else
2328  {
2330  "---replace extract_bit_expr usage before: " +
2331  stmt->ToString());
2332  const auto zero_node =
2333  TM->CreateUniqueIntegerCst(masked_value ? 1 : 0, ebe->type);
2334  propagateValue(ssa, TM, ga->op0, zero_node, DEBUG_CALLSITE);
2335  }
2336  }
2337  }
2338  else if(prev_code1 == bit_ior_concat_expr_K)
2339  {
2340  const auto bice =
2341  GetPointerS<const bit_ior_concat_expr>(GET_CONST_NODE(prev_ga->op1));
2342  THROW_ASSERT(GET_NODE(bice->op2)->get_kind() == integer_cst_K,
2343  "unexpected condition");
2344  const auto nbit_value = tree_helper::GetConstValue(bice->op2);
2346  "---replace extract_bit_expr usage before: " + stmt->ToString());
2347  const auto eb_op = IRman->create_extract_bit_expr(
2348  nbit_value > pos_value ? bice->op1 : bice->op0, ebe->op1, srcp_default);
2349  const auto eb_ga = IRman->CreateGimpleAssign(
2350  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2351  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op, function_id, srcp_default);
2352  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga));
2353  B->PushBefore(eb_ga, stmt, AppM);
2354  const auto bit_mask_constant_node = TM->CreateUniqueIntegerCst(1, ebe->type);
2355  const auto masking = IRman->create_binary_operation(
2356  ebe->type, GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0,
2357  bit_mask_constant_node, srcp_default, truth_and_expr_K);
2358  TM->ReplaceTreeNode(
2359  stmt, ga->op1,
2360  masking);
2362  "---replace extract_bit_expr usage after: " + stmt->ToString());
2363  modified = true;
2364  AppM->RegisterTransformation(GetName(), stmt);
2365  }
2366  else if(prev_code1 == lshift_expr_K)
2367  {
2368  const auto lse = GetPointerS<const lshift_expr>(GET_CONST_NODE(prev_ga->op1));
2369  if(GET_CONST_NODE(lse->op1)->get_kind() == integer_cst_K)
2370  {
2371  const auto lsbit_value = tree_helper::GetConstValue(lse->op1);
2372  if((pos_value - lsbit_value) >= 0)
2373  {
2374  const auto new_pos = TM->CreateUniqueIntegerCst(
2375  pos_value - lsbit_value, tree_helper::CGetType(ebe->op1));
2377  "---replace extract_bit_expr usage before: " +
2378  stmt->ToString());
2379  const auto eb_op =
2380  IRman->create_extract_bit_expr(lse->op0, new_pos, srcp_default);
2381  const auto eb_ga = IRman->CreateGimpleAssign(
2382  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2383  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op, function_id,
2384  srcp_default);
2386  "---Created " + STR(eb_ga));
2387  B->PushBefore(eb_ga, stmt, AppM);
2388  const auto bit_mask_constant_node = TM->CreateUniqueIntegerCst(1, ebe->type);
2389  const auto masking = IRman->create_binary_operation(
2390  ebe->type, GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0,
2391  bit_mask_constant_node, srcp_default, truth_and_expr_K);
2392  TM->ReplaceTreeNode(
2393  stmt, ga->op1,
2394  masking);
2396  "---replace extract_bit_expr usage after: " +
2397  stmt->ToString());
2398  modified = true;
2399  AppM->RegisterTransformation(GetName(), stmt);
2400  }
2401  else
2402  {
2404  "---replace extract_bit_expr usage before: " +
2405  stmt->ToString());
2406  const auto zero_node = TM->CreateUniqueIntegerCst(0LL, ebe->type);
2407  propagateValue(ssa, TM, ga->op0, zero_node, DEBUG_CALLSITE);
2408  }
2409  }
2410  }
2411  else if(prev_code1 == rshift_expr_K)
2412  {
2413  const auto rse = GetPointerS<const rshift_expr>(GET_CONST_NODE(prev_ga->op1));
2414  if(GET_CONST_NODE(rse->op1)->get_kind() == integer_cst_K)
2415  {
2416  const auto rsbit_value = tree_helper::GetConstValue(rse->op1);
2417  THROW_ASSERT((pos_value + rsbit_value) >= 0, "unexpected condition");
2418  const auto new_pos = TM->CreateUniqueIntegerCst(pos_value + rsbit_value,
2419  tree_helper::CGetType(ebe->op1));
2421  "---replace extract_bit_expr usage before: " + stmt->ToString());
2422  const auto eb_op =
2423  IRman->create_extract_bit_expr(rse->op0, new_pos, srcp_default);
2424  const auto eb_ga = IRman->CreateGimpleAssign(
2425  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2426  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op, function_id, srcp_default);
2428  "---Created " + STR(eb_ga));
2429  B->PushBefore(eb_ga, stmt, AppM);
2430  const auto bit_mask_constant_node = TM->CreateUniqueIntegerCst(1, ebe->type);
2431  const auto masking = IRman->create_binary_operation(
2432  ebe->type, GetPointer<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0,
2433  bit_mask_constant_node, srcp_default, truth_and_expr_K);
2434  TM->ReplaceTreeNode(
2435  stmt, ga->op1,
2436  masking);
2438  "---replace extract_bit_expr usage after: " + stmt->ToString());
2439  modified = true;
2440  AppM->RegisterTransformation(GetName(), stmt);
2441  }
2442  else if(GET_CONST_NODE(rse->op0)->get_kind() == integer_cst_K)
2443  {
2444  const auto res_value =
2445  tree_helper::GetConstValue(rse->op0,
2446  tree_helper::IsSignedIntegerType(rse->op0)) >>
2447  pos_value;
2448  if(res_value)
2449  {
2450  if(max_lut_size > 0)
2451  {
2453  "---replace extract_bit_expr usage before: " +
2454  stmt->ToString());
2455  const auto precision = BitLatticeManipulator::Size(ebe_op0_ssa->type);
2456  unsigned int log2;
2457  for(log2 = 1; precision > (1u << log2); ++log2)
2458  {
2459  ;
2460  }
2461  tree_nodeRef op1, op2, op3, op4, op5, op6, op7, op8;
2462  for(auto i = 0u; i < log2; ++i)
2463  {
2464  const auto new_pos =
2466  const auto eb_op =
2467  IRman->create_extract_bit_expr(rse->op1, new_pos, srcp_default);
2468  const auto eb_ga = IRman->CreateGimpleAssign(
2469  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2470  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op, function_id,
2471  srcp_default);
2473  "---Created " + STR(eb_ga));
2474  B->PushBefore(eb_ga, stmt, AppM);
2475  const auto eb_ga_ssa_var =
2476  GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0;
2477  if(i == 0)
2478  {
2479  op1 = eb_ga_ssa_var;
2480  }
2481  else if(i == 1)
2482  {
2483  op2 = eb_ga_ssa_var;
2484  }
2485  else if(i == 2)
2486  {
2487  op3 = eb_ga_ssa_var;
2488  }
2489  else if(i == 3)
2490  {
2491  op4 = eb_ga_ssa_var;
2492  }
2493  else if(i == 4)
2494  {
2495  op5 = eb_ga_ssa_var;
2496  }
2497  else if(i == 5)
2498  {
2499  op6 = eb_ga_ssa_var;
2500  }
2501  else
2502  {
2503  THROW_ERROR("unexpected condition");
2504  }
2505  }
2506  const auto LutConstType = IRman->GetUnsignedLongLongType();
2507 
2508  const auto lut_constant_node =
2509  TM->CreateUniqueIntegerCst(res_value, LutConstType);
2510  const auto eb_op =
2511  IRman->create_lut_expr(ebe->type, lut_constant_node, op1, op2, op3,
2512  op4, op5, op6, op7, op8, srcp_default);
2513  const auto eb_ga = IRman->CreateGimpleAssign(
2514  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2515  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op, function_id,
2516  srcp_default);
2518  "---Created " + STR(eb_ga));
2519  B->PushBefore(eb_ga, stmt, AppM);
2520  const auto bit_mask_constant_node =
2521  TM->CreateUniqueIntegerCst(1, ebe->type);
2522  const auto masking = IRman->create_binary_operation(
2523  ebe->type,
2524  GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0,
2525  bit_mask_constant_node, srcp_default, truth_and_expr_K);
2526  TM->ReplaceTreeNode(stmt, ga->op1,
2527  masking);
2530  "---replace extract_bit_expr usage after: " +
2531  stmt->ToString());
2532  modified = true;
2533  AppM->RegisterTransformation(GetName(), stmt);
2534  }
2535  else
2536  {
2538  "---No lut allowed, lut replacement skipped...");
2539  }
2540  }
2541  else
2542  {
2543  const auto zero_node = TM->CreateUniqueIntegerCst(0, ebe->type);
2545  "---replace extract_bit_expr usage before: " +
2546  stmt->ToString());
2547  TM->ReplaceTreeNode(stmt, ga->op1, zero_node);
2549  "---replace extract_bit_expr usage after: " +
2550  stmt->ToString());
2551  modified = true;
2552  AppM->RegisterTransformation(GetName(), stmt);
2553  }
2554  }
2555  }
2556  else if(prev_code1 == bit_not_expr_K)
2557  {
2558  const auto bne = GetPointerS<const bit_not_expr>(GET_CONST_NODE(prev_ga->op1));
2560  "---replace extract_bit_expr usage before: " + stmt->ToString());
2561  const auto eb_op = IRman->create_extract_bit_expr(bne->op, ebe->op1, srcp_default);
2562  const auto eb_ga = IRman->CreateGimpleAssign(
2563  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2564  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op, function_id, srcp_default);
2565  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga));
2566  B->PushBefore(eb_ga, stmt, AppM);
2567  const auto negating = IRman->create_unary_operation(
2568  ebe->type, GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0,
2569  srcp_default, truth_not_expr_K);
2570  TM->ReplaceTreeNode(stmt, ga->op1, negating);
2572  "---replace extract_bit_expr usage after: " + stmt->ToString());
2573  modified = true;
2574  AppM->RegisterTransformation(GetName(), stmt);
2575  }
2576  else if(prev_code1 == bit_and_expr_K)
2577  {
2578  const auto bae = GetPointerS<const bit_and_expr>(GET_CONST_NODE(prev_ga->op1));
2580  "---replace extract_bit_expr usage before: " + stmt->ToString());
2581  const auto eb_op0 =
2582  IRman->create_extract_bit_expr(bae->op0, ebe->op1, srcp_default);
2583  const auto eb_ga0 = IRman->CreateGimpleAssign(
2584  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2585  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op0, function_id, srcp_default);
2586  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga0));
2587  B->PushBefore(eb_ga0, stmt, AppM);
2588  const auto eb_op1 =
2589  IRman->create_extract_bit_expr(bae->op1, ebe->op1, srcp_default);
2590  const auto eb_ga1 = IRman->CreateGimpleAssign(
2591  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2592  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op1, function_id, srcp_default);
2593  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga1));
2594  B->PushBefore(eb_ga1, stmt, AppM);
2595  const auto anding = IRman->create_binary_operation(
2596  ebe->type, GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga0))->op0,
2597  GetPointer<const gimple_assign>(GET_CONST_NODE(eb_ga1))->op0, srcp_default,
2598  truth_and_expr_K);
2599  TM->ReplaceTreeNode(stmt, ga->op1, anding);
2601  "---replace extract_bit_expr usage after: " + stmt->ToString());
2602  modified = true;
2603  AppM->RegisterTransformation(GetName(), stmt);
2604  }
2605  else if(prev_code1 == bit_ior_expr_K)
2606  {
2607  const auto bie = GetPointerS<const bit_ior_expr>(GET_CONST_NODE(prev_ga->op1));
2609  "---replace extract_bit_expr usage before: " + stmt->ToString());
2610  const auto eb_op0 =
2611  IRman->create_extract_bit_expr(bie->op0, ebe->op1, srcp_default);
2612  const auto eb_ga0 = IRman->CreateGimpleAssign(
2613  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2614  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op0, function_id, srcp_default);
2615  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga0));
2616  B->PushBefore(eb_ga0, stmt, AppM);
2617  const auto eb_op1 =
2618  IRman->create_extract_bit_expr(bie->op1, ebe->op1, srcp_default);
2619  const auto eb_ga1 = IRman->CreateGimpleAssign(
2620  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2621  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op1, function_id, srcp_default);
2622  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga1));
2623  B->PushBefore(eb_ga1, stmt, AppM);
2624  const auto anding = IRman->create_binary_operation(
2625  ebe->type, GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga0))->op0,
2626  GetPointer<const gimple_assign>(GET_CONST_NODE(eb_ga1))->op0, srcp_default,
2627  truth_or_expr_K);
2628  TM->ReplaceTreeNode(stmt, ga->op1, anding);
2630  "---replace extract_bit_expr usage after: " + stmt->ToString());
2631  modified = true;
2632  AppM->RegisterTransformation(GetName(), stmt);
2633  }
2634  else if(prev_code1 == bit_xor_expr_K)
2635  {
2636  const auto bxe = GetPointerS<const bit_xor_expr>(GET_CONST_NODE(prev_ga->op1));
2638  "---replace extract_bit_expr usage before: " + stmt->ToString());
2639  const auto eb_op0 =
2640  IRman->create_extract_bit_expr(bxe->op0, ebe->op1, srcp_default);
2641  const auto eb_ga0 = IRman->CreateGimpleAssign(
2642  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2643  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op0, function_id, srcp_default);
2644  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga0));
2645  B->PushBefore(eb_ga0, stmt, AppM);
2646  const auto eb_op1 =
2647  IRman->create_extract_bit_expr(bxe->op1, ebe->op1, srcp_default);
2648  const auto eb_ga1 = IRman->CreateGimpleAssign(
2649  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2650  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op1, function_id, srcp_default);
2651  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga1));
2652  B->PushBefore(eb_ga1, stmt, AppM);
2653  const auto anding = IRman->create_binary_operation(
2654  ebe->type, GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga0))->op0,
2655  GetPointer<const gimple_assign>(GET_CONST_NODE(eb_ga1))->op0, srcp_default,
2656  truth_xor_expr_K);
2657  TM->ReplaceTreeNode(stmt, ga->op1, anding);
2659  "---replace extract_bit_expr usage after: " + stmt->ToString());
2660  modified = true;
2661  AppM->RegisterTransformation(GetName(), stmt);
2662  }
2663  else if(prev_code1 == cond_expr_K)
2664  {
2665  const auto ce = GetPointerS<const cond_expr>(GET_CONST_NODE(prev_ga->op1));
2667  "---replace extract_bit_expr usage before: " + stmt->ToString());
2668  const auto eb_op1 = IRman->create_extract_bit_expr(ce->op1, ebe->op1, srcp_default);
2669  const auto eb_ga1 = IRman->CreateGimpleAssign(
2670  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2671  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op1, function_id, srcp_default);
2672  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga1));
2673  B->PushBefore(eb_ga1, stmt, AppM);
2674  const auto eb_op2 = IRman->create_extract_bit_expr(ce->op2, ebe->op1, srcp_default);
2675  const auto eb_ga2 = IRman->CreateGimpleAssign(
2676  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2677  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op2, function_id, srcp_default);
2678  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga2));
2679  B->PushBefore(eb_ga2, stmt, AppM);
2680  const auto ceRes = IRman->create_ternary_operation(
2681  ebe->type, ce->op0,
2682  GetPointer<const gimple_assign>(GET_CONST_NODE(eb_ga1))->op0,
2683  GetPointer<const gimple_assign>(GET_CONST_NODE(eb_ga2))->op0, srcp_default,
2684  cond_expr_K);
2685  TM->ReplaceTreeNode(stmt, ga->op1, ceRes);
2687  "---replace extract_bit_expr usage after: " + stmt->ToString());
2688  modified = true;
2689  AppM->RegisterTransformation(GetName(), stmt);
2690  }
2691  else if(prev_code1 == plus_expr_K)
2692  {
2693  const auto pe = GetPointerS<const plus_expr>(GET_CONST_NODE(prev_ga->op1));
2694  if(GET_CONST_NODE(pe->op1)->get_kind() == integer_cst_K &&
2695  BitLatticeManipulator::Size(ebe->op0) <= max_lut_size)
2696  {
2698  "---replace extract_bit_expr usage before: " + stmt->ToString());
2699  auto carry = TM->CreateUniqueIntegerCst(0, ebe->type);
2700  tree_nodeRef sum;
2701  for(integer_cst_t bitIndex = 0; bitIndex <= pos_value; ++bitIndex)
2702  {
2703  const auto bitIndex_node =
2704  TM->CreateUniqueIntegerCst(bitIndex, tree_helper::CGetType(ebe->op1));
2705  const auto eb_op1 =
2706  IRman->create_extract_bit_expr(pe->op0, bitIndex_node, srcp_default);
2707  const auto eb_ga1 = IRman->CreateGimpleAssign(
2708  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2709  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op1, function_id,
2710  srcp_default);
2712  "---Created " + STR(eb_ga1));
2713  B->PushBefore(eb_ga1, stmt, AppM);
2714  const auto eb_op2 =
2715  IRman->create_extract_bit_expr(pe->op1, bitIndex_node, srcp_default);
2716  const auto eb_ga2 = IRman->CreateGimpleAssign(
2717  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2718  TM->CreateUniqueIntegerCst(1, ebe->type), eb_op2, function_id,
2719  srcp_default);
2721  "---Created " + STR(eb_ga2));
2722  B->PushBefore(eb_ga2, stmt, AppM);
2723  const auto sum0 = IRman->create_binary_operation(
2724  ebe->type, GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga1))->op0,
2725  GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga2))->op0,
2726  srcp_default, truth_xor_expr_K);
2727  const auto sum0_ga1 = IRman->CreateGimpleAssign(
2728  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2729  TM->CreateUniqueIntegerCst(1, ebe->type), sum0, function_id,
2730  srcp_default);
2732  "---Created " + STR(sum0_ga1));
2733  B->PushBefore(sum0_ga1, stmt, AppM);
2734  sum = IRman->create_binary_operation(
2735  ebe->type,
2736  GetPointerS<const gimple_assign>(GET_CONST_NODE(sum0_ga1))->op0, carry,
2737  srcp_default, truth_xor_expr_K);
2738  if(bitIndex < pos_value)
2739  {
2740  const auto sum_ga1 = IRman->CreateGimpleAssign(
2741  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2742  TM->CreateUniqueIntegerCst(1, ebe->type), sum, function_id,
2743  srcp_default);
2745  "---Created " + STR(sum_ga1));
2746  B->PushBefore(sum_ga1, stmt, AppM);
2747 
2748  const auto and1 = IRman->create_binary_operation(
2749  ebe->type,
2750  GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga1))->op0, carry,
2751  srcp_default, truth_and_expr_K);
2752  const auto and1_ga = IRman->CreateGimpleAssign(
2753  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2754  TM->CreateUniqueIntegerCst(1, ebe->type), and1, function_id,
2755  srcp_default);
2757  "---Created " + STR(and1_ga));
2758  B->PushBefore(and1_ga, stmt, AppM);
2759 
2760  const auto and2 = IRman->create_binary_operation(
2761  ebe->type,
2762  GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga2))->op0, carry,
2763  srcp_default, truth_and_expr_K);
2764  const auto and2_ga = IRman->CreateGimpleAssign(
2765  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2766  TM->CreateUniqueIntegerCst(1, ebe->type), and2, function_id,
2767  srcp_default);
2769  "---Created " + STR(and2_ga));
2770  B->PushBefore(and2_ga, stmt, AppM);
2771 
2772  const auto and3 = IRman->create_binary_operation(
2773  ebe->type,
2774  GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga1))->op0,
2775  GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga2))->op0,
2776  srcp_default, truth_and_expr_K);
2777  const auto and3_ga = IRman->CreateGimpleAssign(
2778  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2779  TM->CreateUniqueIntegerCst(1, ebe->type), and3, function_id,
2780  srcp_default);
2782  "---Created " + STR(and3_ga));
2783  B->PushBefore(and3_ga, stmt, AppM);
2784 
2785  const auto or1 = IRman->create_binary_operation(
2786  ebe->type,
2787  GetPointerS<const gimple_assign>(GET_CONST_NODE(and1_ga))->op0,
2788  GetPointerS<const gimple_assign>(GET_CONST_NODE(and2_ga))->op0,
2789  srcp_default, truth_or_expr_K);
2790  const auto or1_ga = IRman->CreateGimpleAssign(
2791  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2792  TM->CreateUniqueIntegerCst(1, ebe->type), or1, function_id,
2793  srcp_default);
2795  "---Created " + STR(or1_ga));
2796  B->PushBefore(or1_ga, stmt, AppM);
2797 
2798  const auto carry1 = IRman->create_binary_operation(
2799  ebe->type,
2800  GetPointerS<const gimple_assign>(GET_CONST_NODE(or1_ga))->op0,
2801  GetPointerS<const gimple_assign>(GET_CONST_NODE(and3_ga))->op0,
2802  srcp_default, truth_or_expr_K);
2803  const auto carry1_ga = IRman->CreateGimpleAssign(
2804  ebe->type, TM->CreateUniqueIntegerCst(0, ebe->type),
2805  TM->CreateUniqueIntegerCst(1, ebe->type), carry1, function_id,
2806  srcp_default);
2808  "---Created " + STR(carry1_ga));
2809  B->PushBefore(carry1_ga, stmt, AppM);
2810  carry = GetPointerS<const gimple_assign>(GET_CONST_NODE(carry1_ga))->op0;
2811  }
2812  }
2813  TM->ReplaceTreeNode(stmt, ga->op1, sum);
2815  "---replace extract_bit_expr usage after: " + stmt->ToString());
2816  modified = true;
2817  AppM->RegisterTransformation(GetName(), stmt);
2818  }
2819  }
2820  }
2821  }
2822  }
2823  else if(GET_CONST_NODE(ebe->op0)->get_kind() == integer_cst_K)
2824  {
2825  const auto res_value =
2827  pos_value) &
2828  1) != 0;
2829  const auto res_node = TM->CreateUniqueIntegerCst(res_value, ebe->type);
2830  propagateValue(ssa, TM, ga->op0, res_node, DEBUG_CALLSITE);
2831  }
2832  };
2833  extract_bit_expr_BVO();
2834  }
2835  else if(GET_CONST_NODE(ga->op1)->get_kind() == nop_expr_K)
2836  {
2837  auto nop_expr_BVO = [&] {
2838  const auto ne = GetPointerS<const nop_expr>(GET_CONST_NODE(ga->op1));
2839  if(tree_helper::IsBooleanType(ga->op0))
2840  {
2841  if(tree_helper::IsBooleanType(ne->op))
2842  {
2843  propagateValue(ssa, TM, ga->op0, ne->op, DEBUG_CALLSITE);
2844  }
2845  else
2846  {
2847  const auto ne_op_ssa = GetPointer<const ssa_name>(GET_CONST_NODE(ne->op));
2848  if(ne_op_ssa)
2849  {
2850  if(GET_CONST_NODE(ne_op_ssa->type)->get_kind() == integer_type_K)
2851  {
2853  "---replace extract_bit_expr usage before: " + stmt->ToString());
2854  const auto indexType = IRman->GetUnsignedLongLongType();
2855  const auto zero_node = TM->CreateUniqueIntegerCst(0, indexType);
2856  const auto srcp_default =
2857  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
2858  const auto eb_op = IRman->create_extract_bit_expr(ne->op, zero_node, srcp_default);
2859  const auto eb_ga = IRman->CreateGimpleAssign(
2860  ne->type, TM->CreateUniqueIntegerCst(0, ne->type),
2861  TM->CreateUniqueIntegerCst(1, ne->type), eb_op, function_id, srcp_default);
2862  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + STR(eb_ga));
2863  B->PushBefore(eb_ga, stmt, AppM);
2864  const auto bit_mask_constant_node = TM->CreateUniqueIntegerCst(1, ne->type);
2865  const auto masking = IRman->create_binary_operation(
2866  ne->type, GetPointerS<const gimple_assign>(GET_CONST_NODE(eb_ga))->op0,
2867  bit_mask_constant_node, srcp_default, truth_and_expr_K);
2868  TM->ReplaceTreeNode(
2869  stmt, ga->op1,
2870  masking);
2872  "---replace extract_bit_expr usage after: " + stmt->ToString());
2873  modified = true;
2874  AppM->RegisterTransformation(GetName(), stmt);
2875  }
2876  }
2877  }
2878  }
2879  else if(tree_helper::IsSameType(ga->op0, ne->op))
2880  {
2881  auto bw_op1 = tree_helper::Size(ne->op);
2882  auto bw_op0 = tree_helper::Size(ga->op0);
2883 
2884  if(bw_op1 <= bw_op0)
2885  {
2886  propagateValue(ssa, TM, ga->op0, ne->op, DEBUG_CALLSITE);
2887  }
2888  }
2889  };
2890  nop_expr_BVO();
2891  }
2892  };
2893  ga_BVO();
2894  }
2895  }
2896  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Statement analyzed " + GET_NODE(stmt)->ToString());
2897  }
2898  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--BB analyzed " + STR(B->number));
2899  for(const auto& phi : B->CGetPhiList())
2900  {
2903  auto pn = GetPointerS<gimple_phi>(GET_CONST_NODE(phi));
2904  bool is_virtual = pn->virtual_flag;
2905  if(!is_virtual)
2906  {
2908  const auto ssa = GetPointer<const ssa_name>(GET_CONST_NODE(pn->res));
2909  if(ssa && !ssa->bit_values.empty())
2910  {
2911  const auto& bit_values = ssa->bit_values;
2912  const auto is_constant = is_bit_values_constant(bit_values);
2913  if(is_constant)
2914  {
2915  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Left part is constant " + bit_values);
2916  const auto const_value =
2917  convert_bitvalue_to_integer_cst(bit_values, TM, GET_INDEX_CONST_NODE(pn->res));
2918  const auto val = TM->CreateUniqueIntegerCst(const_value, tree_helper::CGetType(pn->res));
2919 
2920  propagateValue(ssa, TM, pn->res, val, DEBUG_CALLSITE);
2921  if(AppM->ApplyNewTransformation())
2922  {
2923  pn->res = TM->GetTreeReindex(ssa->index);
2924  THROW_ASSERT(ssa->CGetUseStmts().empty(), "unexpected case");
2925  AppM->RegisterTransformation(GetName(), phi);
2926  }
2927  }
2928  }
2929  }
2930  }
2931  }
2932 }
#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) ...
tree_nodeRef CreateNotExpr(const tree_nodeConstRef &condition, const blocRef &block, unsigned int function_decl_nid) const
UTILITY.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
const TreeNodeMap< size_t > & CGetUseStmts() const
Return the use stmts.
Definition: tree_node.cpp:1343
Data structure representing the entire HLS information.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
RangeRef range
Range information about numerical values of the SSA variable.
Definition: tree_node.hpp:4601
File containing functions and utilities to support the printing of debug messagges.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
static bool is_int(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of integer type.
std::string ToString() const
Print this node as string in gimple format.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
Step successfully executed.
const tree_nodeRef CGetTreeReindex(const unsigned int i) const
Return a tree_reindex wrapping the i-th tree_node.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
void ReplaceTreeNode(const tree_nodeRef &stmt, const tree_nodeRef &old_node, const tree_nodeRef &new_node)
Replace the occurrences of tree node old_node with new_node in statement identified by tn...
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
const int output_level
The output level.
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.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
struct definition of the source position.
Definition: tree_node.hpp:832
RelationshipType
The relationship type.
struct definition of the function_decl tree node.
Definition: tree_node.hpp:2759
Source must be executed to satisfy target.
void optimize(const function_decl *fd, tree_managerRef TM, tree_manipulationRef IRman)
do bit value based optimization such as:
mathematical utility function not provided by standard libraries
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
Definition: Range.hpp:63
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.
#define min(x, y)
static void shl(size_t p[2], int n)
Bit_Value_opt(const ParameterConstRef _Param, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
Data structure describing a basic block at tree level.
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.
std::string include_name
include_name is a filename string, this can be the location of a reference, if no definition has been...
Definition: tree_node.hpp:839
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
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.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
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.
std::string convert_to_binary(G _value, unsigned long long precision)
Definition: utility.hpp:110
int sum
Definition: dotproduct.h:3
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
tree_nodeRef create_lut_expr(const tree_nodeConstRef &type, const tree_nodeRef &op0, const tree_nodeRef &op1, const tree_nodeRef &op2, const tree_nodeRef &op3, const tree_nodeRef &op4, const tree_nodeRef &op5, const tree_nodeRef &op6, const tree_nodeRef &op7, const tree_nodeRef &op8, const std::string &srcp) const
create_lut_expr: function used to create a generic lut_expr operation
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
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
~Bit_Value_opt() override
Destructor.
tree_nodeRef CreateUniqueRealCst(long double value, const tree_nodeConstRef &type)
memoization of integer constants
Classes to describe design flow graph.
tree_nodeRef body
body field is the saved representation of the body of the entire function.
Definition: tree_node.hpp:2870
tree_nodeRef CreateUniqueIntegerCst(integer_cst_t value, const tree_nodeConstRef &type)
memoization of integer constants
#define index(x, y)
Definition: Keccak.c:74
tree_nodeRef GetTreeReindex(const unsigned int i)
Return a tree_reindex wrapping the i-th tree_node.
static integer_cst_t convert_bitvalue_to_integer_cst(const std::string &bit_values, tree_managerRef TM, unsigned int var_id)
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
DesignFlowStep_Status GetStatus() const
Return the status of this design step.
static unsigned long long Size(const tree_nodeConstRef &t)
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
This file collects some utility functions and macros.
Call graph hierarchy.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
static bool is_a_pointer(const tree_managerConstRef &TM, const unsigned int index)
Return if treenode index is a pointer.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
Wrapper of design_flow.
const CustomUnorderedSet< std::pair< FrontendFlowStepType, FunctionRelationship > > ComputeFrontendRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
tree_nodeRef GetBooleanType() const
Function that creates a boolean type if it is not already present, otherwise it returns the one that ...
This file collects some utility functions.
static void constrainSSA(ssa_name *op_ssa, tree_managerRef TM)
std::vector< tree_nodeRef > list_of_args
args field holds a chain of parm_decl nodes for the arguments.
Definition: tree_node.hpp:2841
Definition: APInt.hpp:53
Class performing some optimizations on the IR exploiting Bit Value analysis.
DesignFlowStep_Status InternalExec() override
Optimize IR after the BitValue/BitValueIPA has been executed.
static bool is_bit_values_constant(const std::string &bit_values)
void propagateValue(const ssa_name *ssa, tree_managerRef TM, tree_nodeRef old_val, tree_nodeRef new_val, const std::string callSiteString)
tree_nodeRef create_ternary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op0, const tree_nodeRef &op1, const tree_nodeRef &op2, const std::string &srcp, enum kind operation_kind) const
Function used to create a ternary expression.
const unsigned int function_id
The index of the function to be analyzed.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
tree_nodeRef min
minimum values this SSA may reach
Definition: tree_node.hpp:4592
tree_nodeRef GetUnsignedLongLongType() const
Function that creates a long long unsigned int type if it is not already present, otherwise return th...
static bool is_a_complex(const tree_managerConstRef &TM, const unsigned int index)
Return if treenode index is a complex.
This class contains the methods to create a frontend flow step.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
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.
Classes specification of the tree_node data structures not present in the gcc.
this class is used to manage the command-line or XML options.
tree_nodeRef create_extract_bit_expr(const tree_nodeRef &op0, const tree_nodeRef &op1, const std::string &srcp) const
tree_nodeRef create_ssa_name(const tree_nodeConstRef &var, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, bool volatile_flag=false, bool virtual_flag=false) const
MISCELLANEOUS_OBJ_TREE_NODES.
unsigned int bitvalue_version
The version of the bitvalue information on which this step has been applied.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
Definition: tree_node.hpp:212
std::string bit_values
for each bit of the SSA variable tells if it is equal to U,X,0,1
Definition: tree_node.hpp:4598
This struct specifies the ssa_name node.
Definition: tree_node.hpp:4523
bool modified
when true IR has been modified
static bool is_a_vector(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode index is a vector.
Wrapper to call graph.
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.
tree_nodeRef type
starting from GCC 4.7.2 ssa_name has a type
Definition: tree_node.hpp:4540
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
static bool IsPointerType(const tree_nodeConstRef &type)
Return true if treenode index is a pointer.
#define DEBUG_CALLSITE
Autoheader include.
#define B
Definition: generate.c:14
tree_nodeRef max
maximum values this SSA may reach
Definition: tree_node.hpp:4595
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
Class specification of the manager of the tree structures extracted from the raw file.
HLS specialization of generic_device.
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 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:51 for PandA-2024.02 by doxygen 1.8.13