* config/rs6000/rs6000.c (rs6000_rtx_costs): Cost IOR.

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 8c300b82b11..fb5fe7969a3 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -21177,6 +21177,7 @@ static bool
 rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code,
                  int opno ATTRIBUTE_UNUSED, int *total, bool speed)
 {
+  rtx left, right;
   int code = GET_CODE (x);
 
   switch (code)
@@ -21367,16 +21368,17 @@ rs6000_rtx_costs (rtx x, machine_mode mode, int 
outer_code,
       return false;
 
     case AND:
-      if (CONST_INT_P (XEXP (x, 1)))
+      right = XEXP (x, 1);
+      if (CONST_INT_P (right))
        {
-         rtx left = XEXP (x, 0);
+         left = XEXP (x, 0);
          rtx_code left_code = GET_CODE (left);
 
          /* rotate-and-mask: 1 insn.  */
          if ((left_code == ROTATE
               || left_code == ASHIFT
               || left_code == LSHIFTRT)
-             && rs6000_is_valid_shift_mask (XEXP (x, 1), left, mode))
+             && rs6000_is_valid_shift_mask (right, left, mode))
            {
              *total = rtx_cost (XEXP (left, 0), mode, left_code, 0, speed);
              if (!CONST_INT_P (XEXP (left, 1)))
@@ -21390,9 +21392,106 @@ rs6000_rtx_costs (rtx x, machine_mode mode, int 
outer_code,
       return false;
 
     case IOR:
-      /* FIXME */
       *total = COSTS_N_INSNS (1);
-      return true;
+      left = XEXP (x, 0);
+      if (GET_CODE (left) == AND
+         && CONST_INT_P (XEXP (left, 1)))
+       {
+         right = XEXP (x, 1);
+         if (GET_CODE (right) == AND
+             && CONST_INT_P (XEXP (right, 1))
+             && UINTVAL (XEXP (left, 1)) + UINTVAL (XEXP (right, 1)) + 1 == 0)
+           {
+             rtx leftop = XEXP (left, 0);
+             rtx rightop = XEXP (right, 0);
+
+             // rotlsi3_insert_5
+             if (REG_P (leftop)
+                 && REG_P (rightop)
+                 && mode == SImode
+                 && UINTVAL (XEXP (left, 1)) != 0
+                 && UINTVAL (XEXP (right, 1)) != 0
+                 && rs6000_is_valid_mask (XEXP (left, 1), NULL, NULL, mode))
+               return true;
+             // rotldi3_insert_6
+             if (REG_P (leftop)
+                 && REG_P (rightop)
+                 && mode == DImode
+                 && exact_log2 (-UINTVAL (XEXP (left, 1))) > 0)
+               return true;
+             // rotldi3_insert_7
+             if (REG_P (leftop)
+                 && REG_P (rightop)
+                 && mode == DImode
+                 && exact_log2 (-UINTVAL (XEXP (right, 1))) > 0)
+               return true;
+
+             rtx mask = 0;
+             rtx shift = leftop;
+             rtx_code shift_code = GET_CODE (shift);
+             // rotl<mode>3_insert
+             if (shift_code == ROTATE
+                 || shift_code == ASHIFT
+                 || shift_code == LSHIFTRT)
+               mask = right;
+             else
+               {
+                 shift = rightop;
+                 shift_code = GET_CODE (shift);
+                 // rotl<mode>3_insert_2
+                 if (shift_code == ROTATE
+                     || shift_code == ASHIFT
+                     || shift_code == LSHIFTRT)
+                   mask = left;
+               }
+             if (mask
+                 && CONST_INT_P (XEXP (shift, 1))
+                 && rs6000_is_valid_insert_mask (XEXP (mask, 1), shift, mode))
+               {
+                 /* Test both regs even though the one in the mask is
+                    constrained to be equal to the output.  Increasing
+                    cost may well result in rejecting an invalid insn
+                    earlier.  */
+                 rtx reg_op = XEXP (shift, 0);
+                 if (!REG_P (reg_op))
+                   *total += rtx_cost (reg_op, mode, shift_code, 0, speed);
+                 reg_op = XEXP (mask, 0);
+                 if (!REG_P (reg_op))
+                   *total += rtx_cost (reg_op, mode, AND, 0, speed);
+                 return true;
+               }
+           }
+         // rotl<mode>3_insert_3
+         if (GET_CODE (right) == ASHIFT
+             && CONST_INT_P (XEXP (right, 1))
+             && (INTVAL (XEXP (right, 1))
+                 == exact_log2 (UINTVAL (XEXP (left, 1)) + 1)))
+           {
+             rtx reg_op = XEXP (left, 0);
+             if (!REG_P (reg_op))
+               *total += rtx_cost (reg_op, mode, AND, 0, speed);
+             reg_op = XEXP (right, 0);
+             if (!REG_P (reg_op))
+               *total += rtx_cost (reg_op, mode, ASHIFT, 0, speed);
+             return true;
+           }
+         // rotl<mode>3_insert_4
+         if (GET_CODE (right) == LSHIFTRT
+             && CONST_INT_P (XEXP (right, 1))
+             && mode == SImode
+             && (INTVAL (XEXP (right, 1))
+                 + exact_log2 (-UINTVAL (XEXP (left, 1)))) == 32)
+           {
+             rtx reg_op = XEXP (left, 0);
+             if (!REG_P (reg_op))
+               *total += rtx_cost (reg_op, mode, AND, 0, speed);
+             reg_op = XEXP (right, 0);
+             if (!REG_P (reg_op))
+               *total += rtx_cost (reg_op, mode, LSHIFTRT, 0, speed);
+             return true;
+           }
+       }
+      return false;
 
     case CLZ:
     case XOR:

Reply via email to