Hello! As shown by attached testcase, btrq peephole2 generates wrong immediate value for AND mask.
Attached patch fixes this problem and also improves btr{s,r,c}q peephole2 patterns a bit. 2016-05-09 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.md (absneg splitters with general regs): Use general_reg_operand predicate. (btsq peephole2): Use x86_64_immediate_operand to check if new value is suitable for immediate operand. Generate emitted insn using RTL expressions. (btcq peephole2): Ditto. (btrq peephole2): Ditto. Generate correct immediate operand for AND masking. testsuite/ChangeLog: 2016-05-09 Uros Bizjak <ubiz...@gmail.com> * gcc.target/i386/fabsneg-1.c New test. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN, will be backported to gcc-6 and gcc-5 branches. Uros.
Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 236034) +++ config/i386/i386.md (working copy) @@ -9306,7 +9306,7 @@ }) (define_split - [(set (match_operand:SF 0 "register_operand") + [(set (match_operand:SF 0 "general_reg_operand") (match_operator:SF 1 "absneg_operator" [(match_dup 0)])) (use (match_operand:V4SF 2)) (clobber (reg:CC FLAGS_REG))] @@ -9330,7 +9330,7 @@ }) (define_split - [(set (match_operand:DF 0 "register_operand") + [(set (match_operand:DF 0 "general_reg_operand") (match_operator:DF 1 "absneg_operator" [(match_dup 0)])) (use (match_operand 2)) (clobber (reg:CC FLAGS_REG))] @@ -9368,7 +9368,7 @@ }) (define_split - [(set (match_operand:XF 0 "register_operand") + [(set (match_operand:XF 0 "general_reg_operand") (match_operator:XF 1 "absneg_operator" [(match_dup 0)])) (use (match_operand 2)) (clobber (reg:CC FLAGS_REG))] @@ -11049,20 +11049,19 @@ (const_int 1)) (clobber (reg:CC FLAGS_REG))])] "TARGET_64BIT && !TARGET_USE_BT" - [(const_int 0)] + [(parallel [(set (match_dup 0) + (ior:DI (match_dup 0) (match_dup 3))) + (clobber (reg:CC FLAGS_REG))])] { int i = INTVAL (operands[1]); - rtx op1 = gen_int_mode (HOST_WIDE_INT_1U << i, DImode); + operands[3] = gen_int_mode (HOST_WIDE_INT_1U << i, DImode); - if (i >= 31) + if (!x86_64_immediate_operand (operands[3], DImode)) { - emit_move_insn (operands[2], op1); - op1 = operands[2]; + emit_move_insn (operands[2], operands[3]); + operands[3] = operands[2]; } - - emit_insn (gen_iordi3 (operands[0], operands[0], op1)); - DONE; }) (define_peephole2 @@ -11074,20 +11073,19 @@ (const_int 0)) (clobber (reg:CC FLAGS_REG))])] "TARGET_64BIT && !TARGET_USE_BT" - [(const_int 0)] + [(parallel [(set (match_dup 0) + (and:DI (match_dup 0) (match_dup 3))) + (clobber (reg:CC FLAGS_REG))])] { int i = INTVAL (operands[1]); - rtx op1 = gen_int_mode (HOST_WIDE_INT_1U << i, DImode); + operands[3] = gen_int_mode (~(HOST_WIDE_INT_1U << i), DImode); - if (i >= 32) + if (!x86_64_immediate_operand (operands[3], DImode)) { - emit_move_insn (operands[2], op1); - op1 = operands[2]; + emit_move_insn (operands[2], operands[3]); + operands[3] = operands[2]; } - - emit_insn (gen_anddi3 (operands[0], operands[0], op1)); - DONE; }) (define_peephole2 @@ -11100,20 +11098,19 @@ (match_dup 0) (const_int 1) (match_dup 1)))) (clobber (reg:CC FLAGS_REG))])] "TARGET_64BIT && !TARGET_USE_BT" - [(const_int 0)] + [(parallel [(set (match_dup 0) + (xor:DI (match_dup 0) (match_dup 3))) + (clobber (reg:CC FLAGS_REG))])] { int i = INTVAL (operands[1]); - rtx op1 = gen_int_mode (HOST_WIDE_INT_1U << i, DImode); + operands[3] = gen_int_mode (HOST_WIDE_INT_1U << i, DImode); - if (i >= 31) + if (!x86_64_immediate_operand (operands[3], DImode)) { - emit_move_insn (operands[2], op1); - op1 = operands[2]; + emit_move_insn (operands[2], operands[3]); + operands[3] = operands[2]; } - - emit_insn (gen_xordi3 (operands[0], operands[0], op1)); - DONE; }) (define_insn "*bt<mode>" Index: testsuite/gcc.target/i386/fabsneg-1.c =================================================================== --- testsuite/gcc.target/i386/fabsneg-1.c (nonexistent) +++ testsuite/gcc.target/i386/fabsneg-1.c (working copy) @@ -0,0 +1,36 @@ +/* { dg-do run } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O2 -mtune=nocona" } */ + +double x; + +void +__attribute__ ((noinline, noclone)) +test_fabs (double a) +{ + asm volatile ("" : "+r" (a)); + x = __builtin_fabs (a); +} + +void +__attribute__ ((noinline, noclone)) +test_neg (double a) +{ + asm volatile ("" : "+r" (a)); + x = -a; +} + +int main () +{ + test_fabs (-1.0); + + if (x != 1.0) + __builtin_abort (); + + test_neg (-1.0); + + if (x != 1.0) + __builtin_abort (); + + return 0; +}