...as the former is defined as returning MIN_VALUE for argument MIN_VALUE, whereas the latter is 'undefined', and gcc can optimize "abs(x)>=0" to "true", which is wrong for __builtin_aarch64_abs.

There has been much debate here, although not recently - I think the last was https://gcc.gnu.org/ml/gcc-patches/2014-05/msg00387.html . However without a definite solution, we should at least stop the folding, as otherwise this is a bug.

The complication here is that the folding meant we never expanded the call to __builtin_aarch64_absdi, and thus never realized that expanding would cause an ICE: gen_absdi2() takes only two parameters (source and dest operand), and has no parameter corresponding to the scratch operand in the insn_data; but the code in aarch64_simd_expand_args, reads the number of arguments from the insn_data, and so tries to get another operand from the call to __builtin_aarch64_absdi, causing the ICE. Hence, we have to introduce a SIMD_ARG_SCRATCH, used in aarch64_simd_expand_args to skip over the argument.

(There is an alternative way of doing this, i.e. to update the for-loop in aarch64_simd_expand_builtin by adding yet another version of 'k'. However, I thought there were enough versions already that I really didn't want to add one more...)

To go with this, I've renamed qualifier_internal to qualifier_scratch, as it's not clear that any non-scratch internal operands (whatever such might be) would want the same treatment!

Cross-tested check-gcc on aarch64-none-elf.

Ok for trunk?

gcc/ChangeLog:

        * config/aarch64/aarch64-builtins.c (enum aarch64_type_qualifiers):
        Rename qualifier_internal to qualifier_scratch.
        (aarch64_types_unop_qualifiers, aarch64_init_simd_builtins): Follow
        renaming.
        (builtin_simd_arg): New SIMD_ARG_SCRATCH enum value.
        (aarch64_simd_expand_args): Skip over SIMD_ARG_SCRATCHes.
        (aarch64_simd_expand_builtin): Handle qualifier_scratch.
        (aarch64_fold_builtin): Remove folding of abs.
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 1af17900785685e4e005710d3bb1743d88a11c16..4cd3d654c0543fad1b88549683222c060c7978d9 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -117,9 +117,10 @@ enum aarch64_type_qualifiers
   qualifier_maybe_immediate = 0x10, /* 1 << 4  */
   /* void foo (...).  */
   qualifier_void = 0x20, /* 1 << 5  */
-  /* Some patterns may have internal operands, this qualifier is an
-     instruction to the initialisation code to skip this operand.  */
-  qualifier_internal = 0x40, /* 1 << 6  */
+  /* Tells the initialisation code to skip this operand when generating
+     the type of the builtin function (and the expander to skip it when
+     expanding a call to said builtin function).  */
+  qualifier_scratch = 0x40, /* 1 << 6  */
   /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
      rather than using the type of the operand.  */
   qualifier_map_mode = 0x80, /* 1 << 7  */
@@ -140,11 +141,11 @@ typedef struct
   enum aarch64_type_qualifiers *qualifiers;
 } aarch64_simd_builtin_datum;
 
-/*  The qualifier_internal allows generation of a unary builtin from
-    a pattern with a third pseudo-operand such as a match_scratch.  */
+/*  The qualifier_scratch allows generation of a unary builtin from
+    a pattern with a third pseudo-operand i.e. match_scratch.  */
 static enum aarch64_type_qualifiers
 aarch64_types_unop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
-  = { qualifier_none, qualifier_none, qualifier_internal };
+  = { qualifier_none, qualifier_none, qualifier_scratch };
 #define TYPES_UNOP (aarch64_types_unop_qualifiers)
 static enum aarch64_type_qualifiers
 aarch64_types_unopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
@@ -791,7 +792,7 @@ aarch64_init_simd_builtins (void)
 	    type_signature[arg_num] = 's';
 
 	  /* Skip an internal operand for vget_{low, high}.  */
-	  if (qualifiers & qualifier_internal)
+	  if (qualifiers & qualifier_scratch)
 	    continue;
 
 	  /* Some builtins have different user-facing types
@@ -899,6 +900,7 @@ typedef enum
 {
   SIMD_ARG_COPY_TO_REG,
   SIMD_ARG_CONSTANT,
+  SIMD_ARG_SCRATCH,
   SIMD_ARG_STOP
 } builtin_simd_arg;
 
@@ -919,13 +921,13 @@ aarch64_simd_expand_args (rtx target, int icode, int have_retval,
 	  || !(*insn_data[icode].operand[0].predicate) (target, tmode)))
     target = gen_reg_rtx (tmode);
 
-  for (;;)
+  for (;; args++)
     {
-      builtin_simd_arg thisarg = args[argc];
+      builtin_simd_arg thisarg = *args;
 
       if (thisarg == SIMD_ARG_STOP)
 	break;
-      else
+      else if (thisarg != SIMD_ARG_SCRATCH)
 	{
 	  arg[argc] = CALL_EXPR_ARG (exp, argc);
 	  op[argc] = expand_normal (arg[argc]);
@@ -950,6 +952,7 @@ aarch64_simd_expand_args (rtx target, int icode, int have_retval,
 	      break;
 
 	    case SIMD_ARG_STOP:
+	    case SIMD_ARG_SCRATCH:
 	      gcc_unreachable ();
 	    }
 
@@ -1061,6 +1064,8 @@ aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
 		(arg, insn_data[icode].operand[operands_k].mode));
 	  args[k] = op_const_int_p ? SIMD_ARG_CONSTANT : SIMD_ARG_COPY_TO_REG;
 	}
+      else if (d->qualifiers[qualifiers_k] & qualifier_scratch)
+        args[k] = SIMD_ARG_SCRATCH;
       else
 	args[k] = SIMD_ARG_COPY_TO_REG;
 
@@ -1317,9 +1322,6 @@ aarch64_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args,
 
   switch (fcode)
     {
-      BUILTIN_VALLDI (UNOP, abs, 2)
-	return fold_build1 (ABS_EXPR, type, args[0]);
-	break;
       BUILTIN_VALLDI (BINOP, cmge, 0)
 	return fold_build2 (GE_EXPR, type, args[0], args[1]);
 	break;

Reply via email to