From 466a35ffa2b4dc4fc21a8479d1335a161788c78d Mon Sep 17 00:00:00 2001 From: rsandifo Date: Fri, 13 Oct 2017 09:41:39 +0000 Subject: Make more use of GET_MODE_UNIT_SIZE This patch uses GET_MODE_UNIT_SIZE instead of GET_MODE_SIZE in cases where, for compound modes, the mode of the scalar elements is what matters. E.g. the choice between truncation and extension is really based on the modes of the consistuent scalars rather than the mode as a whole. None of the existing code was wrong. The patch simply makes things easier when converting to variable-sized modes. 2017-10-13 Richard Sandiford Alan Hayward David Sherwood gcc/ * optabs.c (add_equal_note): Use GET_MODE_UNIT_SIZE. (widened_mode): Likewise. (expand_unop): Likewise. * ree.c (transform_ifelse): Likewise. (merge_def_and_ext): Likewise. (combine_reaching_defs): Likewise. * simplify-rtx.c (simplify_unary_operation_1): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253715 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/optabs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 67dfa58ff46..75e320022cb 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -138,8 +138,8 @@ add_equal_note (rtx_insn *insns, rtx target, enum rtx_code code, rtx op0, rtx op if (GET_MODE (op0) != VOIDmode && GET_MODE (target) != GET_MODE (op0)) { note = gen_rtx_fmt_e (code, GET_MODE (op0), copy_rtx (op0)); - if (GET_MODE_SIZE (GET_MODE (op0)) - > GET_MODE_SIZE (GET_MODE (target))) + if (GET_MODE_UNIT_SIZE (GET_MODE (op0)) + > GET_MODE_UNIT_SIZE (GET_MODE (target))) note = simplify_gen_unary (TRUNCATE, GET_MODE (target), note, GET_MODE (op0)); else @@ -173,12 +173,12 @@ widened_mode (machine_mode to_mode, rtx op0, rtx op1) if (m0 == VOIDmode && m1 == VOIDmode) return to_mode; - else if (m0 == VOIDmode || GET_MODE_SIZE (m0) < GET_MODE_SIZE (m1)) + else if (m0 == VOIDmode || GET_MODE_UNIT_SIZE (m0) < GET_MODE_UNIT_SIZE (m1)) result = m1; else result = m0; - if (GET_MODE_SIZE (result) > GET_MODE_SIZE (to_mode)) + if (GET_MODE_UNIT_SIZE (result) > GET_MODE_UNIT_SIZE (to_mode)) return to_mode; return result; @@ -2977,9 +2977,9 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target, else { eq_value = gen_rtx_fmt_e (optab_to_code (unoptab), mode, op0); - if (GET_MODE_SIZE (outmode) < GET_MODE_SIZE (mode)) + if (GET_MODE_UNIT_SIZE (outmode) < GET_MODE_UNIT_SIZE (mode)) eq_value = simplify_gen_unary (TRUNCATE, outmode, eq_value, mode); - else if (GET_MODE_SIZE (outmode) > GET_MODE_SIZE (mode)) + else if (GET_MODE_UNIT_SIZE (outmode) > GET_MODE_UNIT_SIZE (mode)) eq_value = simplify_gen_unary (ZERO_EXTEND, outmode, eq_value, mode); } -- cgit v1.2.1 From 71ee1c2d185b364174ca205af3b19c3d71c43af5 Mon Sep 17 00:00:00 2001 From: uros Date: Sat, 14 Oct 2017 09:10:45 +0000 Subject: * target-insns.def: Add memory_blockage. * optabs.c (expand_memory_blockage): New function. (expand_asm_memory_barrier): Rename ... (expand_asm_memory_blockage): ... to this. (expand_mem_thread_fence): Call expand_memory_blockage instead of expand_asm_memory_barrier. (expand_mem_singnal_fence): Ditto. (expand_atomic_load): Ditto. (expand_atomic_store): Ditto. * doc/md.texi (Standard Pattern Names For Generation): Document memory_blockage instruction pattern. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253750 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/optabs.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 75e320022cb..46df49abb10 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6273,10 +6273,10 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval, return true; } -/* Generate asm volatile("" : : : "memory") as the memory barrier. */ +/* Generate asm volatile("" : : : "memory") as the memory blockage. */ static void -expand_asm_memory_barrier (void) +expand_asm_memory_blockage (void) { rtx asm_op, clob; @@ -6292,6 +6292,17 @@ expand_asm_memory_barrier (void) emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, asm_op, clob))); } +/* Do not propagate memory accesses across this point. */ + +static void +expand_memory_blockage (void) +{ + if (targetm.have_memory_blockage) + emit_insn (gen_memory_blockage ()); + else + expand_asm_memory_blockage (); +} + /* This routine will either emit the mem_thread_fence pattern or issue a sync_synchronize to generate a fence for memory model MEMMODEL. */ @@ -6303,14 +6314,14 @@ expand_mem_thread_fence (enum memmodel model) if (targetm.have_mem_thread_fence ()) { emit_insn (targetm.gen_mem_thread_fence (GEN_INT (model))); - expand_asm_memory_barrier (); + expand_memory_blockage (); } else if (targetm.have_memory_barrier ()) emit_insn (targetm.gen_memory_barrier ()); else if (synchronize_libfunc != NULL_RTX) emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode); else - expand_asm_memory_barrier (); + expand_memory_blockage (); } /* Emit a signal fence with given memory model. */ @@ -6321,7 +6332,7 @@ expand_mem_signal_fence (enum memmodel model) /* No machine barrier is required to implement a signal fence, but a compiler memory barrier must be issued, except for relaxed MM. */ if (!is_mm_relaxed (model)) - expand_asm_memory_barrier (); + expand_memory_blockage (); } /* This function expands the atomic load operation: @@ -6343,7 +6354,7 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model) struct expand_operand ops[3]; rtx_insn *last = get_last_insn (); if (is_mm_seq_cst (model)) - expand_asm_memory_barrier (); + expand_memory_blockage (); create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); @@ -6351,7 +6362,7 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model) if (maybe_expand_insn (icode, 3, ops)) { if (!is_mm_relaxed (model)) - expand_asm_memory_barrier (); + expand_memory_blockage (); return ops[0].value; } delete_insns_since (last); @@ -6401,14 +6412,14 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release) { rtx_insn *last = get_last_insn (); if (!is_mm_relaxed (model)) - expand_asm_memory_barrier (); + expand_memory_blockage (); create_fixed_operand (&ops[0], mem); create_input_operand (&ops[1], val, mode); create_integer_operand (&ops[2], model); if (maybe_expand_insn (icode, 3, ops)) { if (is_mm_seq_cst (model)) - expand_asm_memory_barrier (); + expand_memory_blockage (); return const0_rtx; } delete_insns_since (last); -- cgit v1.2.1 From ceaf6aa15a42899d65ac0be36830ae7e3dd85084 Mon Sep 17 00:00:00 2001 From: uros Date: Sat, 14 Oct 2017 10:46:20 +0000 Subject: * optabs.c (expand_memory_blockage): Use targetm.gen_memory_blockage. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253752 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/optabs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 46df49abb10..5369c18cbaf 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6298,7 +6298,7 @@ static void expand_memory_blockage (void) { if (targetm.have_memory_blockage) - emit_insn (gen_memory_blockage ()); + emit_insn (targetm.gen_memory_blockage ()); else expand_asm_memory_blockage (); } -- cgit v1.2.1 From 0bc087fa0e59ada43dccbcc09ed2d4b405a15b18 Mon Sep 17 00:00:00 2001 From: uros Date: Sat, 14 Oct 2017 17:46:49 +0000 Subject: PR bootstrap/82553 * optabs.c (expand_memory_blockage): Fix call of targetm.have_memory_blockage. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253759 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/optabs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 5369c18cbaf..94092fc1594 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6297,7 +6297,7 @@ expand_asm_memory_blockage (void) static void expand_memory_blockage (void) { - if (targetm.have_memory_blockage) + if (targetm.have_memory_blockage ()) emit_insn (targetm.gen_memory_blockage ()); else expand_asm_memory_blockage (); -- cgit v1.2.1 From 1048c15588636609c35c11bd401e073d47e7cd54 Mon Sep 17 00:00:00 2001 From: rsandifo Date: Sun, 22 Oct 2017 21:39:29 +0000 Subject: Make more use of GET_MODE_UNIT_PRECISION This patch is like the earlier GET_MODE_UNIT_SIZE one, but for precisions rather than sizes. There is one behavioural change in expand_debug_expr: we shouldn't use lowpart subregs for non-scalar truncations, since that would just reinterpret some of the scalars and drop the rest. (This probably doesn't trigger in practice.) Using TRUNCATE is fine for scalars, since simplify_gen_unary knows when a subreg can be used. 2017-10-22 Richard Sandiford Alan Hayward David Sherwood gcc/ * cfgexpand.c (expand_debug_expr): Use GET_MODE_UNIT_PRECISION. (expand_debug_source_expr): Likewise. * combine.c (combine_simplify_rtx): Likewise. * cse.c (fold_rtx): Likewise. * optabs.c (expand_float): Likewise. * simplify-rtx.c (simplify_unary_operation_1): Likewise. (simplify_binary_operation_1): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253991 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/optabs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 94092fc1594..15ca315d49e 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4655,7 +4655,8 @@ expand_float (rtx to, rtx from, int unsignedp) int doing_unsigned = unsignedp; if (fmode != GET_MODE (to) - && significand_size (fmode) < GET_MODE_PRECISION (GET_MODE (from))) + && (significand_size (fmode) + < GET_MODE_UNIT_PRECISION (GET_MODE (from)))) continue; icode = can_float_p (fmode, imode, unsignedp); -- cgit v1.2.1 From 0b51f5cec16013df0727aab14e9e06e868641cab Mon Sep 17 00:00:00 2001 From: rsandifo Date: Wed, 1 Nov 2017 09:20:15 +0000 Subject: Add gen_(const_)vec_duplicate helpers This patch adds helper functions for generating constant and non-constant vector duplicates. These routines help with SVE because it is then easier to use: (const:M (vec_duplicate:M X)) for a broadcast of X, even if the number of elements in M isn't known at compile time. It also makes it easier for general rtx code to treat constant and non-constant duplicates in the same way. In the target code, the patch uses gen_vec_duplicate instead of gen_rtx_VEC_DUPLICATE if handling constants correctly is potentially useful. It might be that some or all of the call sites only handle non-constants in practice, in which case the change is a harmless no-op (and a saving of a few characters). Otherwise, the target changes use gen_const_vec_duplicate instead of gen_rtx_CONST_VECTOR if the constant is obviously a duplicate. They also include some changes to use CONSTxx_RTX for easy global constants. 2017-11-01 Richard Sandiford Alan Hayward David Sherwood gcc/ * emit-rtl.h (gen_const_vec_duplicate): Declare. (gen_vec_duplicate): Likewise. * emit-rtl.c (gen_const_vec_duplicate_1): New function, split out from... (gen_const_vector): ...here. (gen_const_vec_duplicate, gen_vec_duplicate): New functions. (gen_rtx_CONST_VECTOR): Use gen_const_vec_duplicate for constants whose elements are all equal. * optabs.c (expand_vector_broadcast): Use gen_const_vec_duplicate. * simplify-rtx.c (simplify_const_unary_operation): Likewise. (simplify_relational_operation): Likewise. * config/aarch64/aarch64.c (aarch64_simd_gen_const_vector_dup): Likewise. (aarch64_simd_dup_constant): Use gen_vec_duplicate. (aarch64_expand_vector_init): Likewise. * config/arm/arm.c (neon_vdup_constant): Likewise. (neon_expand_vector_init): Likewise. (arm_expand_vec_perm): Use gen_const_vec_duplicate. (arm_block_set_unaligned_vect): Likewise. (arm_block_set_aligned_vect): Likewise. * config/arm/neon.md (neon_copysignf): Likewise. * config/i386/i386.c (ix86_expand_vec_perm): Likewise. (expand_vec_perm_even_odd_pack): Likewise. (ix86_vector_duplicate_value): Use gen_vec_duplicate. * config/i386/sse.md (one_cmpl2): Use CONSTM1_RTX. * config/ia64/ia64.c (ia64_expand_vecint_compare): Use gen_const_vec_duplicate. * config/ia64/vect.md (addv2sf3, subv2sf3): Use CONST1_RTX. * config/mips/mips.c (mips_gen_const_int_vector): Use gen_const_vec_duplicate. (mips_expand_vector_init): Use CONST0_RTX. * config/powerpcspe/altivec.md (abs2, nabs2): Likewise. (define_split): Use gen_const_vec_duplicate. * config/rs6000/altivec.md (abs2, nabs2): Use CONST0_RTX. (define_split): Use gen_const_vec_duplicate. * config/s390/vx-builtins.md (vec_genmask): Likewise. (vec_ctd_s64, vec_ctd_u64, vec_ctsl, vec_ctul): Likewise. * config/spu/spu.c (spu_const): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254292 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/optabs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 15ca315d49e..6f7848d6b0b 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -377,13 +377,8 @@ expand_vector_broadcast (machine_mode vmode, rtx op) gcc_checking_assert (VECTOR_MODE_P (vmode)); - n = GET_MODE_NUNITS (vmode); - vec = rtvec_alloc (n); - for (i = 0; i < n; ++i) - RTVEC_ELT (vec, i) = op; - if (CONSTANT_P (op)) - return gen_rtx_CONST_VECTOR (vmode, vec); + return gen_const_vec_duplicate (vmode, op); /* ??? If the target doesn't have a vec_init, then we have no easy way of performing this operation. Most of this sort of generic support @@ -393,6 +388,10 @@ expand_vector_broadcast (machine_mode vmode, rtx op) if (icode == CODE_FOR_nothing) return NULL; + n = GET_MODE_NUNITS (vmode); + vec = rtvec_alloc (n); + for (i = 0; i < n; ++i) + RTVEC_ELT (vec, i) = op; ret = gen_reg_rtx (vmode); emit_insn (GEN_FCN (icode) (ret, gen_rtx_PARALLEL (vmode, vec))); -- cgit v1.2.1 From ccc2ef18f544a180d93344f9f56c552cce45a7d9 Mon Sep 17 00:00:00 2001 From: rsandifo Date: Wed, 1 Nov 2017 11:22:35 +0000 Subject: Add a VEC_SERIES rtl code This patch adds an rtl representation of a vector linear series of the form: a[I] = BASE + I * STEP Like vec_duplicate; - the new rtx can be used for both constant and non-constant vectors - when used for constant vectors it is wrapped in a (const ...) - the constant form is only used for variable-length vectors; fixed-length vectors still use CONST_VECTOR At the moment the code is restricted to integer elements, to avoid concerns over floating-point rounding. 2017-11-01 Richard Sandiford Alan Hayward David Sherwood gcc/ * doc/rtl.texi (vec_series): Document. (const): Say that the operand can be a vec_series. * rtl.def (VEC_SERIES): New rtx code. * rtl.h (const_vec_series_p_1): Declare. (const_vec_series_p): New function. * emit-rtl.h (gen_const_vec_series): Declare. (gen_vec_series): Likewise. * emit-rtl.c (const_vec_series_p_1, gen_const_vec_series) (gen_vec_series): Likewise. * optabs.c (expand_mult_highpart): Use gen_const_vec_series. * simplify-rtx.c (simplify_unary_operation): Handle negations of vector series. (simplify_binary_operation_series): New function. (simplify_binary_operation_1): Use it. Handle VEC_SERIES. (test_vector_ops_series): New function. (test_vector_ops): Call it. * config/powerpcspe/altivec.md (altivec_lvsl): Use gen_const_vec_series. (altivec_lvsr): Likewise. * config/rs6000/altivec.md (altivec_lvsl, altivec_lvsr): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254297 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/optabs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 6f7848d6b0b..7b3d59532f0 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5785,13 +5785,13 @@ expand_mult_highpart (machine_mode mode, rtx op0, rtx op1, for (i = 0; i < nunits; ++i) RTVEC_ELT (v, i) = GEN_INT (!BYTES_BIG_ENDIAN + (i & ~1) + ((i & 1) ? nunits : 0)); + perm = gen_rtx_CONST_VECTOR (mode, v); } else { - for (i = 0; i < nunits; ++i) - RTVEC_ELT (v, i) = GEN_INT (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1)); + int base = BYTES_BIG_ENDIAN ? 0 : 1; + perm = gen_const_vec_series (mode, GEN_INT (base), GEN_INT (2)); } - perm = gen_rtx_CONST_VECTOR (mode, v); return expand_vec_perm (mode, m1, m2, perm, target); } -- cgit v1.2.1 From d2a1b4530f1d00fb35c2aee051b00398a624bd27 Mon Sep 17 00:00:00 2001 From: rsandifo Date: Wed, 1 Nov 2017 12:30:39 +0000 Subject: Widening optab cleanup widening_optab_handler had the comment: /* ??? Why does find_widening_optab_handler_and_mode attempt to widen things that can't be widened? E.g. add_optab... */ if (op > LAST_CONV_OPTAB) return CODE_FOR_nothing; I think it comes from expand_binop using find_widening_optab_handler_and_mode for two things: to test whether a "normal" optab like add_optab is supported for a standard binary operation and to test whether a "convert" optab is supported for a widening operation like umul_widen_optab. In the former case from_mode and to_mode must be the same, in the latter from_mode must be narrower than to_mode. For the former case, find_widening_optab_handler_and_mode is only really testing the modes that are passed in. permit_non_widening must be true here. For the latter case, find_widening_optab_handler_and_mode should only really consider new from_modes that are wider than the original from_mode and narrower than the original to_mode. Logically permit_non_widening should be false, since widening optabs aren't supposed to take operands that are the same width as the destination. We get away with permit_non_widening being true because no target would/should define a widening .md pattern with matching modes. But really, it seems better for expand_binop to handle these two cases itself rather than pushing them down. With that change, find_widening_optab_handler_and_mode is only ever called with permit_non_widening set to false and is only ever called with a "proper" convert optab. We then no longer need widening_optab_handler, we can just use convert_optab_handler directly. The patch also passes the instruction code down to expand_binop_directly. This should be more efficient and removes an extra call to find_widening_optab_handler_and_mode. 2017-11-01 Richard Sandiford Alan Hayward David Sherwood gcc/ * optabs-query.h (convert_optab_p): New function, split out from... (convert_optab_handler): ...here. (widening_optab_handler): Delete. (find_widening_optab_handler): Remove permit_non_widening parameter. (find_widening_optab_handler_and_mode): Likewise. Provide an override that operates on mode class wrappers. * optabs-query.c (widening_optab_handler): Delete. (find_widening_optab_handler_and_mode): Remove permit_non_widening parameter. Assert that the two modes are the same class and that the "from" mode is narrower than the "to" mode. Use convert_optab_handler instead of widening_optab_handler. * expmed.c (expmed_mult_highpart_optab): Use convert_optab_handler instead of widening_optab_handler. * expr.c (expand_expr_real_2): Update calls to find_widening_optab_handler. * optabs.c (expand_widen_pattern_expr): Likewise. (expand_binop_directly): Take the insn_code as a parameter. (expand_binop): Only call find_widening_optab_handler for conversion optabs; use optab_handler otherwise. Update calls to find_widening_optab_handler and expand_binop_directly. Use convert_optab_handler instead of widening_optab_handler. * tree-ssa-math-opts.c (convert_mult_to_widen): Update calls to find_widening_optab_handler and use scalar_mode rather than machine_mode. (convert_plusminus_to_widen): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254302 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/optabs.c | 57 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 24 deletions(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 7b3d59532f0..7cf4d8e4280 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -264,7 +264,7 @@ expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op, || ops->code == WIDEN_MULT_MINUS_EXPR) icode = find_widening_optab_handler (widen_pattern_optab, TYPE_MODE (TREE_TYPE (ops->op2)), - tmode0, 0); + tmode0); else icode = optab_handler (widen_pattern_optab, tmode0); gcc_assert (icode != CODE_FOR_nothing); @@ -979,17 +979,14 @@ avoid_expensive_constant (machine_mode mode, optab binoptab, } /* Helper function for expand_binop: handle the case where there - is an insn that directly implements the indicated operation. + is an insn ICODE that directly implements the indicated operation. Returns null if this is not possible. */ static rtx -expand_binop_directly (machine_mode mode, optab binoptab, +expand_binop_directly (enum insn_code icode, machine_mode mode, optab binoptab, rtx op0, rtx op1, rtx target, int unsignedp, enum optab_methods methods, rtx_insn *last) { - machine_mode from_mode = widened_mode (mode, op0, op1); - enum insn_code icode = find_widening_optab_handler (binoptab, mode, - from_mode, 1); machine_mode xmode0 = insn_data[(int) icode].operand[1].mode; machine_mode xmode1 = insn_data[(int) icode].operand[2].mode; machine_mode mode0, mode1, tmp_mode; @@ -1113,6 +1110,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN ? OPTAB_WIDEN : methods); enum mode_class mclass; + enum insn_code icode; machine_mode wider_mode; scalar_int_mode int_mode; rtx libfunc; @@ -1146,23 +1144,30 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, /* If we can do it with a three-operand insn, do so. */ - if (methods != OPTAB_MUST_WIDEN - && find_widening_optab_handler (binoptab, mode, - widened_mode (mode, op0, op1), 1) - != CODE_FOR_nothing) + if (methods != OPTAB_MUST_WIDEN) { - temp = expand_binop_directly (mode, binoptab, op0, op1, target, - unsignedp, methods, last); - if (temp) - return temp; + if (convert_optab_p (binoptab)) + { + machine_mode from_mode = widened_mode (mode, op0, op1); + icode = find_widening_optab_handler (binoptab, mode, from_mode); + } + else + icode = optab_handler (binoptab, mode); + if (icode != CODE_FOR_nothing) + { + temp = expand_binop_directly (icode, mode, binoptab, op0, op1, + target, unsignedp, methods, last); + if (temp) + return temp; + } } /* If we were trying to rotate, and that didn't work, try rotating the other direction before falling back to shifts and bitwise-or. */ if (((binoptab == rotl_optab - && optab_handler (rotr_optab, mode) != CODE_FOR_nothing) + && (icode = optab_handler (rotr_optab, mode)) != CODE_FOR_nothing) || (binoptab == rotr_optab - && optab_handler (rotl_optab, mode) != CODE_FOR_nothing)) + && (icode = optab_handler (rotl_optab, mode)) != CODE_FOR_nothing)) && is_int_mode (mode, &int_mode)) { optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab); @@ -1178,7 +1183,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, gen_int_mode (bits, GET_MODE (op1)), op1, NULL_RTX, unsignedp, OPTAB_DIRECT); - temp = expand_binop_directly (int_mode, otheroptab, op0, newop1, + temp = expand_binop_directly (icode, int_mode, otheroptab, op0, newop1, target, unsignedp, methods, last); if (temp) return temp; @@ -1225,7 +1230,8 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, else if (binoptab == rotr_optab) otheroptab = vrotr_optab; - if (otheroptab && optab_handler (otheroptab, mode) != CODE_FOR_nothing) + if (otheroptab + && (icode = optab_handler (otheroptab, mode)) != CODE_FOR_nothing) { /* The scalar may have been extended to be too wide. Truncate it back to the proper size to fit in the broadcast vector. */ @@ -1239,7 +1245,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, rtx vop1 = expand_vector_broadcast (mode, op1); if (vop1) { - temp = expand_binop_directly (mode, otheroptab, op0, vop1, + temp = expand_binop_directly (icode, mode, otheroptab, op0, vop1, target, unsignedp, methods, last); if (temp) return temp; @@ -1262,7 +1268,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, && (find_widening_optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab), - next_mode, mode, 0) + next_mode, mode) != CODE_FOR_nothing))) { rtx xop0 = op0, xop1 = op1; @@ -1693,7 +1699,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, && optab_handler (add_optab, word_mode) != CODE_FOR_nothing) { rtx product = NULL_RTX; - if (widening_optab_handler (umul_widen_optab, int_mode, word_mode) + if (convert_optab_handler (umul_widen_optab, int_mode, word_mode) != CODE_FOR_nothing) { product = expand_doubleword_mult (int_mode, op0, op1, target, @@ -1703,7 +1709,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, } if (product == NULL_RTX - && (widening_optab_handler (smul_widen_optab, int_mode, word_mode) + && (convert_optab_handler (smul_widen_optab, int_mode, word_mode) != CODE_FOR_nothing)) { product = expand_doubleword_mult (int_mode, op0, op1, target, @@ -1796,10 +1802,13 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, if (CLASS_HAS_WIDER_MODES_P (mclass)) { + /* This code doesn't make sense for conversion optabs, since we + wouldn't then want to extend the operands to be the same size + as the result. */ + gcc_assert (!convert_optab_p (binoptab)); FOR_EACH_WIDER_MODE (wider_mode, mode) { - if (find_widening_optab_handler (binoptab, wider_mode, mode, 1) - != CODE_FOR_nothing + if (optab_handler (binoptab, wider_mode) || (methods == OPTAB_LIB && optab_libfunc (binoptab, wider_mode))) { -- cgit v1.2.1 From 0d97e6d1fd7ca63c5b9aba845c4bb2bb7e508b93 Mon Sep 17 00:00:00 2001 From: rsandifo Date: Wed, 1 Nov 2017 13:30:34 +0000 Subject: Add an is_narrower_int_mode helper function This patch adds a function for testing whether an arbitrary mode X is an integer mode that is narrower than integer mode Y. This is useful for code like expand_float and expand_fix that could in principle handle vectors as well as scalars. 2017-11-01 Richard Sandiford Alan Hayward David Sherwood gcc/ * machmode.h (is_narrower_int_mode): New function * optabs.c (expand_float, expand_fix): Use it. * dwarf2out.c (rotate_loc_descriptor): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254305 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/optabs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 7cf4d8e4280..8f7089ef0f1 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4811,7 +4811,7 @@ expand_float (rtx to, rtx from, int unsignedp) rtx value; convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab; - if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_PRECISION (SImode)) + if (is_narrower_int_mode (GET_MODE (from), SImode)) from = convert_to_mode (SImode, from, unsignedp); libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from)); @@ -4993,7 +4993,7 @@ expand_fix (rtx to, rtx from, int unsignedp) that the mode of TO is at least as wide as SImode, since those are the only library calls we know about. */ - if (GET_MODE_PRECISION (GET_MODE (to)) < GET_MODE_PRECISION (SImode)) + if (is_narrower_int_mode (GET_MODE (to), SImode)) { target = gen_reg_rtx (SImode); -- cgit v1.2.1