1 /* brig-cmp-inst-handler.cc -- brig cmp instruction handling
2 Copyright (C) 2016-2018 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"
23 #include "diagnostic.h"
24 #include "tree-pretty-print.h"
25 #include "print-tree.h"
26 #include "brig-util.h"
30 brig_cmp_inst_handler::operator () (const BrigBase
*base
)
32 const BrigInstBase
*inst_base
= (const BrigInstBase
*) base
;
33 const BrigInstCmp
*inst
= (const BrigInstCmp
*) base
;
35 tree cmp_type
= get_tree_expr_type_for_hsa_type (inst
->sourceType
);
37 /* The destination type to convert the comparison result to. */
38 tree dest_type
= gccbrig_tree_type_for_hsa_type (inst_base
->type
);
40 const bool is_fp16_dest
41 = (inst_base
->type
& BRIG_TYPE_BASE_MASK
) == BRIG_TYPE_F16
;
42 const bool is_boolean_dest
43 = (inst_base
->type
& BRIG_TYPE_BASE_MASK
) == BRIG_TYPE_B1
;
45 bool is_int_cmp
= VECTOR_TYPE_P (cmp_type
)
46 ? INTEGRAL_TYPE_P (TREE_TYPE (cmp_type
))
47 : INTEGRAL_TYPE_P (cmp_type
);
49 /* The type for the GENERIC comparison. It should match the
50 input operand width for vector comparisons, a boolean
52 tree result_type
= get_comparison_result_type (cmp_type
);
54 /* Save the result as a boolean and extend/convert it to the
55 wanted destination type. */
56 tree expr
= NULL_TREE
;
58 std::vector
<tree
> operands
= build_operands (*inst_base
);
60 switch (inst
->compare
)
62 case BRIG_COMPARE_SEQ
:
64 expr
= build2 (EQ_EXPR
, result_type
, operands
[1], operands
[2]);
66 case BRIG_COMPARE_SNE
:
68 expr
= build2 (NE_EXPR
, result_type
, operands
[1], operands
[2]);
71 expr
= build2 (BIT_AND_EXPR
, TREE_TYPE (expr
),
73 build2 (ORDERED_EXPR
, result_type
, operands
[1],
76 case BRIG_COMPARE_SLT
:
78 expr
= build2 (LT_EXPR
, result_type
, operands
[1], operands
[2]);
80 case BRIG_COMPARE_SLE
:
82 expr
= build2 (LE_EXPR
, result_type
, operands
[1], operands
[2]);
84 case BRIG_COMPARE_SGT
:
86 expr
= build2 (GT_EXPR
, result_type
, operands
[1], operands
[2]);
88 case BRIG_COMPARE_SGE
:
90 expr
= build2 (GE_EXPR
, result_type
, operands
[1], operands
[2]);
92 case BRIG_COMPARE_SEQU
:
93 case BRIG_COMPARE_EQU
:
94 expr
= build2 (UNEQ_EXPR
, result_type
, operands
[1], operands
[2]);
96 case BRIG_COMPARE_SNEU
:
97 case BRIG_COMPARE_NEU
:
98 expr
= build2 (NE_EXPR
, result_type
, operands
[1], operands
[2]);
100 case BRIG_COMPARE_SLTU
:
101 case BRIG_COMPARE_LTU
:
102 expr
= build2 (UNLT_EXPR
, result_type
, operands
[1], operands
[2]);
104 case BRIG_COMPARE_SLEU
:
105 case BRIG_COMPARE_LEU
:
106 expr
= build2 (UNLE_EXPR
, result_type
, operands
[1], operands
[2]);
108 case BRIG_COMPARE_SGTU
:
109 case BRIG_COMPARE_GTU
:
110 expr
= build2 (UNGT_EXPR
, result_type
, operands
[1], operands
[2]);
112 case BRIG_COMPARE_SGEU
:
113 case BRIG_COMPARE_GEU
:
114 expr
= build2 (UNGE_EXPR
, result_type
, operands
[1], operands
[2]);
116 case BRIG_COMPARE_SNUM
:
117 case BRIG_COMPARE_NUM
:
118 expr
= build2 (ORDERED_EXPR
, result_type
, operands
[1], operands
[2]);
120 case BRIG_COMPARE_SNAN
:
121 case BRIG_COMPARE_NAN
:
122 expr
= build2 (UNORDERED_EXPR
, result_type
, operands
[1], operands
[2]);
128 if (expr
== NULL_TREE
)
133 expr
= convert_to_real (brig_to_generic::s_fp32_type
, expr
);
135 else if (VECTOR_TYPE_P (dest_type
) && ANY_INTEGRAL_TYPE_P (dest_type
)
137 && (inst
->sourceType
& BRIG_TYPE_BASE_MASK
) != BRIG_TYPE_F16
)
139 /* In later gcc versions, the output of comparison is not
140 all ones for vectors like still in 4.9.1. We need to use
141 an additional VEC_COND_EXPR to produce the all ones 'true' value
143 VEC_COND_EXPR <a == b, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>; */
146 = build_vector_from_val (dest_type
,
147 build_minus_one_cst (TREE_TYPE (dest_type
)));
149 = build_vector_from_val (dest_type
,
150 build_zero_cst (TREE_TYPE (dest_type
)));
151 expr
= build3 (VEC_COND_EXPR
, dest_type
, expr
, all_ones
, all_zeroes
);
153 else if (INTEGRAL_TYPE_P (dest_type
) && !is_boolean_dest
)
155 /* We need to produce the all-ones pattern for the width of the whole
156 resulting integer type. Use back and forth shifts for propagating
158 tree signed_type
= signed_type_for (dest_type
);
159 tree signed_result
= convert_to_integer (signed_type
, expr
);
161 size_t result_width
= int_size_in_bytes (dest_type
) * BITS_PER_UNIT
;
163 tree shift_amount_cst
164 = build_int_cstu (signed_type
, result_width
- 1);
166 tree shift_left_result
167 = build2 (LSHIFT_EXPR
, signed_type
, signed_result
, shift_amount_cst
);
169 expr
= build2 (RSHIFT_EXPR
, signed_type
, shift_left_result
,
172 else if (SCALAR_FLOAT_TYPE_P (dest_type
))
174 expr
= convert_to_real (dest_type
, expr
);
176 else if (VECTOR_TYPE_P (dest_type
)
177 && (inst
->sourceType
& BRIG_TYPE_BASE_MASK
) == BRIG_TYPE_F16
)
179 /* Because F16 comparison is emulated as an F32 comparison with S32
180 results, we must now truncate the result vector to S16s so it
181 fits to the destination register. We can build the target vector
182 type from the f16 storage type (unsigned ints). */
183 expr
= m_parent
.m_cf
->add_temp_var ("wide_cmp_result", expr
);
184 tree_stl_vec wide_elements
;
185 tree_stl_vec shrunk_elements
;
186 m_parent
.m_cf
->unpack (expr
, wide_elements
);
187 for (size_t i
= 0; i
< wide_elements
.size (); ++i
)
189 tree wide
= wide_elements
.at (i
);
190 shrunk_elements
.push_back
191 (convert_to_integer (short_integer_type_node
, wide
));
193 expr
= m_parent
.m_cf
->pack (shrunk_elements
);
195 build_output_assignment (*inst_base
, operands
[0], expr
);
197 return base
->byteCount
;