re PR target/46254 (ICE: in find_reloads, at reload.c:3806 (unable to generate reload...
authorUros Bizjak <uros@gcc.gnu.org>
Mon, 27 Aug 2012 21:13:07 +0000 (23:13 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Mon, 27 Aug 2012 21:13:07 +0000 (23:13 +0200)
PR target/46254
* config/i386/predicates.md (cmpxchg8b_pic_memory_operand): Return
true for TARGET_64BIT or !flag_pic.
* config/i386/sync.md (*atomic_compare_and_swap_doubledi_pic): Remove.
(atomic_compare_and_swap_double<mode>): Change operand 2 predicate
to cmpxchg8b_pic_memory_operand.  Use DWIH mode iterator.
Add insn constraint.  Conditionally emit xchg asm insns.
(atomic_compare_and_swap<mode>): Update calls.  Check only
cmpxchg8b_pic_memory_operand in memory address fixup.
(DCASMODE): Remove.
(CASHMODE): Rename from DCASHMODE.
(doublemodesuffix): Update modes.
(regprefix): New mode attribute.

(unspecv) <UNSPECV_CMPXCHG_{1,2,3,4}>: Remove.
<UNSPECV_CMPXCHG>: New constant.
(atomic_compare_and_swap<mode>_1): Rename from
atomic_compare_and_swap_single<mode>.  Update calls and
unspec_volatile constants.
(atomic_compare_and_swap<mode>_doubleword): Rename from
atomic_compare_and_swap_double<mode>.  Update calls and
unspec_volatile constants.

testsuite/ChangeLog:

PR target/46254
* gcc.target/i386/pr46254.c: New test.

From-SVN: r190732

gcc/ChangeLog
gcc/config/i386/predicates.md
gcc/config/i386/sync.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr46254.c [new file with mode: 0644]

index 13813df5b3645a14771c2ee15b50642b6f6f31ea..5139e98cc96a8f19e9acf67a1426538166cf2f72 100644 (file)
@@ -1,3 +1,28 @@
+2012-08-27  Uros Bizjak  <ubizjak@gmail.com>
+
+       PR target/46254
+       * config/i386/predicates.md (cmpxchg8b_pic_memory_operand): Return
+       true for TARGET_64BIT or !flag_pic.
+       * config/i386/sync.md (*atomic_compare_and_swap_doubledi_pic): Remove.
+       (atomic_compare_and_swap_double<mode>): Change operand 2 predicate
+       to cmpxchg8b_pic_memory_operand.  Use DWIH mode iterator.
+       Add insn constraint.  Conditionally emit xchg asm insns.
+       (atomic_compare_and_swap<mode>): Update calls.  Check only
+       cmpxchg8b_pic_memory_operand in memory address fixup.
+       (DCASMODE): Remove.
+       (CASHMODE): Rename from DCASHMODE.
+       (doublemodesuffix): Update modes.
+       (regprefix): New mode attribute.
+
+       (unspecv) <UNSPECV_CMPXCHG_{1,2,3,4}>: Remove.
+       <UNSPECV_CMPXCHG>: New constant.
+       (atomic_compare_and_swap<mode>_1): Rename from
+       atomic_compare_and_swap_single<mode>.  Update calls and
+       unspec_volatile constants.
+       (atomic_compare_and_swap<mode>_doubleword): Rename from
+       atomic_compare_and_swap_double<mode>.  Update calls and
+       unspec_volatile constants.
+
 2012-08-27  Walter Lee  <walt@tilera.com>
 
        * doc/md.texi (TILE-Gx): Fix typo.
@@ -6,9 +31,9 @@
 
        * config/tilegx/tilegx.c (tilegx_function_profiler): Fix typo.
        config/tilepro/tilepro.c (tilepro_function_profiler): Ditto.
-       
+
 2012-08-27  Walter Lee  <walt@tilera.com>
-       
+
        * config/tilegx/tilegx.md (*bfins): Rename to insn_bfins.
        (insn_bfins): Delete.
 
        this section.
 
 2012-08-26  Gerald Pfeifer  <gerald@pfeifer.com>
-       
+
        * doc/tm.texi.in (Misc): Move descriptions of NO_DOLLAR_IN_LABEL
        and NO_DOT_IN_LABEL from here...
        (Label Output): ...to here.
        * doc/tm.texi: Regenerate.
-                       
+
 2012-08-26  Gerald Pfeifer  <gerald@pfeifer.com>
 
        * doc/invoke.texi (C++ Dialect Options): Add missing space.
        * doc/extend.texi (__atomic Builtins): Remove space before comma.
 
 2012-08-25  Richard Sandiford  <rdsandiford@googlemail.com>
-            Andrew Pinski  <apinski@cavium.com>
+           Andrew Pinski  <apinski@cavium.com>
 
        * config/mips/mips.h (CASE_VECTOR_MODE): For not
        TARGET_MIPS16_SHORT_JUMP_TABLES use ptr_mode.
index 43c15e4e76d6934f7a832d538d869fcc2eff621b..55e4b5610dfac1b8111b0cbac59a51501ed93b0a 100644 (file)
   struct ix86_address parts;
   int ok;
 
+  if (TARGET_64BIT || !flag_pic)
+    return true;
+
   ok = ix86_decompose_address (XEXP (op, 0), &parts);
   gcc_assert (ok);
 
index 0b79bdec92e0a0f701285150572bf7c57dc702ea..50bedcf0dff320027b88ecdb314354b1bf08bddf 100644 (file)
 ])
 
 (define_c_enum "unspecv" [
-  UNSPECV_CMPXCHG_1
-  UNSPECV_CMPXCHG_2
-  UNSPECV_CMPXCHG_3
-  UNSPECV_CMPXCHG_4
+  UNSPECV_CMPXCHG
   UNSPECV_XCHG
   UNSPECV_LOCK
 ])
   "TARGET_CMPXCHG"
 {
   emit_insn
-   (gen_atomic_compare_and_swap_single<mode>
+   (gen_atomic_compare_and_swap<mode>_1
     (operands[1], operands[2], operands[3], operands[4], operands[6]));
   ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
                     const0_rtx);
 (define_mode_iterator CASMODE
   [(DI "TARGET_64BIT || TARGET_CMPXCHG8B")
    (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
-(define_mode_iterator DCASMODE
-  [(DI "!TARGET_64BIT && TARGET_CMPXCHG8B && !flag_pic")
-   (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
-(define_mode_attr doublemodesuffix [(DI "8") (TI "16")])
-(define_mode_attr DCASHMODE [(DI "SI") (TI "DI")])
+(define_mode_attr CASHMODE [(DI "SI") (TI "DI")])
 
 (define_expand "atomic_compare_and_swap<mode>"
   [(match_operand:QI 0 "register_operand")     ;; bool success output
   if (<MODE>mode == DImode && TARGET_64BIT)
     {
       emit_insn
-       (gen_atomic_compare_and_swap_singledi
+       (gen_atomic_compare_and_swapdi_1
        (operands[1], operands[2], operands[3], operands[4], operands[6]));
     }
   else
     {
-      enum machine_mode hmode = <DCASHMODE>mode;
+      enum machine_mode hmode = <CASHMODE>mode;
       rtx lo_o, lo_e, lo_n, hi_o, hi_e, hi_n, mem;
 
       lo_o = operands[1];
       lo_e = gen_lowpart (hmode, lo_e);
       lo_n = gen_lowpart (hmode, lo_n);
 
-      if (<MODE>mode == DImode
-         && !TARGET_64BIT
-         && flag_pic
-         && !cmpxchg8b_pic_memory_operand (mem, DImode))
-       mem = replace_equiv_address (mem, force_reg (Pmode, XEXP (mem, 0)));
+      if (!cmpxchg8b_pic_memory_operand (mem, <MODE>mode))
+       mem = replace_equiv_address (mem, force_reg (Pmode, XEXP (mem, 0)));
 
-      emit_insn (gen_atomic_compare_and_swap_double<mode>
-                (lo_o, hi_o, mem, lo_e, hi_e, lo_n, hi_n, operands[6]));
+      emit_insn
+       (gen_atomic_compare_and_swap<mode>_doubleword
+        (lo_o, hi_o, mem, lo_e, hi_e, lo_n, hi_n, operands[6]));
     }
+
   ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
                     const0_rtx);
   DONE;
 })
 
-(define_insn "atomic_compare_and_swap_single<mode>"
+(define_insn "atomic_compare_and_swap<mode>_1"
   [(set (match_operand:SWI 0 "register_operand" "=a")
        (unspec_volatile:SWI
          [(match_operand:SWI 1 "memory_operand" "+m")
           (match_operand:SWI 2 "register_operand" "0")
           (match_operand:SWI 3 "register_operand" "<r>")
           (match_operand:SI 4 "const_int_operand")]
-         UNSPECV_CMPXCHG_1))
+         UNSPECV_CMPXCHG))
    (set (match_dup 1)
-       (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG_2))
+       (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    (set (reg:CCZ FLAGS_REG)
-        (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG_3))]
+        (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))]
   "TARGET_CMPXCHG"
   "lock{%;} %K4cmpxchg{<imodesuffix>}\t{%3, %1|%1, %3}")
 
 ;; not match the gcc register numbering, so the pair must be CX:BX.
 ;; That said, in order to take advantage of possible lower-subreg opts,
 ;; treat all of the integral operands in the same way.
-(define_insn "atomic_compare_and_swap_double<mode>"
-  [(set (match_operand:<DCASHMODE> 0 "register_operand" "=a")
-       (unspec_volatile:<DCASHMODE>
-         [(match_operand:DCASMODE 2 "memory_operand" "+m")
-          (match_operand:<DCASHMODE> 3 "register_operand" "0")
-          (match_operand:<DCASHMODE> 4 "register_operand" "1")
-          (match_operand:<DCASHMODE> 5 "register_operand" "b")
-          (match_operand:<DCASHMODE> 6 "register_operand" "c")
-          (match_operand:SI 7 "const_int_operand")]
-         UNSPECV_CMPXCHG_1))
-   (set (match_operand:<DCASHMODE> 1 "register_operand" "=d")
-       (unspec_volatile:<DCASHMODE> [(const_int 0)] UNSPECV_CMPXCHG_2))
-   (set (match_dup 2)
-       (unspec_volatile:DCASMODE [(const_int 0)] UNSPECV_CMPXCHG_3))
-   (set (reg:CCZ FLAGS_REG)
-        (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG_4))]
-  ""
-  "lock{%;} %K7cmpxchg<doublemodesuffix>b\t%2")
-
-;; Theoretically we'd like to use constraint "r" (any reg) for op5,
-;; but that includes ecx.  If op5 and op6 are the same (like when
-;; the input is -1LL) GCC might chose to allocate op5 to ecx, like
-;; op6.  This breaks, as the xchg will move the PIC register contents
-;; to %ecx then --> boom.  Operands 5 and 6 really need to be different
-;; registers, which in this case means op5 must not be ecx.  Instead
-;; of playing tricks with fake early clobbers or the like we just
-;; enumerate all regs possible here, which (as this is !TARGET_64BIT)
-;; are just esi and edi.
-(define_insn "*atomic_compare_and_swap_doubledi_pic"
-  [(set (match_operand:SI 0 "register_operand" "=a")
-       (unspec_volatile:SI
-         [(match_operand:DI 2 "cmpxchg8b_pic_memory_operand" "+m")
-          (match_operand:SI 3 "register_operand" "0")
-          (match_operand:SI 4 "register_operand" "1")
-          (match_operand:SI 5 "register_operand" "SD")
-          (match_operand:SI 6 "register_operand" "c")
+
+;; Operands 5 and 6 really need to be different registers, which in
+;; this case means op5 must not be ecx.  If op5 and op6 are the same
+;; (like when the input is -1LL) GCC might chose to allocate op5 to ecx,
+;; like op6.  This breaks, as the xchg will move the PIC register
+;; contents to %ecx then --> boom.
+
+(define_mode_attr doublemodesuffix [(SI "8") (DI "16")])
+(define_mode_attr regprefix [(SI "e") (DI "r")])
+
+(define_insn "atomic_compare_and_swap<dwi>_doubleword"
+  [(set (match_operand:DWIH 0 "register_operand" "=a,a")
+       (unspec_volatile:DWIH
+         [(match_operand:<DWI> 2 "cmpxchg8b_pic_memory_operand" "+m,m")
+          (match_operand:DWIH 3 "register_operand" "0,0")
+          (match_operand:DWIH 4 "register_operand" "1,1")
+          (match_operand:DWIH 5 "register_operand" "b,!*r")
+          (match_operand:DWIH 6 "register_operand" "c,c")
           (match_operand:SI 7 "const_int_operand")]
-         UNSPECV_CMPXCHG_1))
-   (set (match_operand:SI 1 "register_operand" "=d")
-       (unspec_volatile:SI [(const_int 0)] UNSPECV_CMPXCHG_2))
+         UNSPECV_CMPXCHG))
+   (set (match_operand:DWIH 1 "register_operand" "=d,d")
+       (unspec_volatile:DWIH [(const_int 0)] UNSPECV_CMPXCHG))
    (set (match_dup 2)
-       (unspec_volatile:DI [(const_int 0)] UNSPECV_CMPXCHG_3))
+       (unspec_volatile:<DWI> [(const_int 0)] UNSPECV_CMPXCHG))
    (set (reg:CCZ FLAGS_REG)
-        (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG_4))]
-  "!TARGET_64BIT && TARGET_CMPXCHG8B && flag_pic"
-  "xchg{l}\t%%ebx, %5\;lock{%;} %K7cmpxchg8b\t%2\;xchg{l}\t%%ebx, %5")
+        (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))
+   (clobber (match_scratch:DWIH 8 "=X,&5"))]
+  "TARGET_CMPXCHG<doublemodesuffix>B"
+{
+  bool swap = REGNO (operands[5]) != BX_REG;
+
+  if (swap)
+    output_asm_insn ("xchg{<imodesuffix>}\t%%<regprefix>bx, %5", operands);
+
+  output_asm_insn ("lock{%;} %K7cmpxchg<doublemodesuffix>b\t%2", operands);
+
+  if (swap)
+    output_asm_insn ("xchg{<imodesuffix>}\t%%<regprefix>bx, %5", operands);
+
+  return "";
+})
 
 ;; For operand 2 nonmemory_operand predicate is used instead of
 ;; register_operand to allow combiner to better optimize atomic
index 1306ba61dd8c3e35b06bdd7c0c2be2060740a29d..6f292861348171325dec8c580c173c03ef7165df 100644 (file)
@@ -1,3 +1,8 @@
+2012-08-27  Uros Bizjak  <ubizjak@gmail.com>
+
+       PR target/46254
+       * gcc.target/i386/pr46254.c: New test.
+
 2012-08-27  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * gcc.target/mips/ext_ins.c, gcc.target/mips/octeon-pop-2.c,
diff --git a/gcc/testsuite/gcc.target/i386/pr46254.c b/gcc/testsuite/gcc.target/i386/pr46254.c
new file mode 100644 (file)
index 0000000..512287a
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target fpic } */
+/* { dg-options "-O2 -mcx16 -fpic -mcmodel=large" } */
+
+__int128 i;
+
+void test ()
+{
+  __sync_val_compare_and_swap (&i, i, i);
+}