size_t SymbolTable::map_operand(bh_instruction& instr, size_t operand_idx) { size_t arg_idx = ++(nsymbols_); // Candidate arg_idx if not reused if (bh_is_constant(&instr.operand[operand_idx])) { // Constants if (BH_R123 != instr.constant.type) { // Regular constants table_[arg_idx].const_data = &(instr.constant.value); table_[arg_idx].etype = bhtype_to_etype(instr.constant.type); } else { // "Special" for BH_R123 table_[arg_idx].etype = UINT64; if (1 == operand_idx) { table_[arg_idx].const_data = &(instr.constant.value.r123.start); } else if (2 == operand_idx) { table_[arg_idx].const_data = &(instr.constant.value.r123.key); } else { throw runtime_error("THIS SHOULD NEVER HAPPEN!"); } } table_[arg_idx].data = &table_[arg_idx].const_data; table_[arg_idx].nelem = 1; table_[arg_idx].ndim = 1; table_[arg_idx].start = 0; table_[arg_idx].shape = instr.operand[operand_idx].shape; table_[arg_idx].shape[0] = 1; table_[arg_idx].stride = instr.operand[operand_idx].shape; table_[arg_idx].stride[0] = 0; table_[arg_idx].layout = SCALAR_CONST; table_[arg_idx].base = NULL; } else { table_[arg_idx].const_data= NULL; table_[arg_idx].data = &(bh_base_array(&instr.operand[operand_idx])->data); table_[arg_idx].etype = bhtype_to_etype(bh_base_array(&instr.operand[operand_idx])->type); table_[arg_idx].nelem = bh_base_array(&instr.operand[operand_idx])->nelem; table_[arg_idx].ndim = instr.operand[operand_idx].ndim; table_[arg_idx].start = instr.operand[operand_idx].start; table_[arg_idx].shape = instr.operand[operand_idx].shape; table_[arg_idx].stride = instr.operand[operand_idx].stride; table_[arg_idx].layout = determine_layout(table_[arg_idx]); table_[arg_idx].base = instr.operand[operand_idx].base; } // // Reuse operand identifiers: Detect if we have seen it before and reuse the name. // This is done by comparing the currently investigated operand (arg_idx) // with all other operands in the current scope [1,arg_idx[ // Do remember that 0 is is not a valid operand and we therefore index from 1. // Also we do not want to compare with selv, that is when i == arg_idx. for(size_t i=1; i<arg_idx; ++i) { if (!equivalent(table_[i], table_[arg_idx])) { continue; // Not equivalent, continue search. } // Found one! Use it instead of the incremented identifier. --nsymbols_; arg_idx = i; break; } return arg_idx; }
static inline bool is_constant(const bh_instruction& instr) { for(int i = 0; i < bh_noperands(instr.opcode); ++i) { if (bh_is_constant(&(instr.operand[i]))) { return true; } } return false; }
void Contracter::contract_stupidmath(bh_ir &bhir) { for(size_t pc = 0; pc < bhir.instr_list.size(); ++pc) { bh_instruction& instr = bhir.instr_list[pc]; if (is_doing_stupid_math(instr)) { verbose_print("[Stupid math] Is doing stupid math with a " + std::string(bh_opcode_text(instr.opcode))); // We could have the following: // BH_ADD B A 0 // BH_FREE A // BH_SYNC B // We want to find the add and replace A in all above with B, if A is created in this flush. // Then remove the free of A. // Output operand bh_view* B = &(instr.operand[0]); // The one operand, that isn't constant bh_view* A; if (bh_is_constant(&(instr.operand[1]))) { A = &(instr.operand[2]); } else { A = &(instr.operand[1]); } if (bh_view_same(A, B)) continue; bool freed = false; for (size_t pc_chain = 0; pc_chain < bhir.instr_list.size(); ++pc_chain) { bh_instruction& other_instr = bhir.instr_list[pc_chain]; // Look for matching FREE for B if (other_instr.opcode == BH_FREE and bh_view_same(&(other_instr.operand[0]), B)) { freed = true; break; } } if (!freed) { verbose_print("[Stupid math] \tCan't rectify as it isn't freeing in same flush."); continue; } // Check that A is created by us. bool created_before = false; for (size_t pc_chain = 0; pc_chain < pc; ++pc_chain) { bh_instruction& other_instr = bhir.instr_list[pc_chain]; if (bh_view_same(&(other_instr.operand[0]), A)) { created_before = true; break; } } // Only if we have created A in this flush, are we allowed to change it. if (!created_before) { verbose_print("[Stupid math] \tCan't rectify as other view isn't created in same flush."); continue; } for (size_t pc_chain = 0; pc_chain < bhir.instr_list.size(); ++pc_chain) { if (pc == pc_chain) continue; bh_instruction& other_instr = bhir.instr_list[pc_chain]; // Look for matching FREE for A if (other_instr.opcode == BH_FREE and bh_view_same(&(other_instr.operand[0]), A)) { verbose_print("[Stupid math] \tFound and removed FREE."); other_instr.opcode = BH_NONE; // Remove instruction } else { // Rewrite all uses of A to B for (int idx = 0; idx < bh_noperands(other_instr.opcode); ++idx) { if (bh_view_same(&(other_instr.operand[idx]), A)) { verbose_print("[Stupid math] \tRewriting A to B."); other_instr.operand[idx] = *B; } } } } // Remove self verbose_print("[Stupid math] \tRemoving " + std::string(bh_opcode_text(instr.opcode))); instr.opcode = BH_NONE; } } }
int main() { dispatch_msg *msg; timing_init(); //Initiate the process grid pgrid_init(); while(1) { //Receive the dispatch message from the master-process dispatch_reset(); dispatch_recv(&msg); //Handle the message switch(msg->type) { case BH_CLUSTER_DISPATCH_INIT: { char *name = msg->payload; check_error(exec_init(name),__FILE__,__LINE__); break; } case BH_CLUSTER_DISPATCH_SHUTDOWN: { check_error(exec_shutdown(),__FILE__,__LINE__); return 0; } case BH_CLUSTER_DISPATCH_EXTMETHOD: { bh_opcode opcode = *((bh_opcode *)msg->payload); char *name = msg->payload+sizeof(bh_opcode); check_error(exec_extmethod(name, opcode),__FILE__,__LINE__); break; } case BH_CLUSTER_DISPATCH_EXEC: { //Get the size of the the serialized BhIR bh_intp bhir_size = *((bh_intp*) msg->payload); //Deserialize the BhIR bh_ir bhir = bh_ir(((char*)msg->payload)+sizeof(bh_intp), bhir_size); //The number of new arrays bh_intp *noa = (bh_intp *)(((char*)msg->payload)+sizeof(bh_intp)+bhir_size); //The list of new arrays dispatch_array *darys = (dispatch_array*)(noa+1); //number of new arrays //Insert the new array into the array store and the array maps std::stack<bh_base*> base_darys; for(bh_intp i=0; i < *noa; ++i) { bh_base *ary = dispatch_new_slave_array(&darys[i].ary, darys[i].id); base_darys.push(ary); } //Receive the dispatched array-data from the master-process dispatch_array_data(base_darys); //Update all instruction to reference local arrays for(uint64_t i=0; i < bhir.instr_list.size(); ++i) { bh_instruction *inst = &bhir.instr_list[i]; int nop = bh_noperands(inst->opcode); bh_view *ops = bh_inst_operands(inst); //Convert all instructon operands for(bh_intp j=0; j<nop; ++j) { if(bh_is_constant(&ops[j])) continue; bh_base *base = bh_base_array(&ops[j]); assert(dispatch_slave_exist((bh_intp)base)); bh_base_array(&ops[j]) = dispatch_master2slave((bh_intp)base); } } check_error(exec_execute(&bhir),__FILE__,__LINE__); break; } default: fprintf(stderr, "[VEM-CLUSTER] Slave (rank %d) " "received unknown message type\n", pgrid_myrank); MPI_Abort(MPI_COMM_WORLD,BH_ERROR); } } timing_finalize(); return BH_SUCCESS; }
void Contracter::contract_muladd(bh_ir &bhir) { bool rewritten = false; vector<bh_view*> temp_results; vector<bh_instruction*> instruction_chain; for(size_t pc = 0; pc < bhir.instr_list.size(); ++pc) { if (rewritten) { // We might catch more rewrites if we found one // so we loop back to the beginning pc = 0; rewritten = false; temp_results.clear(); instruction_chain.clear(); } bh_instruction& instr = bhir.instr_list[pc]; bh_view* multiplying_view; if (instr.opcode == BH_MULTIPLY) { if (bh_is_constant(&(instr.operand[1]))) { multiplying_view = &(instr.operand[2]); } else if (bh_is_constant(&(instr.operand[2]))) { multiplying_view = &(instr.operand[1]); } else { continue; } instruction_chain.push_back(&instr); // First BH_MULTIPLY found temp_results.push_back(&(instr.operand[0])); for(size_t sub_pc = pc+1; sub_pc < bhir.instr_list.size(); ++sub_pc) { if (rewritten) break; bh_instruction& other_instr = bhir.instr_list[sub_pc]; if (other_instr.opcode == BH_MULTIPLY) { if (!((bh_is_constant(&(other_instr.operand[1])) and *multiplying_view == other_instr.operand[2]) or (bh_is_constant(&(other_instr.operand[2])) and *multiplying_view == other_instr.operand[1]))) { continue; } instruction_chain.push_back(&other_instr); // Second BH_MULTIPLY found temp_results.push_back(&(other_instr.operand[0])); for(size_t sub_sub_pc = sub_pc+1; sub_sub_pc < bhir.instr_list.size(); ++sub_sub_pc) { if (rewritten) break; bh_instruction& yet_another_instr = bhir.instr_list[sub_sub_pc]; if (yet_another_instr.opcode == BH_ADD or yet_another_instr.opcode == BH_SUBTRACT) { uint found = 0; for(auto it : temp_results) { if (*it == yet_another_instr.operand[1] or *it == yet_another_instr.operand[2]) { found += 1; } } if (found >= 2) { instruction_chain.push_back(&yet_another_instr); verbose_print("[Muladd] Rewriting chain of length " + std::to_string(instruction_chain.size())); rewritten = rewrite_chain(bhir, instruction_chain, temp_results); } } } instruction_chain.pop_back(); temp_results.pop_back(); } } } } }