In trying to build machine specific versions of glibc with newer compilers, we ran into a bug where the current glibc would not build on power6. This was due to glibc using the __builtin_swap64 builtin. Power6 sets the -mavoid-indexed-addresses option. The splitter that I wrote when I wrote the bswap64 did not have an alternate code path for -mavoid-indexed-addresses. This patch adds the alternate code path. I bootstraped it with today's compiler and there were no regressions in make check. Is it ok to apply?
[gcc] 2012-05-03 Michael Meissner <meiss...@linux.vnet.ibm.com> PR target/53199 * config/rs6000/rs6000.md (bswapdi splitters): If -mavoid-indexed-addresses (or -mcpu=power6 which sets it by default) is used, generate an alternate sequence that does not depend on using indexed addressing. [gcc/testsuite] 2012-05-03 Michael Meissner <meiss...@linux.vnet.ibm.com> PR target/53199 * gcc.target/powwerpc/pr53199.c: New file. -- Michael Meissner, IBM 5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA meiss...@linux.vnet.ibm.com fax +1 (978) 399-6899
Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 187099) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -2550,7 +2550,18 @@ (define_split if (GET_CODE (addr1) == PLUS) { emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4))); - addr2 = gen_rtx_PLUS (Pmode, op2, XEXP (addr1, 1)); + if (TARGET_AVOID_XFORM) + { + emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2)); + addr2 = op2; + } + else + addr2 = gen_rtx_PLUS (Pmode, op2, XEXP (addr1, 1)); + } + else if (TARGET_AVOID_XFORM) + { + emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4))); + addr2 = op2; } else { @@ -2600,7 +2611,18 @@ (define_split if (GET_CODE (addr1) == PLUS) { emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4))); - addr2 = gen_rtx_PLUS (Pmode, op2, XEXP (addr1, 1)); + if (TARGET_AVOID_XFORM) + { + emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2)); + addr2 = op2; + } + else + addr2 = gen_rtx_PLUS (Pmode, op2, XEXP (addr1, 1)); + } + else if (TARGET_AVOID_XFORM) + { + emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4))); + addr2 = op2; } else { @@ -2681,7 +2703,18 @@ (define_split if (GET_CODE (addr1) == PLUS) { emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4))); - addr2 = gen_rtx_PLUS (SImode, op2, XEXP (addr1, 1)); + if (TARGET_AVOID_XFORM) + { + emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2)); + addr2 = op2; + } + else + addr2 = gen_rtx_PLUS (SImode, op2, XEXP (addr1, 1)); + } + else if (TARGET_AVOID_XFORM) + { + emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4))); + addr2 = op2; } else { @@ -2726,7 +2759,18 @@ (define_split if (GET_CODE (addr1) == PLUS) { emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4))); - addr2 = gen_rtx_PLUS (SImode, op2, XEXP (addr1, 1)); + if (TARGET_AVOID_XFORM) + { + emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2)); + addr2 = op2; + } + else + addr2 = gen_rtx_PLUS (SImode, op2, XEXP (addr1, 1)); + } + else if (TARGET_AVOID_XFORM) + { + emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4))); + addr2 = op2; } else { Index: gcc/testsuite/gcc.target/powerpc/pr53199.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr53199.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr53199.c (revision 0) @@ -0,0 +1,50 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-options "-O2 -mcpu=power6 -mavoid-indexed-addresses" } */ +/* { dg-final { scan-assembler-times "lwbrx" 6 } } */ +/* { dg-final { scan-assembler-times "stwbrx" 6 } } */ + +/* PR 51399: bswap gets an error if -mavoid-indexed-addresses was used in + creating the two lwbrx instructions. */ + +long long +load64_reverse_1 (long long *p) +{ + return __builtin_bswap64 (*p); +} + +long long +load64_reverse_2 (long long *p) +{ + return __builtin_bswap64 (p[1]); +} + +long long +load64_reverse_3 (long long *p, int i) +{ + return __builtin_bswap64 (p[i]); +} + +void +store64_reverse_1 (long long *p, long long x) +{ + *p = __builtin_bswap64 (x); +} + +void +store64_reverse_2 (long long *p, long long x) +{ + p[1] = __builtin_bswap64 (x); +} + +void +store64_reverse_3 (long long *p, long long x, int i) +{ + p[i] = __builtin_bswap64 (x); +} + +long long +reg_reverse (long long x) +{ + return __builtin_bswap64 (x); +}