diff mbox

wide-int, tree

Message ID C9242BD2-8B7C-4883-BF1B-CD89C22A9E0F@mrs.kithrup.com
State New
Headers show

Commit Message

Mike Stump Feb. 12, 2014, 9:48 p.m. UTC
In resolving a recent x86_64 libitm build problem found while trunk merging, I discovered that fold_builtin_memory_op  grabs an int whose size is based upon the size of a complex long double, which is 256 bits, and then during type hashing (where it calls type_hash_canon), it wants to check to see if this value fits into a uhwi.  to_widest is aborting due to 256 (complex long double) >= 128 (max wide int from i386-modes.def:

> /* Keep the OI and XI modes from confusing the compiler into thinking
>    that these modes could actually be used for computation.  They are
>    only holders for vectors during data movement.  */
> #define MAX_BITSIZE_MODE_ANY_INT (128)

)

to_widest does this to prevent large values from being truncated into smaller values.

The patch below fixes it, however, the question is, is this the right place to fix it.  Another fix would be to admit that the compiler does use 256 bit integers on x86 (for the maximum value of the OImode type) and instead change MAX_BITSIZE_MODE_ANY_INT to be 256.  Other possibilities exist.

This problem is limited to x86, since it is the only port that uses MAX_BITSIZE_MODE_ANY_INT.

Thoughts?


The chain of how we got here:

fold_builtin_3:
      case BUILT_IN_MEMMOVE:
        return fold_builtin_memory_op (loc, arg0, arg1, arg2,
  =>                                   type, ignore, /*endp=*/3);



fold_builtin_memory_op:
        if (FLOAT_MODE_P (TYPE_MODE (srctype))
            || TREE_CODE (srctype) == BOOLEAN_TYPE
            || TREE_CODE (srctype) == ENUMERAL_TYPE)
          {
B           enum machine_mode mode = int_mode_for_mode (TYPE_MODE (srctype));
            if (mode == BLKmode)
              srctype = NULL_TREE;
            else
              srctype = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode),
  =>                                                    1);
          }

build_nonstandard_integer_type:
    if (unsignedp)
      fixup_unsigned_type (itype);
    else
B =>  fixup_signed_type (itype);

    ret = itype;
    if (tree_fits_uhwi_p (TYPE_MAX_VALUE (itype)))
      ret = type_hash_canon (tree_to_uhwi (TYPE_MAX_VALUE (itype)), itype);
    if (precision <= MAX_INT_CACHED_PREC)
      nonstandard_integer_type_cache[precision + unsignedp] = ret;

    return ret;
diff mbox

Patch

diff --git a/gcc/tree.c b/gcc/tree.c
index 2a68b03..8f2891a 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -6970,9 +6970,14 @@  tree_fits_shwi_p (const_tree t)
 bool
 tree_fits_uhwi_p (const_tree t)
 {
-  return (t != NULL_TREE
-         && TREE_CODE (t) == INTEGER_CST
-         && wi::fits_uhwi_p (wi::to_widest (t)));
+  if (t == NULL_TREE)
+    return false;
+  if (TREE_CODE (t) != INTEGER_CST)
+    return false;
+  if (TREE_INT_CST_EXT_NUNITS (t) == 1)
+    return TREE_INT_CST_ELT (t, 0) >= 0;
+  return (TREE_INT_CST_EXT_NUNITS (t) == 2
+         && TREE_INT_CST_ELT (t, 1) == 0);
 }
 
 /* T is an INTEGER_CST whose numerical value (extended according to