[Bug rtl-optimization/115186] Suboptimal codes generated by rtl-expand for divmod

dizhao at os dot amperecomputing.com gcc-bugzilla@gcc.gnu.org
Wed May 22 10:28:55 GMT 2024


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);


More information about the Gcc-bugs mailing list