Patchwork [RFA:] fix group-loads of VOIDmode constants, expr.c:emit_group_load_1

login
register
mail settings
Submitter Hans-Peter Nilsson
Date Dec. 1, 2012, 3:01 a.m.
Message ID <alpine.BSF.2.02.1211302158360.57912@dair.pair.com>
Download mbox | patch
Permalink /patch/203095/
State New
Headers show

Comments

Hans-Peter Nilsson - Dec. 1, 2012, 3:01 a.m.
(No cans of worms opened here, I believe...)

For MMIX with the default, Knuth's ABI (returning values in register
$0, through the register stack), function return values are prepared
in a register-swapped fashion due to the way the register stack works,
which has to be expressed as:

(parallel [
        (expr_list:REG_DEP_TRUE (reg:DI 0 $0)
            (const_int 8 [0x8]))
        (expr_list:REG_DEP_TRUE (reg:DI 1 $1)
            (const_int 0 [0]))
    ])

i.e. a group load.  Compare to the more intuitive "GNU ABI", passing
parameters straightforwardly, with the order in the called and the
calling function being the same, starting with global register $231.

Of course this matters only to >64bit (i.e. >registersize) values like
TImode, alias __int128.  The problem here is that group-loading a
constant for a function return-value doesn't work; it's passed to
simplify_gen_subreg which horks on the VOIDmode constant.  Thankfully,
the code below the context handles this case, twice the register-mode,
just fine, so let's just gate the simplify_gen_subreg call with a test
for a VOIDmode source.  Bootstrapped and checked for
x86_64-*-linux-gnu and checked for mmix-knuth-mmixware, both -mabi=gnu
multilib (no regressions) and the base multilib with the Knuth ABI,
where the patch below fixes:

Running /home/hp/gcctop/tmp/mbasf/gcc/gcc/testsuite/gcc.c-torture/execute/execute.exp ...
...
FAIL: gcc.c-torture/execute/pr54471.c compilation,  -O1  (internal compiler error)
FAIL: gcc.c-torture/execute/pr54471.c compilation,  -O2  (internal compiler error)
FAIL: gcc.c-torture/execute/pr54471.c compilation,  -O3 -fomit-frame-pointer  (internal compiler error)
FAIL: gcc.c-torture/execute/pr54471.c compilation,  -O3 -fomit-frame-pointer -funroll-loops  (internal compiler error)
FAIL: gcc.c-torture/execute/pr54471.c compilation,  -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions  (internal compiler error)
FAIL: gcc.c-torture/execute/pr54471.c compilation,  -O3 -g  (internal compiler error)
FAIL: gcc.c-torture/execute/pr54471.c compilation,  -Os  (internal compiler error)
FAIL: gcc.c-torture/execute/pr54471.c compilation,  -O2 -flto -fno-use-linker-plugin -flto-partition=none  (internal compiler error)
FAIL: gcc.c-torture/execute/pr54471.c compilation,  -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects  (internal compiler error)
...
Running /home/hp/gcctop/tmp/mbasf/gcc/gcc/testsuite/gcc.dg/dg.exp ...
...
FAIL: gcc.dg/pr32912-2.c (internal compiler error)
FAIL: gcc.dg/pr32912-2.c (test for excess errors)
FAIL: gcc.dg/pr32912-3.c (internal compiler error)
FAIL: gcc.dg/pr32912-3.c (test for excess errors)
...
Running /home/hp/gcctop/tmp/mbasf/gcc/gcc/testsuite/gcc.dg/torture/dg-torture.exp ...
...
FAIL: c-c++-common/torture/vector-compare-2.c  -O1  (internal compiler error)
FAIL: c-c++-common/torture/vector-compare-2.c  -O1  (test for excess errors)
FAIL: c-c++-common/torture/vector-compare-2.c  -O2  (internal compiler error)
FAIL: c-c++-common/torture/vector-compare-2.c  -O2  (test for excess errors)
FAIL: c-c++-common/torture/vector-compare-2.c  -O3 -fomit-frame-pointer  (internal compiler error)
FAIL: c-c++-common/torture/vector-compare-2.c  -O3 -fomit-frame-pointer  (test for excess errors)
FAIL: c-c++-common/torture/vector-compare-2.c  -O3 -fomit-frame-pointer -funroll-loops  (internal compiler error)
FAIL: c-c++-common/torture/vector-compare-2.c  -O3 -fomit-frame-pointer -funroll-loops  (test for excess errors)
FAIL: c-c++-common/torture/vector-compare-2.c  -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions  (internal compiler error)
FAIL: c-c++-common/torture/vector-compare-2.c  -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions  (test for excess errors)
FAIL: c-c++-common/torture/vector-compare-2.c  -O3 -g  (internal compiler error)
FAIL: c-c++-common/torture/vector-compare-2.c  -O3 -g  (test for excess errors)
FAIL: c-c++-common/torture/vector-compare-2.c  -Os  (internal compiler error)
FAIL: c-c++-common/torture/vector-compare-2.c  -Os  (test for excess errors)
FAIL: c-c++-common/torture/vector-compare-2.c  -O2 -flto -fno-use-linker-plugin -flto-partition=none  (internal compiler error)
FAIL: c-c++-common/torture/vector-compare-2.c  -O2 -flto -fno-use-linker-plugin -flto-partition=none  (test for excess errors)

(ditto the c++ testsuite for c-c++-common/torture/vector-compare-2.c)

(FWIW, the failing gcc.dg/pr32912-3.c is a regression.)

Ok?

gcc:
	* expr.c (emit_group_load_1): Don't call simplify_gen_subreg for
	a VOIDmode src.


brgds, H-P
Eric Botcazou - Dec. 1, 2012, 8:48 a.m.
> Of course this matters only to >64bit (i.e. >registersize) values like
> TImode, alias __int128.  The problem here is that group-loading a
> constant for a function return-value doesn't work; it's passed to
> simplify_gen_subreg which horks on the VOIDmode constant.  Thankfully,
> the code below the context handles this case, twice the register-mode,
> just fine, so let's just gate the simplify_gen_subreg call with a test
> for a VOIDmode source.

IMO that's not as clear a cut as it seems.  simplify_gen_subreg is supposed to 
work on VOIDmode constants, at least to be callable on them, because there is 
the simplify_gen_subreg -> simplify_subreg -> simplify_immed_subreg path.

Patch

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 192677)
+++ gcc/expr.c	(working copy)
@@ -1739,7 +1739,9 @@  emit_group_load_1 (rtx *tmps, rtx dst, r
 	  emit_move_insn (mem, src);
 	  tmps[i] = adjust_address (mem, mode, (int) bytepos);
 	}
-      else if (CONSTANT_P (src) && GET_MODE (dst) != BLKmode
+      else if (CONSTANT_P (src)
+	       && GET_MODE (src) != VOIDmode
+	       && GET_MODE (dst) != BLKmode
                && XVECLEN (dst, 0) > 1)
         tmps[i] = simplify_gen_subreg (mode, src, GET_MODE(dst), bytepos);
       else if (CONSTANT_P (src))