aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/explow.c2
-rw-r--r--gcc/expmed.c72
-rw-r--r--gcc/expmed.h4
-rw-r--r--gcc/expr.c2
-rw-r--r--gcc/optabs.c11
5 files changed, 53 insertions, 38 deletions
diff --git a/gcc/explow.c b/gcc/explow.c
index 41c3f6a..65f904a 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -27,9 +27,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "memmodel.h"
#include "tm_p.h"
+#include "optabs.h"
#include "expmed.h"
#include "profile-count.h"
-#include "optabs.h"
#include "emit-rtl.h"
#include "recog.h"
#include "diagnostic-core.h"
diff --git a/gcc/expmed.c b/gcc/expmed.c
index d34f0fb..ce88f32 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -31,8 +31,8 @@ along with GCC; see the file COPYING3. If not see
#include "predict.h"
#include "memmodel.h"
#include "tm_p.h"
-#include "expmed.h"
#include "optabs.h"
+#include "expmed.h"
#include "regs.h"
#include "emit-rtl.h"
#include "diagnostic-core.h"
@@ -4193,7 +4193,8 @@ expand_sdiv_pow2 (scalar_int_mode mode, rtx op0, HOST_WIDE_INT d)
rtx
expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
- rtx op0, rtx op1, rtx target, int unsignedp)
+ rtx op0, rtx op1, rtx target, int unsignedp,
+ enum optab_methods methods)
{
machine_mode compute_mode;
rtx tquotient;
@@ -4299,17 +4300,22 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
optab2 = (op1_is_pow2 ? optab1
: (unsignedp ? udivmod_optab : sdivmod_optab));
- FOR_EACH_MODE_FROM (compute_mode, mode)
- if (optab_handler (optab1, compute_mode) != CODE_FOR_nothing
- || optab_handler (optab2, compute_mode) != CODE_FOR_nothing)
- break;
-
- if (compute_mode == VOIDmode)
- FOR_EACH_MODE_FROM (compute_mode, mode)
- if (optab_libfunc (optab1, compute_mode)
- || optab_libfunc (optab2, compute_mode))
+ if (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN)
+ {
+ FOR_EACH_MODE_FROM (compute_mode, mode)
+ if (optab_handler (optab1, compute_mode) != CODE_FOR_nothing
+ || optab_handler (optab2, compute_mode) != CODE_FOR_nothing)
break;
+ if (compute_mode == VOIDmode && methods == OPTAB_LIB_WIDEN)
+ FOR_EACH_MODE_FROM (compute_mode, mode)
+ if (optab_libfunc (optab1, compute_mode)
+ || optab_libfunc (optab2, compute_mode))
+ break;
+ }
+ else
+ compute_mode = mode;
+
/* If we still couldn't find a mode, use MODE, but expand_binop will
probably die. */
if (compute_mode == VOIDmode)
@@ -4412,8 +4418,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
remainder
= expand_binop (int_mode, and_optab, op0,
gen_int_mode (mask, int_mode),
- remainder, 1,
- OPTAB_LIB_WIDEN);
+ remainder, 1, methods);
if (remainder)
return gen_lowpart (mode, remainder);
}
@@ -4721,7 +4726,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
remainder = expand_binop
(int_mode, and_optab, op0,
gen_int_mode (mask, int_mode),
- remainder, 0, OPTAB_LIB_WIDEN);
+ remainder, 0, methods);
if (remainder)
return gen_lowpart (mode, remainder);
}
@@ -4846,7 +4851,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
do_cmp_and_jump (op1, const0_rtx, LT, compute_mode, label2);
do_cmp_and_jump (adjusted_op0, const0_rtx, LT, compute_mode, label1);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
emit_jump_insn (targetm.gen_jump (label5));
@@ -4858,7 +4863,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
emit_label (label2);
do_cmp_and_jump (adjusted_op0, const0_rtx, GT, compute_mode, label3);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
emit_jump_insn (targetm.gen_jump (label5));
@@ -4867,7 +4872,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
expand_dec (adjusted_op0, const1_rtx);
emit_label (label4);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
expand_dec (quotient, const1_rtx);
@@ -4892,7 +4897,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
floor_log2 (d), tquotient, 1);
t2 = expand_binop (int_mode, and_optab, op0,
gen_int_mode (d - 1, int_mode),
- NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ NULL_RTX, 1, methods);
t3 = gen_reg_rtx (int_mode);
t3 = emit_store_flag (t3, NE, t2, const0_rtx, int_mode, 1, 1);
if (t3 == 0)
@@ -4963,7 +4968,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
emit_label (label1);
expand_dec (adjusted_op0, const1_rtx);
tem = expand_binop (compute_mode, udiv_optab, adjusted_op0, op1,
- quotient, 1, OPTAB_LIB_WIDEN);
+ quotient, 1, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
expand_inc (quotient, const1_rtx);
@@ -4987,7 +4992,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
floor_log2 (d), tquotient, 0);
t2 = expand_binop (compute_mode, and_optab, op0,
gen_int_mode (d - 1, compute_mode),
- NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ NULL_RTX, 1, methods);
t3 = gen_reg_rtx (compute_mode);
t3 = emit_store_flag (t3, NE, t2, const0_rtx,
compute_mode, 1, 1);
@@ -5063,7 +5068,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
do_cmp_and_jump (adjusted_op0, const0_rtx, GT,
compute_mode, label1);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
emit_jump_insn (targetm.gen_jump (label5));
@@ -5076,7 +5081,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
do_cmp_and_jump (adjusted_op0, const0_rtx, LT,
compute_mode, label3);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
emit_jump_insn (targetm.gen_jump (label5));
@@ -5085,7 +5090,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
expand_inc (adjusted_op0, const1_rtx);
emit_label (label4);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
expand_inc (quotient, const1_rtx);
@@ -5133,10 +5138,10 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
{
rtx tem;
quotient = expand_binop (int_mode, udiv_optab, op0, op1,
- quotient, 1, OPTAB_LIB_WIDEN);
+ quotient, 1, methods);
tem = expand_mult (int_mode, quotient, op1, NULL_RTX, 1);
remainder = expand_binop (int_mode, sub_optab, op0, tem,
- remainder, 1, OPTAB_LIB_WIDEN);
+ remainder, 1, methods);
}
tem = plus_constant (int_mode, op1, -1);
tem = expand_shift (RSHIFT_EXPR, int_mode, tem, 1, NULL_RTX, 1);
@@ -5158,10 +5163,10 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
{
rtx tem;
quotient = expand_binop (int_mode, sdiv_optab, op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
tem = expand_mult (int_mode, quotient, op1, NULL_RTX, 0);
remainder = expand_binop (int_mode, sub_optab, op0, tem,
- remainder, 0, OPTAB_LIB_WIDEN);
+ remainder, 0, methods);
}
abs_rem = expand_abs (int_mode, remainder, NULL_RTX, 1, 0);
abs_op1 = expand_abs (int_mode, op1, NULL_RTX, 1, 0);
@@ -5258,7 +5263,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
quotient = sign_expand_binop (compute_mode,
udiv_optab, sdiv_optab,
op0, op1, target,
- unsignedp, OPTAB_LIB_WIDEN);
+ unsignedp, methods);
}
}
}
@@ -5273,10 +5278,11 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
/* No divide instruction either. Use library for remainder. */
remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab,
op0, op1, target,
- unsignedp, OPTAB_LIB_WIDEN);
+ unsignedp, methods);
/* No remainder function. Try a quotient-and-remainder
function, keeping the remainder. */
- if (!remainder)
+ if (!remainder
+ && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
{
remainder = gen_reg_rtx (compute_mode);
if (!expand_twoval_binop_libfunc
@@ -5294,10 +5300,14 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
NULL_RTX, unsignedp);
remainder = expand_binop (compute_mode, sub_optab, op0,
remainder, target, unsignedp,
- OPTAB_LIB_WIDEN);
+ methods);
}
}
+ if (methods != OPTAB_LIB_WIDEN
+ && (rem_flag ? remainder : quotient) == NULL_RTX)
+ return NULL_RTX;
+
return gen_lowpart (mode, rem_flag ? remainder : quotient);
}
diff --git a/gcc/expmed.h b/gcc/expmed.h
index b719b94..6a9bab7 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -716,8 +716,10 @@ extern rtx expand_variable_shift (enum tree_code, machine_mode,
rtx, tree, rtx, int);
extern rtx expand_shift (enum tree_code, machine_mode, rtx, poly_int64, rtx,
int);
+#ifdef GCC_OPTABS_H
extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx,
- rtx, int);
+ rtx, int, enum optab_methods = OPTAB_LIB_WIDEN);
+#endif
#endif
extern void store_bit_field (rtx, poly_uint64, poly_uint64,
diff --git a/gcc/expr.c b/gcc/expr.c
index 25e93b6..798285e 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -29,8 +29,8 @@ along with GCC; see the file COPYING3. If not see
#include "memmodel.h"
#include "tm_p.h"
#include "ssa.h"
-#include "expmed.h"
#include "optabs.h"
+#include "expmed.h"
#include "regs.h"
#include "emit-rtl.h"
#include "recog.h"
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 41daa48..bdc692b 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -28,8 +28,8 @@ along with GCC; see the file COPYING3. If not see
#include "memmodel.h"
#include "predict.h"
#include "tm_p.h"
-#include "expmed.h"
#include "optabs.h"
+#include "expmed.h"
#include "emit-rtl.h"
#include "recog.h"
#include "diagnostic-core.h"
@@ -1082,7 +1082,7 @@ expand_doubleword_mod (machine_mode mode, rtx op0, rtx op1, bool unsignedp)
}
}
rtx remainder = expand_divmod (1, TRUNC_MOD_EXPR, word_mode, sum, op1,
- NULL_RTX, 1);
+ NULL_RTX, 1, OPTAB_DIRECT);
if (remainder == NULL_RTX)
return NULL_RTX;
@@ -1180,7 +1180,7 @@ expand_doubleword_divmod (machine_mode mode, rtx op0, rtx op1, rtx *rem,
if (op11 != const1_rtx)
{
rtx rem2 = expand_divmod (1, TRUNC_MOD_EXPR, mode, quot1, op11,
- NULL_RTX, unsignedp);
+ NULL_RTX, unsignedp, OPTAB_DIRECT);
if (rem2 == NULL_RTX)
return NULL_RTX;
@@ -1195,7 +1195,7 @@ expand_doubleword_divmod (machine_mode mode, rtx op0, rtx op1, rtx *rem,
return NULL_RTX;
rtx quot2 = expand_divmod (0, TRUNC_DIV_EXPR, mode, quot1, op11,
- NULL_RTX, unsignedp);
+ NULL_RTX, unsignedp, OPTAB_DIRECT);
if (quot2 == NULL_RTX)
return NULL_RTX;
@@ -2100,6 +2100,9 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
&& CONST_INT_P (op1)
&& is_int_mode (mode, &int_mode)
&& GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
+ && optab_handler ((binoptab == umod_optab || binoptab == udiv_optab)
+ ? udivmod_optab : sdivmod_optab,
+ int_mode) == CODE_FOR_nothing
&& optab_handler (and_optab, word_mode) != CODE_FOR_nothing
&& optab_handler (add_optab, word_mode) != CODE_FOR_nothing
&& optimize_insn_for_speed_p ())