1 /* brig-mem-inst-handler.cc -- brig memory inst handler
2 Copyright (C) 2016-2017 Free Software Foundation, Inc.
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
4 for General Processor Tech.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "brig-code-entry-handler.h"
25 #include "brig-util.h"
26 #include "gimple-expr.h"
27 #include "print-tree.h"
28 #include "tree-pretty-print.h"
30 #include "diagnostic-core.h"
33 brig_mem_inst_handler::build_mem_access (const BrigInstBase
*brig_inst
,
36 bool is_load
= brig_inst
->opcode
== BRIG_OPCODE_LD
;
37 bool is_store
= brig_inst
->opcode
== BRIG_OPCODE_ST
;
39 if (!is_load
&& !is_store
)
42 tree instr_type
= gccbrig_tree_type_for_hsa_type (brig_inst
->type
);
44 if (VECTOR_TYPE_P (TREE_TYPE (data
)))
45 instr_type
= TREE_TYPE (data
);
47 tree ptype
= build_pointer_type (instr_type
);
49 /* The HSAIL mem instructions are unaligned by default.
50 TODO: exploit the align modifier, it should lead to faster code.
52 tree unaligned_type
= build_aligned_type (instr_type
, 8);
54 /* Create a mem ref from the previous result, without offset. */
56 = build2 (MEM_REF
, unaligned_type
, addr
, build_int_cst (ptype
, 0));
60 /* Add a temporary variable so there won't be multiple
61 reads in case of vector unpack. */
62 mem_ref
= add_temp_var ("mem_read", mem_ref
);
63 return build_output_assignment (*brig_inst
, data
, mem_ref
);
67 tree stmt
= build2 (MODIFY_EXPR
, TREE_TYPE (mem_ref
), mem_ref
, data
);
68 return m_parent
.m_cf
->append_statement (stmt
);
74 brig_mem_inst_handler::operator () (const BrigBase
*base
)
76 const BrigInstBase
*brig_inst
77 = (const BrigInstBase
*) &((const BrigInstBasic
*) base
)->base
;
79 if (brig_inst
->opcode
== BRIG_OPCODE_ALLOCA
)
81 tree_stl_vec operands
= build_operands (*brig_inst
);
83 const BrigInstMem
*mem_inst
= (const BrigInstMem
*) brig_inst
;
84 if (mem_inst
->align
!= BRIG_ALIGNMENT_NONE
)
86 alignment
= 1 << (mem_inst
->align
- 1);
89 tree align_opr
= build_int_cstu (size_type_node
, alignment
);
91 inputs
.push_back (operands
[1]);
92 inputs
.push_back (align_opr
);
94 = expand_or_call_builtin (BRIG_OPCODE_ALLOCA
, BRIG_TYPE_U32
,
95 uint32_type_node
, inputs
);
96 build_output_assignment (*brig_inst
, operands
[0], builtin_call
);
97 m_parent
.m_cf
->m_has_allocas
= true;
98 return base
->byteCount
;
101 tree instr_type
= gccbrig_tree_type_for_hsa_type (brig_inst
->type
);
103 const BrigData
*operand_entries
104 = m_parent
.get_brig_data_entry (brig_inst
->operands
);
106 uint32_t data_operand_offset
;
107 memcpy (&data_operand_offset
, &operand_entries
->bytes
, 4);
109 const BrigBase
*operand
110 = m_parent
.get_brig_operand_entry (data_operand_offset
);
112 const BrigData
*operandData
= NULL
;
114 bool is_store
= brig_inst
->opcode
== BRIG_OPCODE_ST
;
116 bool is_three_element_vector_access
117 = operand
->kind
== BRIG_KIND_OPERAND_OPERAND_LIST
118 && (operandData
= m_parent
.get_brig_data_entry
119 (((const BrigOperandOperandList
*) operand
)->elements
))
120 && operandData
->byteCount
/ 4 == 3;
122 if (is_three_element_vector_access
)
124 /* We need to scalarize the 3-element vector accesses here
125 because gcc assumes the GENERIC vector datatypes are of two exponent
127 size_t bytes
= operandData
->byteCount
;
128 const BrigOperandOffset32_t
*operand_ptr
129 = (const BrigOperandOffset32_t
*) operandData
->bytes
;
131 uint32_t addr_operand_offset
;
132 memcpy (&addr_operand_offset
, &operand_entries
->bytes
+ 4, 4);
134 const BrigOperandAddress
*addr_operand
135 = (const BrigOperandAddress
*) m_parent
.get_brig_operand_entry
136 (addr_operand_offset
);
138 tree address_base
= build_address_operand (*brig_inst
, *addr_operand
);
140 uint32_t address_offset
= 0;
143 BrigOperandOffset32_t offset
= *operand_ptr
;
144 const BrigBase
*operand_element
145 = m_parent
.get_brig_operand_entry (offset
);
147 = build_tree_operand (*brig_inst
, *operand_element
, instr_type
);
149 tree ptr_offset
= build_int_cst (size_type_node
, address_offset
);
150 tree address
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (address_base
),
151 address_base
, ptr_offset
);
153 if (is_store
&& TREE_TYPE (data
) != instr_type
)
155 if (int_size_in_bytes (TREE_TYPE (data
))
156 == int_size_in_bytes (instr_type
)
157 && !INTEGRAL_TYPE_P (instr_type
))
158 data
= build1 (VIEW_CONVERT_EXPR
, instr_type
, data
);
160 data
= convert (instr_type
, data
);
163 build_mem_access (brig_inst
, address
, data
);
165 address_offset
+= int_size_in_bytes (instr_type
);
172 tree_stl_vec operands
= build_operands (*brig_inst
);
174 tree
&data
= operands
.at (0);
175 tree
&addr
= operands
.at (1);
176 build_mem_access (brig_inst
, addr
, data
);
179 return base
->byteCount
;