aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c76
1 files changed, 41 insertions, 35 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 2f981abf19b..f2df3de54ea 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -59,7 +59,7 @@ optab optab_table[OTI_MAX];
rtx libfunc_table[LTI_MAX];
/* Tables of patterns for converting one mode to another. */
-convert_optab convert_optab_table[CTI_MAX];
+convert_optab convert_optab_table[COI_MAX];
/* Contains the optab used for each rtx code. */
optab code_to_optab[NUM_RTX_CODE + 1];
@@ -349,8 +349,8 @@ optab_for_tree_code (enum tree_code code, tree type)
this may or may not be TARGET. */
rtx
-expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
- rtx op1, rtx op2, rtx target, int unsignedp)
+expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
+ rtx op1, rtx op2, rtx target, int unsignedp)
{
int icode = (int) ternary_optab->handlers[(int) mode].insn_code;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
@@ -377,7 +377,7 @@ expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
xop0 = convert_modes (mode0,
GET_MODE (op0) != VOIDmode
- ? GET_MODE (op0)
+ ? GET_MODE (op0)
: mode,
xop0, unsignedp);
@@ -397,23 +397,23 @@ expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
/* Now, if insn's predicates don't allow our operands, put them into
pseudo regs. */
-
+
if (!insn_data[icode].operand[1].predicate (xop0, mode0)
- && mode0 != VOIDmode)
+ && mode0 != VOIDmode)
xop0 = copy_to_mode_reg (mode0, xop0);
-
+
if (!insn_data[icode].operand[2].predicate (xop1, mode1)
&& mode1 != VOIDmode)
xop1 = copy_to_mode_reg (mode1, xop1);
-
+
if (!insn_data[icode].operand[3].predicate (xop2, mode2)
&& mode2 != VOIDmode)
xop2 = copy_to_mode_reg (mode2, xop2);
-
+
pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
-
+
emit_insn (pat);
- return temp;
+ return temp;
}
@@ -1184,7 +1184,9 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
if (temp != 0)
{
- if (GET_MODE_CLASS (mode) == MODE_INT)
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ GET_MODE_BITSIZE (GET_MODE (temp))))
return gen_lowpart (mode, temp);
else
return convert_to_mode (mode, temp, unsignedp);
@@ -1231,7 +1233,9 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
unsignedp, OPTAB_DIRECT);
if (temp)
{
- if (class != MODE_INT)
+ if (class != MODE_INT
+ || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ GET_MODE_BITSIZE (wider_mode)))
{
if (target == 0)
target = gen_reg_rtx (mode);
@@ -1759,7 +1763,9 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
unsignedp, methods);
if (temp)
{
- if (class != MODE_INT)
+ if (class != MODE_INT
+ || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ GET_MODE_BITSIZE (wider_mode)))
{
if (target == 0)
target = gen_reg_rtx (mode);
@@ -2186,7 +2192,7 @@ expand_parity (enum machine_mode mode, rtx op0, rtx target)
return 0;
}
-/* Extract the OMODE lowpart from VAL, which has IMODE. Under certain
+/* Extract the OMODE lowpart from VAL, which has IMODE. Under certain
conditions, VAL may already be a SUBREG against which we cannot generate
a further SUBREG. In this case, we expect forcing the value into a
register will work around the situation. */
@@ -2276,7 +2282,7 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
{
rtx targ_piece = operand_subword (target, i, 1, mode);
rtx op0_piece = operand_subword_force (op0, i, mode);
-
+
if (i == word)
{
temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
@@ -2848,7 +2854,7 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
{
rtx targ_piece = operand_subword (target, i, 1, mode);
rtx op0_piece = operand_subword_force (op0, i, mode);
-
+
if (i == word)
{
if (!op0_is_abs)
@@ -2895,7 +2901,7 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
return target;
}
-/* Expand the C99 copysign operation. OP0 and OP1 must be the same
+/* Expand the C99 copysign operation. OP0 and OP1 must be the same
scalar floating point mode. Return NULL if we do not know how to
expand the operation inline. */
@@ -5276,7 +5282,7 @@ debug_optab_libfuncs (void)
}
/* Dump the conversion optabs. */
- for (i = 0; i < (int) CTI_MAX; ++i)
+ for (i = 0; i < (int) COI_MAX; ++i)
for (j = 0; j < NUM_MACHINE_MODES; ++j)
for (k = 0; k < NUM_MACHINE_MODES; ++k)
{
@@ -5371,7 +5377,7 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
case GE_EXPR:
code = unsignedp ? GEU : GE;
break;
-
+
case UNORDERED_EXPR:
code = UNORDERED;
break;
@@ -5417,10 +5423,10 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
ensures that condition is a relational operation. */
gcc_assert (COMPARISON_CLASS_P (cond));
- rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
+ rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
t_op0 = TREE_OPERAND (cond, 0);
t_op1 = TREE_OPERAND (cond, 1);
-
+
/* Expand operands. */
rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)), 1);
rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)), 1);
@@ -5428,7 +5434,7 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
if (!insn_data[icode].operand[4].predicate (rtx_op0, GET_MODE (rtx_op0))
&& GET_MODE (rtx_op0) != VOIDmode)
rtx_op0 = force_reg (GET_MODE (rtx_op0), rtx_op0);
-
+
if (!insn_data[icode].operand[5].predicate (rtx_op1, GET_MODE (rtx_op1))
&& GET_MODE (rtx_op1) != VOIDmode)
rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
@@ -5437,8 +5443,8 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
}
/* Return insn code for VEC_COND_EXPR EXPR. */
-
-static inline enum insn_code
+
+static inline enum insn_code
get_vcond_icode (tree expr, enum machine_mode mode)
{
enum insn_code icode = CODE_FOR_nothing;
@@ -5475,11 +5481,11 @@ expand_vec_cond_expr (tree vec_cond_expr, rtx target)
if (icode == CODE_FOR_nothing)
return 0;
- if (!target)
+ if (!target || !insn_data[icode].operand[0].predicate (target, mode))
target = gen_reg_rtx (mode);
/* Get comparison rtx. First expand both cond expr operands. */
- comparison = vector_compare_rtx (TREE_OPERAND (vec_cond_expr, 0),
+ comparison = vector_compare_rtx (TREE_OPERAND (vec_cond_expr, 0),
unsignedp, icode);
cc_op0 = XEXP (comparison, 0);
cc_op1 = XEXP (comparison, 1);
@@ -5497,7 +5503,7 @@ expand_vec_cond_expr (tree vec_cond_expr, rtx target)
rtx_op2 = force_reg (mode, rtx_op2);
/* Emit instruction! */
- emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
+ emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
comparison, cc_op0, cc_op1));
return target;
@@ -5623,8 +5629,8 @@ expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
}
}
- /* Without an appropriate setcc instruction, use a set of branches to
- get 1 and 0 stored into target. Presumably if the target has a
+ /* Without an appropriate setcc instruction, use a set of branches to
+ get 1 and 0 stored into target. Presumably if the target has a
STORE_FLAG_VALUE that isn't 1, then this will get cleaned up by ifcvt. */
label0 = gen_label_rtx ();
@@ -5717,7 +5723,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
}
/* This function generates the atomic operation MEM CODE= VAL. In this
- case, we do not care about any resulting value. Returns NULL if we
+ case, we do not care about any resulting value. Returns NULL if we
cannot generate the operation. */
rtx
@@ -5770,7 +5776,7 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
val = convert_modes (mode, GET_MODE (val), val, 1);
if (!insn_data[icode].operand[1].predicate (val, mode))
val = force_reg (mode, val);
-
+
insn = GEN_FCN (icode) (mem, val);
if (insn)
{
@@ -5808,7 +5814,7 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
/* This function generates the atomic operation MEM CODE= VAL. In this
case, we do care about the resulting value: if AFTER is true then
- return the value MEM holds after the operation, if AFTER is false
+ return the value MEM holds after the operation, if AFTER is false
then return the value MEM holds before the operation. TARGET is an
optional place for the result value to be stored. */
@@ -5903,7 +5909,7 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
val = convert_modes (mode, GET_MODE (val), val, 1);
if (!insn_data[icode].operand[2].predicate (val, mode))
val = force_reg (mode, val);
-
+
insn = GEN_FCN (icode) (target, mem, val);
if (insn)
{
@@ -5968,7 +5974,7 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
/* This function expands a test-and-set operation. Ideally we atomically
store VAL in MEM and return the previous value in MEM. Some targets
may not support this operation and only support VAL with the constant 1;
- in this case while the return value will be 0/1, but the exact value
+ in this case while the return value will be 0/1, but the exact value
stored in MEM is target defined. TARGET is an option place to stick
the return value. */