static bool nodecl_is_zero( const Nodecl::NodeclBase& n ) { bool res = false; if( n.is<Nodecl::IntegerLiteral>( ) ) res = const_value_is_zero( n.as<Nodecl::IntegerLiteral>( ).get_constant( ) ); else if( n.is<Nodecl::FloatingLiteral>( ) ) res = const_value_is_zero( n.as<Nodecl::FloatingLiteral>( ).get_constant( ) ); return res; }
void LoopNormalize::normalize() { Nodecl::ForStatement loop = this->_loop.as<Nodecl::ForStatement>(); TL::Scope orig_loop_scope = loop.retrieve_context(); TL::ForStatement for_stmt(loop); TL::Symbol induction_var = for_stmt.get_induction_variable(); Nodecl::NodeclBase orig_loop_lower = for_stmt.get_lower_bound(); Nodecl::NodeclBase orig_loop_upper = for_stmt.get_upper_bound(); Nodecl::NodeclBase orig_loop_step = for_stmt.get_step(); // Do nothing if the loop is already a normalized loop if ( orig_loop_lower.is_constant() && const_value_is_zero(orig_loop_lower.get_constant()) && orig_loop_step.is_constant() && const_value_is_one(orig_loop_step.get_constant())) { _transformation = _loop.shallow_copy(); return; } // DO I = L, U, S // A(I) // becomes // DO I1 = 0, (U-L)/S, 1 // A(S * I1 + L) // Nodecl::NodeclBase new_upper; if (orig_loop_upper.is_constant() && orig_loop_lower.is_constant()) { new_upper = const_value_to_nodecl( const_value_sub( orig_loop_upper.get_constant(), orig_loop_lower.get_constant())); if (orig_loop_step.is_constant()) { new_upper = const_value_to_nodecl( const_value_div( new_upper.get_constant(), orig_loop_step.get_constant())); } else { new_upper = Nodecl::Div::make( new_upper, orig_loop_step.shallow_copy(), new_upper.get_type()); } } else { new_upper = Nodecl::Div::make( Nodecl::Minus::make( orig_loop_upper.shallow_copy(), orig_loop_lower.shallow_copy(), orig_loop_upper.get_type()), orig_loop_step.shallow_copy(), orig_loop_upper.get_type()); } Nodecl::NodeclBase normalized_loop_body = loop.get_statement().shallow_copy(); ReplaceInductionVar replace_induction_var(induction_var, orig_loop_lower, orig_loop_step); replace_induction_var.walk(normalized_loop_body); Nodecl::NodeclBase normalized_loop_control; if (IS_FORTRAN_LANGUAGE) { normalized_loop_control = Nodecl::RangeLoopControl::make( induction_var.make_nodecl(), const_value_to_nodecl(const_value_get_signed_int(0)), new_upper, const_value_to_nodecl(const_value_get_signed_int(1))); } else // IS_C_LANGUAGE || IS_CXX_LANGUAGE { Nodecl::NodeclBase init; // i = 0 if (for_stmt.induction_variable_in_separate_scope()) { induction_var.set_value(const_value_to_nodecl(const_value_get_signed_int(0))); init = Nodecl::ObjectInit::make(induction_var); } else { init = Nodecl::Assignment::make( induction_var.make_nodecl(/* ref */ true), const_value_to_nodecl(const_value_get_signed_int(0)), induction_var.get_type().no_ref().get_lvalue_reference_to()); } // i <= new_upper Nodecl::NodeclBase cond = Nodecl::LowerOrEqualThan::make( induction_var.make_nodecl(/* set_ref_type */ true), new_upper, ::get_bool_type()); // i = i + 1 Nodecl::NodeclBase next = Nodecl::Assignment::make( induction_var.make_nodecl(/* set_ref_type */ true), Nodecl::Add::make( induction_var.make_nodecl(/* set_ref_type */ true), const_value_to_nodecl(const_value_get_signed_int(1)), induction_var.get_type().no_ref()), induction_var.get_type().no_ref().get_lvalue_reference_to()); normalized_loop_control = Nodecl::LoopControl::make( Nodecl::List::make(init), cond, next); } Nodecl::NodeclBase normalized_for = Nodecl::ForStatement::make( normalized_loop_control, normalized_loop_body, /* loop-name */ Nodecl::NodeclBase::null()); _transformation = normalized_for; // Compute what value the induction variable should take after the loop if (!for_stmt.induction_variable_in_separate_scope()) { Nodecl::NodeclBase induction_variable = for_stmt.get_induction_variable().make_nodecl(/* set_ref_type */ true); Nodecl::NodeclBase expr = HLT::Utils::compute_induction_variable_final_expr(_loop); _post_transformation_stmts.append( Nodecl::ExpressionStatement::make( Nodecl::Assignment::make( induction_variable, expr, induction_variable.get_type()))); } }