+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
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"
;; 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.
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));
;; 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)
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));
;; 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)