已合并
Revert "!4561 Range Analysis of MUL and MOD" #4583
AtomGit-Bot创建于 2023年8月4日
Revert "!4561 Range Analysis of MUL and MOD" #4583
已合并
AtomGit-Bot创建于 2023年8月4日
refs/pull/4583/head合入到master
8 个文件变更+14-158
@@ -102,10 +102,9 @@ public:
102 102 
103 static constexpr int32_t UINT30_MAX = 0x3fffffff;103 static constexpr int32_t UINT30_MAX = 0x3fffffff;
104 static constexpr int32_t TYPED_ARRAY_ONHEAP_MAX = JSTypedArray::MAX_ONHEAP_LENGTH;104 static constexpr int32_t TYPED_ARRAY_ONHEAP_MAX = JSTypedArray::MAX_ONHEAP_LENGTH;
105- static constexpr int32_t UINT18_MAX = (1 << 18) - 1;105+ static const inline std::vector<int32_t> rangeBounds_ = { INT32_MIN, INT32_MIN + 1,
106- static const inline std::vector<int32_t> rangeBounds_ = { INT32_MIN, INT32_MIN + 1, -UINT18_MAX, -TYPED_ARRAY_ONHEAP_MAX,
107 -1, 0, 1, TYPED_ARRAY_ONHEAP_MAX - 1, TYPED_ARRAY_ONHEAP_MAX, TYPED_ARRAY_ONHEAP_MAX + 1,106 -1, 0, 1, TYPED_ARRAY_ONHEAP_MAX - 1, TYPED_ARRAY_ONHEAP_MAX, TYPED_ARRAY_ONHEAP_MAX + 1,
108- TYPED_ARRAY_ONHEAP_MAX * 3, UINT18_MAX, UINT30_MAX, UINT30_MAX + 1, INT32_MAX - 1, INT32_MAX };107+ TYPED_ARRAY_ONHEAP_MAX * 3, UINT30_MAX, UINT30_MAX + 1, INT32_MAX - 1, INT32_MAX };
109 108 
110 static RangeInfo NONE()109 static RangeInfo NONE()
111 {110 {
@@ -154,81 +153,11 @@ public:
154 153 
155 RangeInfo operator+ (const RangeInfo &rhs) const154 RangeInfo operator+ (const RangeInfo &rhs) const
156 {155 {
157- ASSERT(min_ <= max_ && rhs.min_ <= rhs.max_);
158 int32_t nmax = MaybeAddOverflow(rhs) ? INT32_MAX : max_ + rhs.max_;156 int32_t nmax = MaybeAddOverflow(rhs) ? INT32_MAX : max_ + rhs.max_;
159 int32_t nmin = MaybeAddUnderflow(rhs) ? INT32_MIN : min_ + rhs.min_;157 int32_t nmin = MaybeAddUnderflow(rhs) ? INT32_MIN : min_ + rhs.min_;
160 return RangeInfo(nmin, nmax);158 return RangeInfo(nmin, nmax);
161 }159 }
162 160 
163- RangeInfo operator% (const RangeInfo &rhs) const
164- {
165- ASSERT(min_ <= max_ && rhs.min_ <= rhs.max_);
166- RangeInfo result = RangeInfo(0, 0);
167- int32_t nmax = std::max(std::abs(rhs.min_), std::abs(rhs.max_));
168- if (max_ > 0) result = result.Union(RangeInfo(0, nmax - 1));
169- if (min_ < 0) result = result.Union(RangeInfo(-nmax + 1, 0));
170- return result;
171- }
172- 
173- bool MaybeZero() const
174- {
175- return min_ <= 0 && max_ >= 0;
176- }
177- 
178- RangeInfo operator* (const RangeInfo &rhs) const
179- {
180- ASSERT(min_ <= max_ && rhs.min_ <= rhs.max_);
181- int32_t nmax = GetMaxMulResult(rhs);
182- int32_t nmin = GetMinMulResult(rhs);
183- return RangeInfo(nmin, nmax);
184- }
185- 
186- int32_t GetMaxMulResult(const RangeInfo &rhs) const
187- {
188- return std::max({ TryMul(min_, rhs.min_), TryMul(min_, rhs.max_), TryMul(max_, rhs.min_), TryMul(max_, rhs.max_) });
189- }
190- 
191- int32_t GetMinMulResult(const RangeInfo &rhs) const
192- {
193- return std::min({ TryMul(min_, rhs.min_), TryMul(min_, rhs.max_), TryMul(max_, rhs.min_), TryMul(max_, rhs.max_) });
194- }
195- 
196- int32_t TryMul(int32_t lhs, int32_t rhs) const
197- {
198- if (MaybeMulOverflow(lhs, rhs)){
199- return INT32_MAX;
200- }
201- if (MaybeMulUnderflow(lhs, rhs)){
202- return INT32_MIN;
203- }
204- return lhs * rhs;
205- }
206- 
207- bool MaybeMulOverflowOrUnderflow(const RangeInfo &rhs) const
208- {
209- return MaybeMulOverflow(rhs) || MaybeMulUnderflow(rhs);
210- }
211- 
212- bool MaybeMulUnderflow(const RangeInfo &rhs) const
213- {
214- return MaybeMulUnderflow(min_, rhs.max_) || MaybeMulUnderflow(max_, rhs.min_);
215- }
216- 
217- bool MaybeMulOverflow(const RangeInfo &rhs) const
218- {
219- return MaybeMulOverflow(max_, rhs.max_) || MaybeMulOverflow(min_, rhs.min_);
220- }
221- 
222- bool MaybeMulUnderflow(int32_t lhs, int32_t rhs) const
223- {
224- return (lhs > 0 && rhs < 0 && rhs < INT32_MIN / lhs) || (lhs < 0 && rhs > 0 && lhs < INT32_MIN / rhs);
225- }
226- 
227- bool MaybeMulOverflow(int32_t lhs, int32_t rhs) const
228- {
229- return (lhs > 0 && rhs > 0 && lhs > INT32_MAX / rhs) || (lhs < 0 && rhs < 0 && lhs < INT32_MAX / rhs);
230- }
231- 
232 bool MaybeSubOverflow(const RangeInfo &rhs) const161 bool MaybeSubOverflow(const RangeInfo &rhs) const
233 {162 {
234 return (rhs.min_ < 0) && (max_ > INT32_MAX + rhs.min_);163 return (rhs.min_ < 0) && (max_ > INT32_MAX + rhs.min_);
@@ -246,7 +175,6 @@ public:
246 175 
247 RangeInfo operator- (const RangeInfo &rhs) const176 RangeInfo operator- (const RangeInfo &rhs) const
248 {177 {
249- ASSERT(min_ <= max_ && rhs.min_ <= rhs.max_);
250 int32_t nmax = MaybeSubOverflow(rhs) ? INT32_MAX : max_ - rhs.min_;178 int32_t nmax = MaybeSubOverflow(rhs) ? INT32_MAX : max_ - rhs.min_;
251 int32_t nmin = MaybeSubUnderflow(rhs) ? INT32_MIN : min_ - rhs.max_;179 int32_t nmin = MaybeSubUnderflow(rhs) ? INT32_MIN : min_ - rhs.max_;
252 return RangeInfo(nmin, nmax);180 return RangeInfo(nmin, nmax);
@@ -262,8 +190,6 @@ public:
262 190 
263 RangeInfo SHR(const RangeInfo &rhs) const191 RangeInfo SHR(const RangeInfo &rhs) const
264 {192 {
265- ASSERT(min_ <= max_);
266- ASSERT(rhs.max_ == rhs.min_);
267 if (MaybeShrOverflow(rhs)) {193 if (MaybeShrOverflow(rhs)) {
268 // assume no overflow occurs since overflow will lead to deopt194 // assume no overflow occurs since overflow will lead to deopt
269 return RangeInfo(0, std::max(0, GetMax()));195 return RangeInfo(0, std::max(0, GetMax()));
@@ -278,7 +204,6 @@ public:
278 204 
279 RangeInfo ASHR(const RangeInfo &rhs) const205 RangeInfo ASHR(const RangeInfo &rhs) const
280 {206 {
281- ASSERT(min_ <= max_);
282 ASSERT(rhs.max_ == rhs.min_);207 ASSERT(rhs.max_ == rhs.min_);
283 int32_t shift = rhs.max_ & 0x1f; // 0x1f : shift bits208 int32_t shift = rhs.max_ & 0x1f; // 0x1f : shift bits
284 int32_t nmin = min_ >> shift;209 int32_t nmin = min_ >> shift;
@@ -355,9 +355,7 @@ void NumberSpeculativeLowering::VisitNumberMod(GateRef gate)
355 }355 }
356 GateRef result = Circuit::NullGate();356 GateRef result = Circuit::NullGate();
357 if (gateType.IsIntType()) {357 if (gateType.IsIntType()) {
358- if(GetRange(right).MaybeZero()) {358+ builder_.Int32CheckRightIsZero(right);
359- builder_.Int32CheckRightIsZero(right);
360- }
361 result = CalculateInts<Op>(left, right);359 result = CalculateInts<Op>(left, right);
362 UpdateRange(result, GetRange(gate));360 UpdateRange(result, GetRange(gate));
363 acc_.SetMachineType(gate, MachineType::I32);361 acc_.SetMachineType(gate, MachineType::I32);
@@ -578,9 +576,6 @@ GateRef NumberSpeculativeLowering::CalculateInts(GateRef left, GateRef right)
578 break;576 break;
579 }577 }
580 case TypedBinOp::TYPED_MUL:578 case TypedBinOp::TYPED_MUL:
581- if(!leftRange.MaybeMulOverflowOrUnderflow(rightRange)) {
582- return builder_.Int32Mul(left, right);
583- }
584 res = builder_.MulWithOverflow(left, right);579 res = builder_.MulWithOverflow(left, right);
585 break;580 break;
586 case TypedBinOp::TYPED_MOD: {581 case TypedBinOp::TYPED_MOD: {
@@ -139,12 +139,6 @@ GateRef RangeAnalysis::VisitTypedBinaryOp(GateRef gate)
139 case TypedBinOp::TYPED_SUB:139 case TypedBinOp::TYPED_SUB:
140 range = GetRangeOfCalculate<TypedBinOp::TYPED_SUB>(gate);140 range = GetRangeOfCalculate<TypedBinOp::TYPED_SUB>(gate);
141 break;141 break;
142- case TypedBinOp::TYPED_MOD:
143- range = GetRangeOfCalculate<TypedBinOp::TYPED_MOD>(gate);
144- break;
145- case TypedBinOp::TYPED_MUL:
146- range = GetRangeOfCalculate<TypedBinOp::TYPED_MUL>(gate);
147- break;
148 case TypedBinOp::TYPED_SHR:142 case TypedBinOp::TYPED_SHR:
149 range = GetRangeOfShift<TypedBinOp::TYPED_SHR>(gate);143 range = GetRangeOfShift<TypedBinOp::TYPED_SHR>(gate);
150 break;144 break;
@@ -187,6 +181,7 @@ GateRef RangeAnalysis::VisitRangeGuard(GateRef gate)
187template<TypedBinOp Op>181template<TypedBinOp Op>
188RangeInfo RangeAnalysis::GetRangeOfCalculate(GateRef gate)182RangeInfo RangeAnalysis::GetRangeOfCalculate(GateRef gate)
189{183{
184+ ASSERT((Op == TypedBinOp::TYPED_ADD) || (Op == TypedBinOp::TYPED_SUB));
190 auto left = GetRange(acc_.GetValueIn(gate, 0));185 auto left = GetRange(acc_.GetValueIn(gate, 0));
191 auto right = GetRange(acc_.GetValueIn(gate, 1));186 auto right = GetRange(acc_.GetValueIn(gate, 1));
192 if (left.IsNone() || right.IsNone()) {187 if (left.IsNone() || right.IsNone()) {
@@ -197,10 +192,6 @@ RangeInfo RangeAnalysis::GetRangeOfCalculate(GateRef gate)
197 return left + right;192 return left + right;
198 case TypedBinOp::TYPED_SUB:193 case TypedBinOp::TYPED_SUB:
199 return left - right;194 return left - right;
200- case TypedBinOp::TYPED_MOD:
201- return left % right;
202- case TypedBinOp::TYPED_MUL:
203- return left * right;
204 default:195 default:
205 return RangeInfo::ANY();196 return RangeInfo::ANY();
206 }197 }
@@ -330,12 +321,6 @@ void RangeAnalysis::PrintRangeInfo() const
330 case TypedBinOp::TYPED_ASHR:321 case TypedBinOp::TYPED_ASHR:
331 log += " ashr";322 log += " ashr";
332 break;323 break;
333- case TypedBinOp::TYPED_MOD:
334- log += " mod";
335- break;
336- case TypedBinOp::TYPED_MUL:
337- log += " mul";
338- break;
339 default:324 default:
340 log += " other";325 log += " other";
341 break;326 break;
@@ -14,6 +14,7 @@
14 */14 */
15 15 
16#include "ecmascript/compiler/type_inference/method_type_infer.h"16#include "ecmascript/compiler/type_inference/method_type_infer.h"
17+ 
17#include "ecmascript/jspandafile/js_pandafile_manager.h"18#include "ecmascript/jspandafile/js_pandafile_manager.h"
18#include "ecmascript/ts_types/ts_type_accessor.h"19#include "ecmascript/ts_types/ts_type_accessor.h"
19#include "ecmascript/ts_types/ts_type_parser.h"20#include "ecmascript/ts_types/ts_type_parser.h"
@@ -205,6 +206,10 @@ bool MethodTypeInfer::Infer(GateRef gate)
205 switch (bytecodeInfo.GetOpcode()) {206 switch (bytecodeInfo.GetOpcode()) {
206 case EcmaOpcode::LDNAN:207 case EcmaOpcode::LDNAN:
207 case EcmaOpcode::LDINFINITY:208 case EcmaOpcode::LDINFINITY:
209+ case EcmaOpcode::MOD2_IMM8_V8:
210+ case EcmaOpcode::AND2_IMM8_V8:
211+ case EcmaOpcode::OR2_IMM8_V8:
212+ case EcmaOpcode::XOR2_IMM8_V8:
208 case EcmaOpcode::TONUMBER_IMM8:213 case EcmaOpcode::TONUMBER_IMM8:
209 case EcmaOpcode::NEG_IMM8:214 case EcmaOpcode::NEG_IMM8:
210 case EcmaOpcode::EXP_IMM8_V8:215 case EcmaOpcode::EXP_IMM8_V8:
@@ -214,9 +219,6 @@ bool MethodTypeInfer::Infer(GateRef gate)
214 case EcmaOpcode::ASHR2_IMM8_V8:219 case EcmaOpcode::ASHR2_IMM8_V8:
215 case EcmaOpcode::SHR2_IMM8_V8:220 case EcmaOpcode::SHR2_IMM8_V8:
216 case EcmaOpcode::NOT_IMM8:221 case EcmaOpcode::NOT_IMM8:
217- case EcmaOpcode::AND2_IMM8_V8:
218- case EcmaOpcode::OR2_IMM8_V8:
219- case EcmaOpcode::XOR2_IMM8_V8:
220 return SetIntType(gate);222 return SetIntType(gate);
221 case EcmaOpcode::LDBIGINT_ID16:223 case EcmaOpcode::LDBIGINT_ID16:
222 return SetBigIntType(gate);224 return SetBigIntType(gate);
@@ -259,8 +261,6 @@ bool MethodTypeInfer::Infer(GateRef gate)
259 return InferSub2(gate);261 return InferSub2(gate);
260 case EcmaOpcode::MUL2_IMM8_V8:262 case EcmaOpcode::MUL2_IMM8_V8:
261 return InferMul2(gate);263 return InferMul2(gate);
262- case EcmaOpcode::MOD2_IMM8_V8:
263- return InferMod2(gate);
264 case EcmaOpcode::DIV2_IMM8_V8:264 case EcmaOpcode::DIV2_IMM8_V8:
265 return InferDiv2(gate);265 return InferDiv2(gate);
266 case EcmaOpcode::INC_IMM8:266 case EcmaOpcode::INC_IMM8:
@@ -553,31 +553,6 @@ bool MethodTypeInfer::InferMul2(GateRef gate)
553 return UpdateType(gate, GateType::NumberType());553 return UpdateType(gate, GateType::NumberType());
554}554}
555 555 
556-/*
557- * Type Infer rule(satisfy commutative law):
558- * number % number = number
559- * int % number = number
560- * double % number = double
561- * int % int = int
562- * int % double = double
563- * double % double = double
564- */
565-bool MethodTypeInfer::InferMod2(GateRef gate)
566-{
567- // 2: number of value inputs
568- ASSERT(gateAccessor_.GetNumValueIn(gate) == 2);
569- auto firInType = gateAccessor_.GetGateType(gateAccessor_.GetValueIn(gate, 0));
570- auto secInType = gateAccessor_.GetGateType(gateAccessor_.GetValueIn(gate, 1));
571- if ((firInType.IsNumberType() && secInType.IsDoubleType()) ||
572- (firInType.IsDoubleType() && secInType.IsNumberType())) {
573- return UpdateType(gate, GateType::DoubleType());
574- }
575- if ((firInType.IsIntType() && secInType.IsIntType())) {
576- return UpdateType(gate, GateType::IntType());
577- }
578- return UpdateType(gate, GateType::NumberType());
579-}
580- 
581/*556/*
582 * Type Infer rule(satisfy commutative law):557 * Type Infer rule(satisfy commutative law):
583 * in type lowering, both elements will be changed to float64 firstly.558 * in type lowering, both elements will be changed to float64 firstly.
@@ -84,7 +84,6 @@ private:
84 bool InferAdd2(GateRef gate);84 bool InferAdd2(GateRef gate);
85 bool InferSub2(GateRef gate);85 bool InferSub2(GateRef gate);
86 bool InferMul2(GateRef gate);86 bool InferMul2(GateRef gate);
87- bool InferMod2(GateRef gate);
88 bool InferDiv2(GateRef gate);87 bool InferDiv2(GateRef gate);
89 bool InferIncDec(GateRef gate);88 bool InferIncDec(GateRef gate);
90 bool InferToNumberic(GateRef gate);89 bool InferToNumberic(GateRef gate);
@@ -68,26 +68,6 @@ function testcase6() {
68 }68 }
69}69}
70 70 
71-//mod CheckRightIsZero
72-function testcase7() {
73- const a: number= 20;
74- let b: number = 5 % a;// not gen CheckRightIsZero
75- let c: number = 5 % b;// gen CheckRightIsZero
76-}
77- 
78-//mul_with_overcheck
79-function testcase8(a:number, x:number) {
80- let z = a >>> 1;
81- let b: number = z % 10;//range[0, 4095]
82- 
83- let c: number = 10 * b;//not gen mul_with_overcheck, range[0,262143]
84- let d: number = c * b;//not gen mul_with_overcheck, range[0,1073741823]
85- let e: number = d * c;//gen mul_with_overcheck
86- 
87- x = x >>> 1;
88- let h: number = x * x;//gen mul_with_overcheck
89-}
90- 
91testcase1(); // 871testcase1(); // 8
92testcase2(); // 872testcase2(); // 8
93 73 
@@ -95,7 +75,4 @@ testcase3();
95testcase4();75testcase4();
96 76 
97testcase5(); 77testcase5();
98-testcase6();78+testcase6();
99- 
100-testcase7();
101-testcase8(4, 107341001);//deopt
@@ -18,13 +18,13 @@ declare function AssertType(value:any, type:string):void;
18 let x:number = 123;18 let x:number = 123;
19 let y:number = 2;19 let y:number = 2;
20 let andRes = x & y;20 let andRes = x & y;
21- AssertType(andRes, "int");21+ AssertType(andRes, "number");
22 22 
23 let orRes = x | y;23 let orRes = x | y;
24- AssertType(orRes, "int");24+ AssertType(orRes, "number");
25 25 
26 let xorRes = x ^ y;26 let xorRes = x ^ y;
27- AssertType(xorRes, "int");27+ AssertType(xorRes, "number");
28 28 
29 let shlRes = x << y;29 let shlRes = x << y;
30 AssertType(shlRes, "int");30 AssertType(shlRes, "int");
@@ -18,5 +18,5 @@ declare function AssertType(value:any, type:string):void;
18 let num1 : number = 1;18 let num1 : number = 1;
19 let num2 : number = 2;19 let num2 : number = 2;
20 let ans = num1 % num2;20 let ans = num1 % num2;
21- AssertType(ans, "int");21+ AssertType(ans, "number");
22}22}