PR rtl-optimization/82913
[official-gcc.git] / gcc / c-family / c-cilkplus.c
bloba537193798d231c4f55fd04e9202ee0eef217f30
1 /* This file contains routines to construct and validate Cilk Plus
2 constructs within the C and C++ front ends.
4 Copyright (C) 2013-2017 Free Software Foundation, Inc.
5 Contributed by Aldy Hernandez <aldyh@redhat.com>.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 GCC is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "c-common.h"
28 /* Validate the body of a _Cilk_for construct or a <#pragma simd> for
29 loop.
31 Returns true if there were no errors, false otherwise. */
33 bool
34 c_check_cilk_loop (location_t loc, tree decl)
36 if (TREE_THIS_VOLATILE (decl))
38 error_at (loc, "iteration variable cannot be volatile");
39 return false;
41 return true;
44 /* Calculate number of iterations of CILK_FOR. */
46 tree
47 cilk_for_number_of_iterations (tree cilk_for)
49 tree t, v, n1, n2, step, type, init, cond, incr, itype;
50 enum tree_code cond_code;
51 location_t loc = EXPR_LOCATION (cilk_for);
53 init = TREE_VEC_ELT (OMP_FOR_INIT (cilk_for), 0);
54 v = TREE_OPERAND (init, 0);
55 cond = TREE_VEC_ELT (OMP_FOR_COND (cilk_for), 0);
56 incr = TREE_VEC_ELT (OMP_FOR_INCR (cilk_for), 0);
57 type = TREE_TYPE (v);
59 gcc_assert (TREE_CODE (TREE_TYPE (v)) == INTEGER_TYPE
60 || TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE);
61 n1 = TREE_OPERAND (init, 1);
62 cond_code = TREE_CODE (cond);
63 n2 = TREE_OPERAND (cond, 1);
64 switch (cond_code)
66 case LT_EXPR:
67 case GT_EXPR:
68 case NE_EXPR:
69 break;
70 case LE_EXPR:
71 if (POINTER_TYPE_P (TREE_TYPE (n2)))
72 n2 = fold_build_pointer_plus_hwi_loc (loc, n2, 1);
73 else
74 n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (n2), n2,
75 build_int_cst (TREE_TYPE (n2), 1));
76 cond_code = LT_EXPR;
77 break;
78 case GE_EXPR:
79 if (POINTER_TYPE_P (TREE_TYPE (n2)))
80 n2 = fold_build_pointer_plus_hwi_loc (loc, n2, -1);
81 else
82 n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (n2), n2,
83 build_int_cst (TREE_TYPE (n2), 1));
84 cond_code = GT_EXPR;
85 break;
86 default:
87 gcc_unreachable ();
90 step = NULL_TREE;
91 switch (TREE_CODE (incr))
93 case PREINCREMENT_EXPR:
94 case POSTINCREMENT_EXPR:
95 step = build_int_cst (TREE_TYPE (v), 1);
96 break;
97 case PREDECREMENT_EXPR:
98 case POSTDECREMENT_EXPR:
99 step = build_int_cst (TREE_TYPE (v), -1);
100 break;
101 case MODIFY_EXPR:
102 t = TREE_OPERAND (incr, 1);
103 gcc_assert (TREE_OPERAND (t, 0) == v);
104 switch (TREE_CODE (t))
106 case PLUS_EXPR:
107 step = TREE_OPERAND (t, 1);
108 break;
109 case POINTER_PLUS_EXPR:
110 step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
111 break;
112 case MINUS_EXPR:
113 step = TREE_OPERAND (t, 1);
114 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
115 break;
116 default:
117 gcc_unreachable ();
119 break;
120 default:
121 gcc_unreachable ();
124 itype = type;
125 if (POINTER_TYPE_P (itype))
126 itype = signed_type_for (itype);
127 if (cond_code == NE_EXPR)
129 /* For NE_EXPR, we need to find out if the iterator increases
130 or decreases from whether step is positive or negative. */
131 tree stype = itype;
132 if (TYPE_UNSIGNED (stype))
133 stype = signed_type_for (stype);
134 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node,
135 fold_convert_loc (loc, stype, step),
136 build_int_cst (stype, 0));
137 t = fold_build3_loc (loc, COND_EXPR, itype, cond,
138 build_int_cst (itype, -1),
139 build_int_cst (itype, 1));
141 else
142 t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
143 t = fold_build2_loc (loc, PLUS_EXPR, itype,
144 fold_convert_loc (loc, itype, step), t);
145 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
146 fold_convert_loc (loc, itype, n2));
147 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
148 fold_convert_loc (loc, itype, n1));
149 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
150 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
151 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
152 fold_build1_loc (loc, NEGATE_EXPR, itype,
153 fold_convert_loc (loc, itype,
154 step)));
155 else if (TYPE_UNSIGNED (itype) && cond_code == NE_EXPR)
157 tree t1
158 = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
159 fold_convert_loc (loc, itype, step));
160 tree t2
161 = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
162 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
163 fold_build1_loc (loc, NEGATE_EXPR, itype,
164 fold_convert_loc (loc, itype,
165 step)));
166 t = fold_build3_loc (loc, COND_EXPR, itype, cond, t1, t2);
168 else
169 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
170 fold_convert_loc (loc, itype, step));
171 cond = fold_build2_loc (loc, cond_code, boolean_type_node, n1, n2);
172 t = fold_build3_loc (loc, COND_EXPR, itype, cond, t,
173 build_int_cst (itype, 0));
174 return t;