1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
 From 6983e76741a1bad811783ceac0959ff9953c175d Mon Sep 17 00:00:00 2001 From: Mark Lam <[email protected]> Date: Fri, 20 May 2022 18:33:04 +0000 Subject: [PATCH] Refine B3ReduceStrength's range for sign extension operations. https://bugs.webkit.org/show_bug.cgi?id=240720 <rdar://problem/93536782>
Reviewed by Yusuke Suzuki and Keith Miller.
* Source/JavaScriptCore/b3/B3ReduceStrength.cpp:
Canonical link: https://commits.webkit.org/250808@main gitsvnid: https://svn.webkit.org/repository/webkit/trunk@294563 268f45cccd090410ab3cd52691b4dbfc  Source/JavaScriptCore/b3/B3ReduceStrength.cpp  61 ++++++++++++++++++ 1 file changed, 59 insertions(+), 2 deletions()
diff git a/Source/JavaScriptCore/b3/B3ReduceStrength.cpp b/Source/JavaScriptCore/b3/B3ReduceStrength.cpp index f30a68587876..32bcf3d81415 100644  a/Source/JavaScriptCore/b3/B3ReduceStrength.cpp +++ b/Source/JavaScriptCore/b3/B3ReduceStrength.cpp @@ 1,5 +1,5 @@ /*  * Copyright (C) 20152020 Apple Inc. All rights reserved. + * Copyright (C) 20152022 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ 388,6 +388,61 @@ class IntRange { } } + template<typename T> + IntRange sExt() + { + ASSERT(m_min >= INT32_MIN); + ASSERT(m_max <= INT32_MAX); + int64_t typeMin = std::numeric_limits<T>::min(); + int64_t typeMax = std::numeric_limits<T>::max(); + auto min = m_min; + auto max = m_max; + + if (typeMin <= min && min <= typeMax + && typeMin <= max && max <= typeMax) + return IntRange(min, max); + + // Given type T with N bits, signed extension will turn bit N1 as + // a sign bit. If bits N1 upwards are identical for both min and max, + // then we're guaranteed that even after the sign extension, min and + // max will still be in increasing order. + // + // For example, when T is int8_t, the space of numbers from highest to + // lowest are as follows (in binary bits): + // + // highest 0 111 1111 ^ + // ...  + // 1 0 000 0001  top segment + // 0 0 000 0000 v + // + // 1 1 111 1111 ^ + // 2 1 111 1110  bottom segment + // ...  + // lowest 1 000 0000 v + // + // Note that if we exclude the sign bit, the range is made up of 2 segments + // of contiguous increasing numbers. If min and max are both in the same + // segment before the sign extension, then min and max will continue to be + // in a contiguous segment after the sign extension. Only when min and max + // spans across more than 1 of these segments, will min and max no longer + // be guaranteed to be in a contiguous range after the sign extension. + // + // Hence, we can check if bits N1 and up are identical for the range min + // and max. If so, then the new min and max can be be computed by simply + // applying sign extension to their original values. + + constexpr unsigned numberOfBits = countOfBits<T>; + constexpr int64_t segmentMask = (1ll << (numberOfBits  1))  1; + constexpr int64_t topBitsMask = ~segmentMask; + int64_t minTopBits = topBitsMask & min; + int64_t maxTopBits = topBitsMask & max; + + if (minTopBits == maxTopBits) + return IntRange(static_cast<int64_t>(static_cast<T>(min)), static_cast<int64_t>(static_cast<T>(max))); + + return top<T>(); + } + IntRange zExt32() { ASSERT(m_min >= INT32_MIN); @@ 2765,9 +2820,11 @@ class ReduceStrength { rangeFor(value>child(1), timeToLive  1), value>type()); case SExt8: + return rangeFor(value>child(0), timeToLive  1).sExt<int8_t>(); case SExt16: + return rangeFor(value>child(0), timeToLive  1).sExt<int16_t>(); case SExt32:  return rangeFor(value>child(0), timeToLive  1); + return rangeFor(value>child(0), timeToLive  1).sExt<int32_t>(); case ZExt32: return rangeFor(value>child(0), timeToLive  1).zExt32();
