Integrate GUPC into cc1.
[official-gcc.git] / gcc / c-family / c-upc-pts-packed.c
blobcbba6750cf97437e708213fda5e52ec4d92d4c6b
1 /* c-upc-pts-packed.c: implement UPC packed pointer-to-shared representation
2 Copyright (C) 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc.
4 Contributed by Gary Funck <gary@intrepid.com>
5 and Nenad Vukicevic <nenad@intrepid.com>.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify
10 it 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,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU 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 "tree.h"
27 #include "stringpool.h"
28 #include "ggc.h"
29 #include "hashtab.h"
30 #include "input.h"
31 #include "langhooks.h"
32 #include "flags.h"
33 #include "opts.h"
34 #include "options.h"
35 #include "output.h"
36 #include "toplev.h"
37 #include "tm.h"
38 #include "function.h"
39 #include "stor-layout.h"
40 #include "varasm.h"
41 #include "target.h"
42 #include "cgraph.h"
43 #include "c-common.h"
44 #include "c-pragma.h"
45 #include "c-upc.h"
46 #include "c-upc-gasp.h"
47 #include "c-upc-pts.h"
48 #include "c-upc-pts-ops.h"
49 #include "c-upc-rts-names.h"
51 static tree upc_pts_packed_build_addrfield (location_t, tree);
52 static tree upc_pts_packed_build_cond_expr (location_t, tree);
53 static tree upc_pts_packed_build_constant (location_t, tree);
54 static tree upc_pts_packed_build_cvt (location_t, tree);
55 static tree upc_pts_packed_build_diff (location_t, tree);
56 static tree upc_pts_packed_build_phaseof (location_t, tree);
57 static tree upc_pts_packed_build_sum (location_t, tree);
58 static tree upc_pts_packed_build_threadof (location_t, tree);
59 static tree upc_pts_packed_build_value (location_t, tree, tree, tree, tree);
60 static void upc_pts_packed_init_type (void);
61 static int upc_pts_packed_is_null_p (tree);
63 const upc_pts_ops_t upc_pts_packed_ops =
65 upc_pts_packed_build_value,
66 upc_pts_packed_build_cond_expr,
67 upc_pts_packed_build_constant,
68 upc_pts_packed_build_cvt,
69 upc_pts_packed_build_diff,
70 upc_pts_packed_init_type,
71 upc_pts_packed_is_null_p,
72 upc_pts_packed_build_sum,
73 upc_pts_packed_build_threadof
76 /* Build the internal representation of UPC's packed
77 pointer-to-shared type. */
79 static void
80 upc_pts_packed_init_type (void)
82 tree shared_void_type, shared_char_type;
83 upc_pts_rep_type_node = c_common_type_for_size (UPC_PTS_SIZE, 1);
84 gcc_assert (TYPE_MODE (upc_pts_rep_type_node) != BLKmode);
85 record_builtin_type (RID_SHARED, "upc_shared_ptr_t",
86 upc_pts_rep_type_node);
87 shared_void_type = c_build_qualified_type_1 (void_type_node,
88 TYPE_QUAL_SHARED, NULL_TREE);
89 upc_pts_type_node = build_pointer_type (shared_void_type);
90 shared_char_type = c_build_qualified_type_1 (char_type_node,
91 TYPE_QUAL_SHARED,
92 size_zero_node);
93 upc_char_pts_type_node = build_pointer_type (shared_char_type);
94 upc_vaddr_mask_node =
95 build_int_cst (upc_pts_rep_type_node, UPC_PTS_VADDR_MASK);
96 upc_thread_mask_node =
97 build_int_cst (upc_pts_rep_type_node, UPC_PTS_THREAD_MASK);
98 upc_phase_mask_node =
99 build_int_cst (upc_pts_rep_type_node, UPC_PTS_PHASE_MASK);
100 upc_vaddr_shift_node =
101 build_int_cst (unsigned_type_node, UPC_PTS_VADDR_SHIFT);
102 upc_thread_shift_node =
103 build_int_cst (unsigned_type_node, UPC_PTS_THREAD_SHIFT);
104 upc_phase_shift_node =
105 build_int_cst (unsigned_type_node, UPC_PTS_PHASE_SHIFT);
106 upc_null_pts_node =
107 upc_pts_packed_build_value (UNKNOWN_LOCATION, upc_pts_type_node,
108 integer_zero_node, integer_zero_node,
109 integer_zero_node);
112 /* Called to expand a UPC specific constant into something the
113 backend can handle. Upon return a UPC pointer-to-shared will be
114 seen as the representation type of a UPC pointer-to-shared, with
115 individual (thread, phase, and virtual address) fields. */
117 static tree
118 upc_pts_packed_build_constant (location_t loc, tree c)
120 tree result = c;
121 if (upc_pts_is_valid_p (c))
123 const enum tree_code code = TREE_CODE (c);
124 if (!((code == VIEW_CONVERT_EXPR || code == NOP_EXPR)
125 && (TREE_TYPE (TREE_OPERAND (c, 0)) == upc_pts_rep_type_node)))
127 const tree val =
128 build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node,
129 save_expr (c));
130 const tree phase = upc_pts_packed_build_phaseof (loc, val);
131 const tree thread = upc_pts_packed_build_threadof (loc, val);
132 const tree vaddr = upc_pts_packed_build_addrfield (loc, val);
133 result =
134 upc_pts_packed_build_value (loc, TREE_TYPE (c), vaddr, thread,
135 phase);
138 return result;
141 /* Build a constructor of the form {phase, thread, vaddr}. */
143 static tree
144 upc_pts_packed_build_value (location_t loc, tree type, tree vaddr,
145 tree thread, tree phase)
147 tree result;
148 const tree upc_pts_rep_t = upc_pts_rep_type_node;
149 const int is_null = integer_zerop (phase)
150 && integer_zerop (thread) && integer_zerop (vaddr);
151 const int is_const = TREE_CONSTANT (phase)
152 && TREE_CONSTANT (thread) && TREE_CONSTANT (vaddr);
153 if (is_null)
155 result = fold_convert (upc_pts_rep_t, integer_zero_node);
157 else
159 vaddr = fold_convert (upc_pts_rep_t, vaddr);
160 result =
161 build_binary_op (loc, LSHIFT_EXPR, vaddr, upc_vaddr_shift_node, 0);
162 if (!integer_zerop (thread))
164 thread = fold_convert (upc_pts_rep_t, thread);
165 result = build_binary_op (loc, BIT_IOR_EXPR, result,
166 build_binary_op (loc, LSHIFT_EXPR,
167 thread,
168 upc_thread_shift_node,
169 0), 0);
171 if (!integer_zerop (phase))
173 phase = fold_convert (upc_pts_rep_t, phase);
174 result = build_binary_op (loc, BIT_IOR_EXPR, result,
175 build_binary_op (loc, LSHIFT_EXPR,
176 phase,
177 upc_phase_shift_node,
178 0), 0);
181 TREE_CONSTANT (result) = is_const;
182 /* Wrap the representation value into the specified
183 UPC pointer-to-shared type */
184 result = fold (build1 (VIEW_CONVERT_EXPR, type, result));
185 TREE_CONSTANT (result) = is_const;
186 return result;
189 /* Return TRUE if EXP is a null UPC pointer-to-shared. */
191 static int
192 upc_pts_packed_is_null_p (tree exp)
194 if (exp && upc_pts_is_valid_p (exp))
196 tree value;
197 for (value = exp;
198 TREE_CODE (value) == NOP_EXPR
199 || TREE_CODE (value) == CONVERT_EXPR
200 || TREE_CODE (value) == VIEW_CONVERT_EXPR
201 || TREE_CODE (value) == NON_LVALUE_EXPR;
202 value = TREE_OPERAND (value, 0)) /* loop */ ;
203 if ((TREE_TYPE (value) == upc_pts_rep_type_node)
204 && TREE_CONSTANT (value))
205 return integer_zerop (value);
207 return 0;
210 /* Given EXP, whose type must be the UPC pointer-to-shared
211 representation type, isolate the virtual address field,
212 and return it. Caller must insure that EXP is a
213 stable reference, if required. */
215 static tree
216 upc_pts_packed_build_addrfield (location_t loc, tree exp)
218 tree vaddr;
219 gcc_assert (TREE_TYPE (exp) == upc_pts_rep_type_node);
220 vaddr = build_binary_op (loc, BIT_AND_EXPR,
221 build_binary_op (loc, RSHIFT_EXPR, exp,
222 upc_vaddr_shift_node, 0),
223 upc_vaddr_mask_node, 0);
224 vaddr = fold_convert (sizetype, vaddr);
225 return vaddr;
228 /* Given, EXP, whose type must be the UPC pointer-to-shared
229 representation type, isolate the thread field,
230 and return it. Caller must insure that EXP is a
231 stable reference, if required. */
233 static tree
234 upc_pts_packed_build_threadof (location_t loc, tree exp)
236 tree affinity;
237 gcc_assert (TREE_TYPE (exp) == upc_pts_rep_type_node);
238 affinity = build_binary_op (loc, BIT_AND_EXPR,
239 build_binary_op (loc, RSHIFT_EXPR, exp,
240 upc_thread_shift_node, 0),
241 upc_thread_mask_node, 0);
242 affinity = fold_convert (sizetype, affinity);
243 return affinity;
246 /* Given, EXP, whose type must be the UPC pointer-to-shared
247 representation type, isolate the phase field,
248 and return it. Caller must insure that EXP is a
249 stable reference, if required. */
251 static tree
252 upc_pts_packed_build_phaseof (location_t loc, tree exp)
254 tree phase;
255 gcc_assert (TREE_TYPE (exp) == upc_pts_rep_type_node);
256 phase = build_binary_op (loc, BIT_AND_EXPR,
257 build_binary_op (loc, RSHIFT_EXPR, exp,
258 upc_phase_shift_node, 0),
259 upc_phase_mask_node, 0);
260 phase = fold_convert (sizetype, phase);
261 return phase;
264 /* Rewrite EXP, an expression involving addition of an
265 integer to a UPC pointer-to-shared, into representation-specific
266 lower level operations. */
268 static tree
269 upc_pts_packed_build_sum (location_t loc, tree exp)
271 const tree op0 = TREE_OPERAND (exp, 0);
272 const tree op1 = TREE_OPERAND (exp, 1);
273 const enum tree_code op0_code = TREE_CODE (TREE_TYPE (op0));
274 const tree targ_type = TREE_TYPE (TREE_TYPE (exp));
275 const tree ptrop = (op0_code == POINTER_TYPE) ? op0 : op1;
276 const tree intop = (op0_code == POINTER_TYPE) ? op1 : op0;
277 tree result;
279 if (integer_zerop (intop))
281 result = ptrop;
283 else
285 const tree ptrop_as_pts_rep = fold (build1 (VIEW_CONVERT_EXPR,
286 upc_pts_rep_type_node,
287 ptrop));
288 const tree sptrop = save_expr (ptrop_as_pts_rep);
289 const tree elem_type = strip_array_types (targ_type);
290 const tree elem_size = !VOID_TYPE_P (elem_type)
291 ? size_in_bytes (elem_type) : integer_one_node;
292 const tree block_factor = upc_get_block_factor (elem_type);
293 const int has_phase = !(integer_zerop (block_factor)
294 || integer_onep (block_factor));
295 const tree old_vaddr = upc_pts_packed_build_addrfield (loc, sptrop);
296 const tree index = save_expr (intop);
297 tree phase, thread, vaddr;
298 if (VOID_TYPE_P (targ_type) || integer_zerop (block_factor))
300 /* vaddr = old_vaddr + index * elem_size */
301 vaddr = build_binary_op (loc, PLUS_EXPR, old_vaddr,
302 build_binary_op (loc, MULT_EXPR,
303 index, elem_size, 0),
305 thread = upc_pts_packed_build_threadof (loc, sptrop);
306 phase = integer_zero_node;
308 else
310 const tree old_thread =
311 upc_pts_packed_build_threadof (loc, sptrop);
312 const tree thread_cnt = save_expr (upc_num_threads ());
313 /* n_threads must be a signed type, for various calculations
314 to work properly, below. */
315 const tree n_threads = !TYPE_UNSIGNED (TREE_TYPE (thread_cnt))
316 ? thread_cnt : convert (integer_type_node, thread_cnt);
317 tree tincr, t1, t2;
318 if (has_phase)
320 const tree elem_per_block = block_factor;
321 const tree old_phase =
322 upc_pts_packed_build_phaseof (loc, sptrop);
323 tree nt_elems, phase_diff;
324 /* tincr = old_thread * elem_per_block + old_phase + index; */
325 tincr = build_binary_op (loc, PLUS_EXPR,
326 build_binary_op (loc, PLUS_EXPR,
327 build_binary_op
328 (loc, MULT_EXPR,
329 old_thread,
330 elem_per_block, 0),
331 old_phase, 0),
332 index, 0);
333 tincr = save_expr (tincr);
334 /* nt_elems = n_threads * elem_per_block; */
335 nt_elems = build_binary_op (loc, MULT_EXPR, n_threads,
336 elem_per_block, 0);
337 nt_elems = save_expr (nt_elems);
338 /* Calculate floor_divmod (tincr, nt_elems, &t1, &t2);
339 n_elems and tincr must be a signed type, to ensure
340 that FLOOR_DIV and FLOOR_MOD work as expected. */
341 if (TYPE_UNSIGNED (TREE_TYPE (tincr)))
342 tincr = convert (integer_type_node, tincr);
343 if (TYPE_UNSIGNED (TREE_TYPE (nt_elems)))
344 nt_elems = convert (integer_type_node, nt_elems);
345 t1 =
346 build_binary_op (loc, FLOOR_DIV_EXPR, tincr, nt_elems, 0);
347 t2 =
348 build_binary_op (loc, FLOOR_MOD_EXPR, tincr, nt_elems, 0);
349 t2 = save_expr (t2);
350 /* thread = t2 / elem_per_block; */
351 thread = build_binary_op (loc, TRUNC_DIV_EXPR,
352 t2, elem_per_block, 0);
353 /* phase = t2 % elem_per_block; */
354 phase = build_binary_op (loc, TRUNC_MOD_EXPR,
355 t2, elem_per_block, 0);
356 phase_diff = build_binary_op (loc, MINUS_EXPR,
357 phase, old_phase, 0);
358 /* vaddr = old_vaddr + (t1 * elem_per_block + phase_diff)
359 * * elem_size; */
360 vaddr = build_binary_op (loc, PLUS_EXPR,
361 old_vaddr,
362 build_binary_op (loc, MULT_EXPR,
363 build_binary_op (loc, PLUS_EXPR,
364 build_binary_op (loc, MULT_EXPR,
365 t1, elem_per_block, 0),
366 phase_diff, 0),
367 elem_size, 0), 0);
369 else
371 /* tincr = old_thread + index; */
372 tincr =
373 build_binary_op (loc, PLUS_EXPR, old_thread, index, 0);
374 tincr = save_expr (tincr);
375 /* floor_divmod (tincr, n_threads, &t1, &t2); */
376 if (TYPE_UNSIGNED (TREE_TYPE (tincr)))
377 tincr = convert (integer_type_node, tincr);
378 t1 =
379 build_binary_op (loc, FLOOR_DIV_EXPR, tincr, n_threads, 0);
380 t2 =
381 build_binary_op (loc, FLOOR_MOD_EXPR, tincr, n_threads, 0);
382 /* vaddr = old_vaddr + t1 * elem_size; */
383 vaddr = build_binary_op (loc, PLUS_EXPR, old_vaddr,
384 build_binary_op (loc, MULT_EXPR,
385 t1, elem_size, 0),
387 /* thread = t2; */
388 thread = t2;
389 phase = integer_zero_node;
392 result = upc_pts_packed_build_value (loc, TREE_TYPE (exp),
393 vaddr, thread, phase);
395 return result;
398 /* Expand the expression EXP, which calculates the difference
399 between two UPC pointers-to-shared. */
401 static tree
402 upc_pts_packed_build_diff (location_t loc, tree exp)
404 tree op0 = TREE_OPERAND (exp, 0);
405 tree op1 = TREE_OPERAND (exp, 1);
406 const tree result_type = ptrdiff_type_node;
407 const tree target_type = TREE_TYPE (TREE_TYPE (op0));
408 const tree n_threads = upc_num_threads ();
409 const tree elem_size = convert (ssizetype, size_in_bytes (target_type));
410 const tree block_factor = upc_get_block_factor (target_type);
411 tree thread0, thread1, thread_diff;
412 tree phase_diff;
413 tree off0, off1, offset_diff, elem_diff;
414 tree result;
416 /* The two pointers must both point to UPC shared objects, and we
417 have to perform the reverse of addition on UPC pointers-to-shared */
419 if ((upc_shared_type_p (target_type)
420 && !upc_shared_type_p (TREE_TYPE (TREE_TYPE (op1))))
421 || (upc_shared_type_p (TREE_TYPE (TREE_TYPE (op1)))
422 && !upc_shared_type_p (target_type)))
424 error ("attempt to take the difference of a UPC pointer-to-shared "
425 "and a local pointer");
426 return error_mark_node;
428 op0 = save_expr (op0);
429 op1 = save_expr (op1);
430 op0 = build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node, op0);
431 op1 = build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node, op1);
432 off0 = upc_pts_packed_build_addrfield (loc, op0);
433 off1 = upc_pts_packed_build_addrfield (loc, op1);
434 /* Convert offset fields into ptrdiff_t types so that the
435 result of the difference comes out as a signed type. */
436 off0 = convert (result_type, off0);
437 off1 = convert (result_type, off1);
438 offset_diff = build_binary_op (loc, MINUS_EXPR, off0, off1, 0);
439 elem_diff = build_binary_op (loc, EXACT_DIV_EXPR,
440 offset_diff, elem_size, 0);
441 if (integer_zerop (block_factor))
443 return elem_diff;
445 thread0 = convert (ssizetype, upc_pts_packed_build_threadof (loc, op0));
446 thread1 = convert (ssizetype, upc_pts_packed_build_threadof (loc, op1));
447 thread_diff = build_binary_op (loc, MINUS_EXPR, thread0, thread1, 0);
448 phase_diff = integer_zero_node;
449 if (!tree_int_cst_equal (block_factor, integer_one_node))
451 tree phase0 =
452 convert (ssizetype, upc_pts_packed_build_phaseof (loc, op0));
453 tree phase1 =
454 convert (ssizetype, upc_pts_packed_build_phaseof (loc, op1));
455 phase_diff =
456 save_expr (build_binary_op (loc, MINUS_EXPR, phase0, phase1, 0));
458 /* The expression below calculates the following:
459 (elem_diff - phase_diff) * THREADS
460 + (thread_diff * block_factor) + phase_diff; */
461 result = build_binary_op (loc, PLUS_EXPR,
462 build_binary_op (loc, PLUS_EXPR,
463 build_binary_op (loc, MULT_EXPR,
464 build_binary_op (loc, MINUS_EXPR,
465 elem_diff,
466 phase_diff, 0),
467 n_threads, 0),
468 build_binary_op (loc, MULT_EXPR,
469 thread_diff,
470 block_factor, 0), 0),
471 phase_diff, 0);
472 result = fold_convert (result_type, result);
473 return result;
476 /* Handle conversions between UPC pointers-to-shared and
477 local pointers, or between UPC pointers-to-shared which
478 have differing block factors. */
480 static tree
481 upc_pts_packed_build_cvt (location_t loc, tree exp)
483 const tree type = TREE_TYPE (exp);
484 const tree ptr = TREE_OPERAND (exp, 0);
485 tree tt1, tt2, b1, b2;
486 tree result = exp;
487 tt1 = TREE_TYPE (TREE_TYPE (exp));
488 tt2 = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
489 b1 = upc_get_block_factor (tt1);
490 b2 = upc_get_block_factor (tt2);
491 if (upc_shared_type_p (tt1) != upc_shared_type_p (tt2))
493 if (upc_shared_type_p (tt1))
495 /* Error: local -> shared */
496 result = error_mark_node;
498 else
500 /* shared -> local */
501 int doprofcall = flag_upc_debug
502 || (flag_upc_instrument && get_upc_pupc_mode ());
503 const char *libfunc_name =
504 doprofcall ? UPC_GETADDRG_LIBCALL : UPC_GETADDR_LIBCALL;
505 tree src = build1 (NOP_EXPR, upc_pts_rep_type_node,
506 TREE_OPERAND (exp, 0));
507 tree libfunc, lib_args, lib_call;
508 libfunc = identifier_global_value (get_identifier (libfunc_name));
509 if (!libfunc)
510 internal_error ("library function %s not found", libfunc_name);
511 lib_args = tree_cons (NULL_TREE, src, NULL_TREE);
512 if (doprofcall)
513 lib_args =
514 upc_gasp_add_src_args (lib_args,
515 LOCATION_FILE (input_location),
516 LOCATION_LINE (input_location));
517 lib_call = build_function_call (loc, libfunc, lib_args);
518 result = build1 (VIEW_CONVERT_EXPR, type, lib_call);
521 else if ((upc_shared_type_p (tt1) && !VOID_TYPE_P (tt1))
522 && !(integer_zerop (b1) && integer_zerop (b2)))
524 /* Below, we handle the case of conversions to non-generic
525 shared types. */
526 tree s1 = TYPE_SIZE (tt1);
527 tree s2 = TYPE_SIZE (tt2);
528 /* normalize block sizes, so that [0] => NULL */
529 if (integer_zerop (b1))
530 b1 = NULL;
531 if (integer_zerop (b2))
532 b2 = NULL;
533 /* normalize type size so that 0 => NULL */
534 if (s1 && integer_zerop (s1))
535 s1 = NULL;
536 if (s2 && integer_zerop (s2))
537 s2 = NULL;
538 /* If the source type is an array type, then bypass
539 the check for equal type sizes. This arises when
540 an array is implicitly converted to a pointer to
541 the element type. */
542 if ((TREE_CODE (tt1) != ARRAY_TYPE)
543 && (TREE_CODE (tt2) == ARRAY_TYPE))
545 const tree elem_type1 = strip_array_types (tt1);
546 const tree elem_type2 = strip_array_types (tt2);
547 if (TYPE_MAIN_VARIANT (elem_type1)
548 == TYPE_MAIN_VARIANT (elem_type2))
549 s2 = s1;
551 /* If the source type is a not a generic pointer to shared, and
552 either its block size or type size differs from the target,
553 then the result must have zero phase. If the source type is
554 a generic pointer to shared and the target type is a pointer
555 to a shared type with either an indefinite block size, or
556 a block size of one, then the resulting value must have a
557 phase of zero. */
558 if ((!VOID_TYPE_P (tt2)
559 && !(tree_int_cst_equal (b1, b2)
560 && tree_int_cst_equal (s1, s2)))
561 || (VOID_TYPE_P (tt2)
562 && ((b1 == NULL)
563 || tree_int_cst_equal (b1, integer_one_node))))
565 const tree ptr_as_pts_rep = fold (build1 (VIEW_CONVERT_EXPR,
566 upc_pts_rep_type_node,
567 ptr));
568 const tree sptr = save_expr (ptr_as_pts_rep);
569 const tree ptr_with_zero_phase =
570 upc_pts_packed_build_value (loc, type,
571 upc_pts_packed_build_addrfield (loc, sptr),
572 upc_pts_packed_build_threadof (loc, sptr),
573 integer_zero_node);
574 result = ptr_with_zero_phase;
577 else if (upc_shared_type_p (tt1) && VOID_TYPE_P (tt1))
579 /* If the target is a generic pointer-to-shared type, we can
580 safely use the source value directly. */
582 else
583 gcc_assert (TREE_CODE (type) != CONVERT_EXPR);
584 return result;
587 /* Expand the expression EXP, which is a comparison between two
588 UPC pointers-to-shared.
590 Per 6.4.2p6:
591 Two compatible pointers-to-shared which point to the same object
592 (i.e. having the same address and thread components) shall compare
593 as equal according to == and !=, regardless of whether the phase
594 components match.
596 When a UPC pointer-to-shared is represented as (vaddr, thread, phase)
597 and the underlying pointer component types have a block size <=1,
598 we can use a straight unsigned integer comparison of the
599 representation types. Otherwise, if vaddr comes
600 last, then the straight bit-wise comparison works only for equality.
602 For the equality operation when the block size is greater than 1,
603 the phase field is first masked off. */
604 static tree
605 upc_pts_packed_build_cond_expr (location_t loc, tree exp)
607 tree result;
608 const enum tree_code code = TREE_CODE (exp);
609 tree op0 = TREE_OPERAND (exp, 0);
610 tree op1 = TREE_OPERAND (exp, 1);
611 const tree type0 = TREE_TYPE (op0);
612 const tree type1 = TREE_TYPE (op1);
613 gcc_assert (POINTER_TYPE_P (type0));
614 gcc_assert (POINTER_TYPE_P (type1));
616 const tree ttype0 = TREE_TYPE (type0);
617 const tree ttype1 = TREE_TYPE (type1);
618 const enum tree_code ttcode0 = TREE_CODE (ttype0);
619 const enum tree_code ttcode1 = TREE_CODE (ttype1);
620 const tree elem_type0 = strip_array_types (ttype0);
621 const tree elem_type1 = strip_array_types (ttype1);
622 gcc_assert (TREE_SHARED (elem_type0));
623 gcc_assert (TREE_SHARED (elem_type1));
625 const tree bs0 = upc_get_block_factor (elem_type0);
626 const tree bs1 = upc_get_block_factor (elem_type1);
627 const int has_phase0 = !(integer_zerop (bs0) || integer_onep (bs0));
628 const int has_phase1 = !(integer_zerop (bs1) || integer_onep (bs1));
629 const int has_phase = has_phase0 || has_phase1;
630 const int is_eq_op = (code == EQ_EXPR || code == NE_EXPR);
631 const int is_bitwise_cmp = is_eq_op
632 || (!has_phase && UPC_PTS_VADDR_FIRST);
633 if (is_bitwise_cmp)
635 if (ttcode0 == VIEW_CONVERT_EXPR
636 && TREE_TYPE (TREE_OPERAND (op0, 0)) == upc_pts_rep_type_node)
637 op0 = TREE_OPERAND (op0, 0);
638 else
639 op0 = build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node, op0);
640 if (ttcode1 == VIEW_CONVERT_EXPR
641 && TREE_TYPE (TREE_OPERAND (op1, 0)) == upc_pts_rep_type_node)
642 op1 = TREE_OPERAND (op1, 0);
643 else
644 op1 = build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node, op1);
645 if (is_eq_op && has_phase)
647 /* Mask off the phase value. */
648 tree phase_mask =
649 fold_build1_loc (loc, BIT_NOT_EXPR, upc_pts_rep_type_node,
650 build_binary_op (loc, LSHIFT_EXPR,
651 upc_phase_mask_node,
652 upc_phase_shift_node, 0));
653 op0 = build_binary_op (loc, BIT_AND_EXPR, op0, phase_mask, 0);
654 op1 = build_binary_op (loc, BIT_AND_EXPR, op1, phase_mask, 0);
657 else
659 const tree ptr_diff = build_binary_op (loc, MINUS_EXPR,
660 op0, op1, 0);
661 op0 = ptr_diff;
662 op1 = build_int_cst (TREE_TYPE (op0), 0);
664 TREE_OPERAND (exp, 0) = op0;
665 TREE_OPERAND (exp, 1) = op1;
666 result = exp;
669 return result;