diff mbox

web ICEs on subreg

Message ID D0C5078B-F760-49AF-83DA-26B8CC221A16@comcast.net
State New
Headers show

Commit Message

Mike Stump May 10, 2013, 9:51 p.m. UTC
I have a instruction pattern for my port that reads in part:

  [(parallel [(set (subreg:DI (match_operand:TI 0 "register_operand" "=r") 0)
                   (mem:DI (plus:DI (match_operand:DI 1 "register_operand" "r")
                                    (match_operand:DI 2 "const_int_operand" ""))))
              (set (subreg:DI (match_dup 0) 8)
                   (mem:DI (plus:DI (match_dup 1)
                                    (match_operand:DI 3 "const_int_operand"))))])]

The subreg seems to give web.c fits.  web is looking for the match_dup and failing to find it, due to the fact that DF_REF_LOC is of the form (subreg:DI (reg:TI 5) 8), not (reg:TI 5).  If I add a case for SUBREG like in the below, we can then find and process the subreg.

So, the question is, is the port completely wrong for trying to use subreg in this fashion?  If not, is processing subregs in this way the right way?  If yes, Ok?

Comments

Steven Bosscher May 10, 2013, 10:10 p.m. UTC | #1
On Fri, May 10, 2013 at 11:51 PM, Mike Stump wrote:

> -       if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
> -         break;
> +       {
> +         if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
> +           break;
> +         /* DF_REF_LOC can be (subreg:DI (reg:TI 5) 8) and
> +            recog_data.operand_loc[op] can be (reg:TI 5), and the above
> +            won't find it.  */
> +         if (GET_CODE (*DF_REF_LOC (*ref)) == SUBREG &&
> +             &SUBREG_REG (*DF_REF_LOC (*ref)) == recog_data.operand_loc[op])

Congrats, you've re-invented DF_REF_REAL_LOC.

Ciao!
Steven
Steven Bosscher May 10, 2013, 10:29 p.m. UTC | #2
On Fri, May 10, 2013 at 11:51 PM, Mike Stump wrote:
> I have a instruction pattern for my port that reads in part:
>
>   [(parallel [(set (subreg:DI (match_operand:TI 0 "register_operand" "=r") 0)
>                    (mem:DI (plus:DI (match_operand:DI 1 "register_operand" "r")
>                                     (match_operand:DI 2 "const_int_operand" ""))))
>               (set (subreg:DI (match_dup 0) 8)
>                    (mem:DI (plus:DI (match_dup 1)
>                                     (match_operand:DI 3 "const_int_operand"))))])]
>
> The subreg seems to give web.c fits.  web is looking for the match_dup and failing to find it, due to the fact that DF_REF_LOC is of the form (subreg:DI (reg:TI 5) 8), not (reg:TI 5).  If I add a case for SUBREG like in the below, we can then find and process the subreg.
>
> So, the question is, is the port completely wrong for trying to use subreg in this fashion?  If not, is processing subregs in this way the right way?  If yes, Ok?

I don't think this port is completely wrong. I've looked at some other
ports and there are comparable patterns, e.g. in m68k:

;; We need a separate DEFINE_EXPAND for u?mulsidi3 to be able to use the
;; proper matching constraint.  This is because the matching is between
;; the high-numbered word of the DImode operand[0] and operand[1].
(define_expand "umulsidi3"
  [(parallel
    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
          (mult:SI (match_operand:SI 1 "register_operand" "")
                   (match_operand:SI 2 "register_operand" "")))
     (set (subreg:SI (match_dup 0) 0)
          (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
                                             (zero_extend:DI (match_dup 2)))
                                    (const_int 32))))])]
  "TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
  "")

Your web.c patch looks correct to me, but I can't approve it.

Ciao!
Steven
diff mbox

Patch

diff --git a/gcc/web.c b/gcc/web.c
index b602615..702a4e9 100644
--- a/gcc/web.c
+++ b/gcc/web.c
@@ -133,8 +133,16 @@  union_match_dups (rtx insn, struct web_entry *def_entry,
       ref = type == OP_IN ? use_link : def_link;
       entry = type == OP_IN ? use_entry : def_entry;
       for (; *ref; ref++)
-       if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
-         break;
+       {
+         if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
+           break;
+         /* DF_REF_LOC can be (subreg:DI (reg:TI 5) 8) and
+            recog_data.operand_loc[op] can be (reg:TI 5), and the above
+            won't find it.  */
+         if (GET_CODE (*DF_REF_LOC (*ref)) == SUBREG &&
+             &SUBREG_REG (*DF_REF_LOC (*ref)) == recog_data.operand_loc[op])
+           break;
+       }
 
       if (!*ref && type == OP_INOUT)
        {