annotate gcc/brig/brigfrontend/brig-branch-inst-handler.cc @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* brig-branch-inst-handler.cc -- brig branch instruction handling
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 Copyright (C) 2016-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
kono
parents:
diff changeset
4 for General Processor Tech.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 This file is part of GCC.
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
9 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
10 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
11 version.
kono
parents:
diff changeset
12
kono
parents:
diff changeset
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
16 for more details.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
19 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
20 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 #include "brig-code-entry-handler.h"
kono
parents:
diff changeset
23
kono
parents:
diff changeset
24 #include "errors.h"
kono
parents:
diff changeset
25 #include "brig-util.h"
kono
parents:
diff changeset
26 #include "tree-pretty-print.h"
kono
parents:
diff changeset
27 #include "print-tree.h"
kono
parents:
diff changeset
28 #include "vec.h"
kono
parents:
diff changeset
29 #include "fold-const.h"
kono
parents:
diff changeset
30
kono
parents:
diff changeset
31 size_t
kono
parents:
diff changeset
32 brig_branch_inst_handler::operator () (const BrigBase *base)
kono
parents:
diff changeset
33 {
kono
parents:
diff changeset
34 const BrigInstBase *brig_inst
kono
parents:
diff changeset
35 = (const BrigInstBase *) &((const BrigInstBasic *) base)->base;
kono
parents:
diff changeset
36
kono
parents:
diff changeset
37 if (brig_inst->opcode == BRIG_OPCODE_CALL)
kono
parents:
diff changeset
38 {
kono
parents:
diff changeset
39 const BrigData *operand_entries
kono
parents:
diff changeset
40 = m_parent.get_brig_data_entry (brig_inst->operands);
kono
parents:
diff changeset
41 tree func_ref = NULL_TREE;
kono
parents:
diff changeset
42 vec<tree, va_gc> *out_args;
kono
parents:
diff changeset
43 vec_alloc (out_args, 1);
kono
parents:
diff changeset
44 vec<tree, va_gc> *in_args;
kono
parents:
diff changeset
45 /* Ten elem initially, more reserved if needed. */
kono
parents:
diff changeset
46 vec_alloc (in_args, 10);
kono
parents:
diff changeset
47
kono
parents:
diff changeset
48 size_t operand_count = operand_entries->byteCount / 4;
kono
parents:
diff changeset
49 gcc_assert (operand_count < 4);
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 for (size_t i = 0; i < operand_count; ++i)
kono
parents:
diff changeset
52 {
kono
parents:
diff changeset
53 uint32_t operand_offset
kono
parents:
diff changeset
54 = ((const uint32_t *) &operand_entries->bytes)[i];
kono
parents:
diff changeset
55 const BrigBase *operand_data
kono
parents:
diff changeset
56 = m_parent.get_brig_operand_entry (operand_offset);
kono
parents:
diff changeset
57 if (i == 1)
kono
parents:
diff changeset
58 {
kono
parents:
diff changeset
59 gcc_assert (operand_data->kind == BRIG_KIND_OPERAND_CODE_REF);
kono
parents:
diff changeset
60 func_ref = build_tree_operand (*brig_inst, *operand_data);
kono
parents:
diff changeset
61 continue;
kono
parents:
diff changeset
62 }
kono
parents:
diff changeset
63 gcc_assert (operand_data->kind == BRIG_KIND_OPERAND_CODE_LIST);
kono
parents:
diff changeset
64 const BrigOperandCodeList *codelist
kono
parents:
diff changeset
65 = (const BrigOperandCodeList *) operand_data;
kono
parents:
diff changeset
66 const BrigData *data
kono
parents:
diff changeset
67 = m_parent.get_brig_data_entry (codelist->elements);
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 size_t bytes = data->byteCount;
kono
parents:
diff changeset
70 const BrigOperandOffset32_t *operand_ptr
kono
parents:
diff changeset
71 = (const BrigOperandOffset32_t *) data->bytes;
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 bool out_args_p = i == 0;
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 while (bytes > 0)
kono
parents:
diff changeset
76 {
kono
parents:
diff changeset
77 BrigOperandOffset32_t offset = *operand_ptr;
kono
parents:
diff changeset
78 const BrigBase *code_element
kono
parents:
diff changeset
79 = m_parent.get_brig_code_entry (offset);
kono
parents:
diff changeset
80 gcc_assert (code_element->kind == BRIG_KIND_DIRECTIVE_VARIABLE);
kono
parents:
diff changeset
81 const BrigDirectiveVariable *brig_var
kono
parents:
diff changeset
82 = (const BrigDirectiveVariable *) code_element;
kono
parents:
diff changeset
83 tree var = m_parent.m_cf->arg_variable (brig_var);
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 if (brig_var->type & BRIG_TYPE_ARRAY)
kono
parents:
diff changeset
86 {
kono
parents:
diff changeset
87 /* Array return values are passed as the first argument. */
kono
parents:
diff changeset
88 out_args_p = false;
kono
parents:
diff changeset
89 /* Pass pointer to the element zero and use its element zero
kono
parents:
diff changeset
90 as the base address. */
kono
parents:
diff changeset
91 tree etype = TREE_TYPE (TREE_TYPE (var));
kono
parents:
diff changeset
92 tree ptype = build_pointer_type (etype);
kono
parents:
diff changeset
93 tree element_zero
kono
parents:
diff changeset
94 = build4 (ARRAY_REF, etype, var, integer_zero_node,
kono
parents:
diff changeset
95 NULL_TREE, NULL_TREE);
kono
parents:
diff changeset
96 var = build1 (ADDR_EXPR, ptype, element_zero);
kono
parents:
diff changeset
97 }
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 gcc_assert (var != NULL_TREE);
kono
parents:
diff changeset
100 vec_safe_push (out_args_p ? out_args : in_args, var);
kono
parents:
diff changeset
101 ++operand_ptr;
kono
parents:
diff changeset
102 bytes -= 4;
kono
parents:
diff changeset
103 }
kono
parents:
diff changeset
104 }
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 gcc_assert (func_ref != NULL_TREE);
kono
parents:
diff changeset
107 gcc_assert (out_args->length () == 0 || out_args->length () == 1);
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 tree ret_val_type = void_type_node;
kono
parents:
diff changeset
110 tree ret_val = NULL_TREE;
kono
parents:
diff changeset
111 if (out_args->length () == 1)
kono
parents:
diff changeset
112 {
kono
parents:
diff changeset
113 ret_val = (*out_args)[0];
kono
parents:
diff changeset
114 ret_val_type = TREE_TYPE (ret_val);
kono
parents:
diff changeset
115 }
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 /* Pass the hidden kernel arguments along to the called functions as
kono
parents:
diff changeset
118 they might call builtins that need them or access group/private
kono
parents:
diff changeset
119 memory. */
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 tree group_local_offset
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
122 = m_parent.m_cf->add_temp_var ("group_local_offset",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
123 build_int_cst
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
124 (uint32_type_node,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
125 m_parent.m_cf->
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
126 m_local_group_variables.size()));
111
kono
parents:
diff changeset
127
kono
parents:
diff changeset
128 /* TODO: ensure the callee's frame is aligned! */
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 vec_safe_reserve (in_args, 4);
kono
parents:
diff changeset
131 vec_safe_push (in_args, m_parent.m_cf->m_context_arg);
kono
parents:
diff changeset
132 vec_safe_push (in_args, m_parent.m_cf->m_group_base_arg);
kono
parents:
diff changeset
133 vec_safe_push (in_args, group_local_offset);
kono
parents:
diff changeset
134 vec_safe_push (in_args, m_parent.m_cf->m_private_base_arg);
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136 tree call = build_call_vec (ret_val_type, build_fold_addr_expr (func_ref),
kono
parents:
diff changeset
137 in_args);
kono
parents:
diff changeset
138 TREE_NOTHROW (func_ref) = 1;
kono
parents:
diff changeset
139 TREE_NOTHROW (call) = 1;
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 if (ret_val != NULL_TREE)
kono
parents:
diff changeset
142 {
kono
parents:
diff changeset
143 TREE_ADDRESSABLE (ret_val) = 1;
kono
parents:
diff changeset
144 tree result_assign
kono
parents:
diff changeset
145 = build2 (MODIFY_EXPR, TREE_TYPE (ret_val), ret_val, call);
kono
parents:
diff changeset
146 m_parent.m_cf->append_statement (result_assign);
kono
parents:
diff changeset
147 }
kono
parents:
diff changeset
148 else
kono
parents:
diff changeset
149 {
kono
parents:
diff changeset
150 m_parent.m_cf->append_statement (call);
kono
parents:
diff changeset
151 }
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 m_parent.m_cf->m_called_functions.push_back (func_ref);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
154 if (DECL_EXTERNAL (func_ref))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
155 m_parent.add_decl_call (call);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
156 m_parent.m_cf->start_new_bb ();
111
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 return base->byteCount;
kono
parents:
diff changeset
159 }
kono
parents:
diff changeset
160
kono
parents:
diff changeset
161 tree instr_type = gccbrig_tree_type_for_hsa_type (brig_inst->type);
kono
parents:
diff changeset
162 tree_stl_vec operands = build_operands (*brig_inst);
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 if (brig_inst->opcode == BRIG_OPCODE_BR)
kono
parents:
diff changeset
165 {
kono
parents:
diff changeset
166 tree goto_stmt = build1 (GOTO_EXPR, instr_type, operands[0]);
kono
parents:
diff changeset
167 m_parent.m_cf->append_statement (goto_stmt);
kono
parents:
diff changeset
168 }
kono
parents:
diff changeset
169 else if (brig_inst->opcode == BRIG_OPCODE_SBR)
kono
parents:
diff changeset
170 {
kono
parents:
diff changeset
171 tree select = operands[0];
kono
parents:
diff changeset
172 tree cases = operands[1];
kono
parents:
diff changeset
173
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
174 tree switch_expr = build2 (SWITCH_EXPR, TREE_TYPE (select), select,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
175 NULL_TREE);
111
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 tree default_case
kono
parents:
diff changeset
178 = build_case_label (NULL_TREE, NULL_TREE,
kono
parents:
diff changeset
179 create_artificial_label (UNKNOWN_LOCATION));
kono
parents:
diff changeset
180 append_to_statement_list (default_case, &SWITCH_BODY (switch_expr));
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 tree default_jump
kono
parents:
diff changeset
183 = build1 (GOTO_EXPR, void_type_node, TREE_VEC_ELT (cases, 0));
kono
parents:
diff changeset
184 append_to_statement_list (default_jump, &SWITCH_BODY (switch_expr));
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 for (int c = 0; c < TREE_VEC_LENGTH (cases); ++c)
kono
parents:
diff changeset
187 {
kono
parents:
diff changeset
188 tree case_label
kono
parents:
diff changeset
189 = build_case_label (build_int_cst (integer_type_node, c), NULL_TREE,
kono
parents:
diff changeset
190 create_artificial_label (UNKNOWN_LOCATION));
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 append_to_statement_list (case_label, &SWITCH_BODY (switch_expr));
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 tree jump
kono
parents:
diff changeset
195 = build1 (GOTO_EXPR, void_type_node, TREE_VEC_ELT (cases, c));
kono
parents:
diff changeset
196 append_to_statement_list (jump, &SWITCH_BODY (switch_expr));
kono
parents:
diff changeset
197 }
kono
parents:
diff changeset
198 m_parent.m_cf->append_statement (switch_expr);
kono
parents:
diff changeset
199 }
kono
parents:
diff changeset
200 else if (brig_inst->opcode == BRIG_OPCODE_CBR)
kono
parents:
diff changeset
201 {
kono
parents:
diff changeset
202 tree condition = operands[0];
kono
parents:
diff changeset
203 tree target_goto = build1 (GOTO_EXPR, void_type_node, operands[1]);
kono
parents:
diff changeset
204 /* Represents the if..else as (condition)?(goto foo):(goto bar). */
kono
parents:
diff changeset
205 tree if_stmt
kono
parents:
diff changeset
206 = build3 (COND_EXPR, void_type_node, condition, target_goto, NULL_TREE);
kono
parents:
diff changeset
207 m_parent.m_cf->append_statement (if_stmt);
kono
parents:
diff changeset
208 }
kono
parents:
diff changeset
209 else if (brig_inst->opcode == BRIG_OPCODE_WAVEBARRIER)
kono
parents:
diff changeset
210 {
kono
parents:
diff changeset
211 /* WAVEBARRIER is a NOP when WAVESIZE = 1. */
kono
parents:
diff changeset
212 }
kono
parents:
diff changeset
213 else if (brig_inst->opcode == BRIG_OPCODE_BARRIER)
kono
parents:
diff changeset
214 {
kono
parents:
diff changeset
215 m_parent.m_cf->m_has_barriers = true;
kono
parents:
diff changeset
216 tree_stl_vec call_operands;
kono
parents:
diff changeset
217 /* FIXME. We should add attributes (are there suitable ones in gcc?) that
kono
parents:
diff changeset
218 ensure the barrier won't be duplicated or moved out of loops etc.
kono
parents:
diff changeset
219 Like the 'noduplicate' of LLVM. Same goes for fbarriers. */
kono
parents:
diff changeset
220 m_parent.m_cf->append_statement
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
221 (m_parent.m_cf->expand_or_call_builtin (brig_inst->opcode,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
222 BRIG_TYPE_NONE, NULL_TREE,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
223 call_operands));
111
kono
parents:
diff changeset
224 }
kono
parents:
diff changeset
225 else if (brig_inst->opcode >= BRIG_OPCODE_ARRIVEFBAR
kono
parents:
diff changeset
226 && brig_inst->opcode <= BRIG_OPCODE_WAITFBAR)
kono
parents:
diff changeset
227 {
kono
parents:
diff changeset
228 m_parent.m_cf->m_has_barriers = true;
kono
parents:
diff changeset
229 m_parent.m_cf->append_statement
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
230 (m_parent.m_cf->expand_or_call_builtin (brig_inst->opcode,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
231 BRIG_TYPE_NONE,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
232 uint32_type_node, operands));
111
kono
parents:
diff changeset
233 }
kono
parents:
diff changeset
234 else
kono
parents:
diff changeset
235 gcc_unreachable ();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
236 m_parent.m_cf->start_new_bb ();
111
kono
parents:
diff changeset
237 return base->byteCount;
kono
parents:
diff changeset
238 }