@@ -8059,6 +8059,7 @@ struct genimm_ppc : genimm_base <rtx_code, 5>
bool exam_simple (HOST_WIDE_INT c, machine_mode, int budget);
bool exam_sub (HOST_WIDE_INT c, int budget);
bool exam_mask (HOST_WIDE_INT c, HOST_WIDE_INT mask, int sub_budget);
+ bool exam_rotl (HOST_WIDE_INT c, int bits);
bool exam_search (HOST_WIDE_INT c, int budget);
void exam_full (HOST_WIDE_INT c);
void generate (rtx dest, machine_mode mode) const;
@@ -8137,6 +8138,24 @@ genimm_ppc::exam_mask (HOST_WIDE_INT c, HOST_WIDE_INT mask, int sub_budget)
return false;
}
+/* If we're able to rotate a 16-bit signed constant to form C,
+ return true and fill in the recipe. */
+
+bool
+genimm_ppc::exam_rotl (HOST_WIDE_INT c, int bits)
+{
+ HOST_WIDE_INT sub_c = (unsigned HOST_WIDE_INT)c >> bits;
+ sub_c |= (unsigned HOST_WIDE_INT)c << (64 - bits);
+
+ if ((unsigned HOST_WIDE_INT)sub_c + 0x8000 < 0x10000)
+ {
+ set0 (sub_c);
+ opN (ROTATE, bits);
+ return true;
+ }
+ return false;
+}
+
/* The body of the recursive search for C within BUDGET.
We've already failed exam_simple. */
@@ -8212,6 +8231,35 @@ genimm_ppc::exam_search (HOST_WIDE_INT c, int budget)
}
}
+ /* Rotate the constant left. Because of combinatorial complexity,
+ only consider this with a 16-bit base, which means there's no
+ point in considering this high in the search tree. */
+ if (sub_budget == 1)
+ {
+ /* The 16-bit signed constant upon which we are going to base
+ the rotate can have no more than 15 bits set as a positive
+ or no less than 49 bits set as a negative. */
+ bits = popcount_hwi (c);
+ if (bits <= 15)
+ {
+ /* The constant must be positive, and it must have failed
+ the simpler shift test above. Therefore, any success
+ will be with a rotate of more than 48. */
+ bits = ctz_hwi (c & ~ HOST_WIDE_INT_UC (0x7fff));
+ if (bits > 48 && exam_rotl (c, bits))
+ return true;
+ }
+ else if (bits > 48)
+ {
+ /* The constant must be negative, and it must have rotated
+ copies of the sign bit around into the low order bits.
+ Those copies must be the number of rotations. */
+ bits = ctz_hwi (~c);
+ if (exam_rotl (c, bits))
+ return true;
+ }
+ }
+
return false;
}
@@ -8255,6 +8303,9 @@ genimm_ppc::generate (rtx dest, machine_mode mode) const
case SET:
x = op2;
break;
+ case ROTATE:
+ gcc_assert (mode == DImode);
+ /* FALLTHRU */
case PLUS:
case AND:
case IOR: