00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 """
00032 @package Optimizer Inteface
00033 """
00034
00035 import optimizer
00036 import os
00037 import sys
00038 from ctrump import *
00039
00040 class Option:
00041 """最適化オプション"""
00042 option_types = [int, str, bool, list]
00043
00044 class Val:
00045 def __init__(self,key,opt_type,doc,desc,initial_value):
00046 self.key = key
00047 self.opt_type = opt_type
00048 self.doc = doc
00049 self.desc = desc
00050 self.initial_value = initial_value
00051
00052 def __init__(self,options):
00053 self.options = []
00054 for o in options:
00055 self.append(*o)
00056
00057 def append(self,key,doc,desc,initial_value):
00058 opt_type = type(initial_value)
00059 if not opt_type in self.option_types:
00060 raise TypeError("option must be a int or string or bool.")
00061 self.options.append((key,opt_type,doc,desc,initial_value))
00062
00063 def __iter__(self):
00064 return self.options.__iter__()
00065
00066 def initial_value(self):
00067 ret = {}
00068 for (key,opt_type,d,de,initial_value) in self.options:
00069 if opt_type == list:
00070 (val_key,initial_value) = initial_value[0]
00071
00072 ret[key] = initial_value
00073 return ret
00074
00075 def get_name(self):
00076 return self.name
00077
00078 class OptionValue:
00079 def __init__(self, engine, translators):
00080 self.engine = engine
00081 self.translators = translators
00082
00083 class OptionSet:
00084 def __init__(self, engine_option):
00085 self.engine = engine_option
00086 self.translators = {}
00087
00088 def create_initial_value(self):
00089 engine_value = {}
00090 translator_values = {}
00091
00092 engine_value = self.engine.initial_value()
00093
00094 for k in self.translators:
00095 v = self.translators[k]
00096 translator_values[k] = v.initial_value()
00097
00098 return OptionValue(engine_value, translator_values)
00099
00100 class AnalysisResultBase(object):
00101 """解析結果オブジェクト"""
00102
00103 def __init__(self, stmt, errors, warnings, hints, enabled_translators):
00104 self.stmt = stmt
00105 self.errors = errors
00106 self.warnings = warnings
00107 self.hints = hints
00108 self.enabled_translators = enabled_translators
00109
00110 def get_region(self):
00111 """対象範囲"""
00112 s = self.stmt
00113 if ((s.code == ctrump.STMT_FOR
00114 or s.code == ctrump.STMT_WHILE
00115 or s.code == ctrump.STMT_FOR_DECL) and
00116 (s.body.code == ctrump.STMT_COMPOUND)):
00117 begin_filename = s.body.lbr_loc.path
00118 begin_lineno = s.body.lbr_loc.lineno
00119
00120 end_filename = s.body.rbr_loc.path
00121 end_lineno = s.body.rbr_loc.lineno
00122 else:
00123 (begin_filename, begin_lineno) = ctrump.get_stmt_loc(s)
00124 end_filename = begin_filename
00125 begin_lineno = begin_lineno
00126 end_lineno = begin_lineno
00127
00128 return (begin_filename, begin_lineno, end_filename, end_lineno)
00129
00130 def get_errors(self):
00131 """エラーのリストを取得"""
00132 return self.errors
00133 def get_warnings(self):
00134 """警告のリストを取得"""
00135 return self.warnings
00136 def get_enabled_translators(self):
00137 """有効なトランスレータのリストを取得"""
00138 return self.enabled_translators
00139 def get_hints(self):
00140 """ヒントのリストを取得"""
00141 return self.hints
00142 def get_stmt(self):
00143 """対象となっている文を取得"""
00144 return self.stmt
00145
00146 def do_translate(self, translator, global_option, translate_option):
00147 """トランスレートを行う
00148 :param translator:translator object:
00149 :param global_option:グローバルオプション + エンジンオプションを合わせたOptionValueの値
00150 :param translate_option:トランスレートオプションの値
00151 :return: list of new programs
00152 """
00153 raise NotImplementedError(self.do_translate)
00154
00155 def do_translate_by_name(self, translator_name, global_option, translate_option):
00156 for i in self.get_enabled_translators():
00157 if i.get_name() == translator_name:
00158 return self.do_translate(i, global_option, translate_option)
00159 raise AttributeError(translator_name)
00160
00161 def get_enabled_translator_names(self):
00162 return [x.get_name() for x in self.enabled_translators]
00163
00164 def __repr__(self):
00165 ret = "errors = %s\nwarnings=%s\nhints=%s\n"%(
00166 self.errors, self.warnings, self.hints)
00167 ret += "enabled_translators = %s"%(
00168 [x.get_name() for x in self.enabled_translators])
00169 return ret
00170
00171 class OptimizationMessageBase(object):
00172 """メッセージオブジェクト"""
00173 def get_locations(self):
00174 raise NotImplementedError(self.get_lines())
00175
00176 def get_message(self):
00177 raise NotImplementedError(self.get_lines())
00178
00179 def get_hint(self):
00180 return None
00181
00182 class OptimizationError(OptimizationMessageBase):
00183 """エラーオブジェクト"""
00184 def __init__(self, locs, message):
00185 super(OptimizationError, self).__init__()
00186 self.locs = locs
00187 self.msg = message
00188
00189 def get_locations(self):
00190 return self.locs
00191
00192 def get_message(self):
00193 return self.msg
00194
00195 def __repr__(self):
00196 errors = ""
00197 for i in self.locs:
00198 path,lineno = i
00199 errors += '%s:%s:%s\n'%(path, lineno, self.msg)
00200 return errors
00201
00202 class TranslatorBase(object):
00203 """トランスレータオブジェクト"""
00204 def __init__(self):
00205 super(TranslatorBase,self).__init__()
00206
00207 def get_name(self):
00208 """トランスレータの名前を返す
00209 :return: string"""
00210 raise NotImplementedError(self.get_name)
00211
00212 def get_global_option(self):
00213 """オプションオブジェクトを返す
00214 :return: Option"""
00215
00216 raise NotImplementedError(self.get_global_option)
00217
00218 def get_translate_option(self):
00219 """トランスレート時に渡すオプションオブジェクトを返す
00220 :return: Option"""
00221
00222 raise NotImplementedError(self.get_translate_option)
00223
00224 class LoopParallelTreeNode:
00225 """ループツリーの情報"""
00226 def __init__(self):
00227 self.dep_vec_dir = 0
00228 self.error_bits = 0
00229
00230 def dep(self, vec_dir):
00231 self.dep_vec_dir |= vec_dir
00232
00233 def error(self, error_bits):
00234 error_bits |= error_bits
00235
00236 def get_stmt(self):
00237 return self.loop_node.cfg_info.loop_stmt
00238
00239 FLOW_DEP = (1<<0)
00240 ANTI_DEP = (1<<1)
00241 COMPLICATED_DEP = (1<<2)
00242
00243 class ErrorLoopTreeNode:
00244 """最適化できないループツリーの情報"""
00245 def __init__(self, error_bits, stmt, errors, warnings, hints):
00246 self.error_bits = error_bits
00247 self.stmt = stmt
00248 self.errors = errors
00249 self.warnings = warnings
00250 self.hints = hints
00251 self.children = []
00252 self.dep_vec_dir = 0
00253
00254 def get_stmt(self):
00255 return self.stmt
00256
00257
00258 class LoopAnalysisResult(AnalysisResultBase):
00259 """ループ解析結果"""
00260 def __init__(self, errors, warnings, hints, enabled_translators, loop_node, cfg, attr, ext_info, prog):
00261 super(LoopAnalysisResult,self).__init__(loop_node.get_stmt(), errors, warnings,
00262 hints, enabled_translators)
00263 self.cfg = cfg
00264 self.attr = attr
00265 self.ext_info = ext_info
00266 self.prog = prog
00267 self.loop_node = loop_node
00268
00269 def do_translate(self, translator, global_option, translate_option):
00270 return translator.translate(self.ext_info, self.stmt, self.cfg, self.loop_node, global_option, translate_option, self.prog)
00271
00272 class LoopTranslatorBase(TranslatorBase):
00273 """ループトランスレータ"""
00274
00275 def __init__(self):
00276 super(LoopTranslatorBase,self).__init__()
00277
00278 def is_enabled(self, analyze_results, stmt, cfg, attr, errors, warnings, hints):
00279 """トランスレート可能かどうかを返す
00280 :param analyze_results:result of analyze
00281 :param stmt:loop stmt
00282 :param cfg:loop cfg
00283 :param attr:loop attribute
00284 :param errors:
00285 :param warnings:
00286 :param hints:
00287 :return:True if enabled"""
00288 raise NotImplementedError(self.is_enabled)
00289
00290 def translate(self, analyze_results, stmt, cfg, attr, global_options, translate_options, prog):
00291 """トランスレートを行う
00292 :param analyze_results:result of analyze
00293 :param stmt:loop stmt
00294 :param cfg:loop cfg
00295 :param attr:loop attribute
00296 :param global_options:options
00297 :param translate_option:options
00298 :param prog:translation unit
00299 :return:list of optmized tree"""
00300 raise NotImplementedError(self.translate)
00301
00302 class LoopAnalyzerBase(object):
00303 def __init__(self):
00304 None
00305
00306 def print_stmt_truncate_newline(stmt):
00307 stmt_str = ctrump.pprint_stmt(stmt)
00308 stmt_str = stmt_str.rstrip('\n')
00309 return stmt_str
00310
00311 def get_iv_level(index):
00312 if index.code == ctrump.LOOP_INDEX_INDUCTIVE:
00313 return index.iv_level
00314 elif index.code == ctrump.LOOP_INDEX_POINTER_INC:
00315 return index.iv_level
00316 else:
00317 raise NotImplementedError('get_iv_level %d'%index.code)
00318
00319 class LoopParallelAnalyzer(LoopAnalyzerBase):
00320 '''ループの並列性を解析する
00321 解析結果として、以下のビットのビット論理和を返す
00322 HAS_RANDOM_ACCESS = (1<<0)
00323 HAS_COMPLICATED_CONTROL_FLOW = (1<<1)
00324 UNPREDICTABLE_COUNTER = (1<<2)
00325 HAS_CARRY_DEPENDENCY = (1<<3)
00326 HAS_NESTED_LOOP = (1<<4)
00327 LOAD_STORE_EMPTY = (1<<5)
00328 HAS_OUTPUT_DEPENDENCE = (1<<6)
00329 HAS_DEPEND_ANALYSIS_ERROR = (1<<7)
00330 NO_INDEPENDENT_LOOP = (1<<8)
00331 '''
00332
00333 def __init__(self):
00334 super(LoopParallelAnalyzer,self).__init__()
00335
00336 HAS_RANDOM_ACCESS = (1<<0)
00337 HAS_COMPLICATED_CONTROL_FLOW = (1<<1)
00338 UNPREDICTABLE_COUNTER = (1<<2)
00339 HAS_CARRY_DEPENDENCY = (1<<3)
00340 HAS_NESTED_LOOP = (1<<4)
00341 LOAD_STORE_EMPTY = (1<<5)
00342 HAS_OUTPUT_DEPENDENCE = (1<<6)
00343 HAS_DEPEND_ANALYSIS_ERROR = (1<<7)
00344 NO_INDEPENDENT_LOOP = (1<<8)
00345
00346 def analyze_loop_node(self, loop_node, result_stack, cfg):
00347 errors = []
00348 warnings = []
00349 hints = []
00350
00351 result_stack.append(LoopParallelTreeNode())
00352
00353 error_bits = 0
00354 ei = loop_node.exit_info
00355
00356 stmt_loc_path = loop_node.loc.path
00357 stmt_loc_line = loop_node.loc.lineno
00358
00359 if ei.code == ctrump.LOOP_COUNT_UNPREDICTABLE:
00360 errors.append(OptimizationError([(stmt_loc_path, stmt_loc_line)],
00361 "ループ回数が解析不能です"))
00362 error_bits |= self.UNPREDICTABLE_COUNTER
00363 elif ei.code == ctrump.LOOP_COUNT_PREDICTABLE:
00364 if ei.cmp_op != ctrump.EXPR_BIN_LT:
00365 errors.append(OptimizationError([(stmt_loc_path, stmt_loc_line)],
00366 "ループの条件式の比較が `<' ではありません"))
00367 error_bits |= self.UNPREDICTABLE_COUNTER
00368
00369 if loop_node.carry_dep.popcount():
00370 error_bits |= self.HAS_CARRY_DEPENDENCY
00371 v = ctrump.bitmap_var_name(cfg.var_info, loop_node.carry_dep).rstrip(',')
00372 errors.append(OptimizationError([(stmt_loc_path, stmt_loc_line)],
00373 "ループ繰り越し依存があります : %s"%v))
00374
00375 for i in loop_node.reductions:
00376 if i.op == ctrump.REDUCTIVE_FADD or i.op == ctrump.REDUCTIVE_FSUB or i.op == ctrump.REDUCTIVE_FMUL:
00377 reduc_at = i.at
00378 (reduc_path, reduc_line) = ctrump.get_stmt_loc(reduc_at)
00379 stmt_str = print_stmt_truncate_newline(reduc_at)
00380 warnings.append(OptimizationError([(reduc_path, reduc_line)],
00381 "`%s':浮動小数の結合則を認めると精度が変わります。並列化すると結果が変わるので注意してください"%stmt_str))
00382
00383 for i in loop_node.parallel_stores:
00384 all_invariant = True
00385
00386 for j in i.subscripts:
00387 for k in j.indices:
00388 if k.code != ctrump.LOOP_INDEX_INVARIANT:
00389 all_invariant = False
00390
00391 if all_invariant:
00392 (path, line) = ctrump.get_stmt_loc(i.at_stmt)
00393 stmt_str = print_stmt_truncate_newline(i.at_stmt)
00394 errors.append(OptimizationError([(path, line)],
00395 "`%s':固定インデクスへの出力により出力依存が発生しています"%stmt_str))
00396 error_bits |= self.HAS_OUTPUT_DEPENDENCE
00397
00398 for i in loop_node.random_accesses:
00399 error_bits |= self.HAS_RANDOM_ACCESS
00400
00401 (access_path, access_line) = ctrump.get_stmt_loc(i.access_at_stmt)
00402
00403 if i.code == ctrump.RANDOM_ACCESS_POINTER_NOT_INDUCTIVE:
00404 errors.append(OptimizationError([(access_path, access_line)],
00405 "`%s':ポインタが誘導変数ではありません"%(i.not_inductive_pointer)))
00406 elif i.code == ctrump.RANDOM_ACCESS_COMPLICATED_POINTER:
00407 errors.append(OptimizationError([(access_path, access_line)],
00408 "`%s':解析できませんでした"%(i.complicated_pointer)))
00409 elif i.code == ctrump.RANDOM_ACCESS_ARRAY_NOT_INVARIANT:
00410 errors.append(OptimizationError([(access_path, access_line)],
00411 "`%s%s':ポインタもしくは配列がループ内定数ではありません"%(i.array,ctrump.format_tree_subscripts(i.subscripts))))
00412 elif i.code == ctrump.RANDOM_ACCESS_SUBSCRIPT_NOT_INDUCTIVE:
00413 errors.append(OptimizationError([(access_path, access_line)],
00414 "`%s%s':配列の添字が誘導変数ではありません"%(i.array,ctrump.format_tree_subscripts(i.subscripts))))
00415 elif i.code == ctrump.RANDOM_ACCESS_COMPLICATED_ARRAY:
00416 errors.append(OptimizationError([(access_path, access_line)],
00417 "`%s%s':解析できませんでした"%(i.array,ctrump.format_tree_subscripts(i.subscripts[0].expr))))
00418 elif i.code == ctrump.RANDOM_ACCESS_MULTIPLE_SCALED_INDEX:
00419 errors.append(OptimizationError([(access_path, access_line)],
00420 "`%s':解析できませんでした。添字式の中に複数の変数に係数があります"%(i.access_at_expr)))
00421 elif i.code == ctrump.RANDOM_ACCESS_COMPLICATED_SUBSCRIPT:
00422 errors.append(OptimizationError([(access_path, access_line)],
00423 "`%s':添字式が解析できませんでした。"%(i.complicated_subscript)))
00424 elif i.code == ctrump.RANDOM_ACCESS_INDEX_VAR_NOT_INDUCTIVE:
00425 errors.append(OptimizationError([(access_path, access_line)],
00426 "`%s':添字式の中で使われる変数がループ中で計算されています。"%(i.index_var_not_inductive.name)))
00427 else:
00428 errors.append(OptimizationError([(access_path, access_line)],
00429 "error:random access"))
00430
00431 depinfo = loop_node.depinfo
00432 if depinfo.code == ctrump.LOOP_DEPINFO_HAVE_ERROR_INNER:
00433 pass
00434 elif depinfo.code == ctrump.LOOP_DEPINFO_ANALYZE_ERROR:
00435 error_bits |= self.HAS_DEPEND_ANALYSIS_ERROR
00436 result_stack[-1].dep(LoopParallelTreeNode.COMPLICATED_DEP)
00437 for i in depinfo.errors:
00438 if i.code == ctrump.LOOP_DEPENDENCE_ANALYZE_HAVE_MULTIPLE_INDEX:
00439 mes = "'%s' 複数のインデクスによるアクセスがあります。現在のCTRUMPでは解析できません"%i.access.at_expr
00440 elif i.code == ctrump.LOOP_DEPENDENCE_ANALYZE_HAVE_WEAK_SUBSCRIPT:
00441 (p0,l0) = ctrump.get_stmt_loc(i.access0.at_stmt)
00442 (p1,l1) = ctrump.get_stmt_loc(i.access1.at_stmt)
00443 mes = "二つのメモリ参照'%s'と'%s'の間に複雑な依存関係があります。"%(i.access0.at_expr, i.access1.at_expr)
00444 errors.append(OptimizationError([(p0,l0), (p1,l1)], mes))
00445 elif i.code == ctrump.LOOP_DEPENDENCE_ANALYZE_HAVE_MULTIPLE_OUTPUT:
00446 (p0,l0) = ctrump.get_stmt_loc(i.access0.at_stmt)
00447 (p1,l1) = ctrump.get_stmt_loc(i.access1.at_stmt)
00448 stmt_str = (print_stmt_truncate_newline(i.access0.at_stmt),
00449 print_stmt_truncate_newline(i.access1.at_stmt))
00450 mes = "ひとつの配列に対する複数の書きこみ('%s', '%s')があります。現在のCTRUMPでは解析できません"%stmt_str
00451 errors.append(OptimizationError([(p0,l0), (p1,l1)], mes))
00452 else:
00453 (p0,l0) = ctrump.get_stmt_loc(i.access0.at_stmt)
00454 (p1,l1) = ctrump.get_stmt_loc(i.access1.at_stmt)
00455 errors.append(OptimizationError([(p0,l0), (p1,l1)], '依存性解析時にエラーがありました'))
00456
00457 elif depinfo.code == ctrump.LOOP_DEPINFO:
00458
00459 for i in depinfo.vectors:
00460 num_sub = i.num_subscript
00461 num_vec = i.num_vector
00462 independent = [True]*num_sub
00463 vecdata = i.distance_vectors
00464 for j in range(0,num_vec):
00465 for k in range(0,num_sub):
00466 d = vecdata[j*num_sub+k]
00467 if d.code == ctrump.DEPEND_DISTANCE_STRONG_SIV:
00468 if d.distance == 0:
00469
00470 pass
00471 else:
00472 if d.distance < 0:
00473 dep_type = LoopParallelTreeNode.FLOW_DEP
00474 else:
00475 dep_type = LoopParallelTreeNode.ANTI_DEP
00476
00477 idx0 = d.index0
00478 idx1 = d.index1
00479
00480 result_stack[get_iv_level(idx0)].dep(dep_type)
00481 result_stack[get_iv_level(idx1)].dep(dep_type)
00482 independent[k] = False
00483 else:
00484
00485 independent[k] = False
00486
00487 children = []
00488 for i in loop_node.children:
00489 n = self.analyze_loop_node(i, result_stack, cfg)
00490 error_bits |= n.error_bits
00491 children.append(n)
00492
00493 depinfo = result_stack[-1]
00494
00495 ret = result_stack[-1]
00496 ret.children = children
00497 ret.error_bits = error_bits
00498 ret.loop_node = loop_node
00499
00500 ret.errors = errors
00501 ret.warnings = warnings
00502 ret.hints = hints
00503
00504 result_stack.pop()
00505
00506 return ret
00507
00508
00509
00510 def analyze_loop(self, stmt, cfg, attr):
00511 error_bits = 0
00512
00513 (stmt_loc_path, stmt_loc_line) = ctrump.get_stmt_loc(stmt)
00514
00515 errors = []
00516 warnings = []
00517 hints = []
00518
00519 if attr.code == ctrump.LOOP_UNANALYZED:
00520 errors.append(OptimizationError([(stmt_loc_path,stmt_loc_line)],
00521 "occurs unanalyzed loop(maybe bug)."))
00522 elif attr.code == ctrump.LOOP_COMPLICATED:
00523 (error_path, error_line) = ctrump.get_stmt_loc(attr.stmt)
00524 error_bits |= self.HAS_COMPLICATED_CONTROL_FLOW
00525
00526 if attr.reason == COMPLICATED_LOOP_BREAK:
00527 errors.append(OptimizationError([(error_path, error_line)],
00528 "ループ中に `break' する箇所があります"))
00529 elif attr.reason == COMPLICATED_LOOP_GOTO:
00530 errors.append(OptimizationError([(error_path, error_line)],
00531 "ループ中に goto があります"))
00532 elif attr.reason == COMPLICATED_LOOP_RETURN:
00533 errors.append(OptimizationError([(error_path, error_line)],
00534 "ループから return する箇所があります"))
00535 elif attr.reason == COMPLICATED_LOOP_INVOKE_FUNC:
00536 errors.append(OptimizationError([(error_path, error_line)],
00537 "外部関数を呼んでいます"))
00538 elif attr.reason == COMPLICATED_LOOP_HAS_MULTI_ENTRY:
00539 errors.append(OptimizationError([(error_path, error_line)],
00540 "ループ中にラベルがあります"))
00541
00542 parallel_loop_tree = ErrorLoopTreeNode(error_bits, stmt, errors, warnings, hints)
00543
00544 elif attr.code == ctrump.LOOP:
00545 li_root = attr.loop_info_node
00546
00547 if li_root.num_child != 0:
00548 error_bits |= self.HAS_NESTED_LOOP
00549
00550 num_loop_level = li_root.nest_level
00551 result_stack = []
00552
00553 parallel_loop_tree = self.analyze_loop_node(li_root, result_stack, cfg)
00554
00555 return parallel_loop_tree
00556
00557
00558 class LoopOptimizer:
00559 """ループ最適化エンジン"""
00560 def __init__(self):
00561 self.analyzers = {}
00562 self.translators = []
00563
00564 def analyze_loop(self, stmt, cfg, attr, prog):
00565 """loop が最適化できるかどうか調べる
00566 :param stmt: target stmt
00567 :param cfg: cfg
00568 :param attr: loop attribute
00569 :return: ([errors], [warnings], [hints], [enabled-translator-names])
00570 """
00571 analyze_result = {}
00572
00573 for i in self.analyzers:
00574 a = self.analyzers[i]
00575 result = a.analyze_loop(stmt, cfg, attr)
00576 analyze_result[type(self.analyzers[i])] = result
00577
00578 analysis_results = []
00579
00580 def traverse_result(node):
00581 enabled_translators = []
00582
00583 for t in self.translators:
00584 r = t.is_enabled(analyze_result, node.get_stmt(), cfg, node, node.errors, node.warnings, node.hints)
00585 if r:
00586 enabled_translators.append(t)
00587
00588 analysis_results.append(LoopAnalysisResult(node.errors, node.warnings, node.hints,
00589 enabled_translators, node,
00590 cfg, attr, analyze_result, prog))
00591
00592 for i in node.children:
00593 traverse_result(i)
00594
00595 traverse_result(result)
00596 return analysis_results
00597
00598 def enable_analyzer(self, analyzer_type):
00599 if analyzer_type in self.analyzers:
00600 return self.analyzers[analyzer_type]
00601 ret = analyzer_type()
00602 self.analyzers[analyzer_type] = ret
00603 return ret
00604
00605 def append_translator(self, trns, required_analyzers):
00606 for i in required_analyzers:
00607 self.enable_analyzer(i)
00608 self.translators.append(trns)
00609
00610 def get_translators(self):
00611 return self.translators
00612
00613 engine_options = [
00614 ('enable_ignore_alias', "エイリアスを考慮しない",
00615 '''同じ型のポインタが指す先がオーバーラップしないことを仮定します。
00616 プログラムによっては不具合の原因になることがあります。
00617 よく理解したうえで有効にしてください(未実装:問答無用で最適化されます)''', False),
00618
00619 ('enable_float_associativity', "浮動小数演算の結合、分配法則を認める",
00620 '''浮動小数演算の演算順序を変える変換を有効にします。
00621
00622 例えば、浮動小数の合計を求める、
00623 for (i=0; i<N; i++) {
00624 sum += x * a[i];
00625 }
00626 このようなループの並列化が可能になりますが、結果の誤差が変わります。(未実装:問答無用で最適化されます)
00627 ''', False)
00628 ]
00629
00630 class OptimizeEngine:
00631 """最適化エンジン"""
00632
00633 def __init__(self):
00634 module_path = optimizer.__file__
00635 module_dir = os.path.dirname(module_path)
00636 optimizer_dir = module_dir + os.sep + 'builtin-optimizers'
00637
00638 self.loop_optimizer = LoopOptimizer()
00639
00640 self.optimizers = {}
00641 self.add_translator_directory(optimizer_dir)
00642
00643 self.engine_options = Option(engine_options)
00644
00645 def add_translator_directory(self, plugin_dir_path):
00646 sys.path.insert(0, plugin_dir_path)
00647
00648 try:
00649 files = os.listdir(plugin_dir_path)
00650 loaded = []
00651 valid_suffixes = ['.py', '.pyc', '.pyo']
00652
00653 for i in files:
00654 base, suffix = os.path.splitext(i)
00655 if (not base in loaded) and (suffix in valid_suffixes):
00656 loaded.append(base)
00657 mod = __import__(base)
00658 mod.init_optimizer(self)
00659
00660 except int:
00661 del sys.path[0]
00662
00663 def get_loop_optimizer(self):
00664 return self.loop_optimizer
00665
00666 def get_all_translators(self):
00667 ret = []
00668 ret = ret + self.loop_optimizer.get_translators()
00669
00670 return ret
00671
00672 def analyze(self, prog):
00673 """ :param tree: target translation unit
00674 :return: [(stmt,([errors], [warnings], [hints], [enabled-optimizer-name]))]"""
00675
00676 loops = extract_loop(prog)
00677 results = []
00678
00679 for (stmt, cfg, attr) in loops:
00680 i = self.loop_optimizer.analyze_loop(stmt,cfg,attr,prog)
00681 results += i
00682
00683 return results
00684
00685 def get_global_option_initial_value(self):
00686 set = OptionSet(self.engine_options)
00687
00688 for i in self.get_all_translators():
00689 set.translators[i.get_name()] = i.get_global_option()
00690
00691 return set.create_initial_value()
00692
00693 def get_engine_option(self):
00694 return self.engine_options
00695
00696 def get_translate_option_initial_value(self, translator_name):
00697 for i in self.loop_optimizer.get_translators():
00698 if i.get_name() == translator_name:
00699 return i.get_translate_option().initial_value()
00700
00701 raise NameError("'%s' is not translator name."%translator_name)