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; + }