OSDN Git Service

PR rtl-optimization/42220
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 7 Mar 2010 15:20:12 +0000 (15:20 +0000)
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 7 Mar 2010 15:20:12 +0000 (15:20 +0000)
* regrename.c (scan_rtx) <case STRICT_LOW_PART, ZERO_EXTRACT>:
Use verify_reg_tracked to determine if we should use OP_OUT rather
than OP_INOUT.
(build_def_use): If we see an in-out operand for a register that we
know nothing about, treat is an output if possible, fail the block if
not.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@157263 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/regrename.c

index dfbbb24..25c0efd 100644 (file)
@@ -1,3 +1,13 @@
+2010-03-07  Bernd Schmidt  <bernd.schmidt@analog.com>
+
+       PR rtl-optimization/42220
+       * regrename.c (scan_rtx) <case STRICT_LOW_PART, ZERO_EXTRACT>:
+       Use verify_reg_tracked to determine if we should use OP_OUT rather
+       than OP_INOUT.
+       (build_def_use): If we see an in-out operand for a register that we
+       know nothing about, treat is an output if possible, fail the block if
+       not.
+
 2010-03-06  Alexandre Oliva  <aoliva@redhat.com>
 
        PR debug/42897
index e003fd4..f7891d1 100644 (file)
@@ -889,13 +889,15 @@ scan_rtx (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
       return;
 
     case STRICT_LOW_PART:
-      scan_rtx (insn, &XEXP (x, 0), cl, action, OP_INOUT);
+      scan_rtx (insn, &XEXP (x, 0), cl, action,
+               verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT);
       return;
 
     case ZERO_EXTRACT:
     case SIGN_EXTRACT:
       scan_rtx (insn, &XEXP (x, 0), cl, action,
-               type == OP_IN ? OP_IN : OP_INOUT);
+               (type == OP_IN ? OP_IN :
+                verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT));
       scan_rtx (insn, &XEXP (x, 1), cl, action, OP_IN);
       scan_rtx (insn, &XEXP (x, 2), cl, action, OP_IN);
       return;
@@ -1067,6 +1069,7 @@ build_def_use (basic_block bb)
          int n_ops;
          rtx note;
          rtx old_operands[MAX_RECOG_OPERANDS];
+         bool has_dup[MAX_RECOG_OPERANDS];
          rtx old_dups[MAX_DUP_OPERANDS];
          int i;
          int alt;
@@ -1105,6 +1108,10 @@ build_def_use (basic_block bb)
          n_ops = recog_data.n_operands;
          untracked_operands = 0;
 
+         memset (has_dup, 0, sizeof has_dup);
+         for (i = 0; i < recog_data.n_dups; i++)
+           has_dup[(int)recog_data.dup_num[i]] = true;
+
          /* Simplify the code below by rewriting things to reflect
             matching constraints.  Also promote OP_OUT to OP_INOUT in
             predicated instructions, but only for register operands
@@ -1137,6 +1144,20 @@ build_def_use (basic_block bb)
                      untracked_operands |= 1 << matches;
                    }
                }
+             /* If there's an in-out operand with a register that is not
+                being tracked at all yet, convert it to an earlyclobber
+                output operand.
+                This only works if the operand isn't duplicated, i.e. for
+                a ZERO_EXTRACT in a SET_DEST.  */
+             if (recog_data.operand_type[i] == OP_INOUT
+                 && !(untracked_operands & (1 << i))
+                 && !verify_reg_tracked (recog_data.operand[i]))
+               {
+                 if (has_dup[i])
+                   fail_current_block = true;
+                 recog_data.operand_type[i] = OP_OUT;
+                 recog_op_alt[i][alt].earlyclobber = 1;
+               }
            }
 
          if (fail_current_block)