ifcvt.c (noce_emit_move_insn): Call store_bit_field if the resulting move would be...
authorAndreas Krebbel <krebbel1@de.ibm.com>
Wed, 19 Apr 2006 11:45:41 +0000 (11:45 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Wed, 19 Apr 2006 11:45:41 +0000 (11:45 +0000)
2006-04-19  Andreas Krebbel  <krebbel1@de.ibm.com>

* ifcvt.c (noce_emit_move_insn): Call store_bit_field if the resulting
move would be an INSV insn.
(noce_process_if_block): Don't optimize if the destination is a
ZERO_EXTRACT which can't be handled by noce_emit_move_insn.

2006-04-19  Andreas Krebbel  <krebbel1@de.ibm.com>

* gcc.c-torture/compile/20060419-1.c: Added.

From-SVN: r113072

gcc/ChangeLog
gcc/ifcvt.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20060419-1.c [new file with mode: 0644]

index 5ab45848029927bb440fdefbb5e67f159b0dca07..c80626aef5e8032a985955457ea7681efaaf86ec 100644 (file)
@@ -1,3 +1,10 @@
+2006-04-19  Andreas Krebbel  <krebbel1@de.ibm.com>
+
+       * ifcvt.c (noce_emit_move_insn): Call store_bit_field if the resulting
+       move would be an INSV insn.
+       (noce_process_if_block): Don't optimize if the destination is a 
+       ZERO_EXTRACT which can't be handled by noce_emit_move_insn.
+
 2006-04-19  Andreas Krebbel  <krebbel1@de.ibm.com>
 
        * config/s390/s390.md: Add comments with the instructions emitted
index 23a9b3c7c36ae9e5d969650ee65f61f53bd3ed33..4787a246b0558ef55fdcb1507e6049d3751f895f 100644 (file)
@@ -702,47 +702,76 @@ noce_emit_move_insn (rtx x, rtx y)
       end_sequence();
 
       if (recog_memoized (insn) <= 0)
-       switch (GET_RTX_CLASS (GET_CODE (y)))
-         {
-         case RTX_UNARY:
-           ot = code_to_optab[GET_CODE (y)];
-           if (ot)
-             {
-               start_sequence ();
-               target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
-               if (target != NULL_RTX)
-                 {
-                   if (target != x)
-                     emit_move_insn (x, target);
-                   seq = get_insns ();
-                 }
-               end_sequence ();
-             }
-           break;
-
-         case RTX_BIN_ARITH:
-         case RTX_COMM_ARITH:
-           ot = code_to_optab[GET_CODE (y)];
-           if (ot)
-             {
-               start_sequence ();
-               target = expand_binop (GET_MODE (y), ot,
-                                      XEXP (y, 0), XEXP (y, 1),
-                                      x, 0, OPTAB_DIRECT);
-               if (target != NULL_RTX)
-                 {
-                   if (target != x)
-                     emit_move_insn (x, target);
-                   seq = get_insns ();
-                 }
-               end_sequence ();
-             }
-           break;
+       {
+         if (GET_CODE (x) == ZERO_EXTRACT)
+           {
+             rtx op = XEXP (x, 0);
+             unsigned HOST_WIDE_INT size = INTVAL (XEXP (x, 1));
+             unsigned HOST_WIDE_INT start = INTVAL (XEXP (x, 2));
+
+             /* store_bit_field expects START to be relative to 
+                BYTES_BIG_ENDIAN and adjusts this value for machines with 
+                BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN.  In order to be able to 
+                invoke store_bit_field again it is necessary to have the START
+                value from the first call.  */
+             if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
+               {
+                 if (MEM_P (op))
+                   start = BITS_PER_UNIT - start - size;
+                 else
+                   {
+                     gcc_assert (REG_P (op));
+                     start = BITS_PER_WORD - start - size;
+                   }
+               }
 
-         default:
-           break;
-         }
+             gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD));
+             store_bit_field (op, size, start, GET_MODE (x), y);
+             return;
+           }
 
+         switch (GET_RTX_CLASS (GET_CODE (y)))
+           {
+           case RTX_UNARY:
+             ot = code_to_optab[GET_CODE (y)];
+             if (ot)
+               {
+                 start_sequence ();
+                 target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
+                 if (target != NULL_RTX)
+                   {
+                     if (target != x)
+                       emit_move_insn (x, target);
+                     seq = get_insns ();
+                   }
+                 end_sequence ();
+               }
+             break;
+             
+           case RTX_BIN_ARITH:
+           case RTX_COMM_ARITH:
+             ot = code_to_optab[GET_CODE (y)];
+             if (ot)
+               {
+                 start_sequence ();
+                 target = expand_binop (GET_MODE (y), ot,
+                                        XEXP (y, 0), XEXP (y, 1),
+                                        x, 0, OPTAB_DIRECT);
+                 if (target != NULL_RTX)
+                   {
+                     if (target != x)
+                         emit_move_insn (x, target);
+                     seq = get_insns ();
+                   }
+                 end_sequence ();
+               }
+             break;
+             
+           default:
+             break;
+           }
+       }
+      
       emit_insn (seq);
       return;
     }
@@ -2231,6 +2260,12 @@ noce_process_if_block (struct ce_if_block * ce_info)
     {
       if (no_new_pseudos || GET_MODE (x) == BLKmode)
        return FALSE;
+
+      if (GET_MODE (x) == ZERO_EXTRACT 
+         && (GET_CODE (XEXP (x, 1)) != CONST_INT 
+             || GET_CODE (XEXP (x, 2)) != CONST_INT))
+       return FALSE;
+         
       x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
                                 ? XEXP (x, 0) : x));
     }
index e48bc78add3b175adbfed478d793980c22a5242b..49fa80c9c9f15d5bba0b6ac8d5bdbb61cad67a59 100644 (file)
@@ -1,3 +1,7 @@
+2006-04-19  Andreas Krebbel  <krebbel1@de.ibm.com>
+
+       * gcc.c-torture/compile/20060419-1.c: Added.
+
 2006-04-18  Bernhard Fischer  <aldot@gcc.gnu.org>
 
        * gfortran.dg/label_1.f90: Adjust dg-error.
diff --git a/gcc/testsuite/gcc.c-torture/compile/20060419-1.c b/gcc/testsuite/gcc.c-torture/compile/20060419-1.c
new file mode 100644 (file)
index 0000000..dc346ae
--- /dev/null
@@ -0,0 +1,21 @@
+/* This failed because if conversion didn't handle insv patterns properly.  */
+
+union y
+{
+  int a;
+  unsigned short b;
+};
+
+extern void bar (unsigned short u, union y v);
+
+void
+foo (int check)
+{
+  union y x;
+
+  if (check != 0)
+    x.b = 1;
+  else
+    x.b = 2;
+  bar (x.b, x);
+}