diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 385a669b9b3c31cc9108a660e881b9091c71fc7c..dbde066f7478bec51a8703b017ea553aa98be309 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -4811,7 +4811,7 @@ "" {@ [ cons: =0 , 1 , 2 ; attrs: type , arch ] [ r , %r , r ; logic_reg , * ] <logical>\t%<w>0, %<w>1, %<w>2 - [ rk , ^r , <lconst> ; logic_imm , * ] <logical>\t%<w>0, %<w>1, %2 + [ rk , r , <lconst> ; logic_imm , * ] <logical>\t%<w>0, %<w>1, %2 [ w , 0 , <lconst> ; * , sve ] <logical>\t%Z0.<s>, %Z0.<s>, #%2 [ w , w , w ; neon_logic , simd ] <logical>\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype> } @@ -7192,22 +7192,29 @@ (match_operand:GPF 2 "nonmemory_operand")] "TARGET_SIMD" { - machine_mode int_mode = <V_INT_EQUIV>mode; - rtx bitmask = gen_reg_rtx (int_mode); - emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U - << (GET_MODE_BITSIZE (<MODE>mode) - 1))); + rtx signbit_const = GEN_INT (HOST_WIDE_INT_M1U + << (GET_MODE_BITSIZE (<MODE>mode) - 1)); /* copysign (x, -1) should instead be expanded as orr with the sign bit. */ rtx op2_elt = unwrap_const_vec_duplicate (operands[2]); if (GET_CODE (op2_elt) == CONST_DOUBLE && real_isneg (CONST_DOUBLE_REAL_VALUE (op2_elt))) { - emit_insn (gen_ior<v_int_equiv>3 ( - lowpart_subreg (int_mode, operands[0], <MODE>mode), - lowpart_subreg (int_mode, operands[1], <MODE>mode), bitmask)); + rtx v_bitmask + = force_reg (V2<V_INT_EQUIV>mode, + gen_const_vec_duplicate (V2<V_INT_EQUIV>mode, + signbit_const)); + + emit_insn (gen_iorv2<v_int_equiv>3 ( + lowpart_subreg (V2<V_INT_EQUIV>mode, operands[0], <MODE>mode), + lowpart_subreg (V2<V_INT_EQUIV>mode, operands[1], <MODE>mode), + v_bitmask)); DONE; } + machine_mode int_mode = <V_INT_EQUIV>mode; + rtx bitmask = gen_reg_rtx (int_mode); + emit_move_insn (bitmask, signbit_const); operands[2] = force_reg (<MODE>mode, operands[2]); emit_insn (gen_copysign<mode>3_insn (operands[0], operands[1], operands[2], bitmask)); diff --git a/gcc/testsuite/gcc.target/aarch64/fneg-abs_2.c b/gcc/testsuite/gcc.target/aarch64/fneg-abs_2.c index eed41ea18e69ff60ac79cbdb7c0c935850b49b33..18d10ee834d5d9b4361d890447060e78f09d3a73 100644 --- a/gcc/testsuite/gcc.target/aarch64/fneg-abs_2.c +++ b/gcc/testsuite/gcc.target/aarch64/fneg-abs_2.c @@ -9,8 +9,7 @@ /* ** f1: -** movi v[0-9]+.2s, 0x80, lsl 24 -** orr v[0-9]+.8b, v[0-9]+.8b, v[0-9]+.8b +** orr v[0-9]+.2s, #?128, lsl #?24 ** ret */ float32_t f1 (float32_t a) @@ -22,7 +21,7 @@ float32_t f1 (float32_t a) ** f2: ** movi v[0-9]+.4s, #?0 ** fneg v[0-9]+.2d, v[0-9]+.2d -** orr v[0-9]+.8b, v[0-9]+.8b, v[0-9]+.8b +** orr v[0-9]+.16b, v[0-9]+.16b, v[0-9]+.16b ** ret */ float64_t f2 (float64_t a) diff --git a/gcc/testsuite/gcc.target/aarch64/fneg-abs_4.c b/gcc/testsuite/gcc.target/aarch64/fneg-abs_4.c index d45c3d1210c682f38177a89f1137ab4f6decfbc1..6da95a4b052ca3d9e0b8db0e465c5f40139b2b18 100644 --- a/gcc/testsuite/gcc.target/aarch64/fneg-abs_4.c +++ b/gcc/testsuite/gcc.target/aarch64/fneg-abs_4.c @@ -7,7 +7,7 @@ #include <string.h> /* -** negabs: +** negabs: { xfail *-*-* } ** movi v31.4s, #?0 ** fneg v[0-9]+.2d, v[0-9]+.2d ** orr v[0-9]+.8b, v[0-9]+.8b, v[0-9]+.8b @@ -23,7 +23,7 @@ double negabs (double x) } /* -** negabsf: +** negabsf: { xfail *-*-* } ** movi v[0-9]+.2s, 0x80, lsl 24 ** orr v[0-9]+.8b, v[0-9]+.8b, v[0-9]+.8b ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/pr114741.c b/gcc/testsuite/gcc.target/aarch64/pr114741.c new file mode 100644 index 0000000000000000000000000000000000000000..fd2182da0e966afcf0ab5bdef2f8d3892c2a3d67 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr114741.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ + +#pragma GCC target "+nosve" + +/* +** foo1: +** and w0, w0, 1 +** str w0, \[x1\] +** ret +*/ +void foo1(unsigned v, unsigned *p) +{ + *p = v & 1; +} + +#pragma GCC target "+sve" + +/* +** foo2: +** and w0, w0, 1 +** str w0, \[x1\] +** ret +*/ +void foo2(unsigned v, unsigned *p) +{ + *p = v & 1; +}