Hi! rs6000_expand_atomic_compare_and_swap uses oldval directly in a comparison instruction, but oldval might be a CONST_INT not suitable for the instruction (such as in the testcase below in SImode comparison 0x8000 constant). We need to force those into register if they don't satisfy the predicate.
Bootstrapped/regtested on powerpc64{,le}-linux, ok for trunk? 2016-02-03 Jakub Jelinek <ja...@redhat.com> PR target/69644 * config/rs6000/rs6000.c (rs6000_expand_atomic_compare_and_swap): Force oldval into register if it does not satisfy reg_or_short_operand predicate. Fix up formatting. * gcc.dg/pr69644.c: New test. --- gcc/config/rs6000/rs6000.c.jj 2016-02-02 20:42:01.000000000 +0100 +++ gcc/config/rs6000/rs6000.c 2016-02-03 08:45:31.345521112 +0100 @@ -22275,6 +22275,9 @@ rs6000_expand_atomic_compare_and_swap (r else if (reg_overlap_mentioned_p (retval, oldval)) oldval = copy_to_reg (oldval); + if (mode != TImode && !reg_or_short_operand (oldval, mode)) + oldval = copy_to_mode_reg (mode, oldval); + mem = rs6000_pre_atomic_barrier (mem, mod_s); label1 = NULL_RTX; @@ -22289,10 +22292,8 @@ rs6000_expand_atomic_compare_and_swap (r x = retval; if (mask) - { - x = expand_simple_binop (SImode, AND, retval, mask, - NULL_RTX, 1, OPTAB_LIB_WIDEN); - } + x = expand_simple_binop (SImode, AND, retval, mask, + NULL_RTX, 1, OPTAB_LIB_WIDEN); cond = gen_reg_rtx (CCmode); /* If we have TImode, synthesize a comparison. */ --- gcc/testsuite/gcc.dg/pr69644.c.jj 2016-02-03 08:42:20.827165549 +0100 +++ gcc/testsuite/gcc.dg/pr69644.c 2016-02-03 08:41:51.000000000 +0100 @@ -0,0 +1,11 @@ +/* PR target/69644 */ +/* { dg-do compile } */ + +int +main () +{ + unsigned short x = 0x8000; + if (!__sync_bool_compare_and_swap (&x, 0x8000, 0) || x) + __builtin_abort (); + return 0; +} Jakub