Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(557)

Side by Side Diff: src/arm64/assembler-arm64.cc

Issue 341123003: ARM64: Faster immediate check and fix corner cases (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/arm64/macro-assembler-arm64.cc » ('j') | src/arm64/utils-arm64.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // 2 //
3 // Redistribution and use in source and binary forms, with or without 3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are 4 // modification, are permitted provided that the following conditions are
5 // met: 5 // met:
6 // 6 //
7 // * Redistributions of source code must retain the above copyright 7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer. 8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above 9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following 10 // copyright notice, this list of conditions and the following
(...skipping 2085 matching lines...) Expand 10 before | Expand all | Expand 10 after
2096 2096
2097 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset; 2097 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
2098 } 2098 }
2099 2099
2100 2100
2101 // Code generation helpers. 2101 // Code generation helpers.
2102 void Assembler::MoveWide(const Register& rd, 2102 void Assembler::MoveWide(const Register& rd,
2103 uint64_t imm, 2103 uint64_t imm,
2104 int shift, 2104 int shift,
2105 MoveWideImmediateOp mov_op) { 2105 MoveWideImmediateOp mov_op) {
2106 // Ignore the top 32 bits of an immediate if we're moving to a W register.
2107 if (rd.Is32Bits()) {
2108 // Check that the top 32 bits are zero (a positive 32-bit number) or top
2109 // 33 bits are one (a negative 32-bit number, sign extended to 64 bits).
2110 ASSERT(((imm >> kWRegSizeInBits) == 0) ||
2111 ((imm >> (kWRegSizeInBits - 1)) == 0x1ffffffff));
2112 imm &= kWRegMask;
2113 }
2114
2106 if (shift >= 0) { 2115 if (shift >= 0) {
2107 // Explicit shift specified. 2116 // Explicit shift specified.
2108 ASSERT((shift == 0) || (shift == 16) || (shift == 32) || (shift == 48)); 2117 ASSERT((shift == 0) || (shift == 16) || (shift == 32) || (shift == 48));
2109 ASSERT(rd.Is64Bits() || (shift == 0) || (shift == 16)); 2118 ASSERT(rd.Is64Bits() || (shift == 0) || (shift == 16));
2110 shift /= 16; 2119 shift /= 16;
2111 } else { 2120 } else {
2112 // Calculate a new immediate and shift combination to encode the immediate 2121 // Calculate a new immediate and shift combination to encode the immediate
2113 // argument. 2122 // argument.
2114 shift = 0; 2123 shift = 0;
2115 if ((imm & ~0xffffUL) == 0) { 2124 if ((imm & ~0xffffUL) == 0) {
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
2501 // If it can not be encoded, the function returns false, and the values pointed 2510 // If it can not be encoded, the function returns false, and the values pointed
2502 // to by n, imm_s and imm_r are undefined. 2511 // to by n, imm_s and imm_r are undefined.
2503 bool Assembler::IsImmLogical(uint64_t value, 2512 bool Assembler::IsImmLogical(uint64_t value,
2504 unsigned width, 2513 unsigned width,
2505 unsigned* n, 2514 unsigned* n,
2506 unsigned* imm_s, 2515 unsigned* imm_s,
2507 unsigned* imm_r) { 2516 unsigned* imm_r) {
2508 ASSERT((n != NULL) && (imm_s != NULL) && (imm_r != NULL)); 2517 ASSERT((n != NULL) && (imm_s != NULL) && (imm_r != NULL));
2509 ASSERT((width == kWRegSizeInBits) || (width == kXRegSizeInBits)); 2518 ASSERT((width == kWRegSizeInBits) || (width == kXRegSizeInBits));
2510 2519
2520 bool negate = false;
2521
2511 // Logical immediates are encoded using parameters n, imm_s and imm_r using 2522 // Logical immediates are encoded using parameters n, imm_s and imm_r using
2512 // the following table: 2523 // the following table:
2513 // 2524 //
2514 // N imms immr size S R 2525 // N imms immr size S R
2515 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) 2526 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr)
2516 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) 2527 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr)
2517 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) 2528 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr)
2518 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) 2529 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr)
2519 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) 2530 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr)
2520 // 0 11110s xxxxxr 2 UInt(s) UInt(r) 2531 // 0 11110s xxxxxr 2 UInt(s) UInt(r)
2521 // (s bits must not be all set) 2532 // (s bits must not be all set)
2522 // 2533 //
2523 // A pattern is constructed of size bits, where the least significant S+1 2534 // A pattern is constructed of size bits, where the least significant S+1 bits
2524 // bits are set. The pattern is rotated right by R, and repeated across a 2535 // are set. The pattern is rotated right by R, and repeated across a 32 or
2525 // 32 or 64-bit value, depending on destination register width. 2536 // 64-bit value, depending on destination register width.
2526 // 2537 //
2527 // To test if an arbitary immediate can be encoded using this scheme, an 2538 // Put another way: the basic format of a logical immediate is a single
2528 // iterative algorithm is used. 2539 // contiguous stretch of 1 bits, repeated across the whole word at intervals
2540 // given by a power of 2. To identify them quickly, we first locate the
2541 // lowest stretch of 1 bits, then the next 1 bit above that; that combination
2542 // is different for every logical immediate, so it gives us all the
2543 // information we need to identify the only logical immediate that our input
2544 // could be, and then we simply check if that's the value we actually have.
2529 // 2545 //
2530 // TODO(mcapewel) This code does not consider using X/W register overlap to 2546 // (The rotation parameter does give the possibility of the stretch of 1 bits
2531 // support 64-bit immediates where the top 32-bits are zero, and the bottom 2547 // going 'round the end' of the word. To deal with that, we observe that in
2532 // 32-bits are an encodable logical immediate. 2548 // any situation where that happens the bitwise NOT of the value is also a
2549 // valid logical immediate. So we simply invert the input whenever its low bit
2550 // is set, and then we know that the rotated case can't arise.)
2533 2551
2534 // 1. If the value has all set or all clear bits, it can't be encoded. 2552 if (value & 1) {
2535 if ((value == 0) || (value == 0xffffffffffffffffUL) || 2553 // If the low bit is 1, negate the value, and set a flag to remember that we
2536 ((width == kWRegSizeInBits) && (value == 0xffffffff))) { 2554 // did (so that we can adjust the return values appropriately).
2555 negate = true;
2556 value = ~value;
2557 }
2558
2559 if (width == kWRegSizeInBits) {
2560 // To handle 32-bit logical immediates, the very easiest thing is to repeat
2561 // the input value twice to make a 64-bit word. The correct encoding of that
2562 // as a logical immediate will also be the correct encoding of the 32-bit
2563 // value.
2564
2565 // Avoid making the assumption that the most-significant 32 bits are zero by
ulan 2014/06/30 12:50:08 Yes, this assumption will not hold if negate = tru
m.m.capewell 2014/07/01 09:45:46 Altered the comment to make this clear.
2566 // shifting the value left before duplicating it.
2567 value <<= kWRegSizeInBits;
2568 value |= value >> kWRegSizeInBits;
2569 }
2570
2571 // The basic analysis idea: imagine our input word looks like this.
2572 //
2573 // 0011111000111110001111100011111000111110001111100011111000111110
2574 // c b a
2575 // |<--d-->|
2576 //
2577 // We find the lowest set bit (as an actual power-of-2 value, not its index)
2578 // and call it a. Then we add a to our original number, which wipes out the
2579 // bottommost stretch of set bits and replaces it with a 1 carried into the
2580 // next zero bit. Then we look for the new lowest set bit, which is in
2581 // position b, and subtract it, so now our number is just like the original
2582 // but with the lowest stretch of set bits completely gone. Now we find the
2583 // lowest set bit again, which is position c in the diagram above. Then we'll
2584 // measure the distance d between bit positions a and c (using CLZ), and that
2585 // tells us that the only valid logical immediate that could possibly be equal
2586 // to this number is the one in which a stretch of bits running from a to just
2587 // below b is replicated every d bits.
2588 uint64_t a = LowestSetBit(value);
2589 uint64_t value_plus_a = value + a;
2590 uint64_t b = LowestSetBit(value_plus_a);
2591 uint64_t value_plus_a_minus_b = value_plus_a - b;
2592 uint64_t c = LowestSetBit(value_plus_a_minus_b);
2593
2594 int d, clz_a, out_n;
2595 uint64_t mask;
2596
2597 if (c != 0) {
2598 // The general case, in which there is more than one stretch of set bits.
2599 // Compute the repeat distance d, and set up a bitmask covering the basic
2600 // unit of repetition (i.e. a word with the bottom d bits set). Also, in all
2601 // of these cases the N bit of the output will be zero.
2602 clz_a = CountLeadingZeros(a, kXRegSizeInBits);
2603 int clz_c = CountLeadingZeros(c, kXRegSizeInBits);
2604 d = clz_a - clz_c;
2605 mask = ((UINT64_C(1) << d) - 1);
2606 out_n = 0;
2607 } else {
2608 // Handle degenerate cases.
2609 //
2610 // If any of those 'find lowest set bit' operations didn't find a set bit at
2611 // all, then the word will have been zero thereafter, so in particular the
2612 // last lowest_set_bit operation will have returned zero. So we can test for
2613 // all the special case conditions in one go by seeing if c is zero.
2614 if (a == 0) {
2615 // The input was zero (or all 1 bits, which will come to here too after we
2616 // inverted it at the start of the function), for which we just return
2617 // false.
2618 return false;
2619 } else {
2620 // Otherwise, if c was zero but a was not, then there's just one stretch
2621 // of set bits in our word, meaning that we have the trivial case of
2622 // d == 64 and only one 'repetition'. Set up all the same variables as in
2623 // the general case above, and set the N bit in the output.
2624 clz_a = CountLeadingZeros(a, kXRegSizeInBits);
2625 d = 64;
2626 mask = ~UINT64_C(0);
2627 out_n = 1;
2628 }
2629 }
2630
2631 // If the repeat period d is not a power of two, it can't be encoded.
2632 if (!IS_POWER_OF_TWO(d)) {
2537 return false; 2633 return false;
2538 } 2634 }
ulan 2014/06/30 12:50:08 ASSERT(d >= 2) or assert below that CountLeadingZe
m.m.capewell 2014/07/01 09:45:46 Asserted the index to the multipliers array, as I
2539 2635
2540 unsigned lead_zero = CountLeadingZeros(value, width); 2636 if (((b - a) & ~mask) != 0) {
2541 unsigned lead_one = CountLeadingZeros(~value, width); 2637 // If the bit stretch (b - a) does not fit within the mask derived from the
2542 unsigned trail_zero = CountTrailingZeros(value, width); 2638 // repeat period, then fail.
2543 unsigned trail_one = CountTrailingZeros(~value, width);
2544 unsigned set_bits = CountSetBits(value, width);
2545
2546 // The fixed bits in the immediate s field.
2547 // If width == 64 (X reg), start at 0xFFFFFF80.
2548 // If width == 32 (W reg), start at 0xFFFFFFC0, as the iteration for 64-bit
2549 // widths won't be executed.
2550 int imm_s_fixed = (width == kXRegSizeInBits) ? -128 : -64;
2551 int imm_s_mask = 0x3F;
2552
2553 for (;;) {
2554 // 2. If the value is two bits wide, it can be encoded.
2555 if (width == 2) {
2556 *n = 0;
2557 *imm_s = 0x3C;
2558 *imm_r = (value & 3) - 1;
2559 return true;
2560 }
2561
2562 *n = (width == 64) ? 1 : 0;
2563 *imm_s = ((imm_s_fixed | (set_bits - 1)) & imm_s_mask);
2564 if ((lead_zero + set_bits) == width) {
2565 *imm_r = 0;
2566 } else {
2567 *imm_r = (lead_zero > 0) ? (width - trail_zero) : lead_one;
2568 }
2569
2570 // 3. If the sum of leading zeros, trailing zeros and set bits is equal to
2571 // the bit width of the value, it can be encoded.
2572 if (lead_zero + trail_zero + set_bits == width) {
2573 return true;
2574 }
2575
2576 // 4. If the sum of leading ones, trailing ones and unset bits in the
2577 // value is equal to the bit width of the value, it can be encoded.
2578 if (lead_one + trail_one + (width - set_bits) == width) {
2579 return true;
2580 }
2581
2582 // 5. If the most-significant half of the bitwise value is equal to the
2583 // least-significant half, return to step 2 using the least-significant
2584 // half of the value.
2585 uint64_t mask = (1UL << (width >> 1)) - 1;
2586 if ((value & mask) == ((value >> (width >> 1)) & mask)) {
2587 width >>= 1;
2588 set_bits >>= 1;
2589 imm_s_fixed >>= 1;
2590 continue;
2591 }
2592
2593 // 6. Otherwise, the value can't be encoded.
2594 return false; 2639 return false;
2595 } 2640 }
2641
2642 // The only possible option is b - a repeated every d bits. Now we're going to
2643 // actually construct the valid logical immediate derived from that
2644 // specification, and see if it equals our original input.
2645 //
2646 // To repeat a value every d bits, we multiply it by a number of the form
2647 // (1 + 2^d + 2^(2d) + ...), i.e. 0x0001000100010001 or similar. These can
2648 // be derived using a table lookup on CLZ(d).
2649 static const uint64_t multipliers[] = {
2650 0x0000000000000001UL,
2651 0x0000000100000001UL,
2652 0x0001000100010001UL,
2653 0x0101010101010101UL,
2654 0x1111111111111111UL,
2655 0x5555555555555555UL,
2656 };
2657 uint64_t multiplier = multipliers[CountLeadingZeros(d, kXRegSizeInBits) - 57];
2658 uint64_t candidate = (b - a) * multiplier;
2659
2660 if (value != candidate) {
2661 // The candidate pattern doesn't match our input value, so fail.
2662 return false;
2663 }
2664
2665 // We have a match! This is a valid logical immediate, so now we have to
2666 // construct the bits and pieces of the instruction encoding that generates
2667 // it.
2668
2669 // Count the set bits in our basic stretch. The special case of clz(0) == -1
2670 // makes the answer come out right for stretches that reach the very top of
2671 // the word (e.g. numbers like 0xffffc00000000000).
2672 int clz_b = (b == 0) ? -1 : CountLeadingZeros(b, kXRegSizeInBits);
2673 int s = clz_a - clz_b;
2674
2675 // Decide how many bits to rotate right by, to put the low bit of that basic
2676 // stretch in position a.
2677 int r;
2678 if (negate) {
2679 // If we inverted the input right at the start of this function, here's
2680 // where we compensate: the number of set bits becomes the number of clear
2681 // bits, and the rotation count is based on position b rather than position
2682 // a (since b is the location of the 'lowest' 1 bit after inversion).
2683 s = d - s;
2684 r = (clz_b + 1) & (d - 1);
2685 } else {
2686 r = (clz_a + 1) & (d - 1);
2687 }
2688
2689 // Now we're done, except for having to encode the S output in such a way that
2690 // it gives both the number of set bits and the length of the repeated
2691 // segment. The s field is encoded like this:
2692 //
2693 // imms size S
2694 // ssssss 64 UInt(ssssss)
2695 // 0sssss 32 UInt(sssss)
2696 // 10ssss 16 UInt(ssss)
2697 // 110sss 8 UInt(sss)
2698 // 1110ss 4 UInt(ss)
2699 // 11110s 2 UInt(s)
2700 //
2701 // So we 'or' (-d << 1) with our computed s to form imms.
2702 *n = out_n;
2703 *imm_s = ((-d << 1) | (s - 1)) & 0x3f;
2704 *imm_r = r;
2705
2706 return true;
2596 } 2707 }
2597 2708
2598 2709
2599 bool Assembler::IsImmConditionalCompare(int64_t immediate) { 2710 bool Assembler::IsImmConditionalCompare(int64_t immediate) {
2600 return is_uint5(immediate); 2711 return is_uint5(immediate);
2601 } 2712 }
2602 2713
2603 2714
2604 bool Assembler::IsImmFP32(float imm) { 2715 bool Assembler::IsImmFP32(float imm) {
2605 // Valid values will have the form: 2716 // Valid values will have the form:
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
3037 adr(rd, 0); 3148 adr(rd, 0);
3038 MovInt64(scratch, target_offset); 3149 MovInt64(scratch, target_offset);
3039 add(rd, rd, scratch); 3150 add(rd, rd, scratch);
3040 } 3151 }
3041 } 3152 }
3042 3153
3043 3154
3044 } } // namespace v8::internal 3155 } } // namespace v8::internal
3045 3156
3046 #endif // V8_TARGET_ARCH_ARM64 3157 #endif // V8_TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « no previous file | src/arm64/macro-assembler-arm64.cc » ('j') | src/arm64/utils-arm64.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698