# setting stage id if undefined or updating stage_id value stage_id = optree_set_undefined_stage(optree, stage_id) if isinstance(optree, ML_LeafNode): pass else: for op_input in optree.get_inputs(): unify_stages_rec(op_input, stage_id, memoization_map) memoization_map[optree] = stage_id class Pass_UnifyPipelineStages(OptreeOptimization): """ implementation of pipeline stage uniformisation """ pass_tag = "unify_pipeline_stages" def __init__(self, target): """ pass initialization """ OptreeOptimization.__init__(self, "unify_pipeline_stages", target) def execute(self, optree): """ pass execution """ return unify_stages_rec(optree, {}) # register pass Log.report(Log.Info, "Registering {} pass".format(Pass_UnifyPipelineStages.pass_tag)) Pass.register(Pass_UnifyPipelineStages)
## _m128 register promotion class Pass_M128_Promotion(Pass_Vector_Promotion): pass_tag = "m128_promotion" ## Translation table between standard formats # and __m128-based register formats trans_table = { ML_Binary32: ML_SSE_m128_v1float32, ML_Binary64: ML_SSE_m128_v1float64, v2float64: ML_SSE_m128_v2float64, v4float32: ML_SSE_m128_v4float32, v4bool: ML_SSE_m128_v4bool, v2int64: ML_SSE_m128_v2int64, v4int32: ML_SSE_m128_v4int32, v2uint64: ML_SSE_m128_v2uint64, v4uint32: ML_SSE_m128_v4uint32, ML_Int32: ML_SSE_m128_v1int32, } def get_translation_table(self): return self.trans_table def __init__(self, target): Pass_Vector_Promotion.__init__(self, target) self.set_descriptor("SSE promotion pass") Log.report(LOG_PASS_INFO, "Registering m128_conversion pass") # register pass Pass.register(Pass_M128_Promotion)
self.promote_node(op) for op in optree.get_inputs() ] # register modified inputs new_optree.inputs = new_inputs if parent_converted and optree.get_precision( ) in self.get_translation_table(): new_optree = insert_conversion_when_required( new_optree, self.get_conv_format(optree.get_precision()) ) #Conversion(new_optree, precision = self.get_conv_format(optree.get_precision())) return new_optree elif parent_converted: print(optree.get_precision()) raise NotImplementedError return self.memoize(parent_converted, optree, new_optree) # standard Opt pass API def execute_on_optree(self, optree, fct=None, fct_group=None, memoization_map=None): return self.promote_node(optree) Log.report(LOG_PASS_INFO, "Registering vector_conversion pass") # register pass Pass.register(Pass_Vector_Promotion)
def __init__(self, target, default_precision, default_integer_format=ML_Int32, default_boolean_precision=ML_Int32): FunctionPass.__init__(self, "instantiate_prec") self.default_integer_format = default_integer_format self.default_boolean_precision = default_boolean_precision self.default_precision = default_precision def execute_on_optree(self, optree, fct=None, fct_group=None, memoization_map=None): memoization_map = memoization_map if not memoization_map is None else {} optree_precision = instantiate_precision( optree, self.default_precision, memoization_map=memoization_map, backend=self) return optree # register pass Log.report(LOG_PASS_INFO, "Registering instantiate_abstract_prec pass") Pass.register(PassInstantiateAbstractPrecision) Log.report(LOG_PASS_INFO, "Registering instantiate_prec pass") Pass.register(PassInstantiatePrecision)
check_result = self.check_function(optree) self.memoization_map[optree] = check_result if not check_result: Log.report( Log.Info, "the following node check failed: {}".format( optree.get_str(depth=2, display_precision=True, memoization_map={}))) if not isinstance(optree, ML_LeafNode): for op_input in optree.get_inputs(): check_result &= self.execute(op_input) return check_result ## Generic vector promotion pass class Pass_CheckPrecision(Pass_CheckGeneric): pass_tag = "check_precision" def __init__(self, target): Pass_CheckGeneric.__init__(self, target, check_precision_validity, "check_precision pass") self.memoization_map = {} # register pass Log.report(LOG_PASS_INFO, "Registering check_generic pass") Pass.register(Pass_CheckGeneric) Log.report(LOG_PASS_INFO, "Registering check_precision pass") Pass.register(Pass_CheckPrecision)
target) ## memoization map for promoted optree self.memoization_map = {} self.expander = VectorMaskTestExpander(target) def can_be_transformed(self, node, *args): """ Returns True if @p can be expanded from a multi-precision node to a list of scalar-precision fields, returns False otherwise """ return self.expander.is_expandable(node) def transform_node(self, node, transformed_inputs, *args): """ If node can be transformed returns the transformed node else returns None """ return self.expander.expand_node(node) def reconstruct_from_transformed(self, node, transformed_node): """return a node at the root of a transformation chain, compatible with untransformed nodes """ return transformed_node ## standard Opt pass API def execute(self, optree): """ Implémentation of the standard optimization pass API """ return self.transform_graph(optree) Log.report(LOG_PASS_INFO, "Registering vector_mask_test_legalization pass") # register pass Pass.register(Pass_VectorMaskTestLegalization)
def evaluate_set_range(self, optree, memoization_map=None): """ check if all precision-instantiated operation are supported by the processor """ # memoization map is used to store node's range/interval memoization_map = {} if memoization_map is None else memoization_map if optree in memoization_map: return optree else: if not is_leaf_node(optree): for op in optree.inputs: _ = self.evaluate_set_range(op, memoization_map=memoization_map) if optree.get_interval() is None: op_range = evaluate_range(optree, update_interval=True) else: op_range = optree.get_interval() if not op_range is None: Log.report(LOG_VERBOSE_EVALUATE_RANGE, "range for {} has been evaluated to {}", optree, op_range) # memoization memoization_map[optree] = op_range return optree def execute_on_optree(self, optree, fct=None, fct_group=None, memoization_map=None): return self.evaluate_set_range(optree, memoization_map) Log.report(LOG_PASS_INFO, "Registering evaluate_range pass") # register pass Pass.register(Pass_EvaluateRange)
## memoization map for promoted optree self.memoization_map = {} self.expander = MultiPrecisionExpander(target) def can_be_transformed(self, node, *args): """ Returns True if @p can be expanded from a multi-precision node to a list of scalar-precision fields, returns False otherwise """ return self.expander.is_expandable(node) def transform_node(self, node, transformed_inputs, *args): """ If node can be transformed returns the transformed node else returns None """ return self.expander.expand_node(node) def reconstruct_from_transformed(self, node, transformed_node): """return a node at the root of a transformation chain, compatible with untransformed nodes """ return self.expander.reconstruct_from_transformed( node, transformed_node) ## standard Opt pass API def execute(self, optree): """ Implémentation of the standard optimization pass API """ return self.transform_graph(optree) Log.report(LOG_PASS_INFO, "Registering expand_multi_precision pass") # register pass Pass.register(Pass_ExpandMultiPrecision)
if not result is None: Log.report(LOG_VERBOSE_NUMERICAL_SIMPLIFICATION, "{} has been simplified to {}", node, result) self.memoization_map[node] = result return result class Pass_NumericalSimplification(FunctionPass): """ Pass to expand oepration on vector masks """ pass_tag = "numerical_simplification" def __init__(self, target): FunctionPass.__init__( self, "virtual vector bool legalization pass", target) ## memoization map for promoted optree self.memoization_map = {} self.simplifier = NumericalSimplifier(target) def execute_on_optree(self, node, fct=None, fct_group=None, memoization_map=None): """ If node can be transformed returns the transformed node else returns None """ return self.simplifier.simplify(node) Log.report(LOG_PASS_INFO, "Registering numerical_simplification pass") # register pass Pass.register(Pass_NumericalSimplification)
cond_cp, if_value_cp, else_value_cp) return self.memoize_result(optree, select_cp) elif optree.__class__ in OPERATION_CLASS_TIMING_MODEL: return self.memoize_result( optree, OPERATION_CLASS_TIMING_MODEL[optree.__class__](self, optree)) else: Log.report(Log.Error, "unkwown node in evaluate_critical_path: {}", optree) def execute(self, optree): self.evaluate_critical_path(optree) ordered_list = [ op for op in self.memoization_map.keys() if not self.memoization_map[op] is None ] ordered_list = sorted(ordered_list, key=lambda v: self.memoization_map[v].value, reverse=True) longest_path = self.memoization_map[ordered_list[0]] current = longest_path while current != None: print(current.node.get_tag(), current.value) current = current.previous Log.report(LOG_PASS_INFO, "Registering critical_path_eval pass") # register pass Pass.register(Pass_CriticalPathEval)
OptreeOptimization.__init__(self, "rtl simplification pass", target) ## memoization map for promoted optree self.memoization_map = {} self.simplifier = BasicSimplifier(target) def can_be_transformed(self, node, *args): """ Returns True if @p can be expanded from a multi-precision node to a list of scalar-precision fields, returns False otherwise """ return self.simplifier.is_simplifiable(node) def transform_node(self, node, transformed_inputs, *args): """ If node can be transformed returns the transformed node else returns None """ return self.simplifier.simplify_node(node) def reconstruct_from_transformed(self, node, transformed_node): """return a node at the root of a transformation chain, compatible with untransformed nodes """ return transformed_node ## standard Opt pass API def execute(self, optree): """ Implémentation of the standard optimization pass API """ return self.transform_graph(optree) Log.report(LOG_PASS_INFO, "Registering simplify_rtl pass") # register pass Pass.register(Pass_SimplifyRTL)
# no simplification result = node self.memoization_map[node] = result return result class Pass_LogicalSimplification(FunctionPass): """ Pass to simplify logical operation """ pass_tag = "logical_simplification" def __init__(self, target): FunctionPass.__init__(self, "logical operation simplification pass", target) ## memoization map for promoted optree self.memoization_map = {} self.simplifier = LogicalSimplification(target) def execute_on_optree(self, node, fct=None, fct_group=None, memoization_map=None): """ If node can be transformed returns the transformed node else returns None """ return self.simplifier.simplify(node) Log.report(LOG_PASS_INFO, "Registering logical_simplification pass") # register pass Pass.register(Pass_LogicalSimplification)
OptreeOptimization.__init__(self, "basic legalization pass", target) ## memoization map for promoted optree self.memoization_map = {} self.expander = BasicExpander(target) def can_be_transformed(self, node, *args): """ Returns True if @p can be expanded from a multi-precision node to a list of scalar-precision fields, returns False otherwise """ return self.expander.is_expandable(node) def transform_node(self, node, transformed_inputs, *args): """ If node can be transformed returns the transformed node else returns None """ return self.expander.expand_node(node) def reconstruct_from_transformed(self, node, transformed_node): """return a node at the root of a transformation chain, compatible with untransformed nodes """ return transformed_node ## standard Opt pass API def execute(self, optree): """ Implémentation of the standard optimization pass API """ return self.transform_graph(optree) Log.report(LOG_PASS_INFO, "Registering basic_legalization pass") # register pass Pass.register(Pass_BasicLegalization)
elif isinstance(optree, PlaceHolder): pass elif isinstance(optree, SwitchBlock): #self.check_processor_support(optree.get_pre_statement(), memoization_map) for op in optree.get_extra_inputs(): # TODO: assert case is integer constant self.check_processor_support(op, memoization_map, debug=debug) elif not self.get_target().is_supported_operation(optree, debug=debug): print(self.processor.get_operation_keys(optree)) # Error print print( optree.get_str(display_precision=True, display_id=True, memoization_map={})) # Error print Log.report(Log.Error, "unsupported operation\n") # memoization memoization_map[optree] = True return True def execute(self, optree): memoization_map = {} return self.check_processor_support(optree, memoization_map) Log.report(LOG_PASS_INFO, "Registering check_target_support pass") # register pass Pass.register(Pass_CheckSupport)
""" """ # looking into memoization map if optree in self.memoization_map: return False, self.memoization_map[optree] # has the npde been modified ? arg_changed = False if isinstance(optree, ML_LeafNode): pass else: for index, op_input in enumerate(optree.get_inputs()): is_modified, new_node = self.legalize_operation_rec(op_input) if is_modified: optree.set_input(index, new_node) arg_changed = True local_changed, new_optree = legalize_single_operation(optree, self.format_solver) self.memoization_map[optree] = new_optree return (local_changed or arg_changed), new_optree def execute(self, optree): """ pass execution """ return self.legalize_operation_rec(optree) Log.report(LOG_PASS_INFO, "Registering size_datapath pass") # register pass Pass.register(Pass_RTLLegalize)
if optree.__class__ in support_simplification: code_gen_key = optree.get_codegen_key() if code_gen_key in support_simplification[optree.__class__]: for cond in support_simplification[ optree.__class__][code_gen_key]: if cond(optree): return True return False def get_support_simplification(self, optree): code_gen_key = optree.get_codegen_key() for cond in support_simplification[optree.__class__][code_gen_key]: if cond(optree): return support_simplification[ optree.__class__][code_gen_key][cond](optree, self.processor) Log.report(Log.Error, "support simplification mapping not found") # register pass Log.report(LOG_PASS_INFO, "Registering silence_fp_operations pass") Pass.register(PassSilenceFPOperation) Log.report(LOG_PASS_INFO, "Registering fuse_fma pass") Pass.register(PassFuseFMA) Log.report(LOG_PASS_INFO, "Registering sub_expr_sharing pass") Pass.register(PassSubExpressionSharing) Log.report(LOG_PASS_INFO, "Registering check_processor_support pass") Pass.register(PassCheckProcessorSupport)
from metalibm_core.opt.p_vector_promotion import Pass_Vector_Promotion ## _m256 register promotion class Pass_M256_Promotion(Pass_Vector_Promotion): pass_tag = "m256_promotion" ## Translation table between standard formats # and __m256-based register formats trans_table = { v4float64: ML_AVX_m256_v4float64, v8float32: ML_AVX_m256_v8float32, v4int64: ML_AVX_m256_v4int64, v8int32: ML_AVX_m256_v8int32, v4uint64: ML_AVX_m256_v4uint64, v8uint32: ML_AVX_m256_v8uint32, v8bool: ML_AVX_m256_v8bool, } def get_translation_table(self): return self.trans_table def __init__(self, target): Pass_Vector_Promotion.__init__(self, target) self.set_descriptor("AVX promotion pass") Log.report(LOG_PASS_INFO, "Registering m256_conversion pass") # register pass Pass.register(Pass_M256_Promotion)
## Legalize the precision of a datapath by finely tuning the size # of each operations (limiting width while preventing overflow) class Pass_SizeDatapath(FunctionPass): """ implementation of datapath sizing pass """ pass_tag = "size_datapath" def __init__(self, target): """ pass initialization """ FunctionPass.__init__(self, "size_datapath", target) self.format_solver = FormatSolver() def execute(self, optree): """ pass execution, API required to be executed on an ML_Entity """ return self.format_solver.solve_format_rec(optree) def execute_on_optree(self, optree, fct=None, fct_group=None, memoization_map=None): """ Trampoline required by FunctionPass API """ return self.execute(optree) Log.report(LOG_PASS_INFO, "Registering size_datapath pass") # register pass Pass.register(Pass_SizeDatapath)
target) ## memoization map for promoted optree self.memoization_map = {} self.expander = VirtualBoolVectorLegalizer(target) def can_be_transformed(self, node, *args): """ Returns True if @p can be expanded from a multi-precision node to a list of scalar-precision fields, returns False otherwise """ return self.expander.is_legalizable(node) def transform_node(self, node, transformed_inputs, *args): """ If node can be transformed returns the transformed node else returns None """ return self.expander.legalize_node(node) def reconstruct_from_transformed(self, node, transformed_node): """return a node at the root of a transformation chain, compatible with untransformed nodes """ return transformed_node ## standard Opt pass API def execute(self, optree): """ Implémentation of the standard optimization pass API """ return self.transform_graph(optree) Log.report(LOG_PASS_INFO, "Registering virtual_vector_bool_legalization pass") # register pass Pass.register(Pass_VirtualVectorBoolLegalization)
def execute_on_function(self, fct, fct_group): """ Execute SSA translation pass on function @p fct from function-group @p fct_group """ Log.report(LOG_LEVEL_GEN_BB_INFO, "executing pass {} on fct {}".format( self.pass_tag, fct.get_name())) optree = fct.get_scheme() assert isinstance(optree, BasicBlockList) bb_root = optree.get_input(0) bbg = BasicBlockGraph(bb_root, optree) phi_node_insertion(bbg) variable_renaming(bbg) # registering basic-block generation pass Log.report(LOG_PASS_INFO, "Registering generate Basic-Blocks pass") Pass.register(Pass_GenerateBasicBlock) # registering ssa translation pass Log.report(LOG_PASS_INFO, "Registering ssa translation pass") Pass.register(Pass_SSATranslate) # registering basic-block simplification pass Log.report(LOG_PASS_INFO, "Registering basic-block simplification pass") Pass.register(Pass_BBSimplification) if __name__ == "__main__": bb_root = BasicBlock(tag="bb_root") bb_1 = BasicBlock(tag="bb_1") bb_2 = BasicBlock(tag="bb_2") bb_3 = BasicBlock(tag="bb_3") var_x = Variable("x", precision=None) var_y = Variable("y", precision=None)
function-group @p fct_group """ Log.report( LOG_LEVEL_GEN_BB_INFO, "executing pass {} on fct {}".format(self.pass_tag, fct.get_name())) optree = fct.get_scheme() assert isinstance(optree, BasicBlockList) bb_root = optree.get_input(0) bbg = BasicBlockGraph(bb_root, optree) phi_node_insertion(bbg) variable_renaming(bbg) # registering basic-block generation pass Log.report(LOG_PASS_INFO, "Registering generate Basic-Blocks pass") Pass.register(Pass_GenerateBasicBlock) # registering ssa translation pass Log.report(LOG_PASS_INFO, "Registering ssa translation pass") Pass.register(Pass_SSATranslate) if __name__ == "__main__": bb_root = BasicBlock(tag="bb_root") bb_1 = BasicBlock(tag="bb_1") bb_2 = BasicBlock(tag="bb_2") bb_3 = BasicBlock(tag="bb_3") var_x = Variable("x", precision=None) var_y = Variable("y", precision=None) bb_root.add(ReferenceAssign(var_x, 1)) bb_root.add(ReferenceAssign(var_y, 2))