PandA-2024.02
Bit_Value.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  */
54 #include "Bit_Value.hpp"
56 
58 #include "Dominance.hpp"
59 #include "Parameter.hpp"
60 #include "basic_block.hpp"
61 
63 #include "application_manager.hpp"
64 #include "call_graph.hpp"
65 #include "call_graph_manager.hpp"
66 #include "function_behavior.hpp"
67 #include "op_graph.hpp"
68 
70 #include "design_flow_manager.hpp"
71 
73 #include "Range.hpp"
75 
77 #include "hls_device.hpp"
78 #include "hls_manager.hpp"
79 
81 #include "memory.hpp"
82 
84 #include <cmath>
85 #include <fstream>
86 #include <string>
87 
89 #include <deque>
90 #include <tuple>
91 #include <utility>
92 #include <vector>
93 
94 #include "custom_map.hpp"
95 #include "custom_set.hpp"
96 
98 #include "behavioral_helper.hpp"
99 #include "tree_basic_block.hpp"
100 #include "tree_helper.hpp"
101 #include "tree_manager.hpp"
102 #include "tree_reindex.hpp"
103 
105 #include "compiler_wrapper.hpp"
106 #include "string_manipulation.hpp" // for GET_CLASS
107 
108 const std::map<bit_lattice, std::map<bit_lattice, std::map<bit_lattice, std::deque<bit_lattice>>>>
110  // a b carry
111  {
113  {
114  {
116  {
117  {
120  },
121  {
124  },
125  {
128  },
129  },
130  },
131  {
133  {
134  {
137  },
138  {
141  },
142  {
145  },
146  },
147  },
148  {
150  {
151  {
154  },
155  {
158  },
159  {
162  },
163  },
164  },
165  {
167  {
168  {
171  },
172  {
175  },
176  {
179  },
180  },
181  },
182  },
183  },
184  {
186  {
187  {
189  {
190  {
193  },
194  {
197  },
198  {
201  },
202  },
203  },
204  {
206  {
207  {
210  },
211  {
214  },
215  {
218  },
219  },
220  },
221  {
223  {
224  {
227  },
228  {
231  },
232  {
235  },
236  },
237  },
238  {
240  {
241  {
244  },
245  {
248  },
249  {
252  },
253  },
254  },
255  },
256  },
257  {
259  {
260  {
262  {
263  {
266  },
267  {
270  },
271  {
274  },
275  },
276  },
277  {
279  {
280  {
283  },
284  {
287  },
288  {
291  },
292  },
293  },
294  {
296  {
297  {
300  },
301  {
304  },
305  {
308  },
309  },
310  },
311  {
313  {
314  {
317  },
318  {
321  },
322  {
325  },
326  },
327  },
328  },
329  },
330  {
332  {
333  {
335  {
336  {
339  },
340  {
343  },
344  {
347  },
348  },
349  },
350  {
352  {
353  {
356  },
357  {
360  },
361  {
364  },
365  },
366  },
367  {
369  {
370  {
373  },
374  {
377  },
378  {
381  },
382  },
383  },
384  {
386  {
387  {
390  },
391  {
394  },
395  {
398  },
399  },
400  },
401  },
402  },
403 };
404 
405 const std::map<bit_lattice, std::map<bit_lattice, std::map<bit_lattice, std::deque<bit_lattice>>>>
407  // a b borrow
408  {
410  {
411  {
413  {
414  {
417  },
418  {
421  },
422  {
425  },
426  },
427  },
428  {
430  {
431  {
434  },
435  {
438  },
439  {
442  },
443  },
444  },
445  {
447  {
448  {
451  },
452  {
455  },
456  {
459  },
460  },
461  },
462  {
464  {
465  {
468  },
469  {
472  },
473  {
476  },
477  },
478  },
479  },
480  },
481  {
483  {
484  {
486  {
487  {
490  },
491  {
494  },
495  {
498  },
499  },
500  },
501  {
503  {
504  {
507  },
508  {
511  },
512  {
515  },
516  },
517  },
518  {
520  {
521  {
524  },
525  {
528  },
529  {
532  },
533  },
534  },
535  {
537  {
538  {
541  },
542  {
545  },
546  {
549  },
550  },
551  },
552  },
553  },
554  {
556  {
557  {
559  {
560  {
563  },
564  {
567  },
568  {
571  },
572  },
573  },
574  {
576  {
577  {
580  },
581  {
584  },
585  {
588  },
589  },
590  },
591  {
593  {
594  {
597  },
598  {
601  },
602  {
605  },
606  },
607  },
608  {
610  {
611  {
614  },
615  {
618  },
619  {
622  },
623  },
624  },
625  },
626  },
627  {
629  {
630  {
632  {
633  {
636  },
637  {
640  },
641  {
644  },
645  },
646  },
647  {
649  {
650  {
653  },
654  {
657  },
658  {
661  },
662  },
663  },
664  {
666  {
667  {
670  },
671  {
674  },
675  {
678  },
679  },
680  },
681  {
683  {
684  {
687  },
688  {
691  },
692  {
695  },
696  },
697  },
698  },
699  },
700 };
701 
702 const std::map<bit_lattice, std::map<bit_lattice, bit_lattice>> Bit_Value::bit_ior_expr_map = {
703  {
705  {
710  },
711  },
712  {
714  {
716  {bit_lattice::ONE, bit_lattice::ONE},
717  {bit_lattice::U, bit_lattice::ONE},
718  {bit_lattice::X, bit_lattice::ONE},
719  },
720  },
721  {
723  {
726  {bit_lattice::U, bit_lattice::U},
728  },
729  },
730  {
732  {
735  {bit_lattice::U, bit_lattice::X},
736  {bit_lattice::X, bit_lattice::X},
737  },
738  },
739 };
740 
741 const std::map<bit_lattice, std::map<bit_lattice, bit_lattice>> Bit_Value::bit_xor_expr_map = {
742  {
744  {
749  },
750  },
751  {
753  {
758  },
759  },
760  {
762  {
764  {bit_lattice::ONE, bit_lattice::U},
765  {bit_lattice::U, bit_lattice::U},
767  },
768  },
769  {
771  {
773  {bit_lattice::ONE, bit_lattice::X},
774  {bit_lattice::U, bit_lattice::X},
775  {bit_lattice::X, bit_lattice::X},
776  },
777  },
778 };
779 
780 const std::map<bit_lattice, std::map<bit_lattice, bit_lattice>> Bit_Value::bit_and_expr_map = {
781  {
783  {
785  {bit_lattice::ONE, bit_lattice::ZERO},
786  {bit_lattice::U, bit_lattice::ZERO},
787  {bit_lattice::X, bit_lattice::ZERO},
788  },
789  },
790  {
792  {
797  },
798  },
799  {
801  {
804  {bit_lattice::U, bit_lattice::U},
806  },
807  },
808  {
810  {
813  {bit_lattice::U, bit_lattice::X},
814  {bit_lattice::X, bit_lattice::X},
815  },
816  },
817 };
818 
819 unsigned long long Bit_Value::pointer_resizing(unsigned int output_id) const
820 {
822  "-->Pointer resizing starting from " + TM->CGetTreeNode(output_id)->ToString());
823  unsigned int var = tree_helper::get_base_index(TM, output_id);
824  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Base variable is " + TM->CGetTreeNode(var)->ToString());
825  unsigned long long address_bitsize;
826  if(not_frontend)
827  {
828  auto* hm = GetPointer<HLS_manager>(AppM);
829  if(hm and hm->Rmem)
830  {
831  if(var and function_behavior->is_variable_mem(var))
832  {
833  unsigned long long int max_addr =
834  hm->Rmem->get_base_address(var, function_id) + BitLatticeManipulator::size(TM, var) / 8;
835  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Maximum address is " + STR(max_addr - 1));
836  for(address_bitsize = 1; max_addr > (1ull << address_bitsize); ++address_bitsize)
837  {
838  ;
839  }
841  if(address_bitsize < 4)
842  {
843  address_bitsize = 4;
844  }
846  auto vd = GetPointer<const var_decl>(TM->CGetTreeNode(var));
847  if(hm->Rmem->get_base_address(var, function_id) == 0 && vd)
848  {
849  auto align = vd->algn;
850  align = align < 8 ? 1 : (align / 8);
851  auto index = 0u;
852  bool found = false;
853  for(; index < address_bitsize; ++index)
854  {
855  if((1ULL << index) & align)
856  {
857  found = true;
858  break;
859  }
860  }
861  if(!found)
862  {
863  ++address_bitsize;
864  }
865  }
866  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Memory variable " + STR(address_bitsize));
867  }
868  else
869  {
870  address_bitsize = hm->get_address_bitsize();
871  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Address bus bitsize " + STR(address_bitsize));
872  }
873  }
874  else
875  {
876  address_bitsize = AppM->get_address_bitsize();
877  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Address bitsize " + STR(address_bitsize));
878  }
879  }
880  else
881  {
882  address_bitsize = static_cast<unsigned int>(CompilerWrapper::CGetPointerSize(parameters));
883  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Pointer bitsize " + STR(address_bitsize));
884  }
885  return address_bitsize;
886 }
887 
888 unsigned int Bit_Value::lsb_to_zero(const addr_expr* ae, bool safe) const
889 {
890  const auto vd = GetPointer<const var_decl>(GET_CONST_NODE(ae->op));
891  if(!vd)
892  {
893  return 0;
894  }
895  auto align = vd->algn;
896  if(safe)
897  {
898  align = 1;
899  }
900  else
901  {
902  align = align < 64 ? 8 : (align / 8);
903  }
904  auto index = 0u;
905  bool found = false;
906  for(; index < AppM->get_address_bitsize(); ++index)
907  {
908  if((1ULL << index) & align)
909  {
910  found = true;
911  break;
912  }
913  }
914  return found ? index : 0;
915 }
916 
918  const DesignFlowManagerConstRef dfm)
919  : FunctionFrontendFlowStep(AM, f_id, BIT_VALUE, dfm, params),
920  BitLatticeManipulator(AM->get_tree_manager(), parameters->get_class_debug_level(GET_CLASS(*this))),
922 {
923  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
924 }
925 
926 Bit_Value::~Bit_Value() = default;
927 
930 {
932  switch(relationship_type)
933  {
935  {
936  relationships.insert(std::make_pair(BIT_VALUE, CALLED_FUNCTIONS));
937  relationships.insert(std::make_pair(CALL_GRAPH_BUILTIN_CALL, SAME_FUNCTION));
938  relationships.insert(std::make_pair(COMPUTE_IMPLICIT_CALLS, SAME_FUNCTION));
939  relationships.insert(std::make_pair(DETERMINE_MEMORY_ACCESSES, SAME_FUNCTION));
940  relationships.insert(std::make_pair(ESSA, SAME_FUNCTION));
941  relationships.insert(std::make_pair(EXTRACT_GIMPLE_COND_OP, SAME_FUNCTION));
942  relationships.insert(std::make_pair(FIX_STRUCTS_PASSED_BY_VALUE, SAME_FUNCTION));
943  relationships.insert(std::make_pair(FUNCTION_CALL_TYPE_CLEANUP, SAME_FUNCTION));
944  relationships.insert(std::make_pair(IR_LOWERING, SAME_FUNCTION));
945  relationships.insert(std::make_pair(PARM2SSA, SAME_FUNCTION));
946  if(parameters->isOption(OPT_soft_float) && parameters->getOption<bool>(OPT_soft_float))
947  {
948  relationships.insert(std::make_pair(SOFT_FLOAT_CG_EXT, SAME_FUNCTION));
949  }
950  relationships.insert(std::make_pair(UN_COMPARISON_LOWERING, SAME_FUNCTION));
951  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
952  break;
953  }
955  {
956  break;
957  }
959  {
960  break;
961  }
962  default:
963  THROW_UNREACHABLE("");
964  }
965  return relationships;
966 }
967 
969 {
971 }
972 
974 {
975  const auto bambu_frontend_flow_signature =
976  ApplicationFrontendFlowStep::ComputeSignature(FrontendFlowStepType::BAMBU_FRONTEND_FLOW);
977  not_frontend = design_flow_manager.lock()->GetStatus(bambu_frontend_flow_signature) == DesignFlowStep_Status::EMPTY;
978 
979  const auto tn = TM->CGetTreeNode(function_id);
980  THROW_ASSERT(tn->get_kind() == function_decl_K, "Node is not a function");
981  const auto fd = GetPointerS<const function_decl>(tn);
982  THROW_ASSERT(fd->body, "Function has not a body");
983  const auto sl = GetPointerS<const statement_list>(GET_CONST_NODE(fd->body));
985  BBGraphsCollectionRef bb_graphs_collection(
987  BBGraph cfg(bb_graphs_collection, CFG_SELECTOR);
988  CustomUnorderedMap<unsigned int, vertex> inverse_vertex_map;
990  for(const auto& block : sl->list_of_bloc)
991  {
992  inverse_vertex_map.insert(
993  std::make_pair(block.first, bb_graphs_collection->AddVertex(BBNodeInfoRef(new BBNodeInfo(block.second)))));
994  }
995 
997  for(const auto& curr_bb_pair : sl->list_of_bloc)
998  {
999  const auto curr_bbi = curr_bb_pair.first;
1000  const auto curr_bb = curr_bb_pair.second;
1001  for(const auto& lop : curr_bb->list_of_pred)
1002  {
1003  THROW_ASSERT(static_cast<bool>(inverse_vertex_map.count(lop)),
1004  "BB" + STR(lop) + " (successor of BB" + STR(curr_bbi) + ") does not exist");
1005  bb_graphs_collection->AddEdge(inverse_vertex_map.at(lop), inverse_vertex_map.at(curr_bbi), CFG_SELECTOR);
1006  }
1007 
1008  for(const auto& los : curr_bb->list_of_succ)
1009  {
1010  if(los == bloc::EXIT_BLOCK_ID)
1011  {
1012  bb_graphs_collection->AddEdge(inverse_vertex_map.at(curr_bbi), inverse_vertex_map.at(los), CFG_SELECTOR);
1013  }
1014  }
1015 
1016  if(curr_bb->list_of_succ.empty())
1017  {
1018  bb_graphs_collection->AddEdge(inverse_vertex_map.at(curr_bbi), inverse_vertex_map.at(bloc::EXIT_BLOCK_ID),
1019  CFG_SELECTOR);
1020  }
1021  }
1023  bb_graphs_collection->AddEdge(inverse_vertex_map.at(bloc::ENTRY_BLOCK_ID),
1024  inverse_vertex_map.at(bloc::EXIT_BLOCK_ID), CFG_SELECTOR);
1025  dominance<BBGraph> bb_dominators(cfg, inverse_vertex_map.at(bloc::ENTRY_BLOCK_ID),
1026  inverse_vertex_map.at(bloc::EXIT_BLOCK_ID), parameters);
1028 
1029  BBGraphRef dt(new BBGraph(bb_graphs_collection, D_SELECTOR));
1030  for(const auto& it : bb_dominators.get_dominator_map())
1031  {
1032  if(it.first != inverse_vertex_map.at(bloc::ENTRY_BLOCK_ID))
1033  {
1034  bb_graphs_collection->AddEdge(it.second, it.first, D_SELECTOR);
1035  }
1036  }
1037  dt->GetBBGraphInfo()->bb_index_map = std::move(inverse_vertex_map);
1038 
1039  std::list<vertex> v_topological;
1040  dt->TopologicalSort(v_topological);
1041  THROW_ASSERT(v_topological.size(), "");
1042  bb_topological.reserve(v_topological.size());
1043  std::transform(v_topological.begin(), v_topological.end(), std::back_inserter(bb_topological),
1044  [&](const vertex& v) { return dt->CGetBBNodeInfo(v)->block; });
1045 }
1046 
1048 {
1049  if(parameters->IsParameter("bitvalue") && !parameters->GetParameter<unsigned int>("bitvalue"))
1050  {
1052  }
1053  initialize();
1054  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Performing initial backward");
1055  backward();
1056  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Performed initial backward");
1057  mix();
1058  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "best at the end of initial backward:");
1061  bool restart;
1062  do
1063  {
1064  clear_current();
1065  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Performing forward");
1066  forward();
1067  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Performed forward");
1068  mix();
1069  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "best at the end of forward:");
1072  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Performing backward");
1073  backward();
1074  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Performed backward");
1075  restart = mix();
1076  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "best at end of backward:");
1079  } while(restart);
1080  bb_topological.clear();
1081  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "best at the end of alg:");
1083  auto changed = update_IR();
1086  arguments.clear();
1087  if(changed)
1088  {
1089  function_behavior->UpdateBitValueVersion();
1090  }
1092 }
1093 
1094 // prints the content of a bitstring map
1095 void Bit_Value::print_bitstring_map(const CustomMap<unsigned int, std::deque<bit_lattice>>&
1096 #ifndef NDEBUG
1097  map
1098 #endif
1099 ) const
1100 {
1101 #ifndef NDEBUG
1102  const auto BH = function_behavior->CGetBehavioralHelper();
1103  for(const auto& m : map)
1104  {
1106  "var_uid: " + STR(m.first) + ":" + BH->PrintVariable(m.first) +
1107  " bitstring: " + bitstring_to_string(m.second));
1108  }
1109 #endif
1110 }
1111 
1113 {
1114  bool res = false;
1115  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->Updating IR");
1116  for(const auto& b : best)
1117  {
1118  const auto tn_id = b.first;
1119  const auto tn = TM->GetTreeNode(tn_id);
1120  const auto kind = tn->get_kind();
1121  if(kind == ssa_name_K)
1122  {
1123  auto ssa = GetPointerS<ssa_name>(tn);
1124  if(ssa->bit_values.empty() || BitLatticeManipulator::isBetter(bitstring_to_string(b.second), ssa->bit_values))
1125  {
1126  if(!AppM->ApplyNewTransformation())
1127  {
1128  break;
1129  }
1131  "Variable: " + ssa->ToString() + " bitstring: " + ssa->bit_values + " -> " +
1132  bitstring_to_string(b.second));
1133  ssa->bit_values = bitstring_to_string(b.second);
1134  // ssa->range = Range::fromBitValues(b.second, static_cast<Range::bw_t>(BitLatticeManipulator::Size(tn)),
1135  // signed_var.count(ssa->index));
1136  res = true;
1137  AppM->RegisterTransformation(GetName(), tn);
1138  }
1139  }
1140  else if(kind == function_decl_K)
1141  {
1142  auto fd = GetPointerS<function_decl>(tn);
1143  if(fd->bit_values.empty() || BitLatticeManipulator::isBetter(bitstring_to_string(b.second), fd->bit_values))
1144  {
1145  if(!AppM->ApplyNewTransformation())
1146  {
1147  break;
1148  }
1150  "Function: " + tree_helper::name_function(TM, b.first) + " bitstring: " + fd->bit_values +
1151  " -> " + bitstring_to_string(b.second));
1152  fd->bit_values = bitstring_to_string(b.second);
1153  res = true;
1154  AppM->RegisterTransformation(GetName(), tn);
1155  }
1156  }
1157  else if(kind == integer_cst_K || kind == real_cst_K)
1158  {
1159  // do nothing, constants are recomputed every time
1160  }
1161  else
1162  {
1163  THROW_ERROR("unexpected condition: variable of kind " + tn->get_kind_text());
1164  }
1165  }
1166  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Updated IR");
1167 
1168  return res;
1169 }
1170 
1172 {
1173  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Internal initialize");
1176  arguments.clear();
1177 
1178  const auto CGMan = AppM->CGetCallGraphManager();
1179  const auto cg = CGMan->CGetCallGraph();
1180  const auto v = CGMan->GetVertex(function_id);
1181 
1182  const auto rbf = CGMan->GetReachedBodyFunctions();
1183  OutEdgeIterator oe_it, oe_end;
1184  boost::tie(oe_it, oe_end) = boost::out_edges(v, *cg);
1185  for(; oe_it != oe_end; oe_it++)
1186  {
1187  const auto call_edge_info = cg->CGetFunctionEdgeInfo(*oe_it);
1188  for(const auto& i : call_edge_info->direct_call_points)
1189  {
1190  const auto called_id = CGMan->get_function(boost::target(*oe_it, *cg));
1191  if(i == 0)
1192  {
1193  // never analyze artificial calls
1194  THROW_ASSERT(AppM->CGetFunctionBehavior(called_id)->CGetBehavioralHelper()->get_function_name() == MEMCPY,
1195  "function " + function_behavior->CGetBehavioralHelper()->get_function_name() +
1196  " calls function " +
1197  AppM->CGetFunctionBehavior(called_id)->CGetBehavioralHelper()->get_function_name() +
1198  " with an artificial call: this should not happen");
1199  continue;
1200  }
1201  if(rbf.find(called_id) != rbf.end())
1202  {
1203  direct_call_id_to_called_id[i] = called_id;
1204  }
1205  }
1206  }
1207 
1208  const auto tn = TM->CGetTreeNode(function_id);
1209  const auto fd = GetPointerS<const function_decl>(tn);
1210 
1211  /*
1212  * loop on the list of arguments and initialize best
1213  */
1214  for(const auto& parm_decl_node : fd->list_of_args)
1215  {
1216  const auto parmssa_id = AppM->getSSAFromParm(function_id, GET_INDEX_CONST_NODE(parm_decl_node));
1217  const auto parm_type = tree_helper::CGetType(parm_decl_node);
1218  if(!IsHandledByBitvalue(parm_type))
1219  {
1220  continue;
1221  }
1222  const auto parmssa = TM->CGetTreeNode(parmssa_id);
1223  const auto p = GetPointerS<const ssa_name>(parmssa);
1224  const auto b = p->CGetUseStmts().empty() ?
1225  create_x_bitstring(1) :
1226  (p->bit_values.empty() ? create_u_bitstring(BitLatticeManipulator::Size(parmssa)) :
1227  string_to_bitstring(p->bit_values));
1228  best[parmssa_id] = b;
1229  arguments.insert(parmssa_id);
1231  "Parameter " + STR(GET_CONST_NODE(parm_decl_node)) + "(" +
1232  STR(GET_INDEX_CONST_NODE(parm_decl_node)) + ") bound to " + parmssa->ToString() + ": " +
1233  bitstring_to_string(b) + "");
1234  }
1235 
1236  /*
1237  * initialize the bitvalue strings for the return value that have been set on
1238  * the function_decl from the BitValueIPA
1239  */
1240  const auto fu_type = tree_helper::CGetType(tn);
1241  const auto fret_type_node = tree_helper::GetFunctionReturnType(fu_type);
1242 
1243  if(!fret_type_node || !IsHandledByBitvalue(fret_type_node))
1244  {
1246  "Function returning " + (fret_type_node ? STR(fret_type_node) : "void") + " not considered");
1247  }
1248  else
1249  {
1250  const auto is_signed = tree_helper::IsSignedIntegerType(fret_type_node);
1251  if(fd->bit_values.empty())
1252  {
1253  best[function_id] = fd->range ? fd->range->getBitValues(is_signed) :
1255  }
1256  else
1257  {
1258  best[function_id] = string_to_bitstring(fd->bit_values);
1259  }
1260 
1262  if(is_signed)
1263  {
1265  signed_var.insert(function_id);
1266  }
1267  }
1268 
1269  {
1270  /*
1271  * Compute initialization bitstrings for ssa loaded from ROMs. This
1272  * initialization has to be performed before the other ssa are initialized
1273  * because we must be sure that bitstrings computed in previous executions
1274  * of bitvalues analysis are not thrown away before computing inf() on
1275  * bitvalues used for ROMs. If this initialization is interleaved with the
1276  * initialization of bitvalues of other ssa we may lose some information,
1277  * because some of the old bitstrings attached to ssa are cleared during the
1278  * initialization. If this happens, optimizations on ROMs cannot be
1279  * aggressive enough, with worse cycles and DSP usage for CHStone benchmarks
1280  */
1282  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Initializing ROMs loaded ssa bitvalues");
1283  for(const auto& B : bb_topological)
1284  {
1285  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Analyzing BB" + STR(B->number));
1287  for(const auto& stmt : B->CGetStmtList())
1288  {
1289  const auto stmt_node = GET_CONST_NODE(stmt);
1290  if(stmt_node->get_kind() == gimple_assign_K)
1291  {
1292  const auto ga = GetPointerS<const gimple_assign>(stmt_node);
1293  THROW_ASSERT(!ga->clobber, "");
1294  const auto lhs = GET_CONST_NODE(ga->op0);
1295  // handle lhs
1296  if(lhs->get_kind() == ssa_name_K)
1297  {
1298  const auto lhs_nid = GET_INDEX_CONST_NODE(ga->op0);
1300  "Analyzing " + stmt_node->get_kind_text() + "(" + STR(stmt_node->index) +
1301  "): " + STR(stmt_node));
1302  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---LHS: " + STR(lhs));
1304  "---RHS: " + GET_CONST_NODE(ga->op1)->get_kind_text());
1305 
1306  if(!IsHandledByBitvalue(lhs))
1307  {
1309  "---variable " + STR(GetPointerS<const ssa_name>(lhs)) + " of type " +
1310  STR(tree_helper::CGetType(lhs)) + " not considered");
1311  }
1312  else
1313  {
1314  const auto lhs_signed = tree_helper::IsSignedIntegerType(lhs);
1315  if(lhs_signed)
1316  {
1318  signed_var.insert(lhs_nid);
1319  }
1321  const auto ga_op1_kind = GET_CONST_NODE(ga->op1)->get_kind();
1322  if(ga_op1_kind == array_ref_K || ga_op1_kind == mem_ref_K || ga_op1_kind == target_mem_ref_K ||
1323  ga_op1_kind == target_mem_ref461_K || ga_op1_kind == var_decl_K)
1324  {
1325  const auto hm = GetPointer<const HLS_manager>(AppM);
1326  const auto base_index = tree_helper::get_base_index(TM, GET_INDEX_CONST_NODE(ga->op1));
1327  const auto var_node = TM->GetTreeNode(base_index);
1328  auto vd = GetPointer<var_decl>(var_node);
1329  if(base_index &&
1330  AppM->get_written_objects().find(base_index) == AppM->get_written_objects().end() && hm &&
1331  hm->Rmem && hm->Rmem->get_enable_hls_bit_value() &&
1332  function_behavior->is_variable_mem(base_index) && hm->Rmem->is_sds_var(base_index) && vd &&
1333  vd->init)
1334  {
1335  std::deque<bit_lattice> current_inf;
1336  if(GET_CONST_NODE(vd->init)->get_kind() == constructor_K)
1337  {
1338  current_inf = constructor_bitstring(GET_CONST_NODE(vd->init), lhs_nid);
1339  }
1340  else if(GET_CONST_NODE(vd->init)->get_kind() == integer_cst_K)
1341  {
1342  const auto cst_val = tree_helper::GetConstValue(vd->init);
1343  current_inf = create_bitstring_from_constant(
1344  cst_val, BitLatticeManipulator::Size(GET_CONST_NODE(vd->init)),
1346  }
1347  else if(GET_CONST_NODE(vd->init)->get_kind() == string_cst_K)
1348  {
1349  current_inf = string_cst_bitstring(GET_CONST_NODE(vd->init), lhs_nid);
1350  }
1351  else
1352  {
1353  current_inf = create_u_bitstring(BitLatticeManipulator::Size(lhs));
1354  }
1355 
1357  "---Used the init bitstring " + bitstring_to_string(current_inf));
1358 
1359  vd->bit_values = bitstring_to_string(current_inf);
1360  best[lhs_nid] = current_inf;
1361  }
1362  else
1363  {
1365  }
1367  if(base_index &&
1368  AppM->get_written_objects().find(base_index) != AppM->get_written_objects().end() && hm &&
1369  hm->Rmem && hm->Rmem->get_enable_hls_bit_value() &&
1370  function_behavior->is_variable_mem(base_index) && hm->Rmem->is_private_memory(base_index) &&
1371  hm->Rmem->is_sds_var(base_index))
1372  {
1373  if(vd)
1374  {
1375  if(!private_variables.count(base_index))
1376  {
1377  std::deque<bit_lattice> current_inf;
1378  if(vd->init)
1379  {
1380  if(GET_CONST_NODE(vd->init)->get_kind() == constructor_K)
1381  {
1382  current_inf = constructor_bitstring(GET_CONST_NODE(vd->init), lhs_nid);
1383  }
1384  else if(GET_CONST_NODE(vd->init)->get_kind() == integer_cst_K)
1385  {
1386  const auto cst_val = tree_helper::GetConstValue(vd->init);
1387  current_inf = create_bitstring_from_constant(
1388  cst_val, BitLatticeManipulator::Size(GET_CONST_NODE(vd->init)),
1390  }
1391  else if(GET_CONST_NODE(vd->init)->get_kind() == string_cst_K)
1392  {
1393  current_inf = string_cst_bitstring(GET_CONST_NODE(vd->init), lhs_nid);
1394  }
1395  else
1396  {
1397  current_inf = create_u_bitstring(BitLatticeManipulator::Size(lhs));
1398  }
1399  }
1400  else
1401  {
1402  current_inf.push_back(bit_lattice::X);
1403  }
1406  "---Computed the init bitstring for " +
1407  function_behavior->CGetBehavioralHelper()->PrintVariable(base_index) + " = " +
1408  bitstring_to_string(current_inf));
1409  for(const auto& cur_var : hm->Rmem->get_source_values(base_index))
1410  {
1411  const auto cur_node = TM->CGetTreeNode(cur_var);
1412  const auto source_is_signed = tree_helper::IsSignedIntegerType(cur_node);
1413  const auto source_type = tree_helper::CGetType(cur_node);
1414  const auto source_type_size = BitLatticeManipulator::Size(source_type);
1416  "---source node: " + STR(cur_node) + " source is signed: " +
1417  STR(source_is_signed) + " loaded is signed: " + STR(lhs_signed));
1418  std::deque<bit_lattice> cur_bitstring;
1419  if(cur_node->get_kind() == ssa_name_K)
1420  {
1421  const auto ssa = GetPointerS<const ssa_name>(cur_node);
1422  if(!IsHandledByBitvalue(source_type))
1423  {
1425  "---Not handled by bitvalue");
1426  cur_bitstring = create_u_bitstring(BitLatticeManipulator::Size(cur_node));
1427  }
1428  else
1429  {
1431  "---Is handled by bitvalue");
1432  cur_bitstring = string_to_bitstring(ssa->bit_values);
1433  }
1434  }
1435  else if(cur_node->get_kind() == integer_cst_K)
1436  {
1437  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---Integer constant");
1438  const auto cst_val = tree_helper::GetConstValue(cur_node);
1439  cur_bitstring =
1440  create_bitstring_from_constant(cst_val, source_type_size, lhs_signed);
1441  }
1442  else
1443  {
1444  cur_bitstring = create_u_bitstring(BitLatticeManipulator::Size(cur_node));
1445  }
1446  if(cur_bitstring.size() != 0)
1447  {
1449  "---bitstring = " + bitstring_to_string(cur_bitstring));
1450  if(cur_bitstring.size() < source_type_size && source_is_signed != lhs_signed)
1451  {
1452  cur_bitstring =
1453  sign_extend_bitstring(cur_bitstring, source_is_signed, source_type_size);
1455  "---bitstring = " + bitstring_to_string(cur_bitstring));
1456  }
1457  sign_reduce_bitstring(cur_bitstring, lhs_signed);
1459  "---bitstring = " + bitstring_to_string(cur_bitstring));
1460  }
1461  else
1462  {
1464  "---bitstring empty --> using U");
1465  cur_bitstring = create_u_bitstring(BitLatticeManipulator::Size(cur_node));
1467  "---bitstring = " + bitstring_to_string(cur_bitstring));
1468  }
1469  current_inf = inf(current_inf, cur_bitstring, lhs);
1471  "---inf = " + bitstring_to_string(current_inf));
1472  }
1473  while(current_inf.front() == bit_lattice::X)
1474  {
1475  current_inf.pop_front();
1476  }
1477  if(current_inf.empty())
1478  {
1479  current_inf.push_back(bit_lattice::ZERO);
1480  }
1481  THROW_ASSERT(std::find(current_inf.begin(), current_inf.end(), bit_lattice::X) ==
1482  current_inf.end(),
1483  "Init bitstring must not contain X: " + bitstring_to_string(current_inf));
1484  vd->bit_values = bitstring_to_string(current_inf);
1487  "---Bit Value: variable " +
1488  function_behavior->CGetBehavioralHelper()->PrintVariable(base_index) +
1489  " trimmed to bitsize: " + STR(vd->bit_values.size()) +
1490  " with bit-value pattern: " + vd->bit_values);
1491  private_variables[base_index] = current_inf;
1492  }
1493  const auto var_inf = private_variables.at(base_index);
1495  "---Init bitstring for a private written memory variable " +
1496  bitstring_to_string(var_inf));
1497  best[lhs_nid] = var_inf;
1498  }
1499  }
1500  }
1501  }
1503  "Analyzed " + stmt_node->get_kind_text() + ": " + STR(stmt_node));
1504  }
1505  }
1506  else if(stmt_node->get_kind() == gimple_asm_K)
1507  {
1508  const auto ga = GetPointerS<const gimple_asm>(stmt_node);
1509  if(ga->out)
1510  {
1511  const auto tl = GetPointer<const tree_list>(GET_CONST_NODE(ga->out));
1512  THROW_ASSERT(tl->valu, "only the first output and so only single output gimple_asm are supported");
1513  const auto ssa = GetPointer<const ssa_name>(GET_CONST_NODE(tl->valu));
1514  if(ssa && !ssa->CGetUseStmts().empty() && IsHandledByBitvalue(tl->valu))
1515  {
1517  "Analyzing " + stmt_node->get_kind_text() + "(" + STR(stmt_node->index) + ")");
1519  "---Initializing bitstring for an asm instruction");
1520  best[GET_INDEX_CONST_NODE(tl->valu)] =
1522  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Analyzed " + stmt_node->get_kind_text());
1523  }
1524  }
1525  }
1526  }
1528  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Analyzed BB" + STR(B->number));
1529  }
1530  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Initialized ROMs loaded ssa bitvalues");
1531  }
1532 
1533  const auto set_value = [&](unsigned int node_id) {
1534  if(node_id == 0)
1535  {
1536  return;
1537  }
1538  auto use_node = TM->GetTreeNode(node_id);
1539  if(!IsHandledByBitvalue(use_node))
1540  {
1542  "---variable " + STR(use_node) + " of type " + STR(tree_helper::CGetType(use_node)) +
1543  " not considered");
1544  return;
1545  }
1546 
1547  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->Use: " + STR(use_node));
1548  if(use_node->get_kind() == ssa_name_K)
1549  {
1550  const auto ssa = GetPointerS<ssa_name>(use_node);
1551  const auto ssa_is_signed = tree_helper::IsSignedIntegerType(use_node);
1552  if(ssa_is_signed)
1553  {
1555  signed_var.insert(node_id);
1556  }
1557  if(ssa->volatile_flag)
1558  {
1559  ssa->bit_values.clear();
1560  best[node_id] = create_u_bitstring(BitLatticeManipulator::Size(use_node));
1561  }
1562  else
1563  {
1564  const auto def = ssa->CGetDefStmt();
1565  if(!def || (ssa->var != nullptr && ((GET_CONST_NODE(def)->get_kind() == gimple_nop_K)) &&
1566  GET_CONST_NODE(ssa->var)->get_kind() == var_decl_K))
1567  {
1568  ssa->bit_values.clear();
1569  best[node_id] = create_bitstring_from_constant(0, 1, ssa_is_signed);
1570  if(ssa->var)
1571  {
1573  "---first version of uninitialized var " + STR(GET_CONST_NODE(ssa->var)));
1574  }
1575  else
1576  {
1577  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---uninitialized ssa");
1578  }
1579  if(AppM->ApplyNewTransformation())
1580  {
1581  const auto tree_man = AppM->get_tree_manager();
1582  const auto ssa_node = tree_man->GetTreeReindex(node_id);
1583  const auto cst_value = tree_man->CreateUniqueIntegerCst(0, ssa->type);
1584  const auto uses = ssa->CGetUseStmts();
1585  for(const auto& stmt_use : uses)
1586  {
1587  tree_man->ReplaceTreeNode(stmt_use.first, ssa_node, cst_value);
1588  }
1589  AppM->RegisterTransformation(GetName(), ssa_node);
1590  use_node = GET_NODE(cst_value);
1591  node_id = GET_INDEX_NODE(cst_value);
1592  }
1593  }
1594  }
1595  }
1596 
1597  if(use_node->get_kind() == integer_cst_K)
1598  {
1599  const auto cst_val = tree_helper::GetConstValue(use_node);
1600  const auto is_signed = tree_helper::IsSignedIntegerType(use_node);
1601  best[node_id] = create_bitstring_from_constant(cst_val, BitLatticeManipulator::Size(use_node), is_signed);
1602  if(is_signed)
1603  {
1605  signed_var.insert(node_id);
1606  }
1607  sign_reduce_bitstring(best.at(node_id), is_signed);
1609  "---updated bitstring: " + bitstring_to_string(best.at(node_id)));
1610  }
1612  };
1613 
1614  /*
1615  * now do the real initialization on all the basic blocks
1616  */
1617  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Initializing all ssa bitvalues");
1618  for(const auto& B : bb_topological)
1619  {
1620  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Analyzing BB" + STR(B->number));
1622 
1623  for(const auto& phi : B->CGetPhiList())
1624  {
1626  "Analyzing phi(" + STR(GET_INDEX_CONST_NODE(phi)) + "): " + STR(phi));
1627  const auto pn = GetPointerS<const gimple_phi>(GET_CONST_NODE(phi));
1628  const auto is_virtual = pn->virtual_flag;
1629  if(!is_virtual)
1630  {
1631  const auto res_nid = GET_INDEX_CONST_NODE(pn->res);
1632  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---LHS: " + STR(res_nid));
1633  auto ssa = GetPointer<ssa_name>(GET_NODE(pn->res));
1634  THROW_ASSERT(ssa, "unexpected condition");
1635  if(!IsHandledByBitvalue(pn->res))
1636  {
1638  "---variable " + STR(ssa) + " of type " + STR(tree_helper::CGetType(pn->res)) +
1639  " not considered id: " + STR(res_nid));
1640  continue;
1641  }
1643  {
1645  signed_var.insert(res_nid);
1646  }
1647  if(bb_version == 0 || bb_version != function_behavior->GetBBVersion())
1648  {
1649  ssa->bit_values.clear();
1650  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---bit_values cleared : " + STR(ssa));
1651  }
1652 
1653  if(ssa->CGetUseStmts().empty())
1654  {
1655  best[res_nid] = create_x_bitstring(1);
1656  if(best.count(res_nid))
1657  {
1659  "---updated bitstring: " + bitstring_to_string(best.at(res_nid)));
1660  }
1661  }
1662  else
1663  {
1664  if(ssa->bit_values.empty())
1665  {
1667  }
1668  else
1669  {
1670  best[res_nid] = string_to_bitstring(ssa->bit_values);
1671  }
1672  if(best.count(res_nid))
1673  {
1675  "---updated bitstring: " + bitstring_to_string(best.at(res_nid)));
1676  }
1677 
1678  for(const auto& def_edge : pn->CGetDefEdgesList())
1679  {
1680  set_value(GET_INDEX_CONST_NODE(def_edge.first));
1681  }
1682  }
1683  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Analyzed phi: " + STR(phi));
1684  }
1685  }
1686 
1687  for(const auto& stmt : B->CGetStmtList())
1688  {
1689  // ga->op1 is equal to var_decl when it binds a newly declared variable to an ssa variable. ie. int a;
1690  // we can skip this assignment and focus on the ssa variable
1691  const auto stmt_node = GET_CONST_NODE(stmt);
1693  "Analyzing " + stmt_node->get_kind_text() + "(" + STR(GET_INDEX_CONST_NODE(stmt)) +
1694  "): " + STR(stmt_node));
1695  if(stmt_node->get_kind() == gimple_assign_K)
1696  {
1697  const auto ga = GetPointerS<const gimple_assign>(stmt_node);
1698  THROW_ASSERT(!ga->clobber, "");
1699 
1700  const auto lhs = GET_NODE(ga->op0);
1701  // handle lhs
1702  if(lhs->get_kind() == ssa_name_K)
1703  {
1704  auto lhs_ssa = GetPointerS<ssa_name>(lhs);
1705  const auto lhs_nid = GET_INDEX_CONST_NODE(ga->op0);
1706  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->LHS: " + STR(lhs_ssa));
1707  if(!IsHandledByBitvalue(lhs))
1708  {
1710  "---variable " + STR(lhs_ssa) + " of type " + STR(tree_helper::CGetType(lhs)) +
1711  " not considered");
1712  }
1713  else
1714  {
1715  if(bb_version == 0 || bb_version != function_behavior->GetBBVersion())
1716  {
1717  lhs_ssa->bit_values.clear();
1718  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---bit_values cleared : " + STR(lhs_ssa));
1719  }
1720  const auto lhs_signed = tree_helper::IsSignedIntegerType(lhs);
1721  if(lhs_signed)
1722  {
1724  signed_var.insert(lhs_nid);
1725  }
1726 
1727  const auto ga_op1_kind = GET_CONST_NODE(ga->op1)->get_kind();
1728  if(lhs_ssa->CGetUseStmts().empty())
1729  {
1730  best[lhs_nid] = create_x_bitstring(1);
1731  }
1733  else if(ga_op1_kind == array_ref_K || ga_op1_kind == mem_ref_K || ga_op1_kind == target_mem_ref_K ||
1734  ga_op1_kind == target_mem_ref461_K || ga_op1_kind == var_decl_K)
1735  {
1736  // this computation was moved above, to make sure that no
1737  // bitstrings (computed by previous execution of the same
1738  // bitvalue analysis step) are cleared from ssa variables
1739  // before computation of bitvalues for ssa read from ROMs
1740  THROW_ASSERT(best.find(lhs_nid) != best.end(), "");
1741  }
1742  /*if(tree_helper::is_a_pointer(TM, lhs_nid))
1743  {
1744  HLS_manager* hm = GetPointer<HLS_manager>(AppM);
1745  unsigned int var = tree_helper::get_base_index(TM, lhs_nid);
1746  if(var && hm && hm->Rmem && hm->Rmem->get_enable_hls_bit_value() &&
1747  function_behavior->is_variable_mem(var)) best[lhs_nid] = create_u_bitstring(pointer_resizing(AppM,
1748  lhs_nid, function_behavior, function_id, not_frontend, parameters)); else best[lhs_nid] =
1749  create_u_bitstring (BitLatticeManipulator::Size(GET_NODE(ga->op0)));
1750  }*/
1751  else if(ga_op1_kind == call_expr_K || ga_op1_kind == aggr_init_expr_K)
1752  {
1753  const auto ce = GetPointerS<const call_expr>(GET_CONST_NODE(ga->op1));
1754  if(GET_CONST_NODE(ce->fn)->get_kind() == addr_expr_K)
1755  {
1756  const auto addr_node = GET_CONST_NODE(ce->fn);
1757  const auto ae = GetPointerS<const addr_expr>(addr_node);
1758  const auto fu_decl_node = GET_CONST_NODE(ae->op);
1759  THROW_ASSERT(fu_decl_node->get_kind() == function_decl_K, "node " + STR(fu_decl_node) +
1760  " is not function_decl but " +
1761  fu_decl_node->get_kind_text());
1762  const auto ret_type_node = tree_helper::GetFunctionReturnType(fu_decl_node);
1763  if(IsHandledByBitvalue(ret_type_node))
1764  {
1765  const auto called_fd = GetPointer<const function_decl>(fu_decl_node);
1766  const auto new_bitvalue =
1767  called_fd->bit_values.empty() ?
1768  (called_fd->range ?
1769  called_fd->range->getBitValues(
1770  tree_helper::IsSignedIntegerType(ret_type_node)) :
1772  string_to_bitstring(called_fd->bit_values);
1773  if(best[lhs_nid].empty())
1774  {
1775  best[lhs_nid] = new_bitvalue;
1776  }
1777  else
1778  {
1779  best[lhs_nid] = sup(new_bitvalue, best[lhs_nid], lhs);
1780  }
1781  }
1782  }
1783  else if(GET_CONST_NODE(ce->fn)->get_kind() != ssa_name_K)
1784  {
1785  THROW_UNREACHABLE("call node " + STR(GET_CONST_NODE(ce->fn)) + " is a " +
1786  GET_CONST_NODE(ce->fn)->get_kind_text());
1787  }
1788  }
1789  else if(ga_op1_kind == lut_expr_K)
1790  {
1791  best[lhs_nid] = create_u_bitstring(1);
1792  }
1793  else if(ga_op1_kind == extract_bit_expr_K)
1794  {
1795  best[lhs_nid] = create_u_bitstring(1);
1796  }
1797  else
1798  {
1799  if(lhs_ssa->bit_values.empty())
1800  {
1801  auto u_string = create_u_bitstring(BitLatticeManipulator::Size(lhs));
1802  if(lhs_signed && tree_helper::is_natural(TM, GET_INDEX_CONST_NODE(ga->op0)))
1803  {
1804  u_string.pop_front();
1805  u_string.push_front(bit_lattice::ZERO);
1806  }
1807  best[lhs_nid] = u_string;
1808  }
1809  else
1810  {
1811  best[lhs_nid] = string_to_bitstring(lhs_ssa->bit_values);
1812  }
1813  }
1814  THROW_ASSERT(best.count(lhs_nid), "");
1816  "---updated bitstring: " + bitstring_to_string(best.at(lhs_nid)));
1817  }
1818  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "RHS: " + GET_CONST_NODE(ga->op1)->get_kind_text());
1820  }
1821  }
1822  else if(stmt_node->get_kind() == gimple_asm_K)
1823  {
1824  const auto ga = GetPointerS<const gimple_asm>(stmt_node);
1825  if(ga->out)
1826  {
1827  const auto tl = GetPointer<const tree_list>(GET_CONST_NODE(ga->out));
1828  THROW_ASSERT(tl->valu, "only the first output and so only single output gimple_asm are supported");
1829  const auto out_node = GET_CONST_NODE(tl->valu);
1830  auto out_ssa = GetPointer<ssa_name>(out_node);
1831  if(out_ssa && !out_ssa->CGetUseStmts().empty())
1832  {
1833  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->out: " + STR(out_ssa));
1834 
1835  if(!IsHandledByBitvalue(out_node))
1836  {
1838  "---variable of type " + STR(tree_helper::CGetType(out_node)) + " not considered");
1839  }
1840  else
1841  {
1842  out_ssa->bit_values.clear();
1843  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---bit_values cleared : " + STR(out_ssa));
1844  if(tree_helper::IsSignedIntegerType(out_node))
1845  {
1847  signed_var.insert(out_node->index);
1848  }
1849  best[out_node->index] = create_u_bitstring(BitLatticeManipulator::Size(out_node));
1851  "---updated bitstring: " + bitstring_to_string(best.at(out_node->index)));
1852  }
1854  }
1855  }
1856  }
1857  else
1858  {
1860  "---LHS unhandled for statement kind: " + STR(stmt_node->index));
1861  }
1862 
1863  std::vector<std::tuple<unsigned int, unsigned int>> vars_read;
1864  tree_helper::get_required_values(vars_read, stmt);
1865  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->Requires " + STR(vars_read.size()) + " values");
1866  for(const auto& var_pair : vars_read)
1867  {
1868  const auto ssa_use_node_id = std::get<0>(var_pair);
1869  set_value(ssa_use_node_id);
1870  }
1873  "Analyzed " + stmt_node->get_kind_text() + ": " + STR(stmt_node));
1874  }
1876  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Analyzed BB" + STR(B->number));
1877  }
1878  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Initialized best with all variables in the function:");
1880  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Ended internal initialize");
1881 }
1882 
1884 {
1885  for(const auto& b : best)
1886  {
1887  if(arguments.find(b.first) != arguments.end() || b.first == function_id)
1888  {
1889  current[b.first] = b.second;
1890  }
1891  else
1892  {
1893  const auto position_in_current = current.find(b.first);
1894  if(position_in_current != current.end())
1895  {
1896  current.erase(position_in_current);
1897  }
1898  }
1899  }
1900 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
std::deque< bit_lattice > string_cst_bitstring(const tree_nodeRef &strcst_tn, unsigned int ssa_node_id) const
auxiliary function used to build the bitstring lattice for read-only string_cst
static size_t CGetPointerSize(const ParameterConstRef parameters)
Return the size of the pointer in bit.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
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;.
std::deque< bit_lattice > create_bitstring_from_constant(integer_cst_t value, unsigned long long len, bool signed_value)
Creates a bitstring from a constant input.
boost::graph_traits< graph >::out_edge_iterator OutEdgeIterator
out_edge_iterator definition.
Definition: graph.hpp:1312
static std::string name_function(const tree_managerConstRef &tm, const unsigned int index)
Return the name of the function.
static const std::map< bit_lattice, std::map< bit_lattice, std::map< bit_lattice, std::deque< bit_lattice > > > > plus_expr_map
Map storing the implementation of the forward_transfer&#39;s plus_expr.
Definition: Bit_Value.hpp:86
#define MEMCPY
constant string identifying the operation performed when two objects are memcopied.
Definition: op_graph.hpp:310
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
Step successfully executed.
std::deque< bit_lattice > create_x_bitstring(size_t lenght)
Create a bitstring containing bits initialized at <X>
Definition of the node_info object for the basic_block graph.
string target
Definition: lenet_tvm.py:16
#define GET_CLASS(obj)
Macro returning the actual type of an object.
BBGraphInfoRef GetBBGraphInfo()
Returns the property associated with the graph.
bool not_frontend
True if this step is not executed in the frontend.
Definition: Bit_Value.hpp:110
Definition of the class representing a generic C application.
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
static bool isBetter(const std::string &a_string, const std::string &b_string)
static unsigned long long int align(unsigned long long int address, unsigned long long int alignment)
STL includes.
Definition: memory.cpp:81
static bool is_natural(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is a ssa_name greater or equal to zero.
CustomOrderedMap< T, U > CustomMap
Definition: custom_map.hpp:167
DesignFlowStep_Status InternalExec() override
perform the bit value analysis
Definition: Bit_Value.cpp:1047
#define D_SELECTOR
Selectors used only in basic block graphs; numbers continue from cdfg_edge_info.hpp.
Definition: basic_block.hpp:85
Full implementation of Bit Value analysis as described in BitValue Inference: Detecting and Exploitin...
bool IsHandledByBitvalue(const tree_nodeConstRef &tn) const
Returns true if the type identified by type_id is handled by bitvalue analysis.
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
void backward()
Applies the backward algorithm, as described in the paper, analyzing each assignment statement starti...
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:361
Data structure describing a basic block at tree level.
unsigned int bb_version
The version of the basic block intermediate representation on which this step has been applied...
redefinition of map to manage ordered/unordered structures
static void get_required_values(std::vector< std::tuple< unsigned int, unsigned int >> &required, const tree_nodeRef &tn)
void print_bitstring_map(const CustomMap< unsigned int, std::deque< bit_lattice >> &map) const
Debugging function used to print the contents of the current and best maps.
Definition: Bit_Value.cpp:1095
#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.
static void sign_reduce_bitstring(std::deque< bit_lattice > &bitstring, bool bitstring_is_signed)
Reduce the size of a bitstring erasing all but one most significant zeros in unsigned bitstring and a...
static const std::map< bit_lattice, std::map< bit_lattice, std::map< bit_lattice, std::deque< bit_lattice > > > > minus_expr_map
Map storing the implementation of the forward_transfer&#39;s minus_expr.
Definition: Bit_Value.hpp:92
void forward()
Applies the forward algorithm, as described in the paper, analyzing each assignment statement followi...
static bool IsSignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of integer type.
CustomSet< unsigned int > signed_var
Set storing the signed ssa.
Definition: bit_lattice.hpp:90
std::string bitstring_to_string(const std::deque< bit_lattice > &bitstring)
Translates a bitstring ( expressed as an std::deque of bit_lattice ) into a string of characters...
~Bit_Value() override
Destructor.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
Class used to describe a particular graph with basic blocks as nodes.
std::deque< bit_lattice > inf(const std::deque< bit_lattice > &a, const std::deque< bit_lattice > &b, const unsigned int output_uid) const
Computes the inf between two bitstrings.
unsigned long long pointer_resizing(unsigned int output_id) const
Definition: Bit_Value.cpp:819
unsigned map[NUM_VERTICES]
Definition: bfs.c:12
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
std::deque< bit_lattice > create_u_bitstring(size_t lenght)
Creates a bitstring containing bits initialized at <U>
unsigned int lsb_to_zero(const addr_expr *ae, bool safe) const
Definition: Bit_Value.cpp:888
CustomMap< unsigned int, std::deque< bit_lattice > > current
Map of the current bit-values of each variable.
Definition: bit_lattice.hpp:78
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
Definition: Bit_Value.cpp:973
static const std::map< bit_lattice, std::map< bit_lattice, bit_lattice > > bit_and_expr_map
Map storing the implementation of the forward_transfer&#39;s bit_and_expr_map.
Definition: Bit_Value.hpp:107
Information associated with the whole basic-block graph.
static const std::map< bit_lattice, std::map< bit_lattice, bit_lattice > > bit_ior_expr_map
Map storing the implementation of the forward_transfer&#39;s bit_ior_expr_map.
Definition: Bit_Value.hpp:97
#define index(x, y)
Definition: Keccak.c:74
kind
redefinition of set to manage ordered/unordered structures
static unsigned long long size(const tree_managerConstRef tm, unsigned int index)
static const std::string ComputeSignature(const FrontendFlowStepType frontend_flow_step_type)
Compute the signature of a function frontend flow step.
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
static unsigned long long Size(const tree_nodeConstRef &t)
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
bool update_IR()
Updates the bitvalues of the intermediate representation with the values taken from the input map...
Definition: Bit_Value.cpp:1112
void calculate_dominance_info(enum dominance::cdi_direction dir)
The main entry point into this module.
Definition: Dominance.hpp:701
Call graph hierarchy.
#define DEBUG_LEVEL_NONE
no debugging print is performed.
#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 tree_managerConstRef TM
Definition: bit_lattice.hpp:71
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
Definition: Bit_Value.cpp:968
This struct specifies the block node.
Definition: tree_node.hpp:1820
This file collects some utility functions.
bool mix()
Mixes the content of current and best using the sup operation, storing the result in the best map...
void TopologicalSort(std::list< boost::graph_traits< graphs_collection >::vertex_descriptor > &sorted_vertices) const
Compute the topological order of the graph.
Definition: graph.hpp:996
std::deque< bit_lattice > string_to_bitstring(const std::string &s)
inverse of bitstring_to_string
CustomUnorderedMapUnstable< unsigned int, unsigned int > direct_call_id_to_called_id
Maps the id of a gimple statement to the id of the function called in that statement.
Definition: Bit_Value.hpp:122
void initialize()
Initializes best with C type as bitstring, signed_var and arguments using the information taken from ...
Definition: Bit_Value.cpp:1171
std::deque< bit_lattice > sup(const std::deque< bit_lattice > &a, const std::deque< bit_lattice > &b, const unsigned int output_uid) const
Computes the sup between two bitstrings.
refcount< T > lock() const
Definition: refcount.hpp:212
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.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
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.
Definition: Bit_Value.cpp:929
std::vector< blocRef > bb_topological
Topologically ordered basic blocks.
Definition: Bit_Value.hpp:115
Class specification of the basic_block structure.
CustomMap< unsigned int, std::deque< bit_lattice > > best
Map of the best bit-values of each variable.
Definition: bit_lattice.hpp:85
std::deque< bit_lattice > constructor_bitstring(const tree_nodeRef &ctor_tn, unsigned int ssa_node_id) const
auxiliary function used to build the bitstring lattice for read-only arrays
void clear()
Clean up the internal data structures.
const BBNodeInfoConstRef CGetBBNodeInfo(const vertex node) const
Return the info associated with a basic block.
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
static std::deque< bit_lattice > sign_extend_bitstring(const std::deque< bit_lattice > &bitstring, bool bitstring_is_signed, size_t final_size)
Extends a bitstring.
this class is used to manage the command-line or XML options.
unsigned int bitvalue_version
The version of the bitvalue information on which this step has been applied.
static unsigned int get_base_index(const tree_managerConstRef &TM, const unsigned int index)
Retrun the base address of a memory access.
void clear_current()
Clears all the entry in the current map, except for the input arguments.
Definition: Bit_Value.cpp:1883
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.
CustomUnorderedSet< unsigned int > arguments
Contains the input parameters of the function that&#39;s being analyzed.
Definition: Bit_Value.hpp:127
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
#define CFG_SELECTOR
Control flow graph edge selector.
#define B
Definition: generate.c:14
static tree_nodeConstRef GetFunctionReturnType(const tree_nodeConstRef &function, bool void_as_null=true)
Return the return type of a function.
static const std::map< bit_lattice, std::map< bit_lattice, bit_lattice > > bit_xor_expr_map
Map storing the implementation of the forward_transfer&#39;s bit_xor_expr_map.
Definition: Bit_Value.hpp:102
Bit_Value(const ParameterConstRef Param, const application_managerRef AM, unsigned int f_id, const DesignFlowManagerConstRef dfm)
Constructor.
Definition: Bit_Value.cpp:917
refcount< BBGraphInfo > BBGraphInfoRef
refcount definition of the class
This class contains the base representation for a generic frontend flow step which works on the whole...
Datastructure to represent memory information in high-level synthesis.
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.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
int sl
Definition: adpcm.c:105
This structure defines graphs where nodes are basic_blocks.
#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
Implementation of the wrapper to Gcc for C sources.

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