diff mbox

[PING] Fix ICE with x87 asm operands (PR inline-asm/68843)

Message ID AM4PR07MB15719FB0D103CCD9BD929A25E4440@AM4PR07MB1571.eurprd07.prod.outlook.com
State New
Headers show

Commit Message

Bernd Edlinger May 29, 2016, 2:37 p.m. UTC
Hi,

ping for the RTL optimization stuff.

The problem here is that the code in reg-stack.c
pretty much everywhere assumes that the stack registers
do not have gaps.  IMHO it is not worth to fix the
register allocation in a way that would be necessary for that
configuration to work correctly.

So this patch tries just to detect a situation that can't
possibly work and exit cleanly without raising any ICEs.

In this case we have a regstack of st(1) only. That is
temp_stack.top=0 and temp_stack.reg[0]=FIRST_STACK_REG+1.

So it is just by luck that the assertion in line 2522
triggers, because immediately before that we already
do std::swap (temp_stack[j], temp_stack[k]) with
j=-1 and k=0 in line 2118.  That is because of:

j = (temp_stack.top
     - (REGNO (recog_data.operand[i]) - FIRST_STACK_REG))

This formula only works, if you can assume that st(1) can
only be used in a stack that has at least two elements.

Likewise the return statement in get_hard_regnum:

return i >= 0 ? (FIRST_STACK_REG + regstack->top - i) : -1;

Which is also the same formula, and in this case
it returns FIRST_STACK_REG although the stack only has
one element FIRST_STACK_REG+1 aka st(1).



On 05/22/16 22:02, Uros Bizjak wrote:
> On Sun, May 22, 2016 at 9:00 AM, Bernd Edlinger

> <bernd.edlinger@hotmail.de> wrote:

>> Hi!

>>

>> as described in the PR there are several non-intuitive rules that

>> one has to follow to avoid ICEs with x87 asm operands.

>>

>> This patch adds an explicit rule, that avoids ICE in the first test case and

>> removes an unnecessary error message in the second test case.

>>

>>

>> Boot-strapped and regression-tested on x86_64-pc-linux-gnu.

>> OK for trunk?

>

> This patch is actually dealing with two separate problems

>

> This part:

>

> @@ -607,7 +631,7 @@ check_asm_stack_operands (rtx_insn *insn)

>        record any earlyclobber.  */

>

>     for (i = n_outputs; i < n_outputs + n_inputs; i++)

> -    if (op_alt[i].matches == -1)

> +    if (op_alt[i].matches == -1 && STACK_REG_P (recog_data.operand[i]))

>         {

>    int j;

>

> is OK, although, I'd written it as:

>

>

> +    if (STACK_REG_P (recog_data.operand[i]) && op_alt[i].matches == -1)

>

> with slightly simplified testcase:

>

> --cut here--

> int

> __attribute__((noinline, noclone))

> test (double y)

> {

>    int a, b;

>    asm ("fistpl (%1)\n\t"

>         "movl (%1), %0"

>         : "=r" (a)

>         : "r" (&b), "t" (y)

>         : "st");

>    return a;

> }

>

> int

> main ()

> {

>    int t = -10;

>

>    if (test (t) != t)

>      __builtin_abort ();

>    return 0;

> }

> --cut here--

>

> BTW: It looks to me you also don't need all-memory clobber here.

>


right.

> This part is OK, with a testcase you provided it borders on obvious.

> However, you will need rtl-optimization approval for the other

> problem.

>

> Uros.

>


I changed the patch according to your comments, thanks.

I have the updated patch attached.


Thanks
Bernd.
gcc:
2016-05-22  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR inline-asm/68843
	* reg-stack.c (check_asm_stack_operands): Explicit input arguments
	must be grouped on top of stack.  Don't force early clobber
	on ordinary reg outputs.

testsuite:
2016-05-22  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR inline-asm/68843
	* gcc.target/i386/pr68843-1.c: New test.
	* gcc.target/i386/pr68843-2.c: New test.

Comments

Jeff Law June 9, 2016, 9:10 p.m. UTC | #1
On 05/29/2016 08:37 AM, Bernd Edlinger wrote:

>
>
> gcc:
> 2016-05-22  Bernd Edlinger  <bernd.edlinger@hotmail.de>
>
> 	PR inline-asm/68843
> 	* reg-stack.c (check_asm_stack_operands): Explicit input arguments
> 	must be grouped on top of stack.  Don't force early clobber
> 	on ordinary reg outputs.
>
> testsuite:
> 2016-05-22  Bernd Edlinger  <bernd.edlinger@hotmail.de>
>
> 	PR inline-asm/68843
> 	* gcc.target/i386/pr68843-1.c: New test.
> 	* gcc.target/i386/pr68843-2.c: New test.
OK for the trunk.

Sorry for the wait,
Jeff
diff mbox

Patch

Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c	(revision 236597)
+++ gcc/reg-stack.c	(working copy)
@@ -97,6 +97,9 @@ 
 	All implicitly popped input regs must be closer to the top of
 	the reg-stack than any input that is not implicitly popped.
 
+	All explicitly referenced input operands may not "skip" a reg.
+	Otherwise we can have holes in the stack.
+
    3. It is possible that if an input dies in an insn, reload might
       use the input reg for an output reload.  Consider this example:
 
@@ -461,6 +464,7 @@  check_asm_stack_operands (rtx_insn *insn)
 
   char reg_used_as_output[FIRST_PSEUDO_REGISTER];
   char implicitly_dies[FIRST_PSEUDO_REGISTER];
+  char explicitly_used[FIRST_PSEUDO_REGISTER];
 
   rtx *clobber_reg = 0;
   int n_inputs, n_outputs;
@@ -568,6 +572,7 @@  check_asm_stack_operands (rtx_insn *insn)
      popped.  */
 
   memset (implicitly_dies, 0, sizeof (implicitly_dies));
+  memset (explicitly_used, 0, sizeof (explicitly_used));
   for (i = n_outputs; i < n_outputs + n_inputs; i++)
     if (STACK_REG_P (recog_data.operand[i]))
       {
@@ -581,6 +586,8 @@  check_asm_stack_operands (rtx_insn *insn)
 
 	if (j < n_clobbers || op_alt[i].matches >= 0)
 	  implicitly_dies[REGNO (recog_data.operand[i])] = 1;
+	else if (reg_class_size[(int) op_alt[i].cl] == 1)
+	  explicitly_used[REGNO (recog_data.operand[i])] = 1;
       }
 
   /* Search for first non-popped reg.  */
@@ -600,6 +607,23 @@  check_asm_stack_operands (rtx_insn *insn)
       malformed_asm = 1;
     }
 
+  /* Search for first not-explicitly used reg.  */
+  for (i = FIRST_STACK_REG; i < LAST_STACK_REG + 1; i++)
+    if (! implicitly_dies[i] && ! explicitly_used[i])
+      break;
+
+  /* If there are any other explicitly used regs, that's an error.  */
+  for (; i < LAST_STACK_REG + 1; i++)
+    if (explicitly_used[i])
+      break;
+
+  if (i != LAST_STACK_REG + 1)
+    {
+      error_for_asm (insn,
+		     "explicitly used regs must be grouped at top of stack");
+      malformed_asm = 1;
+    }
+
   /* Enforce rule #3: If any input operand uses the "f" constraint, all
      output constraints must use the "&" earlyclobber.
 
@@ -607,7 +631,7 @@  check_asm_stack_operands (rtx_insn *insn)
      record any earlyclobber.  */
 
   for (i = n_outputs; i < n_outputs + n_inputs; i++)
-    if (op_alt[i].matches == -1)
+    if (STACK_REG_P (recog_data.operand[i]) && op_alt[i].matches == -1)
       {
 	int j;
 
Index: gcc/testsuite/gcc.target/i386/pr68843-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/pr68843-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr68843-1.c	(working copy)
@@ -0,0 +1,12 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+double
+test ()
+{
+  double x = 1.0;
+  asm ("fld %1" /* { dg-error "explicitly used regs must be grouped at top of stack" } */
+       : "=&t" (x)
+       : "u" (x));
+  return x;
+}
Index: gcc/testsuite/gcc.target/i386/pr68843-2.c
===================================================================
--- gcc/testsuite/gcc.target/i386/pr68843-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr68843-2.c	(working copy)
@@ -0,0 +1,22 @@ 
+int
+__attribute__((noinline, noclone))
+test (double y)
+{
+  int a, b;
+  asm ("fistpl (%1)\n\t"
+       "movl (%1), %0"
+       : "=r" (a)
+       : "r" (&b), "t" (y)
+       : "st");
+  return a;
+}
+
+int
+main ()
+{
+  int t = -10;
+
+  if (test (t) != t)
+    __builtin_abort ();
+  return 0;
+}