Commit 567f4828 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[arm] Optimize FitsShifter to remove loop

Operands in Arm can be encoded as (8-bit value, 2*N bit left rotate).
This encoding is checked for with the FitsShifter function.

Previously, this encoding was exhaustively searched for by checking all
16 possible rotations. However, we can simply classify the different
possible rotations as shifting away trailing zeros (without rotation),
or rotating an 8-bit value split over the beginning and end of the
32-bit value (which, after one rotation, becomes the first case).

Hence, we can replace the exhaustive search with a couple of trailing
zeros calculations within these classes.

Change-Id: Id896539c376f695b54bdf31133b2a103b0cf9736
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2831479
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarPatrick Thier <pthier@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74012}
parent 2024f63b
......@@ -1030,10 +1030,53 @@ namespace {
bool FitsShifter(uint32_t imm32, uint32_t* rotate_imm, uint32_t* immed_8,
Instr* instr) {
// imm32 must be unsigned.
for (int rot = 0; rot < 16; rot++) {
uint32_t imm8 = base::bits::RotateLeft32(imm32, 2 * rot);
if ((imm8 <= 0xFF)) {
*rotate_imm = rot;
{
// 32-bit immediates can be encoded as:
// (8-bit value, 2*N bit left rotation)
// e.g. 0xab00 can be encoded as 0xab shifted left by 8 == 2*4, i.e.
// (0xab, 4)
//
// Check three categories which cover all possible shifter fits:
// 1. 0x000000FF: The value is already 8-bit (no shifting necessary),
// 2. 0x000FF000: The 8-bit value is somewhere in the middle of the 32-bit
// value, and
// 3. 0xF000000F: The 8-bit value is split over the beginning and end of
// the 32-bit value.
// For 0x000000FF.
if (imm32 <= 0xFF) {
*rotate_imm = 0;
*immed_8 = imm32;
return true;
}
// For 0x000FF000, count trailing zeros and shift down to 0x000000FF. Note
// that we have to round the trailing zeros down to the nearest multiple of
// two, since we can only encode shifts of 2*N. Note also that we know that
// imm32 isn't zero, since we already checked if it's less than 0xFF.
int half_trailing_zeros = base::bits::CountTrailingZerosNonZero(imm32) / 2;
uint32_t imm8 = imm32 >> (half_trailing_zeros * 2);
if (imm8 <= 0xFF) {
DCHECK_GT(half_trailing_zeros, 0);
// Rotating right by trailing_zeros is equivalent to rotating left by
// 32 - trailing_zeros. We return rotate_right / 2, so calculate
// (32 - trailing_zeros)/2 == 16 - trailing_zeros/2.
*rotate_imm = (16 - half_trailing_zeros);
*immed_8 = imm8;
return true;
}
// For 0xF000000F, rotate by 16 to get 0x000FF000 and continue as if it
// were that case.
uint32_t imm32_rot16 = base::bits::RotateLeft32(imm32, 16);
half_trailing_zeros =
base::bits::CountTrailingZerosNonZero(imm32_rot16) / 2;
imm8 = imm32_rot16 >> (half_trailing_zeros * 2);
if (imm8 <= 0xFF) {
// We've rotated left by 2*8, so we can't have more than that many
// trailing zeroes.
DCHECK_LT(half_trailing_zeros, 8);
// We've already rotated by 2*8, before calculating trailing_zeros/2,
// so we need (32 - (16 + trailing_zeros))/2 == 8 - trailing_zeros/2.
*rotate_imm = 8 - half_trailing_zeros;
*immed_8 = imm8;
return true;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment