aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/i386
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2009-03-12 21:45:39 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2009-03-12 21:45:39 +0100
commit03a181983d217bfc13d295e698edc1eae0e8dacd (patch)
treebeadbfad946cf940235a072c010af8519bd6c4cf /gcc/config/i386
parent122c59c73bbf3ef40c786f4faab80955a677553d (diff)
downloadgcc-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.md28
-rw-r--r--gcc/config/i386/sync.md28
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)