Hello! As shown in the attached testcase, arguments of various __atomic builtins should be converted as signed, so the immediates get properly extended.
2013-10-08 Uros Bizjak <ubiz...@gmail.com> * optabs.c (maybe_emit_atomic_exchange): Convert operands as signed. (maybe_emit_sync_lock_test_and_set): Ditto. (expand_atomic_compare_and_swap): Ditto. (maybe_emit_op): Ditto. testsuite/ChangeLog: 2013-10-08 Uros Bizjak <ubiz...@gmail.com> * g++.dg/ext/atomic-2.C: New test. Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32}. OK for mainline and release branches? Uros.
Index: optabs.c =================================================================== --- optabs.c (revision 203285) +++ optabs.c (working copy) @@ -7041,7 +7041,7 @@ maybe_emit_atomic_exchange (rtx target, rtx mem, r create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); /* VAL may have been promoted to a wider mode. Shrink it if so. */ - create_convert_operand_to (&ops[2], val, mode, true); + create_convert_operand_to (&ops[2], val, mode, false); create_integer_operand (&ops[3], model); if (maybe_expand_insn (icode, 4, ops)) return ops[0].value; @@ -7081,7 +7081,7 @@ maybe_emit_sync_lock_test_and_set (rtx target, rtx create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); /* VAL may have been promoted to a wider mode. Shrink it if so. */ - create_convert_operand_to (&ops[2], val, mode, true); + create_convert_operand_to (&ops[2], val, mode, false); if (maybe_expand_insn (icode, 3, ops)) return ops[0].value; } @@ -7336,8 +7336,8 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, create_output_operand (&ops[0], target_bool, bool_mode); create_output_operand (&ops[1], target_oval, mode); create_fixed_operand (&ops[2], mem); - create_convert_operand_to (&ops[3], expected, mode, true); - create_convert_operand_to (&ops[4], desired, mode, true); + create_convert_operand_to (&ops[3], expected, mode, false); + create_convert_operand_to (&ops[4], desired, mode, false); create_integer_operand (&ops[5], is_weak); create_integer_operand (&ops[6], succ_model); create_integer_operand (&ops[7], fail_model); @@ -7358,8 +7358,8 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, create_output_operand (&ops[0], target_oval, mode); create_fixed_operand (&ops[1], mem); - create_convert_operand_to (&ops[2], expected, mode, true); - create_convert_operand_to (&ops[3], desired, mode, true); + create_convert_operand_to (&ops[2], expected, mode, false); + create_convert_operand_to (&ops[3], desired, mode, false); if (!maybe_expand_insn (icode, 4, ops)) return false; @@ -7788,7 +7788,7 @@ maybe_emit_op (const struct atomic_op_functions *o create_fixed_operand (&ops[op_counter++], mem); /* VAL may have been promoted to a wider mode. Shrink it if so. */ - create_convert_operand_to (&ops[op_counter++], val, mode, true); + create_convert_operand_to (&ops[op_counter++], val, mode, false); if (maybe_expand_insn (icode, num_ops, ops)) return (target == const0_rtx ? const0_rtx : ops[0].value); Index: testsuite/g++.dg/ext/atomic-2.C =================================================================== --- testsuite/g++.dg/ext/atomic-2.C (revision 0) +++ testsuite/g++.dg/ext/atomic-2.C (working copy) @@ -0,0 +1,18 @@ +// { dg-do run { target c++11 } } +// { dg-require-effective-target sync_int_128_runtime } +// { dg-options "-O2" } +// { dg-additional-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } + +#include <atomic> +#include <cassert> + +int +main (int, char **) +{ + std::atomic < __int128_t > i; + + i = -1; + + assert (int64_t (i >> 64) == -1); + assert (int64_t (i) == -1); +}