gcc/upc/
[official-gcc.git] / gcc / upc / upc-pts-packed.c
blobc28d78d6de23d777321c740f3cfdaf22b7a74071
1 /* 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 "coretypes.h"
25 #include "system.h"
26 #include "tree.h"
27 #include "ggc.h"
28 #include "hashtab.h"
29 #include "input.h"
30 #include "langhooks.h"
31 #include "flags.h"
32 #include "opts.h"
33 #include "options.h"
34 #include "output.h"
35 #include "toplev.h"
36 #include "tm.h"
37 #include "function.h"
38 #include "target.h"
39 #include "upc-act.h"
40 #include "upc-gasp.h"
41 #include "upc-pts.h"
42 #include "upc-rts-names.h"
43 #include "cgraph.h"
44 #include "c-family/c-common.h"
45 #include "c-family/c-pragma.h"
46 #include "c-family/c-upc.h"
47 /* define decl_default_tls_model() prototype */
48 #include "rtl.h"
50 static tree upc_pts_packed_build_addrfield (location_t, tree);
51 static tree upc_pts_packed_build_cond_expr (location_t, tree);
52 static tree upc_pts_packed_build_constant (location_t, tree);
53 static tree upc_pts_packed_build_cvt (location_t, tree);
54 static tree upc_pts_packed_build_diff (location_t, tree);
55 static tree upc_pts_packed_build_phaseof (location_t, tree);
56 static tree upc_pts_packed_build_sum (location_t, tree);
57 static tree upc_pts_packed_build_threadof (location_t, tree);
58 static tree upc_pts_packed_build_value (location_t, tree, tree, tree, tree);
59 static void upc_pts_packed_init_type (void);
60 static int upc_pts_packed_is_null_p (tree);
62 const upc_pts_ops_t upc_pts_packed_ops =
64 upc_pts_packed_build_value,
65 upc_pts_packed_build_cond_expr,
66 upc_pts_packed_build_constant,
67 upc_pts_packed_build_cvt,
68 upc_pts_packed_build_diff,
69 upc_pts_packed_init_type,
70 upc_pts_packed_is_null_p,
71 upc_pts_packed_build_sum,
72 upc_pts_packed_build_threadof
75 /* Build the internal representation of UPC's packed
76 pointer-to-shared type. */
78 static void
79 upc_pts_packed_init_type (void)
81 tree shared_void_type, shared_char_type;
82 upc_pts_rep_type_node = c_common_type_for_size (UPC_PTS_SIZE, 1);
83 gcc_assert (TYPE_MODE (upc_pts_rep_type_node) != BLKmode);
84 record_builtin_type (RID_SHARED, "upc_shared_ptr_t",
85 upc_pts_rep_type_node);
86 shared_void_type = c_build_qualified_type_1 (void_type_node,
87 TYPE_QUAL_SHARED, NULL_TREE);
88 upc_pts_type_node = build_pointer_type (shared_void_type);
89 shared_char_type = c_build_qualified_type_1 (char_type_node,
90 TYPE_QUAL_SHARED,
91 size_zero_node);
92 upc_char_pts_type_node = build_pointer_type (shared_char_type);
93 upc_vaddr_mask_node =
94 build_int_cst (upc_pts_rep_type_node, UPC_PTS_VADDR_MASK);
95 upc_thread_mask_node =
96 build_int_cst (upc_pts_rep_type_node, UPC_PTS_THREAD_MASK);
97 upc_phase_mask_node =
98 build_int_cst (upc_pts_rep_type_node, UPC_PTS_PHASE_MASK);
99 upc_vaddr_shift_node =
100 build_int_cst (unsigned_type_node, UPC_PTS_VADDR_SHIFT);
101 upc_thread_shift_node =
102 build_int_cst (unsigned_type_node, UPC_PTS_THREAD_SHIFT);
103 upc_phase_shift_node =
104 build_int_cst (unsigned_type_node, UPC_PTS_PHASE_SHIFT);
105 upc_null_pts_node =
106 upc_pts_packed_build_value (UNKNOWN_LOCATION, upc_pts_type_node,
107 integer_zero_node, integer_zero_node,
108 integer_zero_node);
111 /* Called to expand a UPC specific constant into something the
112 backend can handle. Upon return a UPC pointer-to-shared will be
113 seen as the representation type of a UPC pointer-to-shared, with
114 individual (thread, phase, and virtual address) fields. */
116 static tree
117 upc_pts_packed_build_constant (location_t loc, tree c)
119 tree result = c;
120 if (upc_pts_is_valid_p (c))
122 const enum tree_code code = TREE_CODE (c);
123 if (!((code == VIEW_CONVERT_EXPR || code == NOP_EXPR)
124 && (TREE_TYPE (TREE_OPERAND (c, 0)) == upc_pts_rep_type_node)))
126 const tree val =
127 build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node,
128 save_expr (c));
129 const tree phase = upc_pts_packed_build_phaseof (loc, val);
130 const tree thread = upc_pts_packed_build_threadof (loc, val);
131 const tree vaddr = upc_pts_packed_build_addrfield (loc, val);
132 result =
133 upc_pts_packed_build_value (loc, TREE_TYPE (c), vaddr, thread,
134 phase);
137 return result;
140 /* Build a constructor of the form {phase, thread, vaddr}. */
142 static tree
143 upc_pts_packed_build_value (location_t loc, tree type, tree vaddr,
144 tree thread, tree phase)
146 tree result;
147 const tree upc_pts_rep_t = upc_pts_rep_type_node;
148 const int is_null = integer_zerop (phase)
149 && integer_zerop (thread) && integer_zerop (vaddr);
150 const int is_const = TREE_CONSTANT (phase)
151 && TREE_CONSTANT (thread) && TREE_CONSTANT (vaddr);
152 if (is_null)
154 result = fold_convert (upc_pts_rep_t, integer_zero_node);
156 else
158 vaddr = fold_convert (upc_pts_rep_t, vaddr);
159 result =
160 build_binary_op (loc, LSHIFT_EXPR, vaddr, upc_vaddr_shift_node, 0);
161 if (!integer_zerop (thread))
163 thread = fold_convert (upc_pts_rep_t, thread);
164 result = build_binary_op (loc, BIT_IOR_EXPR, result,
165 build_binary_op (loc, LSHIFT_EXPR,
166 thread,
167 upc_thread_shift_node,
168 0), 0);
170 if (!integer_zerop (phase))
172 phase = fold_convert (upc_pts_rep_t, phase);
173 result = build_binary_op (loc, BIT_IOR_EXPR, result,
174 build_binary_op (loc, LSHIFT_EXPR,
175 phase,
176 upc_phase_shift_node,
177 0), 0);
180 TREE_CONSTANT (result) = is_const;
181 /* Wrap the representation value into the specified
182 UPC pointer-to-shared type */
183 result = fold (build1 (VIEW_CONVERT_EXPR, type, result));
184 TREE_CONSTANT (result) = is_const;
185 return result;
188 /* Return TRUE if EXP is a null UPC pointer-to-shared. */
190 static int
191 upc_pts_packed_is_null_p (tree exp)
193 if (exp && upc_pts_is_valid_p (exp))
195 tree value;
196 for (value = exp;
197 TREE_CODE (value) == NOP_EXPR
198 || TREE_CODE (value) == CONVERT_EXPR
199 || TREE_CODE (value) == VIEW_CONVERT_EXPR
200 || TREE_CODE (value) == NON_LVALUE_EXPR;
201 value = TREE_OPERAND (value, 0)) /* loop */ ;
202 if ((TREE_TYPE (value) == upc_pts_rep_type_node)
203 && TREE_CONSTANT (value))
204 return integer_zerop (value);
206 return 0;
209 /* Given EXP, whose type must be the UPC pointer-to-shared
210 representation type, isolate the virtual address field,
211 and return it. Caller must insure that EXP is a
212 stable reference, if required. */
214 static tree
215 upc_pts_packed_build_addrfield (location_t loc, tree exp)
217 tree vaddr;
218 gcc_assert (TREE_TYPE (exp) == upc_pts_rep_type_node);
219 vaddr = build_binary_op (loc, BIT_AND_EXPR,
220 build_binary_op (loc, RSHIFT_EXPR, exp,
221 upc_vaddr_shift_node, 0),
222 upc_vaddr_mask_node, 0);
223 vaddr = fold_convert (sizetype, vaddr);
224 return vaddr;
227 /* Given, EXP, whose type must be the UPC pointer-to-shared
228 representation type, isolate the thread field,
229 and return it. Caller must insure that EXP is a
230 stable reference, if required. */
232 static tree
233 upc_pts_packed_build_threadof (location_t loc, tree exp)
235 tree affinity;
236 gcc_assert (TREE_TYPE (exp) == upc_pts_rep_type_node);
237 affinity = build_binary_op (loc, BIT_AND_EXPR,
238 build_binary_op (loc, RSHIFT_EXPR, exp,
239 upc_thread_shift_node, 0),
240 upc_thread_mask_node, 0);
241 affinity = fold_convert (sizetype, affinity);
242 return affinity;
245 /* Given, EXP, whose type must be the UPC pointer-to-shared
246 representation type, isolate the phase field,
247 and return it. Caller must insure that EXP is a
248 stable reference, if required. */
250 static tree
251 upc_pts_packed_build_phaseof (location_t loc, tree exp)
253 tree phase;
254 gcc_assert (TREE_TYPE (exp) == upc_pts_rep_type_node);
255 phase = build_binary_op (loc, BIT_AND_EXPR,
256 build_binary_op (loc, RSHIFT_EXPR, exp,
257 upc_phase_shift_node, 0),
258 upc_phase_mask_node, 0);
259 phase = fold_convert (sizetype, phase);
260 return phase;
263 /* Rewrite EXP, an expression involving addition of an
264 integer to a UPC pointer-to-shared, into representation-specific
265 lower level operations. */
267 static tree
268 upc_pts_packed_build_sum (location_t loc, tree exp)
270 const tree op0 = TREE_OPERAND (exp, 0);
271 const tree op1 = TREE_OPERAND (exp, 1);
272 const enum tree_code op0_code = TREE_CODE (TREE_TYPE (op0));
273 const tree targ_type = TREE_TYPE (TREE_TYPE (exp));
274 const tree ptrop = (op0_code == POINTER_TYPE) ? op0 : op1;
275 const tree intop = (op0_code == POINTER_TYPE) ? op1 : op0;
276 tree result;
278 if (integer_zerop (intop))
280 result = ptrop;
282 else
284 const tree ptrop_as_pts_rep = fold (build1 (VIEW_CONVERT_EXPR,
285 upc_pts_rep_type_node,
286 ptrop));
287 const tree sptrop = save_expr (ptrop_as_pts_rep);
288 const tree elem_type = strip_array_types (targ_type);
289 const tree elem_size = !VOID_TYPE_P (elem_type)
290 ? size_in_bytes (elem_type) : integer_one_node;
291 const tree block_factor = upc_get_block_factor (elem_type);
292 const int has_phase = !(integer_zerop (block_factor)
293 || integer_onep (block_factor));
294 const tree old_vaddr = upc_pts_packed_build_addrfield (loc, sptrop);
295 const tree index = save_expr (intop);
296 tree phase, thread, vaddr;
297 if (VOID_TYPE_P (targ_type) || integer_zerop (block_factor))
299 /* vaddr = old_vaddr + index * elem_size */
300 vaddr = build_binary_op (loc, PLUS_EXPR, old_vaddr,
301 build_binary_op (loc, MULT_EXPR,
302 index, elem_size, 0),
304 thread = upc_pts_packed_build_threadof (loc, sptrop);
305 phase = integer_zero_node;
307 else
309 const tree old_thread =
310 upc_pts_packed_build_threadof (loc, sptrop);
311 const tree thread_cnt = save_expr (upc_num_threads ());
312 /* n_threads must be a signed type, for various calculations
313 to work properly, below. */
314 const tree n_threads = !TYPE_UNSIGNED (TREE_TYPE (thread_cnt))
315 ? thread_cnt : convert (integer_type_node, thread_cnt);
316 tree tincr, t1, t2;
317 if (has_phase)
319 const tree elem_per_block = block_factor;
320 const tree old_phase =
321 upc_pts_packed_build_phaseof (loc, sptrop);
322 tree nt_elems, phase_diff;
323 /* tincr = old_thread * elem_per_block + old_phase + index; */
324 tincr = build_binary_op (loc, PLUS_EXPR,
325 build_binary_op (loc, PLUS_EXPR,
326 build_binary_op
327 (loc, MULT_EXPR,
328 old_thread,
329 elem_per_block, 0),
330 old_phase, 0),
331 index, 0);
332 tincr = save_expr (tincr);
333 /* nt_elems = n_threads * elem_per_block; */
334 nt_elems = build_binary_op (loc, MULT_EXPR, n_threads,
335 elem_per_block, 0);
336 nt_elems = save_expr (nt_elems);
337 /* Calculate floor_divmod (tincr, nt_elems, &t1, &t2);
338 n_elems and tincr must be a signed type, to ensure
339 that FLOOR_DIV and FLOOR_MOD work as expected. */
340 if (TYPE_UNSIGNED (TREE_TYPE (tincr)))
341 tincr = convert (integer_type_node, tincr);
342 if (TYPE_UNSIGNED (TREE_TYPE (nt_elems)))
343 nt_elems = convert (integer_type_node, nt_elems);
344 t1 =
345 build_binary_op (loc, FLOOR_DIV_EXPR, tincr, nt_elems, 0);
346 t2 =
347 build_binary_op (loc, FLOOR_MOD_EXPR, tincr, nt_elems, 0);
348 t2 = save_expr (t2);
349 /* thread = t2 / elem_per_block; */
350 thread = build_binary_op (loc, TRUNC_DIV_EXPR,
351 t2, elem_per_block, 0);
352 /* phase = t2 % elem_per_block; */
353 phase = build_binary_op (loc, TRUNC_MOD_EXPR,
354 t2, elem_per_block, 0);
355 phase_diff = build_binary_op (loc, MINUS_EXPR,
356 phase, old_phase, 0);
357 /* vaddr = old_vaddr + (t1 * elem_per_block + phase_diff)
358 * * elem_size; */
359 vaddr = build_binary_op (loc, PLUS_EXPR,
360 old_vaddr,
361 build_binary_op (loc, MULT_EXPR,
362 build_binary_op (loc, PLUS_EXPR,
363 build_binary_op (loc, MULT_EXPR,
364 t1, elem_per_block, 0),
365 phase_diff, 0),
366 elem_size, 0), 0);
368 else
370 /* tincr = old_thread + index; */
371 tincr =
372 build_binary_op (loc, PLUS_EXPR, old_thread, index, 0);
373 tincr = save_expr (tincr);
374 /* floor_divmod (tincr, n_threads, &t1, &t2); */
375 if (TYPE_UNSIGNED (TREE_TYPE (tincr)))
376 tincr = convert (integer_type_node, tincr);
377 t1 =
378 build_binary_op (loc, FLOOR_DIV_EXPR, tincr, n_threads, 0);
379 t2 =
380 build_binary_op (loc, FLOOR_MOD_EXPR, tincr, n_threads, 0);
381 /* vaddr = old_vaddr + t1 * elem_size; */
382 vaddr = build_binary_op (loc, PLUS_EXPR, old_vaddr,
383 build_binary_op (loc, MULT_EXPR,
384 t1, elem_size, 0),
386 /* thread = t2; */
387 thread = t2;
388 phase = integer_zero_node;
391 result = upc_pts_packed_build_value (loc, TREE_TYPE (exp),
392 vaddr, thread, phase);
394 return result;
397 /* Expand the expression EXP, which calculates the difference
398 between two UPC pointers-to-shared. */
400 static tree
401 upc_pts_packed_build_diff (location_t loc, tree exp)
403 tree op0 = TREE_OPERAND (exp, 0);
404 tree op1 = TREE_OPERAND (exp, 1);
405 const tree result_type = ptrdiff_type_node;
406 const tree target_type = TREE_TYPE (TREE_TYPE (op0));
407 const tree n_threads = upc_num_threads ();
408 const tree elem_size = convert (ssizetype, size_in_bytes (target_type));
409 const tree block_factor = upc_get_block_factor (target_type);
410 tree thread0, thread1, thread_diff;
411 tree phase_diff;
412 tree off0, off1, offset_diff, elem_diff;
413 tree result;
415 /* The two pointers must both point to UPC shared objects, and we
416 have to perform the reverse of addition on UPC pointers-to-shared */
418 if ((upc_shared_type_p (target_type)
419 && !upc_shared_type_p (TREE_TYPE (TREE_TYPE (op1))))
420 || (upc_shared_type_p (TREE_TYPE (TREE_TYPE (op1)))
421 && !upc_shared_type_p (target_type)))
423 error ("attempt to take the difference of a UPC pointer-to-shared "
424 "and a local pointer");
425 return error_mark_node;
427 op0 = save_expr (op0);
428 op1 = save_expr (op1);
429 op0 = build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node, op0);
430 op1 = build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node, op1);
431 off0 = upc_pts_packed_build_addrfield (loc, op0);
432 off1 = upc_pts_packed_build_addrfield (loc, op1);
433 /* Convert offset fields into ptrdiff_t types so that the
434 result of the difference comes out as a signed type. */
435 off0 = convert (result_type, off0);
436 off1 = convert (result_type, off1);
437 offset_diff = build_binary_op (loc, MINUS_EXPR, off0, off1, 0);
438 elem_diff = build_binary_op (loc, EXACT_DIV_EXPR,
439 offset_diff, elem_size, 0);
440 if (integer_zerop (block_factor))
442 return elem_diff;
444 thread0 = convert (ssizetype, upc_pts_packed_build_threadof (loc, op0));
445 thread1 = convert (ssizetype, upc_pts_packed_build_threadof (loc, op1));
446 thread_diff = build_binary_op (loc, MINUS_EXPR, thread0, thread1, 0);
447 phase_diff = integer_zero_node;
448 if (!tree_int_cst_equal (block_factor, integer_one_node))
450 tree phase0 =
451 convert (ssizetype, upc_pts_packed_build_phaseof (loc, op0));
452 tree phase1 =
453 convert (ssizetype, upc_pts_packed_build_phaseof (loc, op1));
454 phase_diff =
455 save_expr (build_binary_op (loc, MINUS_EXPR, phase0, phase1, 0));
457 /* The expression below calculates the following:
458 (elem_diff - phase_diff) * THREADS
459 + (thread_diff * block_factor) + phase_diff; */
460 result = build_binary_op (loc, PLUS_EXPR,
461 build_binary_op (loc, PLUS_EXPR,
462 build_binary_op (loc, MULT_EXPR,
463 build_binary_op (loc, MINUS_EXPR,
464 elem_diff,
465 phase_diff, 0),
466 n_threads, 0),
467 build_binary_op (loc, MULT_EXPR,
468 thread_diff,
469 block_factor, 0), 0),
470 phase_diff, 0);
471 result = fold_convert (result_type, result);
472 return result;
475 /* Handle conversions between UPC pointers-to-shared and
476 local pointers, or between UPC pointers-to-shared which
477 have differing block factors. */
479 static tree
480 upc_pts_packed_build_cvt (location_t loc, tree exp)
482 const tree type = TREE_TYPE (exp);
483 const tree ptr = TREE_OPERAND (exp, 0);
484 tree tt1, tt2, b1, b2;
485 tree result = exp;
486 tt1 = TREE_TYPE (TREE_TYPE (exp));
487 tt2 = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
488 b1 = upc_get_block_factor (tt1);
489 b2 = upc_get_block_factor (tt2);
490 if (upc_shared_type_p (tt1) != upc_shared_type_p (tt2))
492 if (upc_shared_type_p (tt1))
494 /* Error: local -> shared */
495 result = error_mark_node;
497 else
499 /* shared -> local */
500 int doprofcall = flag_upc_debug
501 || (flag_upc_instrument && get_upc_pupc_mode ());
502 const char *libfunc_name =
503 doprofcall ? UPC_GETADDRG_LIBCALL : UPC_GETADDR_LIBCALL;
504 tree src = build1 (NOP_EXPR, upc_pts_rep_type_node,
505 TREE_OPERAND (exp, 0));
506 tree libfunc, lib_args, lib_call;
507 libfunc = identifier_global_value (get_identifier (libfunc_name));
508 if (!libfunc)
509 internal_error ("library function %s not found", libfunc_name);
510 lib_args = tree_cons (NULL_TREE, src, NULL_TREE);
511 if (doprofcall)
512 lib_args =
513 upc_gasp_add_src_args (lib_args, input_filename, input_line);
514 lib_call = build_function_call (loc, libfunc, lib_args);
515 result = build1 (VIEW_CONVERT_EXPR, type, lib_call);
518 else if ((upc_shared_type_p (tt1) && !VOID_TYPE_P (tt1))
519 && !(integer_zerop (b1) && integer_zerop (b2)))
521 /* Below, we handle the case of conversions to non-generic
522 shared types. */
523 tree s1 = TYPE_SIZE (tt1);
524 tree s2 = TYPE_SIZE (tt2);
525 /* normalize block sizes, so that [0] => NULL */
526 if (integer_zerop (b1))
527 b1 = NULL;
528 if (integer_zerop (b2))
529 b2 = NULL;
530 /* normalize type size so that 0 => NULL */
531 if (s1 && integer_zerop (s1))
532 s1 = NULL;
533 if (s2 && integer_zerop (s2))
534 s2 = NULL;
535 /* If the source type is a not a generic pointer to shared, and
536 either its block size or type size differs from the target,
537 then the result must have zero phase. If the source type is
538 a generic pointer to shared and the target type is a pointer
539 to a shared type with either an indefinite block size, or
540 a block size of one, then the resulting value must have a
541 phase of zero. */
542 if ((!VOID_TYPE_P (tt2)
543 && !(tree_int_cst_equal (b1, b2)
544 && tree_int_cst_equal (s1, s2)))
545 || (VOID_TYPE_P (tt2)
546 && ((b1 == NULL)
547 || tree_int_cst_equal (b1, integer_one_node))))
549 const tree ptr_as_pts_rep = fold (build1 (VIEW_CONVERT_EXPR,
550 upc_pts_rep_type_node,
551 ptr));
552 const tree sptr = save_expr (ptr_as_pts_rep);
553 const tree ptr_with_zero_phase =
554 upc_pts_packed_build_value (loc, type,
555 upc_pts_packed_build_addrfield (loc, sptr),
556 upc_pts_packed_build_threadof (loc, sptr),
557 integer_zero_node);
558 result = ptr_with_zero_phase;
561 else if (upc_shared_type_p (tt1) && VOID_TYPE_P (tt1))
563 /* If the target is a generic pointer-to-shared type, we can
564 safely use the source value directly. */
566 else
567 gcc_assert (TREE_CODE (type) != CONVERT_EXPR);
568 return result;
571 /* Expand the expression EXP, which is a comparison between two
572 UPC pointers-to-shared.
574 Per 6.4.2p6:
575 Two compatible pointers-to-shared which point to the same object
576 (i.e. having the same address and thread components) shall compare
577 as equal according to == and !=, regardless of whether the phase
578 components match.
580 When a UPC pointer-to-shared is represented as (vaddr, thread, phase)
581 and the underlying pointer component types have a block size <=1,
582 we can use a straight unsigned integer comparison of the
583 representation types. Otherwise, if vaddr comes
584 last, then the straight bit-wise comparison works only for equality.
586 For the equality operation when the block size is greater than 1,
587 the phase field is first masked off. */
588 static tree
589 upc_pts_packed_build_cond_expr (location_t loc, tree exp)
591 tree result;
592 const enum tree_code code = TREE_CODE (exp);
593 tree op0 = TREE_OPERAND (exp, 0);
594 tree op1 = TREE_OPERAND (exp, 1);
595 const tree type0 = TREE_TYPE (op0);
596 const tree type1 = TREE_TYPE (op1);
597 gcc_assert (POINTER_TYPE_P (type0));
598 gcc_assert (POINTER_TYPE_P (type1));
600 const tree ttype0 = TREE_TYPE (type0);
601 const tree ttype1 = TREE_TYPE (type1);
602 const enum tree_code ttcode0 = TREE_CODE (ttype0);
603 const enum tree_code ttcode1 = TREE_CODE (ttype1);
604 const tree elem_type0 = strip_array_types (ttype0);
605 const tree elem_type1 = strip_array_types (ttype1);
606 gcc_assert (TREE_SHARED (elem_type0));
607 gcc_assert (TREE_SHARED (elem_type1));
609 const tree bs0 = upc_get_block_factor (elem_type0);
610 const tree bs1 = upc_get_block_factor (elem_type1);
611 const int has_phase0 = !(integer_zerop (bs0) || integer_onep (bs0));
612 const int has_phase1 = !(integer_zerop (bs1) || integer_onep (bs1));
613 const int has_phase = has_phase0 || has_phase1;
614 const int is_eq_op = (code == EQ_EXPR || code == NE_EXPR);
615 const int is_bitwise_cmp = is_eq_op
616 || (!has_phase && UPC_PTS_VADDR_FIRST);
617 if (is_bitwise_cmp)
619 if (ttcode0 == VIEW_CONVERT_EXPR
620 && TREE_TYPE (TREE_OPERAND (op0, 0)) == upc_pts_rep_type_node)
621 op0 = TREE_OPERAND (op0, 0);
622 else
623 op0 = build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node, op0);
624 if (ttcode1 == VIEW_CONVERT_EXPR
625 && TREE_TYPE (TREE_OPERAND (op1, 0)) == upc_pts_rep_type_node)
626 op1 = TREE_OPERAND (op1, 0);
627 else
628 op1 = build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node, op1);
629 if (is_eq_op)
631 /* Mask off the phase value. */
632 tree phase_mask =
633 fold_build1_loc (loc, BIT_NOT_EXPR, upc_pts_rep_type_node,
634 build_binary_op (loc, LSHIFT_EXPR,
635 upc_phase_mask_node,
636 upc_phase_shift_node, 0));
637 op0 = build_binary_op (loc, BIT_AND_EXPR, op0, phase_mask, 0);
638 op1 = build_binary_op (loc, BIT_AND_EXPR, op1, phase_mask, 0);
641 else
643 const tree ptr_diff = build_binary_op (loc, MINUS_EXPR,
644 op0, op1, 0);
645 op0 = ptr_diff;
646 op1 = build_int_cst (TREE_TYPE (op0), 0);
648 TREE_OPERAND (exp, 0) = op0;
649 TREE_OPERAND (exp, 1) = op1;
650 result = exp;
653 return result;