diff options
author | Uros Bizjak <uros@gcc.gnu.org> | 2012-08-27 23:13:07 +0200 |
---|---|---|
committer | Uros Bizjak <uros@gcc.gnu.org> | 2012-08-27 23:13:07 +0200 |
commit | 28591f4a8cbfab06692dcd8ae9a69ef95ecdf378 (patch) | |
tree | b4bfc575aa3d64996935f92d5870b3d297d870c0 /gcc | |
parent | d7920cf0719e3cc28e61a98d640f6d1cb46d797e (diff) | |
download | gcc-28591f4a8cbfab06692dcd8ae9a69ef95ecdf378.zip gcc-28591f4a8cbfab06692dcd8ae9a69ef95ecdf378.tar.gz gcc-28591f4a8cbfab06692dcd8ae9a69ef95ecdf378.tar.bz2 |
re PR target/46254 (ICE: in find_reloads, at reload.c:3806 (unable to generate reloads) with -fPIC -mcmodel={medium|large} and __sync_val_compare_and_swap)
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 35 | ||||
-rw-r--r-- | gcc/config/i386/predicates.md | 3 | ||||
-rw-r--r-- | gcc/config/i386/sync.md | 119 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr46254.c | 11 |
5 files changed, 102 insertions, 71 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 13813df..5139e98 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. @@ -80,12 +105,12 @@ 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. @@ -100,7 +125,7 @@ * 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. diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 43c15e4..55e4b56 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -971,6 +971,9 @@ struct ix86_address parts; int ok; + if (TARGET_64BIT || !flag_pic) + return true; + ok = ix86_decompose_address (XEXP (op, 0), &parts); gcc_assert (ok); diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md index 0b79bde..50bedcf 100644 --- a/gcc/config/i386/sync.md +++ b/gcc/config/i386/sync.md @@ -28,10 +28,7 @@ ]) (define_c_enum "unspecv" [ - UNSPECV_CMPXCHG_1 - UNSPECV_CMPXCHG_2 - UNSPECV_CMPXCHG_3 - UNSPECV_CMPXCHG_4 + UNSPECV_CMPXCHG UNSPECV_XCHG UNSPECV_LOCK ]) @@ -316,7 +313,7 @@ "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); @@ -326,11 +323,7 @@ (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 @@ -346,12 +339,12 @@ 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]; @@ -365,32 +358,31 @@ 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}") @@ -399,52 +391,47 @@ ;; 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1306ba6..6f29286 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..512287a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr46254.c @@ -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); +} |