93 #include <boost/multiprecision/integer.hpp> 109 "copysign",
"fabs",
"finite",
"fpclassify",
"huge_val",
"inf",
"infinity",
"isfinite",
110 "isinf",
"isinf_sign",
"isnan",
"isnormal",
"nan",
"nans",
"signbit"};
119 "acos",
"acosh",
"asin",
"asinh",
"atan",
"atanh",
"atan2",
"cbrt",
"ceil",
120 "copysign",
"cos",
"cosh",
"erf",
"erfc",
"exp",
"exp2",
"expm1",
"fabs",
121 "fdim",
"finite",
"floor",
"fma",
"fmod",
"fpclassify",
"frexp",
"huge_val",
"hypot",
122 "ilogb",
"inf",
"infinity",
"isfinite",
"isinf",
"isinf_sign",
"isnan",
"isnormal",
"ldexp",
123 "lgamma",
"llrint",
"llround",
"log",
"log10",
"log1p",
"log2",
"logb",
"lrint",
124 "lround",
"modf",
"nan",
"nans",
"nearbyint",
"nextafter",
"nexttoward",
"pow",
"remainder",
125 "remquo",
"rint",
"round",
"scalb",
"scalbln",
"scalbn",
"sin",
"signbit",
"sinh",
126 "sincos",
"sqrt",
"tan",
"tanh",
"tgamma",
"trunc"};
128 static std::string
strip_fname(std::string fname,
bool* single_prec =
nullptr)
132 *single_prec =
false;
134 if(fname.find(
"__internal_") == 0)
136 fname = fname.substr(
sizeof(
"__internal_") - 1);
138 else if(fname.find(
"__builtin_") == 0)
140 fname = fname.substr(
sizeof(
"__builtin_") - 1);
142 else if(fname.find(
"__") == 0)
144 fname = fname.substr(
sizeof(
"__") - 1);
146 if(fname.back() ==
'f' && libm_func.count(fname.substr(0, fname.size() - 1)))
148 fname = fname.substr(0, fname.size() - 1);
158 unsigned int _function_id,
const DesignFlowManagerConstRef _design_flow_manager)
160 TreeM(_AppM->get_tree_manager()),
163 isTopFunction(AppM->CGetCallGraphManager()->GetRootFunctions().count(function_id)),
164 bindingCompleted(fd->list_of_args.size() == 0),
165 paramBinding(fd->list_of_args.size(), nullptr)
180 if(
parameters->isOption(OPT_fp_rounding_mode))
182 const auto rnd_mode =
parameters->getOption<std::string>(OPT_fp_rounding_mode);
183 if(rnd_mode ==
"nearest_even")
188 else if(rnd_mode ==
"truncate")
198 if(
parameters->isOption(OPT_fp_exception_mode))
200 const auto exc_mode =
parameters->getOption<std::string>(OPT_fp_exception_mode);
201 if(exc_mode ==
"ieee")
206 else if(exc_mode ==
"saturation")
211 else if(exc_mode ==
"overflow")
223 if(
funcFF.empty() && !
parameters->getOption<std::string>(OPT_fp_format).empty())
225 const auto CGM =
AppM->CGetCallGraphManager();
227 const auto inline_math_it = std::find(opts.begin(), opts.end(),
"inline-math");
229 if(inline_math_it != opts.end())
231 opts.erase(inline_math_it);
235 const auto inline_conversion_it = std::find(opts.begin(), opts.end(),
"inline-conversion");
236 if(inline_conversion_it != opts.end())
238 opts.erase(inline_conversion_it);
243 for(
const auto& opt : opts)
247 const auto f_index = [&]() {
250 const auto top_symbols =
parameters->getOption<std::vector<std::string>>(OPT_top_functions_names);
251 THROW_ASSERT(top_symbols.size() == 1,
"Expected single top function name");
252 if(top_symbols.size() > 1)
254 THROW_WARNING(
"Multiple top functions defined, @ is replaced with first one.");
256 format[0] = top_symbols.front();
264 THROW_ERROR(
"Function " +
format[0] +
" does not exists. (Maybe it has been inlined)");
266 const auto function_v = CGM->GetVertex(f_index);
267 if(
funcFF.count(function_v))
276 format[0] +
" specialized with fp format " + userFF->ToString());
281 if(
parameters->isOption(OPT_fp_format_propagate) &&
parameters->getOption<
bool>(OPT_fp_format_propagate))
285 for(
const auto& root_func : CGM->GetRootFunctions())
287 std::list<CallGraph::vertex_descriptor> func_sort;
289 const auto reached_from_top = CGM->GetReachedFunctionsFrom(root_func);
290 for(
const auto func_id : reached_from_top)
292 reached_v.insert(CGM->GetVertex(func_id));
294 const auto TopCG = CGM->CGetCallSubGraph(reached_v);
295 TopCG->TopologicalSort(func_sort);
297 for(
const auto func : func_sort)
300 FunctionVersionRef current_v;
301 if(static_cast<bool>(
funcFF.count(func)))
303 current_v =
funcFF.at(func);
309 const auto insertion =
311 funcFF.insert({func, current_v});
316 FloatFormatRef callers_ff =
317 !current_v->callers.empty() ? current_v->callers.front()->userRequired :
nullptr;
318 const auto common_null = callers_ff ==
nullptr;
319 for(
const auto& caller : current_v->callers)
321 const auto caller_null = caller->userRequired ==
nullptr;
322 if((caller_null ^ common_null) || (!common_null && *callers_ff != *caller->userRequired))
324 callers_ff =
nullptr;
330 if(current_v->userRequired ==
nullptr)
332 current_v->userRequired = callers_ff;
333 current_v->internal =
true;
335 else if(callers_ff ==
nullptr)
337 current_v->internal = current_v->callers.empty();
341 current_v->internal = *current_v->userRequired == *callers_ff;
344 const auto func_id =
AppM->CGetCallGraphManager()->get_function(func);
347 "Analysing function " +
350 AppM->CGetFunctionBehavior(func_id)->CGetBehavioralHelper()))));
354 CallGraph::out_edge_iterator ei, ei_end;
355 for(boost::tie(ei, ei_end) = boost::out_edges(func, *TopCG); ei != ei_end; ++ei)
359 TreeM, GetPointerS<const function_decl>(
TreeM->CGetTreeNode(CGM->get_function(called))));
361 if(static_cast<bool>(libm_func.count(called_fname)))
366 FunctionVersionRef called_v;
367 if(static_cast<bool>(
funcFF.count(called)))
369 called_v =
funcFF.at(called);
375 const auto insertion =
377 funcFF.insert({called, called_v});
380 called_v->callers.push_back(current_v);
389 const auto function_v =
AppM->CGetCallGraphManager()->GetVertex(
function_id);
390 if(static_cast<bool>(
funcFF.count(function_v)))
398 const auto insertion =
419 switch(relationship_type)
423 relationships.insert(std::make_pair(DETERMINE_MEMORY_ACCESSES,
SAME_FUNCTION));
424 relationships.insert(std::make_pair(EXTRACT_GIMPLE_COND_OP,
SAME_FUNCTION));
425 relationships.insert(std::make_pair(FUNCTION_CALL_TYPE_CLEANUP,
ALL_FUNCTIONS));
426 relationships.insert(std::make_pair(IR_LOWERING,
SAME_FUNCTION));
428 relationships.insert(std::make_pair(UN_COMPARISON_LOWERING,
SAME_FUNCTION));
442 relationships.insert(std::make_pair(FUNCTION_CALL_TYPE_CLEANUP,
SAME_FUNCTION));
462 return relationships;
473 "Floating-point lowering should not be executed");
475 static const auto ff_already_propagated =
476 parameters->isOption(OPT_fp_format_propagate) &&
parameters->getOption<
bool>(OPT_fp_format_propagate);
479 if(!ff_already_propagated && !
_version->ieee_format())
481 const auto CG =
AppM->CGetCallGraphManager()->CGetCallGraph();
483 for(boost::tie(ie, ie_end) = boost::in_edges(
_version->function_vertex, *CG); ie != ie_end; ie++)
485 if(static_cast<bool>(
funcFF.count(ie->m_source)))
487 const auto& funcV =
funcFF.at(ie->m_source);
488 if(funcV->ieee_format() || *(funcV->userRequired) != *(
_version->userRequired))
506 "A standard floating-point format function should be internal.");
514 "-->Function " + fn_name +
" implementing " +
_version->ToString() +
" floating-point format");
516 "---IO interface is " +
STR((
_version->ieee_format() ||
_version->internal) ?
"not " :
"") +
520 bool modified =
false;
522 for(
const auto&
block : sl->list_of_bloc)
525 for(
const auto&
phi :
block.second->CGetPhiList())
532 for(
const auto& stmt :
block.second->CGetStmtList())
543 "Adding view-convert expressions to support hardware implemented FU call arguments");
544 for(
const auto& ssa_uses :
hwParam)
546 const auto ssa = ssa_uses.first;
547 const auto ssa_ridx =
TreeM->GetTreeReindex(ssa->index);
549 std::vector<tree_nodeRef>* out_ssa =
550 out_int !=
outputInterface.end() ? &std::get<1>(out_int->second) :
nullptr;
551 for(
const auto& call_stmt_idx : ssa_uses.second)
553 const auto call_stmt =
TreeM->CGetTreeReindex(call_stmt_idx);
554 const auto call_node = GetPointerS<const gimple_node>(
GET_CONST_NODE(call_stmt));
555 const auto& call_bb = sl->list_of_bloc.at(call_node->bb_index);
557 "---View-convert for " + ssa->ToString() +
" in BB" +
STR(call_bb->number) +
" " +
558 call_node->ToString());
564 const auto vc_ssa = GetPointerS<gimple_assign>(
GET_NODE(vc_stmt))->op0;
565 call_bb->PushBefore(vc_stmt, call_stmt,
AppM);
566 TreeM->ReplaceTreeNode(call_stmt, ssa_ridx, vc_ssa);
570 out_ssa->begin(), out_ssa->end(),
583 "Adding view-convert expressions to support hardware implemented FU call return values");
586 const auto call_stmt = ssa->CGetDefStmt();
587 const auto def_node = GetPointerS<const gimple_node>(
GET_CONST_NODE(call_stmt));
588 const auto call_bb = sl->list_of_bloc.at(def_node->bb_index);
590 "-->View-convert for " + ssa->ToString() +
" in BB" +
STR(call_bb->number) +
" " +
591 def_node->ToString());
592 const auto ssa_ridx =
TreeM->GetTreeReindex(ssa->index);
599 const auto vc_ssa = GetPointerS<const gimple_assign>(
GET_CONST_NODE(vc_stmt))->op0;
605 const auto new_ssa = GetPointer<ssa_name>(
GET_NODE(vc_ssa));
608 "---Input interface " + std::get<0>(if_info->second)->ToString() +
" moved");
612 const auto ssa_uses = ssa->CGetUseStmts();
613 for(
const auto& stmt_use : ssa_uses)
616 "---Replace use - before: " +
GET_CONST_NODE(stmt_use.first)->ToString());
617 TreeM->ReplaceTreeNode(stmt_use.first, ssa_ridx, vc_ssa);
621 call_bb->PushAfter(vc_stmt, call_stmt,
AppM);
633 (!
parameters->isOption(OPT_fp_format_interface) || !
parameters->getOption<
bool>(OPT_fp_format_interface)))
641 const auto first_bb = sl->list_of_bloc.at(entry_bb->list_of_succ.front());
647 "Unexpected parameter node type (" + parm->get_kind_text() +
")");
648 const auto parmSSA = GetPointerS<ssa_name>(parm);
651 const auto parm_ridx =
TreeM->CGetTreeReindex(parmSSA->index);
652 const auto parm_type =
int_type_for(parmSSA->type,
false);
654 "Lowering top function parameter type of " + parmSSA->ToString() +
": " +
655 GET_NODE(parmSSA->type)->ToString() +
" -> " +
GET_NODE(parm_type)->ToString());
657 if(
GET_NODE(parm_type)->get_kind() == pointer_type_K)
672 {ssa_ff, std::vector<unsigned int>()}});
677 const auto& oentry_list = std::get<1>(oentry->second);
678 auto& ientry_list = std::get<1>(ientry.first->second);
679 for(
const auto& e : oentry_list)
681 ientry_list.push_back(e->index);
686 "---Input interface required for current parameter");
690 "---Lowering statement added to BB" +
STR(first_bb->number) +
": " +
692 const auto lowered_parm = GetPointerS<gimple_assign>(
GET_NODE(vc_stmt))->op0;
693 const auto parm_uses = parmSSA->CGetUseStmts();
694 for(
const auto& stmt_uses : parm_uses)
696 TreeM->ReplaceTreeNode(stmt_uses.first, parm_ridx, lowered_parm);
698 first_bb->PushFront(vc_stmt,
AppM);
704 paramBinding.clear();
707 const auto gr = GetPointerS<gimple_return>(
GET_NODE(ret_stmt));
708 const auto ret_ssa = GetPointerS<ssa_name>(
GET_NODE(gr->op));
710 "Return value type restore added for variable " + ret_ssa->ToString());
711 const auto bb = sl->list_of_bloc.at(gr->bb_index);
713 if(
GET_NODE(ret_ssa->type)->get_kind() == pointer_type_K)
725 outputInterface.insert({ret_ssa, {ssa_ff, std::vector<tree_nodeRef>({vc_stmt})}});
727 "---Output interface required for current variable use");
730 const auto lowered_ret = GetPointerS<gimple_assign>(
GET_NODE(vc_stmt))->op0;
731 bb->PushBefore(vc_stmt, ret_stmt,
AppM);
732 TreeM->ReplaceTreeNode(ret_stmt, gr->op, lowered_ret);
734 modified |= topReturn.size();
741 if(modified_signature)
757 "Unexpected parameter node type (" +
param->get_kind_text() +
")");
758 const auto parmSSA = GetPointerS<ssa_name>(
param);
763 "Lowering type of " + parmSSA->ToString() +
" bound to paremeter " + pd->ToString() +
764 ": " +
GET_NODE(parmSSA->type)->ToString() +
" -> " +
766 parmSSA->type = pd->type;
775 "Missing binding for parameter " + pd->ToString());
786 "Lowering type for " +
STR(
viewConvert.size()) +
" ssa variables");
800 "Lowering " +
STR(
nopConvert.size()) +
" view-convert expressions to nop expressions");
805 const auto ga = GetPointerS<gimple_assign>(
GET_NODE(vcStmt));
807 const auto vc = GetPointerS<view_convert_expr>(
GET_NODE(ga->op1));
810 "At this point " +
GET_NODE(vc->op)->ToString() +
" should be of integer type.");
813 "Destination variable should of integer type (" +
GET_CONST_NODE(resType)->get_kind_text() +
")");
815 TreeM->ReplaceTreeNode(vcStmt, ga->op1, nop);
830 const auto* SSA = if_info.first;
832 const auto ssa =
TreeM->GetTreeReindex(SSA->index);
833 auto& exclude = std::get<1>(if_info.second);
837 const auto& oentry_list = std::get<1>(oentry->second);
838 std::transform(oentry_list.begin(), oentry_list.end(), std::back_inserter(exclude),
848 const auto ssaUses = SSA->CGetUseStmts();
849 if(ssaUses.size() == exclude.size())
852 "---Input interface for " + SSA->ToString() +
" has no users, skipping...");
856 auto defStmt = SSA->CGetDefStmt();
857 const auto def = GetPointerS<gimple_node>(
GET_NODE(defStmt));
859 if(def->get_kind() == gimple_assign_K)
862 "BB " +
STR(def->bb_index) +
" not present in current function.");
863 bb = sl->list_of_bloc.at(def->bb_index);
865 "Input interface will be inserted in BB" +
STR(bb->number));
867 else if(def->get_kind() == gimple_phi_K)
870 "BB " +
STR(def->bb_index) +
" not present in current function.");
871 bb = sl->list_of_bloc.at(def->bb_index);
874 "Input interface for phi will be inserted in BB" +
STR(bb->number));
879 "Multiple successors after entry basic block.");
880 const auto realEntryBBIdx = sl->list_of_bloc.at(
BB_ENTRY)->list_of_succ.front();
881 bb = sl->list_of_bloc.at(realEntryBBIdx);
884 "Input interface for parameter will be inserted in BB" +
STR(bb->number));
887 const auto convertedSSA =
891 "-->Interface from " + std::get<0>(if_info.second)->ToString() +
" to " +
892 _version->userRequired->ToString() +
" generated output " +
893 GET_NODE(convertedSSA)->ToString());
895 for(
const auto& ssaUse : ssaUses)
897 const auto& useStmt = ssaUse.first;
898 if(std::find(exclude.begin(), exclude.end(),
GET_INDEX_NODE(useStmt)) != exclude.end())
904 TreeM->ReplaceTreeNode(useStmt, ssa, convertedSSA);
905 const auto* ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(useStmt));
909 auto* te = GetPointer<ternary_expr>(
GET_NODE(ga->op1));
912 te->type =
TreeM->GetTreeNode(convertedSSA_type->index);
921 inputInterface.clear();
932 const auto* SSA = if_info.first;
933 const auto ssa =
TreeM->GetTreeReindex(SSA->index);
934 const auto& useStmts = std::get<1>(if_info.second);
936 auto defStmt = SSA->CGetDefStmt();
937 const auto gn = GetPointerS<gimple_node>(
GET_NODE(defStmt));
939 "BB" +
STR(gn->bb_index) +
" not present in current function.");
940 auto bb = sl->list_of_bloc.at(gn->bb_index);
941 if(gn->get_kind() == gimple_nop_K)
943 THROW_ASSERT(bb->number ==
BB_ENTRY,
"Parameter definition should be associated to entry block");
944 THROW_ASSERT(bb->list_of_succ.size() == 1,
"Multiple successors after entry basic block.");
945 THROW_ASSERT(sl->list_of_bloc.count(bb->list_of_succ.front()),
946 "BB " +
STR(bb->list_of_succ.front()) +
" not present in current function.");
948 bb = sl->list_of_bloc.at(bb->list_of_succ.front());
951 "Output interface for " + SSA->ToString() +
" will be inserted in BB" +
STR(bb->number));
953 const auto convertedSSA =
957 for(
const auto& stmt : useStmts)
959 TreeM->ReplaceTreeNode(stmt, ssa, convertedSSA);
965 outputInterface.clear();
993 if(!use_internal ||
_version->ieee_format())
1009 AppM->CGetFunctionBehavior(f_decl->
index)->CGetBehavioralHelper())));
1013 bool changed_parm =
false, changed_type =
false;
1015 const auto is_ptr_type = decl_type->get_kind() == pointer_type_K;
1022 const auto f_type =
TreeM->CGetTreeReindex(dup_ft);
1027 const auto ft = GetPointerS<function_type>(
GET_NODE(f_type));
1032 const auto ret_type = GetPointerS<const type_node>(
GET_CONST_NODE(int_ret));
1036 ft->algn = ret_type->algn;
1037 ft->qual = ret_type->qual;
1038 ft->size = ret_type->size;
1039 changed_type =
true;
1041 prms = ft->prms ? GetPointerS<tree_list>(
GET_NODE(ft->prms)) :
nullptr;
1046 const auto pd = GetPointerS<parm_decl>(
GET_NODE(
arg));
1047 const auto& parm_type = pd->type;
1049 "Analysing parameter " + pd->ToString() +
" of type " +
STR(parm_type));
1054 const auto parm_int_type = GetPointerS<const type_node>(
GET_CONST_NODE(int_parm_type));
1055 pd->algn = parm_int_type->algn;
1056 pd->argt = int_parm_type;
1057 pd->packed_flag = parm_int_type->packed_flag;
1058 pd->type = int_parm_type;
1061 prms->
valu = int_parm_type;
1062 changed_type =
true;
1065 "---Parameter type lowered to " +
STR(int_parm_type) +
" " +
1067 changed_parm =
true;
1069 prms = prms ? (prms->
chan ? GetPointerS<tree_list>(
GET_NODE(prms->
chan)) :
nullptr) :
nullptr;
1077 return changed_parm || changed_type;
1088 const auto def = GetPointer<gimple_assign>(
GET_NODE(defStmt));
1091 const auto ue = GetPointer<unary_expr>(
GET_NODE(def->op1));
1095 if(ue->get_kind() == view_convert_expr_K)
1098 TreeM->ReplaceTreeNode(defStmt, def->op1, nop);
1100 else if(ue->get_kind() == imagpart_expr_K || ue->get_kind() == realpart_expr_K)
1102 const auto ssa_ridx =
TreeM->CGetTreeReindex(ssa->
index);
1103 const auto def_bb = GetPointerS<statement_list>(
GET_NODE(
fd->
body))->list_of_bloc.at(def->bb_index);
1105 const auto vc_stmt =
1108 "---Inserting view-convert operation after complex part expression - " +
1110 const auto lowered_ssa = GetPointerS<gimple_assign>(
GET_NODE(vc_stmt))->op0;
1113 for(
const auto& stmt_uses : ssa_uses)
1115 TreeM->ReplaceTreeNode(stmt_uses.first, ssa_ridx, lowered_ssa);
1117 def_bb->PushAfter(vc_stmt, defStmt,
AppM);
1132 ssa->
type = vc_type;
1135 const auto vd = GetPointer<var_decl>(
GET_NODE(ssa->
var));
1136 THROW_ASSERT(vd,
"SSA name associated variable is espected to be a variable declaration " +
1141 "---Variable declaration before - " + vd->ToString() +
" " +
GET_NODE(vd->type)->ToString());
1142 const auto var_int_type = GetPointerS<type_node>(
GET_NODE(vc_type));
1143 vd->algn = var_int_type->algn;
1144 vd->packed_flag = var_int_type->packed_flag;
1147 "---Variable declaration after - " + vd->ToString() +
" " +
GET_NODE(vd->type)->ToString());
1152 "---Variable declaration - " + vd->ToString() +
" " +
GET_NODE(vd->type)->ToString());
1158 const auto* ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(use_count.first));
1162 auto* te = GetPointer<ternary_expr>(
GET_NODE(ga->op1));
1173 uint64_t Sign, Exp, Frac;
1175 Sign = bits >> (inFF->exp_bits + inFF->frac_bits);
1176 Exp = (bits >> (inFF->frac_bits)) & ((1ULL << inFF->exp_bits) - 1);
1177 Frac = bits & ((1ULL << inFF->frac_bits) - 1);
1179 uint64_t FExp, SFrac;
1180 bool ExpOverflow =
false;
1182 const auto needed_bits = [](
int i) ->
auto 1187 lz = 32 - __builtin_clz(static_cast<unsigned int>(i));
1192 lz = 32 - __builtin_clz(static_cast<unsigned int>(i)) + ((i & (i - 1)) != 0);
1194 return static_cast<unsigned int>(lz);
1196 const auto exp_bits_diff =
1197 inFF->exp_bits > outFF->exp_bits ? (inFF->exp_bits - outFF->exp_bits) : (outFF->exp_bits - inFF->exp_bits);
1198 const auto exp_type_size =
std::max({
static_cast<unsigned int>(inFF->exp_bits) + (exp_bits_diff == 1),
1199 static_cast<unsigned int>(outFF->exp_bits) + (exp_bits_diff == 1),
1200 needed_bits(inFF->exp_bias), needed_bits(outFF->exp_bias)});
1202 const auto biasDiff = inFF->exp_bias - outFF->exp_bias;
1203 const auto rangeDiff = ((1 << outFF->exp_bits) - !outFF->has_subnorm) - ((1 << inFF->exp_bits) - !inFF->has_subnorm);
1204 if((inFF->exp_bits != outFF->exp_bits) || (inFF->exp_bias != outFF->exp_bias))
1206 FExp = Exp +
static_cast<uint64_t
>(biasDiff);
1207 bool ExpUnderflow =
false;
1208 if(biasDiff < 0 || biasDiff > rangeDiff)
1210 const auto expOverflow = (FExp >> outFF->exp_bits) & ((1ULL << (exp_type_size - outFF->exp_bits - 1)) - 1);
1211 ExpOverflow = expOverflow != 0ULL;
1212 ExpUnderflow = (FExp >> (exp_type_size - 1)) & 1;
1213 THROW_ASSERT((!ExpOverflow && !ExpUnderflow) || bits == 0,
1214 "Target FP format can not represent a program constant.");
1215 const auto ExExp = ExpUnderflow ? 0ULL : ((1ULL << outFF->exp_bits) - 1);
1216 FExp = FExp & ((1ULL << outFF->exp_bits) - 1);
1217 FExp = ExpOverflow ? ExExp : FExp;
1218 Frac = ExpUnderflow ? 0 : Frac;
1219 ExpOverflow = ExpOverflow ^ ExpUnderflow;
1222 FExp = FExp & ((1ULL << outFF->exp_bits) - 1);
1223 const bool ExpNull = Exp == 0;
1224 const bool FracNull = Frac == 0;
1225 bool inputZero = ExpNull && FracNull;
1226 if(biasDiff < 0 || biasDiff > rangeDiff)
1228 inputZero = inputZero || ExpUnderflow;
1230 FExp = inputZero ? 0ULL : FExp;
1234 if(inFF->has_subnorm && !outFF->has_subnorm)
1236 const bool ExpNull = Exp == 0;
1237 Frac = ExpNull ? 0ULL : Frac;
1242 if(inFF->frac_bits > outFF->frac_bits)
1244 const auto bits_diff = inFF->frac_bits - outFF->frac_bits;
1246 SFrac = Frac >> bits_diff;
1250 const bool GuardBit = (Frac >> (bits_diff - 1)) & 1;
1255 const bool RoundBit = (Frac >> (bits_diff - 2)) & 1;
1256 LSB = LSB | RoundBit;
1261 const bool Sticky = (Frac & ((1ULL << (bits_diff - 2)) - 1)) != 0;
1265 const bool Round = GuardBit & LSB;
1266 SFrac = SFrac |
static_cast<uint64_t
>(Round);
1269 else if(inFF->frac_bits < outFF->frac_bits)
1271 const auto bits_diff = outFF->frac_bits - inFF->frac_bits;
1272 SFrac = Frac << bits_diff;
1279 bool out_nan =
false;
1290 " type will always result in a static value.");
1297 out_nan |= Exp == ((1ULL << inFF->exp_bits) - 1);
1299 uint64_t RExp, NFrac, RFrac;
1301 RExp = out_nan ? ((1ULL << outFF->exp_bits) - 1) : FExp;
1302 RExp <<= outFF->frac_bits;
1304 if(biasDiff < 0 || biasDiff > rangeDiff)
1306 out_nan |= ExpOverflow;
1313 const auto in_nan = (Exp == ((1ULL << inFF->exp_bits) - 1)) && (Frac != 0);
1314 NFrac = in_nan ? ((1ULL << outFF->frac_bits) - 1) : 0;
1323 NFrac = ((1ULL << outFF->frac_bits) - 1);
1326 RFrac = out_nan ? NFrac : SFrac;
1328 uint64_t out_val = RExp | RFrac;
1335 FSign = inFF->sign ==
bit_lattice::ONE ? (1ULL << (outFF->exp_bits + outFF->frac_bits)) : 0;
1339 FSign = Sign << (outFF->exp_bits + outFF->frac_bits);
1344 return TreeM->CreateUniqueIntegerCst(
1345 static_cast<int64_t>(out_val),
1347 outFF->exp_bits + outFF->frac_bits),
1351 #define FLOAT_CAST_FU_NAME "__float_cast" 1354 const FloatFormatRef inFF,
const FloatFormatRef outFF)
const 1364 THROW_ASSERT(inFF,
"Interface input float format must be defined.");
1365 THROW_ASSERT(outFF,
"Interface output float format must be defined.");
1369 const auto spec_suffix = inFF->ToString() +
"_to_" + outFF->ToString();
1375 ") with fp format " + spec_suffix);
1379 const std::vector<tree_nodeRef>
args = {
1381 TreeM->CreateUniqueIntegerCst(static_cast<long long>(inFF->exp_bits), default_int_type),
1382 TreeM->CreateUniqueIntegerCst(static_cast<long long>(inFF->frac_bits), default_int_type),
1383 TreeM->CreateUniqueIntegerCst(static_cast<long long>(inFF->exp_bias), default_int_type),
1384 TreeM->CreateUniqueIntegerCst(static_cast<long long>(inFF->rounding_mode), default_int_type),
1385 TreeM->CreateUniqueIntegerCst(static_cast<long long>(inFF->exception_mode), default_int_type),
1386 TreeM->CreateUniqueIntegerCst(static_cast<long long>(inFF->has_one), default_bool_type),
1387 TreeM->CreateUniqueIntegerCst(static_cast<long long>(inFF->has_subnorm), default_bool_type),
1388 TreeM->CreateUniqueIntegerCst(
1391 TreeM->CreateUniqueIntegerCst(static_cast<long long>(outFF->exp_bits), default_int_type),
1392 TreeM->CreateUniqueIntegerCst(static_cast<long long>(outFF->frac_bits), default_int_type),
1393 TreeM->CreateUniqueIntegerCst(static_cast<long long>(outFF->exp_bias), default_int_type),
1394 TreeM->CreateUniqueIntegerCst(static_cast<long long>(outFF->rounding_mode), default_int_type),
1395 TreeM->CreateUniqueIntegerCst(static_cast<long long>(outFF->exception_mode), default_int_type),
1396 TreeM->CreateUniqueIntegerCst(static_cast<long long>(outFF->has_one), default_bool_type),
1397 TreeM->CreateUniqueIntegerCst(static_cast<long long>(outFF->has_subnorm), default_bool_type),
1398 TreeM->CreateUniqueIntegerCst(
1408 bb->PushFront(cast_stmt,
AppM);
1412 bb->PushAfter(cast_stmt, stmt,
AppM);
1414 auto out_var = GetPointer<const gimple_assign>(
GET_CONST_NODE(cast_stmt))->op0;
1415 const auto out_type =
1417 outFF->exp_bits + outFF->frac_bits),
1421 const auto nop_stmt =
1423 out_var = GetPointer<const gimple_assign>(
GET_CONST_NODE(nop_stmt))->op0;
1424 bb->PushAfter(nop_stmt, cast_stmt,
AppM);
1432 const auto called_func_vertex =
AppM->CGetCallGraphManager()->GetVertex(spec_function->index);
1433 const auto calledFF = FunctionVersionRef(
new FunctionVersion(called_func_vertex, inFF));
1437 funcFF.insert(std::make_pair(called_func_vertex, calledFF));
1438 THROW_ASSERT(res.second || res.first->second->compare(*calledFF,
true) == 0,
1439 "Same function registered with different formats: " + res.first->second->ToString() +
" and " +
1450 int_ff_type, op,
TreeM->CreateUniqueIntegerCst(1LL << (ff->exp_bits + ff->frac_bits), int_ff_type),
1455 THROW_ERROR(
"Negate operation on fixed sign type will flatten all values.");
1466 int_ff_type, op,
TreeM->CreateUniqueIntegerCst((1LL << (ff->exp_bits + ff->frac_bits)) - 1, int_ff_type),
1476 THROW_ERROR(
"Negate operation on fixed negative sign type will flatten all values.");
1483 const tree_nodeRef& current_tree_node,
const std::string& current_srcp)
1485 THROW_ASSERT(specFF,
"FP format specialization missing");
1487 auto called_function =
TreeM->GetFunction(fu_name);
1488 THROW_ASSERT(called_function,
"The library miss this function " + fu_name);
1489 const auto spec_suffix = specFF->ToString();
1490 auto spec_function =
TreeM->GetFunction(fu_name + spec_suffix);
1494 "---Generating specialized version of " + fu_name +
" (" +
STR(called_function->index) +
1495 ") with fp format " + spec_suffix);
1497 THROW_ASSERT(spec_function,
"Error cloning function " + fu_name +
" (" +
STR(called_function->index) +
").");
1503 version_args[0] =
TreeM->CreateUniqueIntegerCst(static_cast<long long>(specFF->exp_bits), default_int_type);
1504 version_args[1] =
TreeM->CreateUniqueIntegerCst(static_cast<long long>(specFF->frac_bits), default_int_type);
1505 version_args[2] =
TreeM->CreateUniqueIntegerCst(static_cast<long long>(specFF->exp_bias), default_int_type);
1506 version_args[3] =
TreeM->CreateUniqueIntegerCst(static_cast<long long>(specFF->rounding_mode), default_int_type);
1507 version_args[4] =
TreeM->CreateUniqueIntegerCst(static_cast<long long>(specFF->exception_mode), default_int_type);
1508 version_args[5] =
TreeM->CreateUniqueIntegerCst(static_cast<long long>(specFF->has_one), default_bool_type);
1509 version_args[6] =
TreeM->CreateUniqueIntegerCst(static_cast<long long>(specFF->has_subnorm), default_bool_type);
1510 version_args[7] =
TreeM->CreateUniqueIntegerCst(
1515 "Static arguments for specialization parameters of " + fu_name + spec_suffix +
" (" +
1516 STR(spec_function->index) +
") where not specified.");
1518 std::back_inserter(args));
1519 called_function = spec_function;
1520 TreeM->ReplaceTreeNode(current_statement, current_tree_node,
1528 const auto called_func_vertex =
AppM->CGetCallGraphManager()->GetVertex(called_function->index);
1529 const auto calledFF = FunctionVersionRef(
new FunctionVersion(called_func_vertex, specFF));
1533 funcFF.insert(std::make_pair(called_func_vertex, calledFF));
1534 THROW_ASSERT(res.second || res.first->second->compare(*calledFF,
true) == 0,
1535 "Same function registered with different formats: " + res.first->second->ToString() +
" and " +
1536 calledFF->ToString() +
" (" + fu_name +
")");
1545 "Required interface type must be unique (" +
STR(type_interface) +
")");
1546 const auto curr_tn =
GET_NODE(current_tree_node);
1548 "-->Update recursively (ti=" +
STR(type_interface) +
") (" +
STR(current_tree_node->
index) +
" " +
1549 curr_tn->get_kind_text() +
") " +
STR(current_tree_node));
1550 const auto current_srcp = [curr_tn]() -> std::string {
1551 const auto srcp_tn = GetPointer<const srcp>(curr_tn);
1554 return srcp_tn->include_name +
":" +
STR(srcp_tn->line_number) +
":" +
STR(srcp_tn->column_number);
1558 bool modified =
false;
1559 const auto is_internal_call = [&](
const tree_nodeRef& fn) ->
bool {
1560 static const auto mcpy_node =
TreeM->GetFunction(
MEMCPY);
1561 static const auto mset_node =
TreeM->GetFunction(
MEMSET);
1562 const auto fn_fd = GetPointerS<function_decl>(
GET_NODE(fn));
1567 THROW_UNREACHABLE(
"Function pointers not supported from user defined floating point format functions");
1574 const auto ff_it =
funcFF.find(fn_v);
1575 if(ff_it !=
funcFF.end())
1577 return ff_it->second->internal &&
_version->ieee_format() == ff_it->second->ieee_format();
1579 else if(fn_fd->builtin_flag || fn_fd->index == mcpy_node->index || fn_fd->index == mset_node->index)
1586 const auto ExaminateFunctionCall = [&](
tree_nodeRef fn) ->
int {
1587 const auto ae = GetPointer<addr_expr>(
GET_NODE(fn));
1591 const auto called_fd = GetPointerS<const function_decl>(
GET_CONST_NODE(fn));
1592 ae->type =
GET_CONST_NODE(called_fd->type)->get_kind() == pointer_type_K ?
1604 THROW_UNREACHABLE(
"Function pointers not supported from user defined floating point format functions");
1618 switch(curr_tn->get_kind())
1621 case aggr_init_expr_K:
1623 const auto ce = GetPointerS<const call_expr>(curr_tn);
1624 type_interface = ExaminateFunctionCall(ce->fn);
1625 for(
const auto&
arg : ce->args)
1633 const auto ce = GetPointerS<const gimple_call>(curr_tn);
1634 type_interface = ExaminateFunctionCall(ce->fn);
1635 for(
const auto&
arg : ce->args)
1643 const auto gp = GetPointerS<const gimple_phi>(curr_tn);
1645 for(
const auto& de : gp->CGetDefEdgesList())
1651 case gimple_assign_K:
1653 const auto ga = GetPointerS<const gimple_assign>(curr_tn);
1654 const auto rhs_type =
GET_NODE(ga->op1)->get_kind();
1655 if(rhs_type == call_expr_K || rhs_type == aggr_init_expr_K)
1657 const auto ce = GetPointerS<const call_expr>(
GET_NODE(ga->op1));
1658 const auto fn = GetPointer<const addr_expr>(
GET_CONST_NODE(ce->fn)) ?
1663 bool is_f32 =
false;
1664 const auto tf_fname =
strip_fname(fname, &is_f32);
1665 if(supported_libm_calls.count(tf_fname))
1668 "---Replacing libm call with templatized version");
1674 replaceWithCall(specFF,
"__" + tf_fname, ce->args, current_statement, ga->op1, current_srcp);
1676 if(supported_libm_calls_inlined.count(tf_fname))
1685 const auto type_i = [&]() {
1736 const auto SSA = GetPointerS<ssa_name>(curr_tn);
1764 if(SSA->var !=
nullptr &&
GET_CONST_NODE(SSA->var)->get_kind() == parm_decl_K &&
1770 THROW_ASSERT(argIt !=
args.end(),
"parm_decl associated with ssa_name not found in function parameters");
1771 const auto arg_pos =
static_cast<size_t>(argIt -
args.begin());
1772 THROW_ASSERT(arg_pos <
args.size(),
"Computed parameter position outside actual parameters number");
1774 bindingCompleted = std::find(paramBinding.begin(), paramBinding.end(),
nullptr) == paramBinding.end();
1776 "---Variable " + SSA->ToString() +
" is defined from parameter " +
STR(arg_pos));
1788 "---Input interface required for current parameter");
1805 "---Skipping input interface for current parameter");
1812 inputInterface.insert({SSA, {ssa_ff, std::vector<unsigned int>()}});
1829 outputInterface.insert({SSA, {ssa_ff, std::vector<tree_nodeRef>({current_statement})}});
1833 std::get<1>(oif->second).push_back(current_statement);
1836 "---Output interface required for current variable use");
1845 auto current = current_tree_node;
1850 current = GetPointerS<const tree_list>(
GET_CONST_NODE(current))->chan;
1856 const auto ue = GetPointerS<const unary_expr>(curr_tn);
1857 const auto& expr_type = ue->type;
1864 switch(curr_tn->get_kind())
1873 else if(bitsize_in > 32 && bitsize_in < 64)
1878 FloatFormatRef outFF;
1879 if(bitsize_out <= 32)
1884 else if(bitsize_out > 32 && bitsize_out <= 64)
1889 const auto bitsize_str_in =
STR(bitsize_in);
1890 const auto bitsize_str_out = bitsize_out == 96 ?
"x80" :
STR(bitsize_out);
1894 const auto fu_name =
"__" + std::string(is_unsigned ?
"u" :
"") +
"int" + bitsize_str_in +
1895 "_to_float" + bitsize_str_out;
1898 current_statement, current_tree_node, current_srcp);
1908 case view_convert_expr_K:
1920 "Unhandled floating point format (size = " +
STR(float_size) +
")");
1923 THROW_ASSERT(ff,
"Float format should be defined here");
1924 const auto float_negate =
floatAbs(ue->op, ff);
1925 TreeM->ReplaceTreeNode(current_statement, current_tree_node, float_negate);
1933 "Unhandled floating point format (size = " +
STR(float_size) +
")");
1936 THROW_ASSERT(ff,
"Float format should be defined here");
1937 const auto float_negate =
floatNegate(ue->op, ff);
1938 TreeM->ReplaceTreeNode(current_statement, current_tree_node, float_negate);
1949 "Unhandled input floating point format (size = " +
STR(bitsize_in) +
")");
1951 "Unhandled output floating point format (size = " +
STR(bitsize_out) +
")");
1954 const auto fu_name =
"__float" +
STR(bitsize_in) +
"_to_float" +
STR(bitsize_out) +
"_ieee";
1956 const auto called_function =
TreeM->GetFunction(fu_name);
1957 THROW_ASSERT(called_function,
"The library miss this function " + fu_name);
1958 std::vector<tree_nodeRef>
args = {
1960 TreeM->CreateUniqueIntegerCst(static_cast<long long>(inFF->exception_mode),
1963 TreeM->ReplaceTreeNode(current_statement, current_tree_node,
1970 "---Added call point for " +
STR(called_function->index));
1979 const auto vc_expr =
1981 TreeM->ReplaceTreeNode(current_statement, current_tree_node, vc_expr);
1987 THROW_UNREACHABLE(
"Operation not yet supported: function with user-defined floating point format " 1988 "should use a unique format type.");
1992 case indirect_ref_K:
1993 case imagpart_expr_K:
1994 case realpart_expr_K:
1998 case alignof_expr_K:
2000 case bit_not_expr_K:
2003 case cleanup_point_expr_K:
2005 case convert_expr_K:
2007 case fix_ceil_expr_K:
2008 case fix_floor_expr_K:
2009 case fix_round_expr_K:
2010 case fix_trunc_expr_K:
2011 case misaligned_indirect_ref_K:
2013 case non_lvalue_expr_K:
2014 case reference_expr_K:
2015 case reinterpret_cast_expr_K:
2017 case static_cast_expr_K:
2019 case truth_not_expr_K:
2022 case reduc_max_expr_K:
2023 case reduc_min_expr_K:
2024 case reduc_plus_expr_K:
2025 case vec_unpack_hi_expr_K:
2026 case vec_unpack_lo_expr_K:
2027 case vec_unpack_float_hi_expr_K:
2028 case vec_unpack_float_lo_expr_K:
2032 case aggr_init_expr_K:
2033 case case_label_expr_K:
2035 case identifier_node_K:
2037 case statement_list_K:
2039 case target_mem_ref_K:
2040 case target_mem_ref461_K:
2056 THROW_ERROR(
"not yet supported soft float function: " + curr_tn->get_kind_text());
2067 switch(curr_tn->get_kind())
2069 case fix_trunc_expr_K:
2072 const auto inFF = bitsize_in == 32 ?
float32FF : (bitsize_in == 64 ?
float64FF :
nullptr);
2074 if(bitsize_out < 32)
2078 else if(bitsize_out > 32 && bitsize_out < 64)
2083 const auto bitsize_str_in = bitsize_in == 96 ?
"x80" :
STR(bitsize_in);
2084 const auto bitsize_str_out = bitsize_out == 96 ?
"x80" :
STR(bitsize_out);
2085 const auto fu_name =
"__float" + bitsize_str_in +
"_to_" + (is_unsigned ?
"u" :
"") +
"int" +
2086 bitsize_str_out +
"_round_to_zero";
2088 current_statement, current_tree_node, current_srcp);
2097 case view_convert_expr_K:
2107 case aggr_init_expr_K:
2108 case case_label_expr_K:
2110 case identifier_node_K:
2112 case statement_list_K:
2114 case target_mem_ref_K:
2115 case target_mem_ref461_K:
2131 case alignof_expr_K:
2133 case bit_not_expr_K:
2136 case cleanup_point_expr_K:
2138 case convert_expr_K:
2140 case fix_ceil_expr_K:
2141 case fix_floor_expr_K:
2142 case fix_round_expr_K:
2144 case imagpart_expr_K:
2145 case indirect_ref_K:
2146 case misaligned_indirect_ref_K:
2149 case non_lvalue_expr_K:
2152 case realpart_expr_K:
2153 case reference_expr_K:
2154 case reinterpret_cast_expr_K:
2156 case static_cast_expr_K:
2158 case truth_not_expr_K:
2161 case reduc_max_expr_K:
2162 case reduc_min_expr_K:
2163 case reduc_plus_expr_K:
2164 case vec_unpack_hi_expr_K:
2165 case vec_unpack_lo_expr_K:
2166 case vec_unpack_float_hi_expr_K:
2167 case vec_unpack_float_lo_expr_K:
2180 const auto be = GetPointerS<binary_expr>(curr_tn);
2188 (curr_tn->get_kind() == unordered_expr_K || curr_tn->get_kind() == ordered_expr_K ||
2189 curr_tn->get_kind() == complex_expr_K)) ?
2194 (curr_tn->get_kind() == unordered_expr_K || curr_tn->get_kind() == ordered_expr_K ||
2195 curr_tn->get_kind() == complex_expr_K)) ?
2200 bool add_call =
true;
2201 std::string fu_suffix;
2202 switch(curr_tn->get_kind())
2223 if(bitsize == 32 || bitsize == 64)
2226 if(
parameters->getOption<std::string>(OPT_hls_fpdiv) ==
"SRT4")
2228 fu_suffix = fu_suffix +
"SRT4";
2230 else if(
parameters->getOption<std::string>(OPT_hls_fpdiv) ==
"G")
2232 fu_suffix = fu_suffix +
"G";
2234 else if(
parameters->getOption<std::string>(OPT_hls_fpdiv) ==
"SF")
2240 THROW_ERROR(
"FP-Division algorithm not supported:" +
2241 parameters->getOption<std::string>(OPT_hls_fpdiv));
2274 fu_suffix =
"ltgt_quiet";
2283 THROW_ERROR(
"Unsupported tree node " + curr_tn->get_kind_text());
2287 case bit_and_expr_K:
2288 case bit_ior_expr_K:
2289 case bit_xor_expr_K:
2291 case ceil_div_expr_K:
2292 case ceil_mod_expr_K:
2293 case complex_expr_K:
2294 case compound_expr_K:
2295 case eh_filter_expr_K:
2296 case exact_div_expr_K:
2298 case floor_div_expr_K:
2299 case floor_mod_expr_K:
2300 case goto_subroutine_K:
2303 case lrotate_expr_K:
2310 case mult_highpart_expr_K:
2311 case ordered_expr_K:
2312 case pointer_plus_expr_K:
2313 case postdecrement_expr_K:
2314 case postincrement_expr_K:
2315 case predecrement_expr_K:
2316 case preincrement_expr_K:
2318 case round_div_expr_K:
2319 case round_mod_expr_K:
2320 case rrotate_expr_K:
2323 case trunc_div_expr_K:
2324 case trunc_mod_expr_K:
2325 case truth_and_expr_K:
2326 case truth_andif_expr_K:
2327 case truth_or_expr_K:
2328 case truth_orif_expr_K:
2329 case truth_xor_expr_K:
2330 case try_catch_expr_K:
2332 case unordered_expr_K:
2333 case widen_sum_expr_K:
2334 case widen_mult_expr_K:
2335 case with_size_expr_K:
2336 case vec_lshift_expr_K:
2337 case vec_rshift_expr_K:
2338 case widen_mult_hi_expr_K:
2339 case widen_mult_lo_expr_K:
2340 case vec_pack_trunc_expr_K:
2341 case vec_pack_sat_expr_K:
2342 case vec_pack_fix_trunc_expr_K:
2343 case vec_extracteven_expr_K:
2344 case vec_extractodd_expr_K:
2345 case vec_interleavehigh_expr_K:
2346 case vec_interleavelow_expr_K:
2347 case extract_bit_expr_K:
2348 case sat_plus_expr_K:
2349 case sat_minus_expr_K:
2350 case extractvalue_expr_K:
2351 case extractelement_expr_K:
2359 case aggr_init_expr_K:
2360 case case_label_expr_K:
2362 case identifier_node_K:
2364 case statement_list_K:
2366 case target_mem_ref_K:
2367 case target_mem_ref461_K:
2394 const auto fu_name =
"__float_" + fu_suffix;
2396 current_statement, current_tree_node, current_srcp);
2407 if(curr_tn->get_kind() == mem_ref_K)
2409 const auto mr = GetPointerS<mem_ref>(curr_tn);
2414 THROW_UNREACHABLE(
"Real type expression not handled: " + curr_tn->get_kind_text() +
" " +
2415 curr_tn->ToString());
2421 if(curr_tn->get_kind() == mem_ref_K)
2423 const auto mr = GetPointerS<mem_ref>(curr_tn);
2426 else if(curr_tn->get_kind() == pointer_plus_expr_K)
2428 const auto pp = GetPointerS<pointer_plus_expr>(curr_tn);
2433 THROW_UNREACHABLE(
"Real pointer type expression not handled: " + curr_tn->get_kind_text() +
" " +
2434 curr_tn->ToString());
2441 const auto te = GetPointerS<ternary_expr>(curr_tn);
2455 const auto qe = GetPointerS<quaternary_expr>(curr_tn);
2473 const auto le = GetPointerS<lut_expr>(curr_tn);
2508 const auto co = GetPointerS<constructor>(curr_tn);
2509 for(
const auto& idx_valu : co->list_of_idx_valu)
2517 const auto gc = GetPointerS<gimple_cond>(curr_tn);
2521 case gimple_switch_K:
2523 const auto se = GetPointerS<gimple_switch>(curr_tn);
2527 case gimple_multi_way_if_K:
2529 const auto gmwi = GetPointerS<gimple_multi_way_if>(curr_tn);
2530 for(
const auto& cond : gmwi->list_of_cond)
2539 case gimple_return_K:
2541 const auto re = GetPointerS<gimple_return>(curr_tn);
2556 const auto gf = GetPointerS<const gimple_for>(curr_tn);
2562 case gimple_while_K:
2564 const auto gw = GetPointerS<gimple_while>(curr_tn);
2573 case target_mem_ref_K:
2575 const auto tmr = GetPointerS<target_mem_ref>(curr_tn);
2590 case target_mem_ref461_K:
2592 const auto tmr = GetPointerS<target_mem_ref461>(curr_tn);
2611 const auto cst = GetPointerS<real_cst>(curr_tn);
2614 (cst->valx.front() ==
'-' && cst->valr.front() != cst->valx.front()) ? (
"-" + cst->valr) : cst->valr;
2619 int_cst =
TreeM->CreateUniqueIntegerCst(static_cast<long long>(cst_val),
2630 TreeM->ReplaceTreeNode(current_statement, current_tree_node, int_cst);
2633 "---Real type constant " + curr_tn->ToString() +
" converted to " +
2658 case function_decl_K:
2664 case case_label_expr_K:
2665 case gimple_label_K:
2668 case gimple_pragma_K:
2676 case gimple_predict_K:
2678 case identifier_node_K:
2680 case namespace_decl_K:
2682 case placeholder_expr_K:
2683 case statement_list_K:
2684 case translation_unit_decl_K:
2686 case template_decl_K:
2687 case tree_reindex_K:
2700 "<--Updated recursively (" +
STR(current_tree_node->
index) +
") " +
STR(current_tree_node));
2706 : exp_bits(_exp_bits),
2707 frac_bits(_frac_bits),
2708 exp_bias(_exp_bias),
2709 rounding_mode(_rounding_mode),
2710 exception_mode(_exception_mode),
2712 has_subnorm(_has_subnorm),
2741 std::stringstream ss;
2744 ss <<
"b" << (
exp_bias < 0 ?
"_" :
"");
2794 #define FP_FORMAT_EXP 1 2795 #define FP_FORMAT_SIG 2 2796 #define FP_FORMAT_BIAS 3 2797 #define FP_FORMAT_RND 4 2798 #define FP_FORMAT_EXC 5 2799 #define FP_FORMAT_SPEC 6 2800 #define FP_FORMAT_SIGN 7 2803 std::replace(ff_str.begin(), ff_str.end(),
'_',
'-');
2804 static const std::regex fp_format(
"^e(\\d+)m(\\d+)b([_-]?\\d+)(\\D)(\\D)(\\D*)(\\d?)$");
2806 if(std::regex_search(ff_str.data(), what, fp_format))
2808 const auto e = std::stoi(std::string(
2810 const auto m = std::stoi(std::string(
2812 const auto b = std::stoi(std::string(
2814 FloatFormatRef ff(
new FloatFormat(static_cast<uint8_t>(e), static_cast<uint8_t>(m), b));
2842 for(
const auto& s : spec)
2850 ff->has_subnorm =
true;
2858 const auto sign =
static_cast<bool>(std::stoi(std::string(what[
FP_FORMAT_SIGN].first, 1)));
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
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) ...
static bool IsStore(const tree_nodeConstRef &tn, const CustomOrderedSet< unsigned int > &fun_mem_data)
Return true if the tree node is a gimple_assign writing something which will be allocated in memory...
static bool lowering_needed(const ssa_name *ssa)
tree_nodeRef generate_interface(const blocRef &bb, tree_nodeRef stmt, const tree_nodeRef &ssa, FloatFormatRef inFF, FloatFormatRef outFF) const
Generate necessary statements to convert ssa variable from inFF to outFF and insert them after stmt i...
static std::string strip_fname(std::string fname, bool *single_prec=nullptr)
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
const TreeNodeMap< size_t > & CGetUseStmts() const
Return the use stmts.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
const tree_nodeRef CGetDefStmt() const
Return the def stmt (checking that is unique)
tree_nodeRef floatNegate(const tree_nodeRef &op, const FloatFormatRef &ff) const
Generate float negate operation based on given floating-point format.
#define MEMCPY
constant string identifying the operation performed when two objects are memcopied.
File containing functions and utilities to support the printing of debug messagges.
static tree_nodeRef float64_type
std::string ToString() const
Print this node as string in gimple format.
CustomMap< ssa_name *, std::set< unsigned int > > hwParam
Hardware implemented functions need parameters specified as real_type, thus it is necessary to add a ...
Step successfully executed.
#define CASE_BINARY_EXPRESSION
This macro collects all case labels for binary_expr objects.
std::vector< tree_nodeRef > paramBinding
#define GET_CLASS(obj)
Macro returning the actual type of an object.
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.
bool operator!=(const FunctionVersion &other) const
Definition of the class representing a generic C application.
const int output_level
The output level.
const std::vector< std::string > SplitString(const std::string &input, const std::string &separators)
Function which splits a string into tokens.
#define CASE_DECL_NODES
NOTE that cast_expr is a unary expression but it could not be included in the CASE_UNARY_EXPRESSION b...
static std::string print_type(const tree_managerConstRef &TM, unsigned int type, bool global=false, bool print_qualifiers=false, bool print_storage=false, unsigned int var=0, const var_pp_functorConstRef &vppf=var_pp_functorConstRef(), const std::string &prefix="", const std::string &tail="")
Print a type and its variable in case var is not zero.
Step successfully executed but without any IR change.
const CallGraph::vertex_descriptor function_vertex
CustomMap< ssa_name *, std::tuple< FloatFormatRef, std::vector< unsigned int > > > inputInterface
SSA variable which requires cast renaming from standard to user-defined float format in all but given...
static bool inline_conversion
RelationshipType
The relationship type.
struct definition of the function_decl tree node.
bool signature_lowering(function_decl *f_decl) const
Source must be executed to satisfy target.
CustomMap< ssa_name *, bool > viewConvert
DesignFlowStep_Status InternalExec() override
Fixes the var_decl duplication.
static tree_nodeRef float32_ptr_type
tree_nodeRef var
var is the variable being referenced (macro SSA_NAME_VAR).
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
static std::string GetString(const enum kind k)
Given a kind, return the corresponding string.
static const std::set< std::string > libm_func
List of low level implementation libm functions.
CustomOrderedMap< T, U > CustomMap
boost::graph_traits< graph >::in_edge_iterator InEdgeIterator
in_edge_iterator definition.
exceptions managed by PandA
tree_nodeRef CloneFunction(const tree_nodeRef &tn, const std::string &funNameSuffix)
CloneFunction duplicates a function.
tree_nodeRef create_binary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op0, const tree_nodeRef &op1, const std::string &srcp, enum kind operation_kind) const
Function used to create a binary expression.
tree_nodeRef GetSignedIntegerType() const
Function that creates a integer type if it is not already present, otherwise it returns the one that ...
#define BUILTIN_WAIT_CALL
constant defining the builtin wait call intrinsic function
bool RecursiveExaminate(const tree_nodeRef ¤t_statement, const tree_nodeRef ¤t_tree_node, int castRename)
Recursive examine tree node.
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
void ssa_lowering(ssa_name *ssa, bool internal_type) const
static std::string print_function_name(const tree_managerConstRef &TM, const function_decl *fd)
Return the name of the function in a string.
This class provides methods to build a basic blocks graph.
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...
static CustomMap< CallGraph::vertex_descriptor, FunctionVersionRef > funcFF
Floating-point function version map.
redefinition of map to manage ordered/unordered structures
tree_nodeRef create_unary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op, const std::string &srcp, enum kind operation_kind) const
EXPRESSION_TREE_NODES.
tree_nodeRef CreateGimpleAssign(const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, const tree_nodeRef &op, unsigned int function_decl_nid, const std::string &srcp) const
Create gimple assignment.
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define THROW_WARNING(str_expr)
helper function used to throw a warning in a standard way: though it uses PRINT_DBG_MEX, the debug level used is such that the message is always printed
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
void replaceWithCall(const FloatFormatRef &specFF, const std::string &fu_name, std::vector< tree_nodeRef > args, const tree_nodeRef ¤t_statement, const tree_nodeRef ¤t_tree_node, const std::string ¤t_scrp)
Replace current_tree_node with a call_expr to fu_name function specialized with specFF fp format in c...
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
static void addCallPointAndExpand(CustomUnorderedSet< unsigned int > &AV, const application_managerRef AM, unsigned int caller_id, unsigned int called_id, unsigned int call_id, enum FunctionEdgeInfo::CallType call_type, int DL)
static bool IsUnsignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of unsigned integer type.
#define MEMSET
constant string identifying the operation performed when two objects are memsetted.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Standard functor that returns the name of a variable.
soft_float_cg_ext(const ParameterConstRef _parameters, const application_managerRef AppM, unsigned int _function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
Base class for step of design flow.
CustomMap< ssa_name *, std::tuple< FloatFormatRef, std::vector< tree_nodeRef > > > outputInterface
SSA variable which requires cast renaming from user-defined to standard float format in given stateme...
static void RequestCallOpt(const tree_nodeConstRef &call_stmt, unsigned int caller_id, FunctionOptType opt)
Request optimization for given call statement.
tree_nodeRef GetPointerType(const tree_nodeConstRef &ptd, unsigned long long algn=0) const
Function that creates a pointer type if it is not already present, otherwise it returns the one that ...
tree_nodeRef floatAbs(const tree_nodeRef &op, const FloatFormatRef &ff) const
Generate float absolute value operation based on given floating-point format.
#define CASE_QUATERNARY_EXPRESSION
This macro collects all case labels for quaternary_expr objects.
tree_nodeRef int_ptr_type
#define CASE_UNARY_EXPRESSION
This macro collects all case labels for unary_expr objects.
unsigned int create_tree_node(const tree_nodeRef &tn, int mode=tree_node_dup_mode::DEFAULT)
tree_node visitors
FloatFormatRef userRequired
static tree_nodeRef float64_ptr_type
int compare(const FunctionVersion &other, bool format_only=false) const
std::string ToString() const
const unsigned int index
Represent the index read from the raw file and the index-1 of the vector of tree_node associated to t...
static bool IsFunctionType(const tree_nodeConstRef &type)
Return true if the treenode is of type function type.
Classes to describe design flow graph.
tree_nodeRef body
body field is the saved representation of the body of the entire function.
Target must be reexecuted.
~soft_float_cg_ext() override
Destructor.
static const FloatFormatRef float32FF(new FloatFormat(8, 23, -127))
static const FloatFormatRef float64FF(new FloatFormat(11, 52, -1023))
#define BB_ENTRY
constant identifying the basic block node of type entry
tree_nodeRef chan
purp is the TREE_CHAIN field: tree_list nodes are made into lists by chaining through the TREE_CHAIN ...
tree_nodeRef int_type_for(const tree_nodeRef &type, bool use_internal) const
#define FLOAT_CAST_FU_NAME
#define GET_CONST_NODE(t)
refcount< const tree_node > tree_nodeConstRef
DesignFlowStep_Status GetStatus() const
Return the status of this design step.
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
CustomUnorderedSet< unsigned int > already_visited
Already visited tree node (used to avoid infinite recursion)
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#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
tree_nodeRef cstCast(uint64_t in, const FloatFormatRef &inFF, const FloatFormatRef &outFF) const
Cast real type constant from inFF to outFF format.
std::vector< tree_nodeRef > topReturn
Step that extends the call graph with the soft-float calls where appropriate.
tree_nodeRef GetBooleanType() const
Function that creates a boolean type if it is not already present, otherwise it returns the one that ...
This struct specifies the block node.
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
This file collects some utility functions.
std::vector< tree_nodeRef > list_of_args
args field holds a chain of parm_decl nodes for the arguments.
static const std::set< std::string > supported_libm_calls
tree_nodeRef GetCustomIntegerType(unsigned long long prec, bool unsigned_p) const
create an integer type starting from a given prec
static tree_nodeRef float32_type
const tree_managerRef TreeM
Tree manager.
std::vector< tree_nodeRef > nopConvert
tree_nodeRef CreateCallExpr(const tree_nodeConstRef &called_function, const std::vector< tree_nodeRef > &args, const std::string &srcp) const
Create a call_expr.
const unsigned int function_id
The index of the function to be analyzed.
#define CASE_CST_NODES
This macro collects all case labels for cast nodes.
const application_managerRef AppM
The application manager.
This struct specifies the tree_list node.
static const std::set< std::string > supported_libm_calls_inlined
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
bool operator==(const FunctionVersion &other) const
#define CASE_FAKE_NODES
This macro collects all case labels for fake or empty nodes.
FunctionVersionRef _version
T * GetPointer(const refcount< U > &t)
Template function used to hide dynamic_cast The template parameter T represents a type of an object h...
std::vector< ssa_name * > hwReturn
Hardware implemented functions return values as real_type, thus a view_convert is necessary...
Class specification of the basic_block structure.
Data structures used in operations graph.
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.
#define THROW_ERROR_CODE(code, str_expr)
helper function used to throw an error with a code error
tree_nodeRef type
type field holds the data type of the object, when relevant.
static tree_nodeConstRef CGetPointedType(const tree_nodeConstRef &pointer)
Return the pointed type of a pointer object.
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.
#define CASE_CPP_NODES
This macro collects all case labels for cpp nodes.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
tree_nodeRef valu
purp is the TREE_VALUE field which stores the elements of the list.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
tree node duplication class.
This struct specifies the ssa_name node.
absl::node_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMapStable
#define CASE_GIMPLE_NODES
This macro collects all cases labels for gimple nodes.
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
#define GET_INDEX_CONST_NODE(t)
refcount< const var_pp_functor > var_pp_functorConstRef
static bool IsPointerType(const tree_nodeConstRef &type)
Return true if treenode index is a pointer.
static tree_nodeConstRef GetFunctionReturnType(const tree_nodeConstRef &function, bool void_as_null=true)
Return the return type of a function.
static CustomMap< unsigned int, std::array< tree_nodeRef, 8 > > versioning_args
Static arguments list to feed specialization parameters of versioned functions.
Step is symbolic and it has already been marked.
static bool IsLoad(const tree_nodeConstRef &tn, const CustomOrderedSet< unsigned int > &fun_mem_data)
Return true if the tree node is a gimple_assign reading something which will be allocated in memory...
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
#define CASE_TERNARY_EXPRESSION
This macro collects all case labels for ternary_expr objects.
const tree_manipulationRef tree_man
tree manipulation
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
unsigned long long convert_fp_to_bits(std::string num, unsigned long long precision)
convert a real number stored in a string into bits with a given precision
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.
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...