diff options
author | dhuth <derickhuth@gmail.com> | 2014-08-27 09:52:06 -0600 |
---|---|---|
committer | dhuth <derickhuth@gmail.com> | 2014-08-27 09:52:06 -0600 |
commit | bff810cc371a38f493d688c54f71013f5a7d53bf (patch) | |
tree | fbe86954bb3c01deb21da9e41ebff5baa2889a45 /ir_suif.cc | |
download | chill-bff810cc371a38f493d688c54f71013f5a7d53bf.tar.gz chill-bff810cc371a38f493d688c54f71013f5a7d53bf.tar.bz2 chill-bff810cc371a38f493d688c54f71013f5a7d53bf.zip |
Initial commit
Diffstat (limited to 'ir_suif.cc')
-rw-r--r-- | ir_suif.cc | 1438 |
1 files changed, 1438 insertions, 0 deletions
diff --git a/ir_suif.cc b/ir_suif.cc new file mode 100644 index 0000000..a0ea357 --- /dev/null +++ b/ir_suif.cc @@ -0,0 +1,1438 @@ +/***************************************************************************** + Copyright (C) 2009-2011 University of Utah + All Rights Reserved. + + Purpose: + CHiLL's SUIF interface. + + Notes: + Array supports mixed pointer and array type in a single declaration. + + History: + 02/23/2009 Created by Chun Chen. +*****************************************************************************/ + +#include <typeinfo> +#include <useful.h> +#include "ir_suif.hh" +#include "ir_suif_utils.hh" +#include "chill_error.hh" + +// ---------------------------------------------------------------------------- +// Class: IR_suifScalarSymbol +// ---------------------------------------------------------------------------- + +std::string IR_suifScalarSymbol::name() const { + return vs_->name(); +} + + +int IR_suifScalarSymbol::size() const { + return vs_->type()->size(); +} + + +bool IR_suifScalarSymbol::operator==(const IR_Symbol &that) const { + if (typeid(*this) != typeid(that)) + return false; + + const IR_suifScalarSymbol *l_that = static_cast<const IR_suifScalarSymbol *>(&that); + return this->vs_ == l_that->vs_; +} + +IR_Symbol *IR_suifScalarSymbol::clone() const { + return new IR_suifScalarSymbol(ir_, vs_); +} + +// ---------------------------------------------------------------------------- +// Class: IR_suifArraySymbol +// ---------------------------------------------------------------------------- + +std::string IR_suifArraySymbol::name() const { + return vs_->name(); +} + + +int IR_suifArraySymbol::elem_size() const { + type_node *tn = vs_->type(); + if (tn->is_modifier()) + tn = static_cast<modifier_type *>(tn)->base(); + + while (tn->is_array()) + tn = static_cast<array_type *>(tn)->elem_type(); + + return tn->size(); +} + + +int IR_suifArraySymbol::n_dim() const { + type_node *tn = vs_->type(); + if (tn->is_modifier()) + tn = static_cast<modifier_type *>(tn)->base(); + + int n = 0; + while (true) { + if (tn->is_array()) { + n++; + tn = static_cast<array_type *>(tn)->elem_type(); + } + else if (tn->is_ptr()) { + n++; + tn = static_cast<ptr_type *>(tn)->ref_type(); + } + else + break; + } + + return n - indirect_; +} + + +omega::CG_outputRepr *IR_suifArraySymbol::size(int dim) const { + type_node *tn = vs_->type(); + if (tn->is_modifier()) + tn = static_cast<modifier_type *>(tn)->base(); + + for (int i = 0; i < dim; i++) { + if (tn->is_array()) + tn = static_cast<array_type *>(tn)->elem_type(); + else if (tn->is_ptr()) + tn = static_cast<ptr_type *>(tn)->ref_type(); + else + throw ir_error("array parsing error"); + } + if (tn->is_ptr()) + return new omega::CG_suifRepr(operand()); + else if (!tn->is_array()) + throw ir_error("array parsing error"); + + array_bound ub = static_cast<array_type *>(tn)->upper_bound(); + int c = 1; + omega::CG_outputRepr *ub_repr = NULL; + if (ub.is_constant()) + c += ub.constant(); + else if (ub.is_variable()) { + var_sym *vs = ub.variable(); + + if (static_cast<const IR_suifCode *>(ir_)->init_code_ != NULL) { + tree_node_list *tnl = static_cast<omega::CG_suifRepr *>(static_cast<const IR_suifCode *>(ir_)->init_code_)->GetCode(); + tree_node_list_iter iter(tnl); + while(!iter.is_empty()) { + tree_node *tn = iter.step(); + if (tn->is_instr()) { + instruction *ins = static_cast<tree_instr *>(tn)->instr(); + operand dst = ins->dst_op(); + if (dst.is_symbol() && dst.symbol() == vs) { + operand op; + if (ins->opcode() == io_cpy) + op = ins->src_op(0).clone(); + else + op = operand(ins->clone()); + + ub_repr = new omega::CG_suifRepr(op); + break; + } + } + } + } + if (ub_repr == NULL) + ub_repr = new omega::CG_suifRepr(operand(vs)); + } + else + throw ir_error("array parsing error"); + + array_bound lb = static_cast<array_type *>(tn)->lower_bound(); + omega::CG_outputRepr *lb_repr = NULL; + if (lb.is_constant()) + c -= lb.constant(); + else if (lb.is_variable()) { + var_sym *vs = ub.variable(); + + tree_node_list *tnl = static_cast<omega::CG_suifRepr *>(static_cast<const IR_suifCode *>(ir_)->init_code_)->GetCode(); + tree_node_list_iter iter(tnl); + while(!iter.is_empty()) { + tree_node *tn = iter.step(); + if (tn->is_instr()) { + instruction *ins = static_cast<tree_instr *>(tn)->instr(); + operand dst = ins->dst_op(); + if (dst.is_symbol() && dst.symbol() == vs) { + operand op; + if (ins->opcode() == io_cpy) + op = ins->src_op(0).clone(); + else + op = operand(ins->clone()); + + lb_repr = new omega::CG_suifRepr(op); + break; + } + } + } + if (lb_repr == NULL) + lb_repr = new omega::CG_suifRepr(operand(vs)); + } + else + throw ir_error("array parsing error"); + + omega::CG_outputRepr *repr = ir_->builder()->CreateMinus(ub_repr, lb_repr); + if (c != 0) + repr = ir_->builder()->CreatePlus(repr, ir_->builder()->CreateInt(c)); + + return repr; +} + + +IR_ARRAY_LAYOUT_TYPE IR_suifArraySymbol::layout_type() const { + if (static_cast<const IR_suifCode *>(ir_)->is_fortran_) + return IR_ARRAY_LAYOUT_COLUMN_MAJOR; + else + return IR_ARRAY_LAYOUT_ROW_MAJOR; +} + + +bool IR_suifArraySymbol::operator==(const IR_Symbol &that) const { + if (typeid(*this) != typeid(that)) + return false; + + const IR_suifArraySymbol *l_that = static_cast<const IR_suifArraySymbol *>(&that); + return this->vs_ == l_that->vs_ && this->offset_ == l_that->offset_; +} + + +IR_Symbol *IR_suifArraySymbol::clone() const { + return new IR_suifArraySymbol(ir_, vs_, indirect_, offset_); +} + +// ---------------------------------------------------------------------------- +// Class: IR_suifConstantRef +// ---------------------------------------------------------------------------- + +bool IR_suifConstantRef::operator==(const IR_Ref &that) const { + if (typeid(*this) != typeid(that)) + return false; + + const IR_suifConstantRef *l_that = static_cast<const IR_suifConstantRef *>(&that); + + if (this->type_ != l_that->type_) + return false; + + if (this->type_ == IR_CONSTANT_INT) + return this->i_ == l_that->i_; + else + return this->f_ == l_that->f_; +} + + +omega::CG_outputRepr *IR_suifConstantRef::convert() { + if (type_ == IR_CONSTANT_INT) { + omega::CG_suifRepr *result = new omega::CG_suifRepr(operand(static_cast<int>(i_), type_s32)); + delete this; + return result; + } + else + throw ir_error("constant type not supported"); +} + + +IR_Ref *IR_suifConstantRef::clone() const { + if (type_ == IR_CONSTANT_INT) + return new IR_suifConstantRef(ir_, i_); + else if (type_ == IR_CONSTANT_FLOAT) + return new IR_suifConstantRef(ir_, f_); + else + throw ir_error("constant type not supported"); +} + + +// ---------------------------------------------------------------------------- +// Class: IR_suifScalarRef +// ---------------------------------------------------------------------------- + +bool IR_suifScalarRef::is_write() const { + if (ins_pos_ != NULL && op_pos_ == -1) + return true; + else + return false; +} + + +IR_ScalarSymbol *IR_suifScalarRef::symbol() const { + return new IR_suifScalarSymbol(ir_, vs_); +} + + +bool IR_suifScalarRef::operator==(const IR_Ref &that) const { + if (typeid(*this) != typeid(that)) + return false; + + const IR_suifScalarRef *l_that = static_cast<const IR_suifScalarRef *>(&that); + + if (this->ins_pos_ == NULL) + return this->vs_ == l_that->vs_; + else + return this->ins_pos_ == l_that->ins_pos_ && this->op_pos_ == l_that->op_pos_; +} + + +omega::CG_outputRepr *IR_suifScalarRef::convert() { + omega::CG_suifRepr *result = new omega::CG_suifRepr(operand(vs_)); + delete this; + return result; +} + + +IR_Ref * IR_suifScalarRef::clone() const { + if (ins_pos_ == NULL) + return new IR_suifScalarRef(ir_, vs_); + else + return new IR_suifScalarRef(ir_, ins_pos_, op_pos_); +} + + +// ---------------------------------------------------------------------------- +// Class: IR_suifArrayRef +// ---------------------------------------------------------------------------- + +bool IR_suifArrayRef::is_write() const { + return ::is_lhs(const_cast<in_array *>(ia_)); +} + + +omega::CG_outputRepr *IR_suifArrayRef::index(int dim) const { + operand op = find_array_index(ia_, n_dim(), dim, static_cast<const IR_suifCode *>(ir_)->is_fortran_); + return new omega::CG_suifRepr(op.clone()); +} + + +IR_ArraySymbol *IR_suifArrayRef::symbol() const { + in_array *current = ia_; + + // find the indirectness of the symbol, i.e., if it is (**A)[i,j] + int indirect = 0; + if (!static_cast<const IR_suifCode *>(ir_)->is_fortran_) { + operand op = ia_->base_op(); + while (op.is_instr()) { + instruction *ins = op.instr(); + if (ins->opcode() == io_lod) { + indirect++; + op = ins->src_op(0); + } + else + break; + } + if (op.is_symbol()) + indirect++; + } + + while (true) { + operand op = current->base_op(); + if (op.is_symbol()) { + return new IR_suifArraySymbol(ir_, op.symbol(), indirect); + } + else if (op.is_instr()) { + instruction *ins = op.instr(); + if (ins->opcode() == io_ldc) { + immed value = static_cast<in_ldc *>(ins)->value(); + if (value.is_symbol()) { + sym_node *the_sym = value.symbol(); + if (the_sym->is_var()) + return new IR_suifArraySymbol(ir_, static_cast<var_sym *>(the_sym), indirect); + else + break; + } + else + break; + } + else if (ins->opcode() == io_cvt) { + operand op = static_cast<in_rrr *>(ins)->src_op(); + if (op.is_symbol()) { + return new IR_suifArraySymbol(ir_, op.symbol(), indirect); + } + else if (op.is_instr()) { + instruction *ins = op.instr(); + if (ins->opcode() == io_lod) { + operand op = static_cast<in_rrr *>(ins)->src_op(); + if (op.is_symbol()) { + return new IR_suifArraySymbol(ir_, op.symbol(), indirect); + } + else if (op.is_instr()) { + instruction *ins = op.instr(); + if (ins->opcode() == io_array) { + current = static_cast<in_array *>(ins); + continue; + } + else if (ins->opcode() == io_add) { + operand op1 = ins->src_op(0); + operand op2 = ins->src_op(1); + if (!op1.is_symbol() || !op2.is_immed()) + throw ir_error("can't recognize array reference format"); + immed im = op2.immediate(); + if (!im.is_integer()) + throw ir_error("can't recognize array reference format"); + return new IR_suifArraySymbol(ir_, op1.symbol(), indirect, im.integer()); + } + else + break; + } + else + break; + } + else + break; + } + else + break; + } + else { + while (ins->opcode() == io_lod) { + operand op = ins->src_op(0); + if (op.is_instr()) + ins = op.instr(); + else if (op.is_symbol()) + return new IR_suifArraySymbol(ir_, op.symbol(), indirect); + else + break; + } + break; + } + } + else + break; + } + + fprintf(stderr, "Warning: null array symbol found, dependence graph bloated!\n"); + + return new IR_suifArraySymbol(ir_, NULL); +} + + +bool IR_suifArrayRef::operator==(const IR_Ref &that) const { + if (typeid(*this) != typeid(that)) + return false; + + const IR_suifArrayRef *l_that = static_cast<const IR_suifArrayRef *>(&that); + + return this->ia_ == l_that ->ia_; +} + + +omega::CG_outputRepr *IR_suifArrayRef::convert() { + omega::CG_suifRepr *result = new omega::CG_suifRepr(operand(this->ia_->clone())); + delete this; + return result; +} + + +IR_Ref *IR_suifArrayRef::clone() const { + return new IR_suifArrayRef(ir_, ia_); +} + + + +// ---------------------------------------------------------------------------- +// Class: IR_suifLoop +// ---------------------------------------------------------------------------- + +IR_ScalarSymbol *IR_suifLoop::index() const { + var_sym *vs = tf_->index(); + return new IR_suifScalarSymbol(ir_, vs); +} + +omega::CG_outputRepr *IR_suifLoop::lower_bound() const { + tree_node_list *tnl = tf_->lb_list(); + tree_node_list_iter iter(tnl); + if (iter.is_empty()) + return new omega::CG_suifRepr(operand()); + tree_node *tn = iter.step(); + if (!iter.is_empty()) + throw ir_error("cannot handle lower bound"); + if (tn->kind() != TREE_INSTR) + throw ir_error("cannot handle lower bound"); + instruction *ins = static_cast<tree_instr *>(tn)->instr(); + return new omega::CG_suifRepr(operand(ins)); +} + +omega::CG_outputRepr *IR_suifLoop::upper_bound() const { + tree_node_list *tnl = tf_->ub_list(); + tree_node_list_iter iter(tnl); + if (iter.is_empty()) + return new omega::CG_suifRepr(operand()); + tree_node *tn = iter.step(); + if (!iter.is_empty()) + throw ir_error("cannot handle lower bound"); + if (tn->kind() != TREE_INSTR) + throw ir_error("cannot handle lower bound"); + instruction *ins = static_cast<tree_instr *>(tn)->instr(); + return new omega::CG_suifRepr(operand(ins)); +} + +IR_CONDITION_TYPE IR_suifLoop::stop_cond() const { + if (tf_->test() == FOR_SLT || tf_->test() == FOR_ULT) + return IR_COND_LT; + else if (tf_->test() == FOR_SLTE || tf_->test() == FOR_ULTE) + return IR_COND_LE; + else if (tf_->test() == FOR_SGT || tf_->test() == FOR_UGT) + return IR_COND_GT; + else if (tf_->test() == FOR_SGTE || tf_->test() == FOR_UGTE) + return IR_COND_GE; + else + throw ir_error("loop stop condition unsupported"); +} + +IR_Block *IR_suifLoop::body() const { + tree_node_list *tnl = tf_->body(); + return new IR_suifBlock(ir_, tnl); +} + +int IR_suifLoop::step_size() const { + operand op = tf_->step_op(); + if (!op.is_null()) { + if (op.is_immed()) { + immed im = op.immediate(); + if (im.is_integer()) + return im.integer(); + else + throw ir_error("cannot handle non-integer stride"); + } + else + throw ir_error("cannot handle non-constant stride"); + } + else + return 1; +} + + +IR_Block *IR_suifLoop::convert() { + const IR_Code *ir = ir_; + tree_node_list *tnl = tf_->parent(); + tree_node_list_e *start, *end; + start = end = tf_->list_e(); + delete this; + return new IR_suifBlock(ir, tnl, start, end); +} + + +IR_Control *IR_suifLoop::clone() const { + return new IR_suifLoop(ir_, tf_); +} + +// ---------------------------------------------------------------------------- +// Class: IR_suifBlock +// ---------------------------------------------------------------------------- + +omega::CG_outputRepr *IR_suifBlock::extract() const { + tree_node_list *tnl = new tree_node_list; + tree_node_list_iter iter(tnl_); + while (!iter.is_empty()) { + tree_node *tn = iter.peek(); + if (tn->list_e() == start_) + break; + tn = iter.step(); + } + + while (!iter.is_empty()) { + tree_node *tn = iter.step(); + tnl->append(tn->clone()); + if (tn->list_e() == end_) + break; + } + + return new omega::CG_suifRepr(tnl); +} + +IR_Control *IR_suifBlock::clone() const { + return new IR_suifBlock(ir_, tnl_, start_, end_); +} + + +// ---------------------------------------------------------------------------- +// Class: IR_suifIf +// ---------------------------------------------------------------------------- +omega::CG_outputRepr *IR_suifIf::condition() const { + tree_node_list *tnl = ti_->header(); + tree_node_list_iter iter(tnl); + if (iter.is_empty()) + throw ir_error("unrecognized if structure"); + tree_node *tn = iter.step(); + if (!iter.is_empty()) + throw ir_error("unrecognized if structure"); + if (!tn->is_instr()) + throw ir_error("unrecognized if structure"); + instruction *ins = static_cast<tree_instr *>(tn)->instr(); + if (!ins->opcode() == io_bfalse) + throw ir_error("unrecognized if structure"); + operand op = ins->src_op(0); + return new omega::CG_suifRepr(op); +} + +IR_Block *IR_suifIf::then_body() const { + tree_node_list *tnl = ti_->then_part(); + if (tnl == NULL) + return NULL; + tree_node_list_iter iter(tnl); + if (iter.is_empty()) + return NULL; + + return new IR_suifBlock(ir_, tnl); +} + +IR_Block *IR_suifIf::else_body() const { + tree_node_list *tnl = ti_->else_part(); + if (tnl == NULL) + return NULL; + tree_node_list_iter iter(tnl); + if (iter.is_empty()) + return NULL; + + return new IR_suifBlock(ir_, tnl); +} + + +IR_Block *IR_suifIf::convert() { + const IR_Code *ir = ir_; + tree_node_list *tnl = ti_->parent(); + tree_node_list_e *start, *end; + start = end = ti_->list_e(); + delete this; + return new IR_suifBlock(ir, tnl, start, end); +} + + +IR_Control *IR_suifIf::clone() const { + return new IR_suifIf(ir_, ti_); +} + + +// ---------------------------------------------------------------------------- +// Class: IR_suifCode_Global_Init +// ---------------------------------------------------------------------------- + +IR_suifCode_Global_Init *IR_suifCode_Global_Init::pinstance = NULL; + + +IR_suifCode_Global_Init *IR_suifCode_Global_Init::Instance () { + if (pinstance == NULL) + pinstance = new IR_suifCode_Global_Init; + return pinstance; +} + + +IR_suifCode_Global_Init::IR_suifCode_Global_Init() { + LIBRARY(useful, init_useful, exit_useful); + LIBRARY(annotes, init_annotes, exit_annotes); + + int argc = 1; + char *argv[1]; + argv[0] = "chill"; + init_suif(argc, argv); +} + + +// ---------------------------------------------------------------------------- +// Class: IR_suifCode_Global_Cleanup +// ---------------------------------------------------------------------------- + +IR_suifCode_Global_Cleanup::~IR_suifCode_Global_Cleanup() { + delete IR_suifCode_Global_Init::Instance(); + exit_suif1(); +} + + +namespace { + IR_suifCode_Global_Cleanup suifcode_global_cleanup_instance; +} + +// ---------------------------------------------------------------------------- +// Class: IR_suifCode +// ---------------------------------------------------------------------------- + +IR_suifCode::IR_suifCode(const char *filename, int proc_num): IR_Code() { + IR_suifCode_Global_Init::Instance(); + + std::string new_filename(filename); + int pos = new_filename.find_last_of('.'); + new_filename = new_filename.substr(0, pos) + ".lxf"; + fileset->add_file(const_cast<char *>(filename), const_cast<char *>(new_filename.c_str())); + fileset->reset_iter(); + fse_ = fileset->next_file(); + fse_->reset_proc_iter(); + + int cur_proc = 0; + while ((psym_ = fse_->next_proc()) && cur_proc < proc_num) + ++cur_proc; + if (cur_proc != proc_num) { + throw ir_error("procedure number cannot be found"); + } + + if (psym_->src_lang() == src_fortran) + is_fortran_ = true; + else + is_fortran_ = false; + + if (!psym_->is_in_memory()) + psym_->read_proc(TRUE, is_fortran_); + push_clue(psym_->block()); + + symtab_ = psym_->block()->proc_syms(); + ocg_ = new omega::CG_suifBuilder(symtab_); +} + + +IR_suifCode::~IR_suifCode() { + tree_node_list *tnl = psym_->block()->body(); + + if (init_code_ != NULL) + tnl->insert_before(static_cast<omega::CG_suifRepr *>(init_code_)->GetCode(), tnl->head()); + if (cleanup_code_ != NULL) + tnl->insert_after(static_cast<omega::CG_suifRepr *>(cleanup_code_)->GetCode(), tnl->tail()); + + pop_clue(psym_->block()); + if (!psym_->is_written()) + psym_->write_proc(fse_); + psym_->flush_proc(); +} + + +IR_ScalarSymbol *IR_suifCode::CreateScalarSymbol(const IR_Symbol *sym, int) { + if (typeid(*sym) == typeid(IR_suifScalarSymbol)) { + type_node *tn = static_cast<const IR_suifScalarSymbol *>(sym)->vs_->type(); + while (tn->is_modifier()) + tn = static_cast<modifier_type *>(tn)->base(); + var_sym *vs = symtab_->new_unique_var(tn); + return new IR_suifScalarSymbol(this, vs); + } + else if (typeid(*sym) == typeid(IR_suifArraySymbol)) { + type_node *tn = static_cast<const IR_suifArraySymbol *>(sym)->vs_->type(); + while (tn->is_modifier()) + tn = static_cast<modifier_type *>(tn)->base(); + while (tn->is_array() || tn->is_ptr()) { + if (tn->is_array()) + tn = static_cast<array_type *>(tn)->elem_type(); + else if (tn->is_ptr()) + tn = static_cast<ptr_type *>(tn)->ref_type(); + } + while (tn->is_modifier()) + tn = static_cast<modifier_type *>(tn)->base(); + var_sym *vs = symtab_->new_unique_var(tn); + return new IR_suifScalarSymbol(this, vs); + } + else + throw std::bad_typeid(); +} + + +IR_ArraySymbol *IR_suifCode::CreateArraySymbol(const IR_Symbol *sym, std::vector<omega::CG_outputRepr *> &size, int) { + type_node *tn; + + if (typeid(*sym) == typeid(IR_suifScalarSymbol)) { + tn = static_cast<const IR_suifScalarSymbol *>(sym)->vs_->type(); + } + else if (typeid(*sym) == typeid(IR_suifArraySymbol)) { + tn = static_cast<const IR_suifArraySymbol *>(sym)->vs_->type(); + if (tn->is_modifier()) + tn = static_cast<modifier_type *>(tn)->base(); + while (tn->is_array() || tn->is_ptr()) { + if (tn->is_array()) + tn = static_cast<array_type *>(tn)->elem_type(); + else if (tn->is_ptr()) + tn = static_cast<ptr_type *>(tn)->ref_type(); + } + } + else + throw std::bad_typeid(); + + if (is_fortran_) + for (int i = 0; i < size.size(); i++) { + var_sym *temporary = symtab_->new_unique_var(type_s32); + init_code_ = ocg_->StmtListAppend(init_code_, ocg_->CreateAssignment(0, new omega::CG_suifRepr(operand(temporary)), size[i])); + + tn = new array_type(tn, array_bound(1), array_bound(temporary)); + symtab_->add_type(tn); + } + else + for (int i = size.size()-1; i >= 0; i--) { + var_sym *temporary = symtab_->new_unique_var(type_s32); + init_code_ = ocg_->StmtListAppend(init_code_, ocg_->CreateAssignment(0, new omega::CG_suifRepr(operand(temporary)), size[i])); + + tn = new array_type(tn, array_bound(1), array_bound(temporary)); + symtab_->add_type(tn); + } + + static int suif_array_counter = 1; + std::string s = std::string("_P") + omega::to_string(suif_array_counter++); + var_sym *vs = new var_sym(tn, const_cast<char *>(s.c_str())); + vs->add_to_table(symtab_); + + return new IR_suifArraySymbol(this, vs); +} + + +IR_ScalarRef *IR_suifCode::CreateScalarRef(const IR_ScalarSymbol *sym) { + return new IR_suifScalarRef(this, static_cast<const IR_suifScalarSymbol *>(sym)->vs_); +} + + +IR_ArrayRef *IR_suifCode::CreateArrayRef(const IR_ArraySymbol *sym, std::vector<omega::CG_outputRepr *> &index) { + if (sym->n_dim() != index.size()) + throw std::invalid_argument("incorrect array symbol dimensionality"); + + const IR_suifArraySymbol *l_sym = static_cast<const IR_suifArraySymbol *>(sym); + + var_sym *vs = l_sym->vs_; + type_node *tn1 = vs->type(); + if (tn1->is_modifier()) + tn1 = static_cast<modifier_type *>(tn1)->base(); + + type_node *tn2 = tn1; + while (tn2->is_array() || tn2->is_ptr()) { + if (tn2->is_array()) + tn2 = static_cast<array_type *>(tn2)->elem_type(); + else if (tn2->is_ptr()) + tn2 = static_cast<ptr_type *>(tn2)->ref_type(); + } + + instruction *base_ins; + if (tn1->is_ptr()) { + base_symtab *cur_symtab; + + cur_symtab = symtab_; + type_node *found_array_tn = NULL; + while (cur_symtab != NULL) { + type_node_list_iter iter(cur_symtab->types()); + while (!iter.is_empty()) { + type_node *tn = iter.step(); + if (!tn->is_array()) + continue; + if (static_cast<array_type *>(tn)->elem_type() == static_cast<ptr_type *>(tn1)->ref_type()) { + array_bound b = static_cast<array_type *>(tn)->upper_bound(); + if (b.is_unknown()) { + found_array_tn = tn; + break; + } + } + } + if (found_array_tn == NULL) + cur_symtab = cur_symtab->parent(); + else + break; + } + + cur_symtab = symtab_; + type_node *found_ptr_array_tn = NULL; + while (cur_symtab != NULL) { + type_node_list_iter iter(cur_symtab->types()); + while (!iter.is_empty()) { + type_node *tn = iter.step(); + if (!tn->is_ptr()) + continue; + if (static_cast<ptr_type *>(tn)->ref_type() == found_array_tn) { + found_ptr_array_tn = tn; + break; + } + } + if (found_ptr_array_tn == NULL) + cur_symtab = cur_symtab->parent(); + else + break; + } + + if (found_ptr_array_tn == NULL) + throw ir_error("can't find the type for the to-be-created array"); + base_ins = new in_rrr(io_cvt, found_ptr_array_tn, operand(), operand(vs)); + } + else { + base_ins = new in_ldc(tn1->ptr_to(), operand(), immed(vs)); + } + + in_array *ia = new in_array(tn2->ptr_to(), operand(), operand(base_ins), tn2->size(), l_sym->n_dim()); + + for (int i = 0; i < index.size(); i++) { + int t; + if (is_fortran_) + t = index.size() - i - 1; + else + t = i; + + omega::CG_suifRepr *bound = static_cast<omega::CG_suifRepr *>(l_sym->size(t)); + ia->set_bound(t, bound->GetExpression()); + delete bound; + omega::CG_suifRepr *idx = static_cast<omega::CG_suifRepr *>(index[i]); + ia->set_index(t, idx->GetExpression()); + delete idx; + } + + return new IR_suifArrayRef(this, ia); +} + + +std::vector<IR_ArrayRef *> IR_suifCode::FindArrayRef(const omega::CG_outputRepr *repr) const { + std::vector<IR_ArrayRef *> arrays; + + tree_node_list *tnl = static_cast<const omega::CG_suifRepr *>(repr)->GetCode(); + if (tnl != NULL) { + tree_node_list_iter iter(tnl); + while (!iter.is_empty()) { + tree_node *tn = iter.step(); + switch (tn->kind()) { + case TREE_FOR: { + tree_for *tnf = static_cast<tree_for *>(tn); + omega::CG_suifRepr *r = new omega::CG_suifRepr(tnf->body()); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + break; + } + case TREE_IF: { + tree_if *tni = static_cast<tree_if *>(tn); + omega::CG_suifRepr *r = new omega::CG_suifRepr(tni->header()); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + r = new omega::CG_suifRepr(tni->then_part()); + a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + r = new omega::CG_suifRepr(tni->else_part()); + a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + break; + } + case TREE_BLOCK: { + omega::CG_suifRepr *r = new omega::CG_suifRepr(static_cast<tree_block *>(tn)->body()); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + break; + } + case TREE_INSTR: { + omega::CG_suifRepr *r = new omega::CG_suifRepr(operand(static_cast<tree_instr *>(tn)->instr())); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + break; + } + default: + throw ir_error("control structure not supported"); + } + } + } + else { + operand op = static_cast<const omega::CG_suifRepr *>(repr)->GetExpression(); + if (op.is_instr()) { + instruction *ins = op.instr(); + switch (ins->opcode()) { + case io_array: { + IR_suifArrayRef *ref = new IR_suifArrayRef(this, static_cast<in_array *>(ins)); + for (int i = 0; i < ref->n_dim(); i++) { + omega::CG_suifRepr *r = new omega::CG_suifRepr(find_array_index(ref->ia_, ref->n_dim(), i, is_fortran_)); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + } + arrays.push_back(ref); + break; + } + case io_str: + case io_memcpy: { + omega::CG_suifRepr *r1 = new omega::CG_suifRepr(ins->src_op(1)); + std::vector<IR_ArrayRef *> a1 = FindArrayRef(r1); + delete r1; + std::copy(a1.begin(), a1.end(), back_inserter(arrays)); + omega::CG_suifRepr *r2 = new omega::CG_suifRepr(ins->src_op(0)); + std::vector<IR_ArrayRef *> a2 = FindArrayRef(r2); + delete r2; + std::copy(a2.begin(), a2.end(), back_inserter(arrays)); + break; + } + default: + for (int i = 0; i < ins->num_srcs(); i++) { + omega::CG_suifRepr *r = new omega::CG_suifRepr(ins->src_op(i)); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + } + } + } + } + + return arrays; +} + + +std::vector<IR_ScalarRef *> IR_suifCode::FindScalarRef(const omega::CG_outputRepr *repr) const { + std::vector<IR_ScalarRef *> scalars; + + tree_node_list *tnl = static_cast<const omega::CG_suifRepr *>(repr)->GetCode(); + if (tnl != NULL) { + tree_node_list_iter iter(tnl); + while (!iter.is_empty()) { + tree_node *tn = iter.step(); + switch (tn->kind()) { + case TREE_FOR: { + tree_for *tnf = static_cast<tree_for *>(tn); + omega::CG_suifRepr *r = new omega::CG_suifRepr(tnf->body()); + std::vector<IR_ScalarRef *> a = FindScalarRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(scalars)); + break; + } + case TREE_IF: { + tree_if *tni = static_cast<tree_if *>(tn); + omega::CG_suifRepr *r = new omega::CG_suifRepr(tni->header()); + std::vector<IR_ScalarRef *> a = FindScalarRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(scalars)); + r = new omega::CG_suifRepr(tni->then_part()); + a = FindScalarRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(scalars)); + r = new omega::CG_suifRepr(tni->else_part()); + a = FindScalarRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(scalars)); + break; + } + case TREE_BLOCK: { + omega::CG_suifRepr *r = new omega::CG_suifRepr(static_cast<tree_block *>(tn)->body()); + std::vector<IR_ScalarRef *> a = FindScalarRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(scalars)); + break; + } + case TREE_INSTR: { + omega::CG_suifRepr *r = new omega::CG_suifRepr(operand(static_cast<tree_instr *>(tn)->instr())); + std::vector<IR_ScalarRef *> a = FindScalarRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(scalars)); + break; + } + default: + throw ir_error("control structure not supported"); + } + } + } + else { + operand op = static_cast<const omega::CG_suifRepr *>(repr)->GetExpression(); + if (op.is_instr()) { + instruction *ins = op.instr(); + for (int i = 0; i < ins->num_srcs(); i++) { + operand op = ins->src_op(i); + if (op.is_symbol()) + scalars.push_back(new IR_suifScalarRef(this, ins, i)); + else if (op.is_instr()) { + omega::CG_suifRepr *r = new omega::CG_suifRepr(op); + std::vector<IR_ScalarRef *> a = FindScalarRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(scalars)); + } + } + + operand op = ins->dst_op(); + if (op.is_symbol()) + scalars.push_back(new IR_suifScalarRef(this, ins, -1)); + } + else if (op.is_symbol()) + scalars.push_back(new IR_suifScalarRef(this, op.symbol())); + } + + return scalars; +} + + +std::vector<IR_Control *> IR_suifCode::FindOneLevelControlStructure(const IR_Block *block) const { + std::vector<IR_Control *> controls; + + IR_suifBlock *l_block = static_cast<IR_suifBlock *>(const_cast<IR_Block *>(block)); + tree_node_list_iter iter(l_block->tnl_); + while(!iter.is_empty()) { + tree_node *tn = iter.peek(); + if (tn->list_e() == l_block->start_) + break; + iter.step(); + } + tree_node_list_e *start = NULL; + tree_node_list_e *prev = NULL; + while (!iter.is_empty()) { + tree_node *tn = iter.step(); + if (tn->kind() == TREE_FOR) { + if (start != NULL) { + controls.push_back(new IR_suifBlock(this, l_block->tnl_, start, prev)); + start = NULL; + } + controls.push_back(new IR_suifLoop(this, static_cast<tree_for *>(tn))); + } + else if (tn->kind() == TREE_IF) { + if (start != NULL) { + controls.push_back(new IR_suifBlock(this, l_block->tnl_, start, prev)); + start = NULL; + } + controls.push_back(new IR_suifIf(this, static_cast<tree_if *>(tn))); + } + else if (start == NULL && !is_null_statement(tn)) { + start = tn->list_e(); + } + prev = tn->list_e(); + if (prev == l_block->end_) + break; + } + + if (start != NULL && start != l_block->start_) + controls.push_back(new IR_suifBlock(this, l_block->tnl_, start, prev)); + + return controls; +} + + +IR_Block *IR_suifCode::MergeNeighboringControlStructures(const std::vector<IR_Control *> &controls) const { + if (controls.size() == 0) + return NULL; + + tree_node_list *tnl = NULL; + tree_node_list_e *start, *end; + for (int i = 0; i < controls.size(); i++) { + switch (controls[i]->type()) { + case IR_CONTROL_LOOP: { + tree_for *tf = static_cast<IR_suifLoop *>(controls[i])->tf_; + if (tnl == NULL) { + tnl = tf->parent(); + start = end = tf->list_e(); + } + else { + if (tnl != tf->parent()) + throw ir_error("controls to merge not at the same level"); + end = tf->list_e(); + } + break; + } + case IR_CONTROL_BLOCK: { + if (tnl == NULL) { + tnl = static_cast<IR_suifBlock *>(controls[0])->tnl_; + start = static_cast<IR_suifBlock *>(controls[0])->start_; + end = static_cast<IR_suifBlock *>(controls[0])->end_; + } + else { + if (tnl != static_cast<IR_suifBlock *>(controls[0])->tnl_) + throw ir_error("controls to merge not at the same level"); + end = static_cast<IR_suifBlock *>(controls[0])->end_; + } + break; + } + default: + throw ir_error("unrecognized control to merge"); + } + } + + return new IR_suifBlock(controls[0]->ir_, tnl, start, end); +} + + +IR_Block *IR_suifCode::GetCode() const { + return new IR_suifBlock(this, psym_->block()->body()); +} + + +void IR_suifCode::ReplaceCode(IR_Control *old, omega::CG_outputRepr *repr) { + tree_node_list *tnl = static_cast<omega::CG_suifRepr *>(repr)->GetCode(); + + switch (old->type()) { + case IR_CONTROL_LOOP: { + tree_for *tf_old = static_cast<IR_suifLoop *>(old)->tf_; + tree_node_list *tnl_old = tf_old->parent(); + + tnl_old->insert_before(tnl, tf_old->list_e()); + tnl_old->remove(tf_old->list_e()); + delete tf_old; + + break; + } + case IR_CONTROL_BLOCK: { + IR_suifBlock *sb = static_cast<IR_suifBlock *>(old); + tree_node_list_iter iter(sb->tnl_); + bool need_deleting = false; + while (!iter.is_empty()) { + tree_node *tn = iter.step(); + tree_node_list_e *pos = tn->list_e(); + if (pos == sb->start_) { + sb->tnl_->insert_before(tnl, pos); + need_deleting = true; + } + if (need_deleting) { + sb->tnl_->remove(pos); + delete tn; + } + if (pos == sb->end_) + break; + } + + break; + } + default: + throw ir_error("control structure to be replaced not supported"); + } + + delete old; + delete repr; +} + + +void IR_suifCode::ReplaceExpression(IR_Ref *old, omega::CG_outputRepr *repr) { + operand op = static_cast<omega::CG_suifRepr *>(repr)->GetExpression(); + + if (typeid(*old) == typeid(IR_suifArrayRef)) { + in_array *ia_orig = static_cast<IR_suifArrayRef *>(old)->ia_; + + if (op.is_instr()) { + instruction *ia_repl = op.instr(); + if (ia_repl->opcode() == io_array) { + if (ia_orig->elem_type()->is_struct()) { + static_cast<in_array *>(ia_repl)->set_offset(ia_orig->offset()); + struct_type *tn = static_cast<struct_type *>(ia_orig->elem_type()); + int left; + type_node *field_tn = tn->field_type(tn->find_field_by_offset(ia_orig->offset(), left)); + static_cast<in_array *>(ia_repl)->set_result_type(field_tn->ptr_to()); + } + replace_instruction(ia_orig, ia_repl); + delete ia_orig; + } + else { + instruction *parent_instr = ia_orig->dst_op().instr(); + if (parent_instr->opcode() == io_str) { + throw ir_error("replace left hand arrary reference not supported yet"); + } + else if (parent_instr->opcode() == io_lod) { + instruction *instr = parent_instr->dst_op().instr(); + if (instr->dst_op() == operand(parent_instr)) { + parent_instr->remove(); + instr->set_dst(op); + } + else { + for (int i = 0; i < instr->num_srcs(); i++) + if (instr->src_op(i) == operand(parent_instr)) { + parent_instr->remove(); + instr->set_src_op(i, op); + break; + } + } + + delete parent_instr; + } + else + throw ir_error("array reference to be replaced does not appear in any instruction"); + } + } + else if (op.is_symbol()) { + var_sym *vs = op.symbol(); + instruction *parent_instr = ia_orig->dst_op().instr(); + if (parent_instr->opcode() == io_str) { + tree_node *tn = parent_instr->parent(); + operand op = parent_instr->src_op(1).clone(); + instruction *new_instr = new in_rrr(io_cpy, vs->type(), operand(vs), op); + tree_node_list *tnl = tn->parent(); + tnl->insert_before(new tree_instr(new_instr), tn->list_e()); + tnl->remove(tn->list_e()); + + delete tn; + } + else if (parent_instr->opcode() == io_lod) { + instruction *instr = parent_instr->dst_op().instr(); + if (instr->dst_op() == operand(parent_instr)) { + parent_instr->remove(); + instr->set_dst(operand(vs)); + } + else { + for (int i = 0; i < instr->num_srcs(); i++) + if (instr->src_op(i) == operand(parent_instr)) { + parent_instr->remove(); + instr->set_src_op(i, operand(vs)); + break; + } + } + + delete parent_instr; + } + else + throw ir_error("array reference to be replaced does not appear in any instruction"); + } + else + throw ir_error("can't handle replacement expression"); + } + else + throw ir_error("replacing a scalar variable not implemented"); + + delete old; + delete repr; +} + + + +IR_OPERATION_TYPE IR_suifCode::QueryExpOperation(const omega::CG_outputRepr *repr) const { + operand op = static_cast<const omega::CG_suifRepr *>(repr)->GetExpression(); + + if (op.is_immed()) + return IR_OP_CONSTANT; + else if (op.is_symbol()) + return IR_OP_VARIABLE; + else if (op.is_instr()) { + instruction *ins = op.instr(); + switch (ins->opcode()) { + case io_cpy: + return IR_OP_ASSIGNMENT; + case io_add: + return IR_OP_PLUS; + case io_sub: + return IR_OP_MINUS; + case io_mul: + return IR_OP_MULTIPLY; + case io_div: + return IR_OP_DIVIDE; + case io_neg: + return IR_OP_NEGATIVE; + case io_min: + return IR_OP_MIN; + case io_max: + return IR_OP_MAX; + case io_cvt: + return IR_OP_POSITIVE; + default: + return IR_OP_UNKNOWN; + } + } + else if (op.is_null()) + return IR_OP_NULL; + else + return IR_OP_UNKNOWN; +} + + +IR_CONDITION_TYPE IR_suifCode::QueryBooleanExpOperation(const omega::CG_outputRepr *repr) const { + operand op = static_cast<const omega::CG_suifRepr *>(repr)->GetExpression(); + if (op.is_instr()) { + instruction *ins = op.instr(); + switch (ins->opcode()) { + case io_seq: + return IR_COND_EQ; + case io_sne: + return IR_COND_NE; + case io_sl: + return IR_COND_LT; + case io_sle: + return IR_COND_LE; + default: + return IR_COND_UNKNOWN; + } + } + else + return IR_COND_UNKNOWN; +} + + +std::vector<omega::CG_outputRepr *> IR_suifCode::QueryExpOperand(const omega::CG_outputRepr *repr) const { + std::vector<omega::CG_outputRepr *> v; + + operand op = static_cast<const omega::CG_suifRepr *>(repr)->GetExpression(); + if (op.is_immed() || op.is_symbol()) { + omega::CG_suifRepr *repr = new omega::CG_suifRepr(op); + v.push_back(repr); + } + else if (op.is_instr()) { + instruction *ins = op.instr(); + omega::CG_suifRepr *repr; + operand op1, op2; + switch (ins->opcode()) { + case io_cpy: + case io_neg: + case io_cvt: + op1 = ins->src_op(0); + repr = new omega::CG_suifRepr(op1); + v.push_back(repr); + break; + case io_add: + case io_sub: + case io_mul: + case io_div: + case io_min: + case io_max: + op1 = ins->src_op(0); + repr = new omega::CG_suifRepr(op1); + v.push_back(repr); + op2 = ins->src_op(1); + repr = new omega::CG_suifRepr(op2); + v.push_back(repr); + break; + case io_seq: + case io_sne: + case io_sl: + case io_sle: + op1 = ins->src_op(0); + repr = new omega::CG_suifRepr(op1); + v.push_back(repr); + op2 = ins->src_op(1); + repr = new omega::CG_suifRepr(op2); + v.push_back(repr); + break; + default: + throw ir_error("operation not supported"); + } + } + else + throw ir_error("operand type not supported"); + + return v; +} + + +// IR_Constant *IR_suifCode::QueryExpConstant(const CG_outputRepr *repr) const { +// CG_suifRepr *l_repr = static_cast<CG_suifRepr *>(const_cast<CG_outputRepr *>(repr)); + +// operand op = l_repr->GetExpression(); +// if (op.is_immed()) { +// immed im = op.immediate(); + +// switch (im.kind()) { +// case im_int: +// return new IR_suifConstant(this, static_cast<coef_t>(im.integer())); +// case im_extended_int: +// return new IR_suifConstant(this, static_cast<coef_t>(im.long_int())); +// case im_float: +// return new IR_suifConstant(this, im.flt()); +// default: +// assert(-1); +// } +// } +// else +// assert(-1); +// } + + +// IR_ScalarRef *IR_suifCode::QueryExpVariable(const CG_outputRepr *repr) const { +// CG_suifRepr *l_repr = static_cast<CG_suifRepr *>(const_cast<CG_outputRepr *>(repr)); + +// operand op = l_repr->GetExpression(); +// if (op.is_symbol()) +// return new IR_suifScalarRef(this, op.symbol()); +// else +// assert(-1); +// } + + +IR_Ref *IR_suifCode::Repr2Ref(const omega::CG_outputRepr *repr) const { + operand op = static_cast<const omega::CG_suifRepr *>(repr)->GetExpression(); + if (op.is_immed()) { + immed im = op.immediate(); + + switch (im.kind()) { + case im_int: + return new IR_suifConstantRef(this, static_cast<omega::coef_t>(im.integer())); + case im_extended_int: + return new IR_suifConstantRef(this, static_cast<omega::coef_t>(im.long_int())); + case im_float: + return new IR_suifConstantRef(this, im.flt()); + default: + throw ir_error("immediate value not integer or floatint point"); + } + } + else if (op.is_symbol()) + return new IR_suifScalarRef(this, op.symbol()); + else + throw ir_error("unrecognized reference type"); +} |