1 | #include <iostream> |
2 | #include <algorithm> |
3 | #include "triton/ir/basic_block.h" |
4 | #include "triton/ir/instructions.h" |
5 | #include "triton/ir/type.h" |
6 | #include "triton/ir/function.h" |
7 | |
8 | namespace triton { |
9 | namespace ir { |
10 | |
11 | class phi_node; |
12 | |
13 | |
14 | basic_block::basic_block(context &ctx, const std::string &name, function *parent, basic_block* next): |
15 | value(type::get_label_ty(ctx), name), ctx_(ctx), parent_(parent) { |
16 | if(parent_) |
17 | parent_->insert_block(this, next); |
18 | } |
19 | |
20 | basic_block* basic_block::create(context &ctx, const std::string &name, function *parent, basic_block* next){ |
21 | return new basic_block(ctx, name, parent, next); |
22 | } |
23 | |
24 | void basic_block::replace_phi_uses_with(basic_block* before, basic_block* after) { |
25 | for(ir::instruction* i: inst_list_){ |
26 | auto* curr_phi = dynamic_cast<ir::phi_node*>(i); |
27 | if(!curr_phi) |
28 | break; |
29 | // curr_phi->replace_uses_of_with(before, after); |
30 | for (size_t idx = 0; idx < curr_phi->get_num_incoming(); ++idx) |
31 | if (curr_phi->get_incoming_block(idx) == before) |
32 | curr_phi->set_incoming_block(idx, after); |
33 | } |
34 | } |
35 | |
36 | void basic_block::append_instruction(ir::instruction* i){ |
37 | i->set_parent(this); |
38 | inst_list_.push_back(i); |
39 | } |
40 | |
41 | basic_block* basic_block::split_before(ir::instruction* loc, const std::string& name) { |
42 | basic_block* ret = basic_block::create(ctx_, name, parent_, this); |
43 | ret->set_name(get_name()); |
44 | set_name("after_" + name); |
45 | |
46 | // splice instruction list |
47 | auto loc_it = std::find(inst_list_.begin(), inst_list_.end(), loc); |
48 | ret->get_inst_list().splice(ret->get_inst_list().begin(), inst_list_, inst_list_.begin(), loc_it); |
49 | for(ir::instruction* i: ret->get_inst_list()) |
50 | i->set_parent(ret); |
51 | // the predecessors of `this` becomes the predecessors of `ret` |
52 | for(ir::basic_block* pred: get_predecessors()){ |
53 | auto* term = dynamic_cast<ir::terminator_inst*>(pred->get_inst_list().back()); |
54 | assert(term); |
55 | term->replace_uses_of_with(this, ret); |
56 | replace_phi_uses_with(pred, ret); |
57 | } |
58 | ir::branch_inst* br = branch_inst::create(this); |
59 | ret->append_instruction(br); |
60 | return ret; |
61 | } |
62 | |
63 | std::vector<basic_block*> basic_block::get_predecessors() const { |
64 | std::vector<basic_block*> ret; |
65 | for(ir::user* u: users_) |
66 | if(auto term = dynamic_cast<ir::terminator_inst*>(u)) |
67 | ret.push_back(term->get_parent()); |
68 | return ret; |
69 | } |
70 | |
71 | std::vector<basic_block*> basic_block::get_successors() const { |
72 | std::vector<basic_block*> ret; |
73 | for(ir::instruction* i: inst_list_) |
74 | for(ir::value* v: i->ops()) |
75 | if(auto block = dynamic_cast<ir::basic_block*>(v)) |
76 | ret.push_back(block); |
77 | return ret; |
78 | } |
79 | |
80 | basic_block::iterator basic_block::get_first_non_phi(){ |
81 | auto it = begin(); |
82 | for(; it != end(); it++) |
83 | if(!dynamic_cast<phi_node*>(*it)){ |
84 | return it; |
85 | } |
86 | return it; |
87 | } |
88 | |
89 | } |
90 | |
91 | } |
92 | |