The following patch fixes a missed gimplification of components
of registers used as asm outputs with non-memory constraints.

The solution is to handle !allows_mem during gimplification rather
than leaving it up to RTL expansion.  I'm only handling the case
where we'd otherwise ICE because of invalid GIMPLE, not all
!allows_mem cases we could handle to simplify things at this stage
(in particular not the COMPONENT_REF case in the testcase or the
whole-aggregate case there).

This is a wrong-code bug when checking is disabled as the asm
misses virtual operands in that case.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2016-03-24  Richard Biener  <rguent...@suse.de>

        PR middle-end/70370
        * gimplify.c (gimplify_asm_expr): Handle !allows_mem outputs
        with register bases.

        * gcc.dg/torture/pr70370.c: New testcase.

Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c      (revision 234415)
--- gcc/gimplify.c      (working copy)
*************** gimplify_asm_expr (tree *expr_p, gimple_
*** 5191,5196 ****
--- 5205,5236 ----
          ret = tret;
        }
  
+       /* If the constraint does not allow memory make sure we gimplify
+          it to a register if it is not already but its base is.  This
+        happens for complex and vector components.  */
+       if (!allows_mem)
+       {
+         tree op = TREE_VALUE (link);
+         if (! is_gimple_val (op)
+             && is_gimple_reg_type (TREE_TYPE (op))
+             && is_gimple_reg (get_base_address (op)))
+           {
+             tree tem = create_tmp_reg (TREE_TYPE (op));
+             tree ass;
+             if (is_inout)
+               {
+                 ass = build2 (MODIFY_EXPR, TREE_TYPE (tem),
+                               tem, unshare_expr (op));
+                 gimplify_and_add (ass, pre_p);
+               }
+             ass = build2 (MODIFY_EXPR, TREE_TYPE (tem), op, tem);
+             gimplify_and_add (ass, post_p);
+ 
+             TREE_VALUE (link) = tem;
+             tret = GS_OK;
+           }
+       }
+ 
        vec_safe_push (outputs, link);
        TREE_CHAIN (link) = NULL_TREE;
  
Index: gcc/testsuite/gcc.dg/torture/pr70370.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr70370.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr70370.c      (working copy)
***************
*** 0 ****
--- 1,45 ----
+ /* { dg-do compile } */
+ 
+ _Complex float
+ test1 (_Complex float f)
+ {
+   __asm__ ("" : "+r" (__real f));
+   return f;
+ }
+ 
+ _Complex float
+ test2 (_Complex float f)
+ {
+   __asm__ ("" : "=r" (__real f));
+   return f;
+ }
+ 
+ struct X { int i; };
+ 
+ struct X 
+ test3 (struct X x)
+ {
+   __asm__ ("" : "=r" (x.i));
+   return x;
+ }
+ 
+ struct X
+ test4 (struct X x)
+ {
+   __asm__ ("" : "+r" (x.i));
+   return x;
+ }
+ 
+ struct X 
+ test5 (struct X x)
+ {
+   __asm__ ("" : "=r" (x));
+   return x;
+ }
+ 
+ struct X
+ test6 (struct X x)
+ {
+   __asm__ ("" : "+r" (x));
+   return x;
+ }

Reply via email to