/* 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.
/* 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)
}
/* (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;
switch (GET_CODE (op))
{
case BSWAP:
+ case BITREVERSE:
/* (popcount (bswap <X>)) = (popcount <X>). */
return simplify_gen_unary (POPCOUNT, mode, XEXP (op, 0),
GET_MODE (XEXP (op, 0)));
{
case NOT:
case BSWAP:
+ case BITREVERSE:
return simplify_gen_unary (PARITY, mode, XEXP (op, 0),
GET_MODE (XEXP (op, 0)));
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 <X>)) = (float <X>). */
if (GET_CODE (op) == SIGN_EXTEND)
result = wi::bswap (op0);
break;
+ case BITREVERSE:
+ result = wi::bitreverse (op0);
+ break;
+
case TRUNCATE:
case ZERO_EXTEND:
result = wide_int::from (op0, width, UNSIGNED);
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);
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;