diff options
author | Jakub Jelinek <jakub@redhat.com> | 2009-03-12 21:45:39 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2009-03-12 21:45:39 +0100 |
commit | 03a181983d217bfc13d295e698edc1eae0e8dacd (patch) | |
tree | beadbfad946cf940235a072c010af8519bd6c4cf /gcc/config/i386 | |
parent | 122c59c73bbf3ef40c786f4faab80955a677553d (diff) | |
download | gcc-03a181983d217bfc13d295e698edc1eae0e8dacd.zip gcc-03a181983d217bfc13d295e698edc1eae0e8dacd.tar.gz gcc-03a181983d217bfc13d295e698edc1eae0e8dacd.tar.bz2 |
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
Diffstat (limited to 'gcc/config/i386')
-rw-r--r-- | gcc/config/i386/predicates.md | 28 | ||||
-rw-r--r-- | gcc/config/i386/sync.md | 28 |
2 files changed, 49 insertions, 7 deletions
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index b2bef64..f1c7103 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -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" diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md index e267574..05aad00 100644 --- a/gcc/config/i386/sync.md +++ b/gcc/config/i386/sync.md @@ -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) |