SUBREG_PROMOTED_VAR_P handling in expand_direct_optab_fn
authorRichard Sandiford <richard.sandiford@linaro.org>
Sun, 22 Oct 2017 21:41:57 +0000 (21:41 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sun, 22 Oct 2017 21:41:57 +0000 (21:41 +0000)
This is needed by the later SVE LAST reductions, where an 8-bit
or 16-bit result is zero- rather than sign-extended to 32 bits.
I think it could occur in other situations too.

2017-09-19  Richard Sandiford  <richard.sandiford@linaro.org>
    Alan Hayward  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* internal-fn.c (expand_direct_optab_fn): Don't assign directly
to a SUBREG_PROMOTED_VAR.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r253992

gcc/ChangeLog
gcc/internal-fn.c

index ebaf8b354cc3c343bc298fd7f641fdfe08de7e82..64ee44ec6f3931b2f00c74b43b1cd0cee97208bb 100644 (file)
@@ -1,3 +1,10 @@
+2017-10-22  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * internal-fn.c (expand_direct_optab_fn): Don't assign directly
+       to a SUBREG_PROMOTED_VAR.
+
 2017-10-22  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index ce9e8bb75e988b502714e335bd13293f4fbdc060..94873c2948ad01c8ffaeb2a3473409b74b9ed6f5 100644 (file)
@@ -2606,7 +2606,15 @@ expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
   tree lhs = gimple_call_lhs (stmt);
   tree lhs_type = TREE_TYPE (lhs);
   rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
-  create_output_operand (&ops[0], lhs_rtx, insn_data[icode].operand[0].mode);
+
+  /* Do not assign directly to a promoted subreg, since there is no
+     guarantee that the instruction will leave the upper bits of the
+     register in the state required by SUBREG_PROMOTED_SIGN.  */
+  rtx dest = lhs_rtx;
+  if (GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
+    dest = NULL_RTX;
+
+  create_output_operand (&ops[0], dest, insn_data[icode].operand[0].mode);
 
   for (unsigned int i = 0; i < nargs; ++i)
     {