diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 1de24943c2e..76aeafb8f15 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -2742,6 +2742,17 @@ integer of mode @var{m}. The mode of @var{x} must be @var{m} or Represents the value @var{x} with the order of bytes reversed, carried out in mode @var{m}, which must be a fixed-point machine mode. The mode of @var{x} must be @var{m} or @code{VOIDmode}. + +@findex bitreverse +@item (bitreverse:@var{m} @var{x}) +Represents the value @var{x} with the order of bits reversed, carried out +in mode @var{m}, which must be a fixed-point machine mode. +The mode of @var{x} must be @var{m} or @code{VOIDmode}. + +@findex copysign +@item (copysign:@var{m} @var{x} @var{y}) +Represents the value @var{x} with the sign of @var{y}. +Both @var{x} and @var{y} must have floating point machine mode @var{m}. @end table @node Comparisons diff --git a/gcc/rtl.def b/gcc/rtl.def index 6ddbce380dc..88e2b198503 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -664,6 +664,9 @@ DEF_RTL_EXPR(POPCOUNT, "popcount", "e", RTX_UNARY) /* Population parity (number of 1 bits modulo 2). */ DEF_RTL_EXPR(PARITY, "parity", "e", RTX_UNARY) +/* Reverse bits. */ +DEF_RTL_EXPR(BITREVERSE, "bitreverse", "e", RTX_UNARY) + /* Reference to a signed bit-field of specified size and position. Operand 0 is the memory unit (usually SImode or QImode) which contains the field's first bit. Operand 1 is the width, in bits. @@ -753,6 +756,9 @@ DEF_RTL_EXPR(US_TRUNCATE, "us_truncate", "e", RTX_UNARY) /* Floating point multiply/add combined instruction. */ DEF_RTL_EXPR(FMA, "fma", "eee", RTX_TERNARY) +/* Floating point copysign. Operand 0 with the sign of operand 1. */ +DEF_RTL_EXPR(COPYSIGN, "copysign", "ee", RTX_BIN_ARITH) + /* Information about the variable and its location. */ DEF_RTL_EXPR(VAR_LOCATION, "var_location", "te", RTX_EXTRA) diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index 4e20a341977..276be67aa67 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -1040,10 +1040,10 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode, } /* (not (bswap x)) -> (bswap (not x)). */ - if (GET_CODE (op) == BSWAP) + if (GET_CODE (op) == BSWAP || GET_CODE (op) == BITREVERSE) { rtx x = simplify_gen_unary (NOT, mode, XEXP (op, 0), mode); - return simplify_gen_unary (BSWAP, mode, x, mode); + return simplify_gen_unary (GET_CODE (op), mode, x, mode); } break; @@ -1419,6 +1419,7 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode, switch (GET_CODE (op)) { case BSWAP: + case BITREVERSE: /* (popcount (bswap )) = (popcount ). */ return simplify_gen_unary (POPCOUNT, mode, XEXP (op, 0), GET_MODE (XEXP (op, 0))); @@ -1448,6 +1449,7 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode, { case NOT: case BSWAP: + case BITREVERSE: return simplify_gen_unary (PARITY, mode, XEXP (op, 0), GET_MODE (XEXP (op, 0))); @@ -1481,6 +1483,12 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode, return XEXP (op, 0); break; + case BITREVERSE: + /* (bitreverse (bitreverse x)) -> x. */ + if (GET_CODE (op) == BITREVERSE) + return XEXP (op, 0); + break; + case FLOAT: /* (float (sign_extend )) = (float ). */ if (GET_CODE (op) == SIGN_EXTEND) @@ -2114,6 +2122,10 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode, result = wi::bswap (op0); break; + case BITREVERSE: + result = wi::bitreverse (op0); + break; + case TRUNCATE: case ZERO_EXTEND: result = wide_int::from (op0, width, UNSIGNED); @@ -4356,6 +4368,31 @@ simplify_ashift: return op0; return 0; + case COPYSIGN: + if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) + return op0; + if (CONST_DOUBLE_AS_FLOAT_P (trueop1)) + { + REAL_VALUE_TYPE f1; + real_convert (&f1, mode, CONST_DOUBLE_REAL_VALUE (trueop1)); + rtx tmp = simplify_gen_unary (ABS, mode, op0, mode); + if (REAL_VALUE_NEGATIVE (f1)) + tmp = simplify_gen_unary (NEG, mode, op0, mode); + return tmp; + } + if (GET_CODE (op0) == NEG || GET_CODE (op0) == ABS) + return simplify_gen_binary (COPYSIGN, mode, XEXP (op0, 0), op1); + if (GET_CODE (op1) == ABS + && ! side_effects_p (op1)) + return simplify_gen_unary (ABS, mode, op0, mode); + if (GET_CODE (op0) == COPYSIGN + && ! side_effects_p (XEXP (op0, 1))) + return simplify_gen_binary (COPYSIGN, mode, XEXP (op0, 0), op1); + if (GET_CODE (op1) == COPYSIGN + && ! side_effects_p (XEXP (op1, 0))) + return simplify_gen_binary (COPYSIGN, mode, op0, XEXP (op1, 1)); + return 0; + case VEC_SERIES: if (op1 == CONST0_RTX (GET_MODE_INNER (mode))) return gen_vec_duplicate (mode, op0); @@ -4996,6 +5033,14 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode, real_from_target (&r, tmp0, mode); return const_double_from_real_value (r, mode); } + else if (code == COPYSIGN) + { + REAL_VALUE_TYPE f0, f1; + real_convert (&f0, mode, CONST_DOUBLE_REAL_VALUE (op0)); + real_convert (&f1, mode, CONST_DOUBLE_REAL_VALUE (op1)); + real_copysign (&f0, &f1); + return const_double_from_real_value (f0, mode); + } else { REAL_VALUE_TYPE f0, f1, value, result;