diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/explow.c | 2 | ||||
-rw-r--r-- | gcc/expmed.c | 72 | ||||
-rw-r--r-- | gcc/expmed.h | 4 | ||||
-rw-r--r-- | gcc/expr.c | 2 | ||||
-rw-r--r-- | gcc/optabs.c | 11 |
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, @@ -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 ()) |