Commit 28591f4a by Uros Bizjak

re PR target/46254 (ICE: in find_reloads, at reload.c:3806 (unable to generate…

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
parent d7920cf0
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> 2012-08-27 Walter Lee <walt@tilera.com>
* doc/md.texi (TILE-Gx): Fix typo. * doc/md.texi (TILE-Gx): Fix typo.
...@@ -6,9 +31,9 @@ ...@@ -6,9 +31,9 @@
* config/tilegx/tilegx.c (tilegx_function_profiler): Fix typo. * config/tilegx/tilegx.c (tilegx_function_profiler): Fix typo.
config/tilepro/tilepro.c (tilepro_function_profiler): Ditto. config/tilepro/tilepro.c (tilepro_function_profiler): Ditto.
2012-08-27 Walter Lee <walt@tilera.com> 2012-08-27 Walter Lee <walt@tilera.com>
* config/tilegx/tilegx.md (*bfins): Rename to insn_bfins. * config/tilegx/tilegx.md (*bfins): Rename to insn_bfins.
(insn_bfins): Delete. (insn_bfins): Delete.
...@@ -80,12 +105,12 @@ ...@@ -80,12 +105,12 @@
this section. this section.
2012-08-26 Gerald Pfeifer <gerald@pfeifer.com> 2012-08-26 Gerald Pfeifer <gerald@pfeifer.com>
* doc/tm.texi.in (Misc): Move descriptions of NO_DOLLAR_IN_LABEL * doc/tm.texi.in (Misc): Move descriptions of NO_DOLLAR_IN_LABEL
and NO_DOT_IN_LABEL from here... and NO_DOT_IN_LABEL from here...
(Label Output): ...to here. (Label Output): ...to here.
* doc/tm.texi: Regenerate. * doc/tm.texi: Regenerate.
2012-08-26 Gerald Pfeifer <gerald@pfeifer.com> 2012-08-26 Gerald Pfeifer <gerald@pfeifer.com>
* doc/invoke.texi (C++ Dialect Options): Add missing space. * doc/invoke.texi (C++ Dialect Options): Add missing space.
...@@ -100,7 +125,7 @@ ...@@ -100,7 +125,7 @@
* doc/extend.texi (__atomic Builtins): Remove space before comma. * doc/extend.texi (__atomic Builtins): Remove space before comma.
2012-08-25 Richard Sandiford <rdsandiford@googlemail.com> 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 * config/mips/mips.h (CASE_VECTOR_MODE): For not
TARGET_MIPS16_SHORT_JUMP_TABLES use ptr_mode. TARGET_MIPS16_SHORT_JUMP_TABLES use ptr_mode.
......
...@@ -971,6 +971,9 @@ ...@@ -971,6 +971,9 @@
struct ix86_address parts; struct ix86_address parts;
int ok; int ok;
if (TARGET_64BIT || !flag_pic)
return true;
ok = ix86_decompose_address (XEXP (op, 0), &parts); ok = ix86_decompose_address (XEXP (op, 0), &parts);
gcc_assert (ok); gcc_assert (ok);
......
...@@ -28,10 +28,7 @@ ...@@ -28,10 +28,7 @@
]) ])
(define_c_enum "unspecv" [ (define_c_enum "unspecv" [
UNSPECV_CMPXCHG_1 UNSPECV_CMPXCHG
UNSPECV_CMPXCHG_2
UNSPECV_CMPXCHG_3
UNSPECV_CMPXCHG_4
UNSPECV_XCHG UNSPECV_XCHG
UNSPECV_LOCK UNSPECV_LOCK
]) ])
...@@ -316,7 +313,7 @@ ...@@ -316,7 +313,7 @@
"TARGET_CMPXCHG" "TARGET_CMPXCHG"
{ {
emit_insn 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])); (operands[1], operands[2], operands[3], operands[4], operands[6]));
ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG), ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
const0_rtx); const0_rtx);
...@@ -326,11 +323,7 @@ ...@@ -326,11 +323,7 @@
(define_mode_iterator CASMODE (define_mode_iterator CASMODE
[(DI "TARGET_64BIT || TARGET_CMPXCHG8B") [(DI "TARGET_64BIT || TARGET_CMPXCHG8B")
(TI "TARGET_64BIT && TARGET_CMPXCHG16B")]) (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
(define_mode_iterator DCASMODE (define_mode_attr CASHMODE [(DI "SI") (TI "DI")])
[(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_expand "atomic_compare_and_swap<mode>" (define_expand "atomic_compare_and_swap<mode>"
[(match_operand:QI 0 "register_operand") ;; bool success output [(match_operand:QI 0 "register_operand") ;; bool success output
...@@ -346,12 +339,12 @@ ...@@ -346,12 +339,12 @@
if (<MODE>mode == DImode && TARGET_64BIT) if (<MODE>mode == DImode && TARGET_64BIT)
{ {
emit_insn emit_insn
(gen_atomic_compare_and_swap_singledi (gen_atomic_compare_and_swapdi_1
(operands[1], operands[2], operands[3], operands[4], operands[6])); (operands[1], operands[2], operands[3], operands[4], operands[6]));
} }
else 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; rtx lo_o, lo_e, lo_n, hi_o, hi_e, hi_n, mem;
lo_o = operands[1]; lo_o = operands[1];
...@@ -365,32 +358,31 @@ ...@@ -365,32 +358,31 @@
lo_e = gen_lowpart (hmode, lo_e); lo_e = gen_lowpart (hmode, lo_e);
lo_n = gen_lowpart (hmode, lo_n); lo_n = gen_lowpart (hmode, lo_n);
if (<MODE>mode == DImode if (!cmpxchg8b_pic_memory_operand (mem, <MODE>mode))
&& !TARGET_64BIT mem = replace_equiv_address (mem, force_reg (Pmode, XEXP (mem, 0)));
&& flag_pic
&& !cmpxchg8b_pic_memory_operand (mem, DImode))
mem = replace_equiv_address (mem, force_reg (Pmode, XEXP (mem, 0)));
emit_insn (gen_atomic_compare_and_swap_double<mode> emit_insn
(lo_o, hi_o, mem, lo_e, hi_e, lo_n, hi_n, operands[6])); (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), ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
const0_rtx); const0_rtx);
DONE; 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") [(set (match_operand:SWI 0 "register_operand" "=a")
(unspec_volatile:SWI (unspec_volatile:SWI
[(match_operand:SWI 1 "memory_operand" "+m") [(match_operand:SWI 1 "memory_operand" "+m")
(match_operand:SWI 2 "register_operand" "0") (match_operand:SWI 2 "register_operand" "0")
(match_operand:SWI 3 "register_operand" "<r>") (match_operand:SWI 3 "register_operand" "<r>")
(match_operand:SI 4 "const_int_operand")] (match_operand:SI 4 "const_int_operand")]
UNSPECV_CMPXCHG_1)) UNSPECV_CMPXCHG))
(set (match_dup 1) (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) (set (reg:CCZ FLAGS_REG)
(unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG_3))] (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))]
"TARGET_CMPXCHG" "TARGET_CMPXCHG"
"lock{%;} %K4cmpxchg{<imodesuffix>}\t{%3, %1|%1, %3}") "lock{%;} %K4cmpxchg{<imodesuffix>}\t{%3, %1|%1, %3}")
...@@ -399,52 +391,47 @@ ...@@ -399,52 +391,47 @@
;; not match the gcc register numbering, so the pair must be CX:BX. ;; 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, ;; That said, in order to take advantage of possible lower-subreg opts,
;; treat all of the integral operands in the same way. ;; 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") ;; Operands 5 and 6 really need to be different registers, which in
(unspec_volatile:<DCASHMODE> ;; this case means op5 must not be ecx. If op5 and op6 are the same
[(match_operand:DCASMODE 2 "memory_operand" "+m") ;; (like when the input is -1LL) GCC might chose to allocate op5 to ecx,
(match_operand:<DCASHMODE> 3 "register_operand" "0") ;; like op6. This breaks, as the xchg will move the PIC register
(match_operand:<DCASHMODE> 4 "register_operand" "1") ;; contents to %ecx then --> boom.
(match_operand:<DCASHMODE> 5 "register_operand" "b")
(match_operand:<DCASHMODE> 6 "register_operand" "c") (define_mode_attr doublemodesuffix [(SI "8") (DI "16")])
(match_operand:SI 7 "const_int_operand")] (define_mode_attr regprefix [(SI "e") (DI "r")])
UNSPECV_CMPXCHG_1))
(set (match_operand:<DCASHMODE> 1 "register_operand" "=d") (define_insn "atomic_compare_and_swap<dwi>_doubleword"
(unspec_volatile:<DCASHMODE> [(const_int 0)] UNSPECV_CMPXCHG_2)) [(set (match_operand:DWIH 0 "register_operand" "=a,a")
(set (match_dup 2) (unspec_volatile:DWIH
(unspec_volatile:DCASMODE [(const_int 0)] UNSPECV_CMPXCHG_3)) [(match_operand:<DWI> 2 "cmpxchg8b_pic_memory_operand" "+m,m")
(set (reg:CCZ FLAGS_REG) (match_operand:DWIH 3 "register_operand" "0,0")
(unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG_4))] (match_operand:DWIH 4 "register_operand" "1,1")
"" (match_operand:DWIH 5 "register_operand" "b,!*r")
"lock{%;} %K7cmpxchg<doublemodesuffix>b\t%2") (match_operand:DWIH 6 "register_operand" "c,c")
;; 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")
(match_operand:SI 7 "const_int_operand")] (match_operand:SI 7 "const_int_operand")]
UNSPECV_CMPXCHG_1)) UNSPECV_CMPXCHG))
(set (match_operand:SI 1 "register_operand" "=d") (set (match_operand:DWIH 1 "register_operand" "=d,d")
(unspec_volatile:SI [(const_int 0)] UNSPECV_CMPXCHG_2)) (unspec_volatile:DWIH [(const_int 0)] UNSPECV_CMPXCHG))
(set (match_dup 2) (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) (set (reg:CCZ FLAGS_REG)
(unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG_4))] (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))
"!TARGET_64BIT && TARGET_CMPXCHG8B && flag_pic" (clobber (match_scratch:DWIH 8 "=X,&5"))]
"xchg{l}\t%%ebx, %5\;lock{%;} %K7cmpxchg8b\t%2\;xchg{l}\t%%ebx, %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 ;; For operand 2 nonmemory_operand predicate is used instead of
;; register_operand to allow combiner to better optimize atomic ;; register_operand to allow combiner to better optimize atomic
......
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> 2012-08-27 Richard Sandiford <rdsandiford@googlemail.com>
* gcc.target/mips/ext_ins.c, gcc.target/mips/octeon-pop-2.c, * gcc.target/mips/ext_ins.c, gcc.target/mips/octeon-pop-2.c,
......
/* { 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment