https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115186
--- Comment #1 from Di Zhao <dizhao at os dot amperecomputing.com> --- A raw fix below can fix this case (not sure if this is the right way): diff --git a/gcc/expmed.cc b/gcc/expmed.cc index 50d22762cae..bf42a0ff5ca 100644 --- a/gcc/expmed.cc +++ b/gcc/expmed.cc @@ -3976,7 +3976,10 @@ expmed_mult_highpart (scalar_int_mode mode, rtx op0, rtx op1, bool sign_adjust = false; enum mult_variant variant; struct algorithm alg; - rtx narrow_op1, tem; + rtx narrow_op1, tem, tem2; + rtx_insn *shift_add_insns; + rtx_insn *mult_insns; + unsigned shift_add_cost, mult_cost; /* We can't support modes wider than HOST_BITS_PER_INT. */ gcc_assert (HWI_COMPUTABLE_MODE_P (mode)); @@ -4014,6 +4017,7 @@ expmed_mult_highpart (scalar_int_mode mode, rtx op0, rtx op1, if (tem) return tem; + start_sequence (); tem = convert_to_mode (wider_mode, op0, unsignedp); tem = expand_mult_const (wider_mode, tem, cnst1, 0, &alg, variant); tem = extract_high_half (mode, tem); @@ -4021,8 +4025,29 @@ expmed_mult_highpart (scalar_int_mode mode, rtx op0, rtx op1, /* Adjust result for signedness. */ if (sign_adjust) tem = force_operand (gen_rtx_MINUS (mode, tem, op0), tem); + shift_add_insns = get_insns (); + end_sequence (); + shift_add_cost = seq_cost (shift_add_insns, speed); + + start_sequence (); + tem2 = expmed_mult_highpart_optab (mode, op0, op1, target, unsignedp, + max_cost); + mult_insns = get_insns (); + end_sequence (); + mult_cost = seq_cost (mult_insns, speed); - return tem; + if (tem2 && mult_cost < shift_add_cost) + { + emit_insn (mult_insns); + return tem2; + } + else if (shift_add_cost < max_cost) + { + emit_insn (shift_add_insns); + return tem; + } + else + return 0; } return expmed_mult_highpart_optab (mode, op0, narrow_op1, target, unsignedp, max_cost);