builtins.c (expand_builtin_sync_operation, [...]): Care for extending CONST_INTs correctly.
* builtins.c (expand_builtin_sync_operation, expand_builtin_compare_and_swap, expand_builtin_lock_test_and_set): Care for extending CONST_INTs correctly. * config/i386/sync.md (sync_double_compare_and_swapdi_pic, sync_double_compare_and_swap_ccdi_pic): Use "SD" as constraint for operand 3. From-SVN: r123064
This commit is contained in:
parent
b5e5ca5fd3
commit
1e395249a9
@ -1,3 +1,14 @@
|
||||
2007-03-19 Michael Matz <matz@suse.de>
|
||||
|
||||
* builtins.c (expand_builtin_sync_operation,
|
||||
expand_builtin_compare_and_swap,
|
||||
expand_builtin_lock_test_and_set): Care for extending CONST_INTs
|
||||
correctly.
|
||||
|
||||
* config/i386/sync.md (sync_double_compare_and_swapdi_pic,
|
||||
sync_double_compare_and_swap_ccdi_pic): Use "SD" as constraint
|
||||
for operand 3.
|
||||
|
||||
2007-03-19 Andreas Krebbel <krebbel1@de.ibm.com>
|
||||
|
||||
* doc/tm.texi: Add brackets around the return type of
|
||||
|
@ -5771,13 +5771,18 @@ expand_builtin_sync_operation (enum machine_mode mode, tree exp,
|
||||
rtx target, bool ignore)
|
||||
{
|
||||
rtx val, mem;
|
||||
enum machine_mode old_mode;
|
||||
|
||||
/* Expand the operands. */
|
||||
mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
|
||||
|
||||
val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL, mode, EXPAND_NORMAL);
|
||||
/* If VAL is promoted to a wider mode, convert it back to MODE. */
|
||||
val = convert_to_mode (mode, val, 1);
|
||||
/* If VAL is promoted to a wider mode, convert it back to MODE. Take care
|
||||
of CONST_INTs, where we know the old_mode only from the call argument. */
|
||||
old_mode = GET_MODE (val);
|
||||
if (old_mode == VOIDmode)
|
||||
old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
|
||||
val = convert_modes (mode, old_mode, val, 1);
|
||||
|
||||
if (ignore)
|
||||
return expand_sync_operation (mem, val, code);
|
||||
@ -5795,18 +5800,27 @@ expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
|
||||
bool is_bool, rtx target)
|
||||
{
|
||||
rtx old_val, new_val, mem;
|
||||
enum machine_mode old_mode;
|
||||
|
||||
/* Expand the operands. */
|
||||
mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
|
||||
|
||||
|
||||
old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL, mode, EXPAND_NORMAL);
|
||||
/* If OLD_VAL is promoted to a wider mode, convert it back to MODE. */
|
||||
old_val = convert_to_mode (mode, old_val, 1);
|
||||
/* If VAL is promoted to a wider mode, convert it back to MODE. Take care
|
||||
of CONST_INTs, where we know the old_mode only from the call argument. */
|
||||
old_mode = GET_MODE (old_val);
|
||||
if (old_mode == VOIDmode)
|
||||
old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
|
||||
old_val = convert_modes (mode, old_mode, old_val, 1);
|
||||
|
||||
new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL, mode, EXPAND_NORMAL);
|
||||
/* If NEW_VAL is promoted to a wider mode, convert it back to MODE. */
|
||||
new_val = convert_to_mode (mode, new_val, 1);
|
||||
/* If VAL is promoted to a wider mode, convert it back to MODE. Take care
|
||||
of CONST_INTs, where we know the old_mode only from the call argument. */
|
||||
old_mode = GET_MODE (new_val);
|
||||
if (old_mode == VOIDmode)
|
||||
old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2)));
|
||||
new_val = convert_modes (mode, old_mode, new_val, 1);
|
||||
|
||||
if (is_bool)
|
||||
return expand_bool_compare_and_swap (mem, old_val, new_val, target);
|
||||
@ -5825,12 +5839,17 @@ expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp,
|
||||
rtx target)
|
||||
{
|
||||
rtx val, mem;
|
||||
enum machine_mode old_mode;
|
||||
|
||||
/* Expand the operands. */
|
||||
mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
|
||||
val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL, mode, EXPAND_NORMAL);
|
||||
/* If VAL is promoted to a wider mode, convert it back to MODE. */
|
||||
val = convert_to_mode (mode, val, 1);
|
||||
/* If VAL is promoted to a wider mode, convert it back to MODE. Take care
|
||||
of CONST_INTs, where we know the old_mode only from the call argument. */
|
||||
old_mode = GET_MODE (val);
|
||||
if (old_mode == VOIDmode)
|
||||
old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
|
||||
val = convert_modes (mode, old_mode, val, 1);
|
||||
|
||||
return expand_sync_lock_test_and_set (mem, val, target);
|
||||
}
|
||||
|
@ -98,6 +98,15 @@
|
||||
""
|
||||
"lock{\;| }cmpxchg<doublemodesuffix>b{\t| }%1")
|
||||
|
||||
;; Theoretically we'd like to use constraint "r" (any reg) for operand
|
||||
;; 3, but that includes ecx. If operand 3 and 4 are the same (like when
|
||||
;; the input is -1LL) GCC might chose to allocate operand 3 to ecx, like
|
||||
;; operand 4. This breaks, as the xchg will move the PIC register contents
|
||||
;; to %ecx then --> boom. Operands 3 and 4 really need to be different
|
||||
;; registers, which in this case means operand 3 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 "*sync_double_compare_and_swapdi_pic"
|
||||
[(set (match_operand:DI 0 "register_operand" "=A")
|
||||
(match_operand:DI 1 "memory_operand" "+m"))
|
||||
@ -105,7 +114,7 @@
|
||||
(unspec_volatile:DI
|
||||
[(match_dup 1)
|
||||
(match_operand:DI 2 "register_operand" "A")
|
||||
(match_operand:SI 3 "register_operand" "r")
|
||||
(match_operand:SI 3 "register_operand" "SD")
|
||||
(match_operand:SI 4 "register_operand" "c")]
|
||||
UNSPECV_CMPXCHG_1))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
@ -189,6 +198,8 @@
|
||||
""
|
||||
"lock{\;| }cmpxchg<doublemodesuffix>b{\t| }%1")
|
||||
|
||||
;; See above for the explanation of using the constraint "SD" for
|
||||
;; 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"))
|
||||
@ -196,7 +207,7 @@
|
||||
(unspec_volatile:DI
|
||||
[(match_dup 1)
|
||||
(match_operand:DI 2 "register_operand" "A")
|
||||
(match_operand:SI 3 "register_operand" "r")
|
||||
(match_operand:SI 3 "register_operand" "SD")
|
||||
(match_operand:SI 4 "register_operand" "c")]
|
||||
UNSPECV_CMPXCHG_1))
|
||||
(set (reg:CCZ FLAGS_REG)
|
||||
|
Loading…
Reference in New Issue
Block a user