/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
- Copyright (C) 1987-2018 Free Software Foundation, Inc.
+ Copyright (C) 1987-2019 Free Software Foundation, Inc.
This file is part of GCC.
enum insn_code icode;
int nops = TREE_CODE_LENGTH (ops->code);
int op;
+ bool sbool = false;
oprnd0 = ops->op0;
tmode0 = TYPE_MODE (TREE_TYPE (oprnd0));
for these ops. */
widen_pattern_optab
= optab_for_tree_code (ops->code, ops->type, optab_default);
+ else if ((ops->code == VEC_UNPACK_HI_EXPR
+ || ops->code == VEC_UNPACK_LO_EXPR)
+ && VECTOR_BOOLEAN_TYPE_P (ops->type)
+ && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (oprnd0))
+ && TYPE_MODE (ops->type) == TYPE_MODE (TREE_TYPE (oprnd0))
+ && SCALAR_INT_MODE_P (TYPE_MODE (ops->type)))
+ {
+ /* For VEC_UNPACK_{LO,HI}_EXPR if the mode of op0 and result is
+ the same scalar mode for VECTOR_BOOLEAN_TYPE_P vectors, use
+ vec_unpacks_sbool_{lo,hi}_optab, so that we can pass in
+ the pattern number of elements in the wider vector. */
+ widen_pattern_optab
+ = (ops->code == VEC_UNPACK_HI_EXPR
+ ? vec_unpacks_sbool_hi_optab : vec_unpacks_sbool_lo_optab);
+ sbool = true;
+ }
else
widen_pattern_optab
= optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default);
oprnd1 = ops->op1;
tmode1 = TYPE_MODE (TREE_TYPE (oprnd1));
}
+ else if (sbool)
+ {
+ nops = 2;
+ op1 = GEN_INT (TYPE_VECTOR_SUBPARTS (TREE_TYPE (oprnd0)).to_constant ());
+ tmode1 = tmode0;
+ }
/* The last operand is of a wider mode than the rest of the operands. */
if (nops == 2)
start_sequence ();
/* Do the actual arithmetic. */
- enum machine_mode op0_mode = CONSTANT_P (op0) ? int_mode : VOIDmode;
- enum machine_mode op1_mode = CONSTANT_P (op1) ? int_mode : VOIDmode;
+ machine_mode op0_mode = GET_MODE (op0);
+ machine_mode op1_mode = GET_MODE (op1);
+ if (op0_mode == VOIDmode)
+ op0_mode = int_mode;
+ if (op1_mode == VOIDmode)
+ op1_mode = int_mode;
for (i = 0; i < GET_MODE_BITSIZE (int_mode) / BITS_PER_WORD; i++)
{
rtx target_piece = operand_subword (target, i, 1, int_mode);