1 /* Schedule GIMPLE vector statements.
2 Copyright (C) 2020 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
27 #include "tree-pass.h"
30 #include "optabs-tree.h"
32 #include "gimple-iterator.h"
33 #include "gimplify-me.h"
37 #include "tree-ssa-dce.h"
39 /* Expand all VEC_COND_EXPR gimple assignments into calls to internal
40 function based on type of selected expansion. */
43 gimple_expand_vec_cond_expr (gimple_stmt_iterator
*gsi
,
44 hash_map
<tree
, unsigned int> *vec_cond_ssa_name_uses
)
46 tree lhs
, op0a
= NULL_TREE
, op0b
= NULL_TREE
;
49 machine_mode cmp_op_mode
;
52 imm_use_iterator imm_iter
;
54 /* Only consider code == GIMPLE_ASSIGN. */
55 gassign
*stmt
= dyn_cast
<gassign
*> (gsi_stmt (*gsi
));
59 code
= gimple_assign_rhs_code (stmt
);
60 if (code
!= VEC_COND_EXPR
)
63 tree op0
= gimple_assign_rhs1 (stmt
);
64 tree op1
= gimple_assign_rhs2 (stmt
);
65 tree op2
= gimple_assign_rhs3 (stmt
);
66 lhs
= gimple_assign_lhs (stmt
);
67 machine_mode mode
= TYPE_MODE (TREE_TYPE (lhs
));
69 gcc_assert (!COMPARISON_CLASS_P (op0
));
70 if (TREE_CODE (op0
) == SSA_NAME
)
72 unsigned int used_vec_cond_exprs
= 0;
73 unsigned int *slot
= vec_cond_ssa_name_uses
->get (op0
);
75 used_vec_cond_exprs
= *slot
;
79 FOR_EACH_IMM_USE_STMT (use_stmt
, imm_iter
, op0
)
81 gassign
*assign
= dyn_cast
<gassign
*> (use_stmt
);
83 && gimple_assign_rhs_code (assign
) == VEC_COND_EXPR
84 && gimple_assign_rhs1 (assign
) == op0
)
85 used_vec_cond_exprs
++;
87 vec_cond_ssa_name_uses
->put (op0
, used_vec_cond_exprs
);
90 gassign
*def_stmt
= dyn_cast
<gassign
*> (SSA_NAME_DEF_STMT (op0
));
93 tcode
= gimple_assign_rhs_code (def_stmt
);
94 op0a
= gimple_assign_rhs1 (def_stmt
);
95 op0b
= gimple_assign_rhs2 (def_stmt
);
97 tree op0a_type
= TREE_TYPE (op0a
);
98 if (used_vec_cond_exprs
>= 2
99 && (get_vcond_mask_icode (mode
, TYPE_MODE (op0a_type
))
101 && expand_vec_cmp_expr_p (op0a_type
, TREE_TYPE (lhs
), tcode
))
103 /* Keep the SSA name and use vcond_mask. */
104 tcode
= TREE_CODE (op0
);
108 tcode
= TREE_CODE (op0
);
111 tcode
= TREE_CODE (op0
);
113 if (TREE_CODE_CLASS (tcode
) != tcc_comparison
)
115 gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0
)));
116 if (get_vcond_mask_icode (mode
, TYPE_MODE (TREE_TYPE (op0
)))
118 return gimple_build_call_internal (IFN_VCOND_MASK
, 3, op0
, op1
, op2
);
122 gcc_assert (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (op0
)))
125 op0b
= build_zero_cst (TREE_TYPE (op0
));
129 cmp_op_mode
= TYPE_MODE (TREE_TYPE (op0a
));
130 unsignedp
= TYPE_UNSIGNED (TREE_TYPE (op0a
));
133 gcc_assert (known_eq (GET_MODE_SIZE (mode
), GET_MODE_SIZE (cmp_op_mode
))
134 && known_eq (GET_MODE_NUNITS (mode
),
135 GET_MODE_NUNITS (cmp_op_mode
)));
137 icode
= get_vcond_icode (mode
, cmp_op_mode
, unsignedp
);
138 if (icode
== CODE_FOR_nothing
)
142 && TREE_CODE (op0
) == VECTOR_CST
)
144 /* A VEC_COND_EXPR condition could be folded from EQ_EXPR/NE_EXPR
145 into a constant when only get_vcond_eq_icode is supported.
146 Verify < 0 and != 0 behave the same and change it to NE_EXPR. */
147 unsigned HOST_WIDE_INT nelts
;
148 if (!VECTOR_CST_NELTS (op0
).is_constant (&nelts
))
150 if (VECTOR_CST_STEPPED_P (op0
))
152 nelts
= vector_cst_encoded_nelts (op0
);
154 for (unsigned int i
= 0; i
< nelts
; ++i
)
155 if (tree_int_cst_sgn (vector_cst_elt (op0
, i
)) == 1)
159 if (tcode
== EQ_EXPR
|| tcode
== NE_EXPR
)
161 tree tcode_tree
= build_int_cst (integer_type_node
, tcode
);
162 return gimple_build_call_internal (IFN_VCONDEQ
, 5, op0a
, op0b
, op1
,
167 gcc_assert (icode
!= CODE_FOR_nothing
);
168 tree tcode_tree
= build_int_cst (integer_type_node
, tcode
);
169 return gimple_build_call_internal (unsignedp
? IFN_VCONDU
: IFN_VCOND
,
170 5, op0a
, op0b
, op1
, op2
, tcode_tree
);
175 /* Iterate all gimple statements and try to expand
176 VEC_COND_EXPR assignments. */
179 gimple_expand_vec_cond_exprs (void)
181 gimple_stmt_iterator gsi
;
183 hash_map
<tree
, unsigned int> vec_cond_ssa_name_uses
;
184 auto_bitmap dce_ssa_names
;
186 FOR_EACH_BB_FN (bb
, cfun
)
188 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
190 gimple
*g
= gimple_expand_vec_cond_expr (&gsi
,
191 &vec_cond_ssa_name_uses
);
194 tree lhs
= gimple_assign_lhs (gsi_stmt (gsi
));
195 gimple_set_lhs (g
, lhs
);
196 gsi_replace (&gsi
, g
, false);
201 for (hash_map
<tree
, unsigned int>::iterator it
= vec_cond_ssa_name_uses
.begin ();
202 it
!= vec_cond_ssa_name_uses
.end (); ++it
)
203 bitmap_set_bit (dce_ssa_names
, SSA_NAME_VERSION ((*it
).first
));
205 simple_dce_from_worklist (dce_ssa_names
);
212 const pass_data pass_data_gimple_isel
=
214 GIMPLE_PASS
, /* type */
216 OPTGROUP_VEC
, /* optinfo_flags */
218 PROP_cfg
, /* properties_required */
219 0, /* properties_provided */
220 0, /* properties_destroyed */
221 0, /* todo_flags_start */
222 TODO_update_ssa
, /* todo_flags_finish */
225 class pass_gimple_isel
: public gimple_opt_pass
228 pass_gimple_isel (gcc::context
*ctxt
)
229 : gimple_opt_pass (pass_data_gimple_isel
, ctxt
)
232 /* opt_pass methods: */
233 virtual bool gate (function
*)
238 virtual unsigned int execute (function
*)
240 return gimple_expand_vec_cond_exprs ();
243 }; // class pass_gimple_isel
248 make_pass_gimple_isel (gcc::context
*ctxt
)
250 return new pass_gimple_isel (ctxt
);