On some tests involving storing a pointer to a string constant in a vector, on powerpc with SPE vectors, an ICE occurs of the form:
t2.c: In function 'f': t2.c:7:1: error: unrecognizable insn: } ^ (insn 9 8 10 2 (set (subreg:SI (reg:V2SI 125 [ D.1618 ]) 4) (lo_sum:SI (reg:SI 126) (symbol_ref/f:SI ("*.LC0") [flags 0x82] <var_decl 0xf745b000 *.LC0>))) t2.c:6 -1 (nil)) t2.c:7:1: internal compiler error: in extract_insn, at recog.c:2130 Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions. The patterns to set individual words of SPE vectors only allow input_operand and do not allow for the LO_SUM constructs used for pointers to strings. This patch fixes things by adding further patterns for the LO_SUM case. (It's possible the issue could also arise with the patterns for subregs of TFmode at offset 8 and 12, but I couldn't get the compiler to generate stores of string constant pointers to such subregs.) The original test I had for this issue in a 4.6-based compiler simplified to char *a1[20]; int a2[20]; char a3[1]; void f (void) { int i; for (i = 1; i < 20; i++) { a1[i] = ""; a2[i] = 0; } } with -O3, where the vectors were generated internally, but that doesn't ICE with trunk, so I created the synthetic testcases in this patch that do ICE with trunk. Tested with no regressions with cross to powerpc-eabispe. OK to commit? 2012-06-19 Joseph Myers <jos...@codesourcery.com> * config/rs6000/spe.md (*mov_si<mode>_e500_subreg0): Rename to mov_si<mode>_e500_subreg0. (*mov_si<mode>_e500_subreg0_elf_low) (*mov_si<mode>_e500_subreg4_elf_low): New patterns. testsuite: 2012-06-19 Joseph Myers <jos...@codesourcery.com> * gcc.c-torture/compile/vector-5.c, gcc.c-torture/compile/vector-6.c: New tests. Index: gcc/testsuite/gcc.c-torture/compile/vector-5.c =================================================================== --- gcc/testsuite/gcc.c-torture/compile/vector-5.c (revision 0) +++ gcc/testsuite/gcc.c-torture/compile/vector-5.c (revision 0) @@ -0,0 +1,7 @@ +typedef int v2si __attribute__((__vector_size__(8))); + +v2si +f (int x) +{ + return (v2si) { x, (__INTPTR_TYPE__) "" }; +} Index: gcc/testsuite/gcc.c-torture/compile/vector-6.c =================================================================== --- gcc/testsuite/gcc.c-torture/compile/vector-6.c (revision 0) +++ gcc/testsuite/gcc.c-torture/compile/vector-6.c (revision 0) @@ -0,0 +1,7 @@ +typedef int v2si __attribute__((__vector_size__(8))); + +v2si +f (int x) +{ + return (v2si) { (__INTPTR_TYPE__) "", x }; +} Index: gcc/config/rs6000/spe.md =================================================================== --- gcc/config/rs6000/spe.md (revision 188753) +++ gcc/config/rs6000/spe.md (working copy) @@ -1,5 +1,5 @@ ;; e500 SPE description -;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 ;; Free Software Foundation, Inc. ;; Contributed by Aldy Hernandez (a...@quesejoda.com) @@ -2329,7 +2329,7 @@ "evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1" [(set_attr "length" "16")]) -(define_insn "*mov_si<mode>_e500_subreg0" +(define_insn "mov_si<mode>_e500_subreg0" [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,&r") 0) (match_operand:SI 1 "input_operand" "r,m"))] "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) @@ -2339,6 +2339,24 @@ evmergelohi %0,%0,%0\;{l%U1%X1|lwz%U1%X1} %0,%1\;evmergelohi %0,%0,%0" [(set_attr "length" "4,12")]) +(define_insn_and_split "*mov_si<mode>_e500_subreg0_elf_low" + [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 0) + (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r") + (match_operand 2 "" "")))] + "((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)) + && TARGET_ELF && !TARGET_64BIT && can_create_pseudo_p ()" + "#" + "&& 1" + [(pc)] +{ + rtx tmp = gen_reg_rtx (SImode); + emit_insn (gen_elf_low (tmp, operands[1], operands[2])); + emit_insn (gen_mov_si<mode>_e500_subreg0 (operands[0], tmp)); + DONE; +} + [(set_attr "length" "8")]) + ;; ??? Could use evstwwe for memory stores in some cases, depending on ;; the offset. (define_insn "*mov_si<mode>_e500_subreg0_2" @@ -2360,6 +2378,15 @@ mr %0,%1 {l%U1%X1|lwz%U1%X1} %0,%1") +(define_insn "*mov_si<mode>_e500_subreg4_elf_low" + [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 4) + (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r") + (match_operand 2 "" "")))] + "((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)) + && TARGET_ELF && !TARGET_64BIT" + "{ai|addic} %0,%1,%K2") + (define_insn "*mov_si<mode>_e500_subreg4_2" [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") (subreg:SI (match_operand:SPE64TF 1 "register_operand" "r,r") 4))] -- Joseph S. Myers jos...@codesourcery.com