re PR target/39431 (ICE in spill_failure, at reload1.c:2093)

PR target/39431
	* config/i386/predicates.md (cmpxchg8b_pic_memory_operand): New
	predicate.
	* config/i386/sync.md (sync_compare_and_swap<mode>,
	sync_compare_and_swap_cc<mode>): For DImode with -m32 -fpic check
	if operands[1] is cmpxchg8b_pic_memory_operand, if not force address
	into a register.
	(sync_double_compare_and_swapdi_pic,
	sync_double_compare_and_swap_ccdi_pic): Require operand 1 to be
	cmpxchg8b_pic_memory_operand instead of just memory_operand.

	* gcc.target/i386/pr39431.c: New test.

From-SVN: r144825
This commit is contained in:
Jakub Jelinek 2009-03-12 21:45:39 +01:00 committed by Jakub Jelinek
parent 122c59c73b
commit 03a181983d
5 changed files with 82 additions and 7 deletions

View file

@ -1,3 +1,16 @@
2008-03-12 Jakub Jelinek <jakub@redhat.com>
PR target/39431
* config/i386/predicates.md (cmpxchg8b_pic_memory_operand): New
predicate.
* config/i386/sync.md (sync_compare_and_swap<mode>,
sync_compare_and_swap_cc<mode>): For DImode with -m32 -fpic check
if operands[1] is cmpxchg8b_pic_memory_operand, if not force address
into a register.
(sync_double_compare_and_swapdi_pic,
sync_double_compare_and_swap_ccdi_pic): Require operand 1 to be
cmpxchg8b_pic_memory_operand instead of just memory_operand.
2009-03-12 H.J. Lu <hongjiu.lu@intel.com>
PR target/39445

View file

@ -887,6 +887,34 @@
return parts.disp != NULL_RTX;
})
;; Returns 1 if OP is memory operand which will need zero or
;; one register at most, not counting stack pointer or frame pointer.
(define_predicate "cmpxchg8b_pic_memory_operand"
(match_operand 0 "memory_operand")
{
struct ix86_address parts;
int ok;
ok = ix86_decompose_address (XEXP (op, 0), &parts);
gcc_assert (ok);
if (parts.base == NULL_RTX
|| parts.base == arg_pointer_rtx
|| parts.base == frame_pointer_rtx
|| parts.base == hard_frame_pointer_rtx
|| parts.base == stack_pointer_rtx)
return 1;
if (parts.index == NULL_RTX
|| parts.index == arg_pointer_rtx
|| parts.index == frame_pointer_rtx
|| parts.index == hard_frame_pointer_rtx
|| parts.index == stack_pointer_rtx)
return 1;
return 0;
})
;; Returns 1 if OP is memory operand that cannot be represented
;; by the modRM array.
(define_predicate "long_memory_operand"

View file

@ -1,5 +1,5 @@
;; GCC machine description for i386 synchronization instructions.
;; Copyright (C) 2005, 2006, 2007, 2008
;; Copyright (C) 2005, 2006, 2007, 2008, 2009
;; Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@ -82,8 +82,15 @@
low = force_reg (hmode, low);
high = force_reg (hmode, high);
if (<MODE>mode == DImode)
emit_insn (gen_sync_double_compare_and_swapdi
(operands[0], operands[1], operands[2], low, high));
{
if (flag_pic && !cmpxchg8b_pic_memory_operand (operands[1], DImode))
operands[1] = replace_equiv_address (operands[1],
force_reg (Pmode,
XEXP (operands[1],
0)));
emit_insn (gen_sync_double_compare_and_swapdi
(operands[0], operands[1], operands[2], low, high));
}
else if (<MODE>mode == TImode)
emit_insn (gen_sync_double_compare_and_swapti
(operands[0], operands[1], operands[2], low, high));
@ -131,7 +138,7 @@
;; are just esi and edi.
(define_insn "*sync_double_compare_and_swapdi_pic"
[(set (match_operand:DI 0 "register_operand" "=A")
(match_operand:DI 1 "memory_operand" "+m"))
(match_operand:DI 1 "cmpxchg8b_pic_memory_operand" "+m"))
(set (match_dup 1)
(unspec_volatile:DI
[(match_dup 1)
@ -173,8 +180,15 @@
low = force_reg (hmode, low);
high = force_reg (hmode, high);
if (<MODE>mode == DImode)
emit_insn (gen_sync_double_compare_and_swap_ccdi
(operands[0], operands[1], operands[2], low, high));
{
if (flag_pic && !cmpxchg8b_pic_memory_operand (operands[1], DImode))
operands[1] = replace_equiv_address (operands[1],
force_reg (Pmode,
XEXP (operands[1],
0)));
emit_insn (gen_sync_double_compare_and_swap_ccdi
(operands[0], operands[1], operands[2], low, high));
}
else if (<MODE>mode == TImode)
emit_insn (gen_sync_double_compare_and_swap_ccti
(operands[0], operands[1], operands[2], low, high));
@ -224,7 +238,7 @@
;; operand 3.
(define_insn "*sync_double_compare_and_swap_ccdi_pic"
[(set (match_operand:DI 0 "register_operand" "=A")
(match_operand:DI 1 "memory_operand" "+m"))
(match_operand:DI 1 "cmpxchg8b_pic_memory_operand" "+m"))
(set (match_dup 1)
(unspec_volatile:DI
[(match_dup 1)

View file

@ -1,3 +1,8 @@
2008-03-12 Jakub Jelinek <jakub@redhat.com>
PR target/39431
* gcc.target/i386/pr39431.c: New test.
2009-03-12 H.J. Lu <hongjiu.lu@intel.com>
PR target/39445

View file

@ -0,0 +1,15 @@
/* PR target/39431 */
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-options "-O2 -march=i686 -fpic" { target { ilp32 && fpic } } } */
extern void bar (char *, int);
int
foo (long long *p, long long oldv, long long *q, int n)
{
char buf[n];
bar (buf, n);
p[256 + n] = __sync_val_compare_and_swap (p + n, oldv, oldv + 6);
return __sync_bool_compare_and_swap (q + n, oldv, oldv + 8);
}