https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80754

            Bug ID: 80754
           Summary: invalid smull instructions generated after r247881
           Product: gcc
           Version: 8.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: amker at gcc dot gnu.org
  Target Milestone: ---

Hi,
After r247881, below invalid smull instructions are generated:
  smull r2, r2, lr, r3
in test gcc.c-torture/execute/pr53645-2.c for arm-none-linux-gnueabi and
cortex-a9

The revision simply changes rtx cost for tieable modes:

diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 321363f..d9f57c3 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -4164,6 +4164,13 @@ rtx_cost (rtx x, machine_mode mode, enum rtx_code
outer_code,
        return COSTS_N_INSNS (2 + factor);
       break;

+    case TRUNCATE:
+      if (MODES_TIEABLE_P (mode, GET_MODE (XEXP (x, 0))))
+       {
+         total = 0;
+         break;
+       }
+      /* FALLTHRU */
     default:
       if (targetm.rtx_costs (x, mode, outer_code, opno, &total, speed))
        return total

I noticed that in arm.h/arm.c:

/* Implement MODES_TIEABLE_P.  */

bool
arm_modes_tieable_p (machine_mode mode1, machine_mode mode2)
{
  if (GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2))
    return true;

  /* We specifically want to allow elements of "structure" modes to
     be tieable to the structure.  This more general condition allows
     other rarer situations too.  */
  if (TARGET_NEON
      && (VALID_NEON_DREG_MODE (mode1)
          || VALID_NEON_QREG_MODE (mode1)
          || VALID_NEON_STRUCT_MODE (mode1))
      && (VALID_NEON_DREG_MODE (mode2)
          || VALID_NEON_QREG_MODE (mode2)
          || VALID_NEON_STRUCT_MODE (mode2)))
    return true;

  return false;
}

So SImode/DImode are tieable on ARM target, while we have :

(define_insn "*smulsi3_highpart_v6"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
        (truncate:SI
         (lshiftrt:DI
          (mult:DI
           (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
          (const_int 32))))
   (clobber (match_scratch:SI 3 "=r"))]
  "TARGET_32BIT && arm_arch6"
  "smull%?\\t%3, %0, %2, %1"
  [(set_attr "type" "smull")
   (set_attr "predicable" "yes")
   (set_attr "predicable_short_it" "no")]
)

It looks operand 0 and 3 now get allocated to the same register.  
I think this might be a backend issue either in tieable interface or
"*smulsi3_highpart_v6" constraint?

Thanks,
bin

Reply via email to