Skip to content

Commit b0a81d5

Browse files
Jiawei-ShaoDawn LUCI CQ
authored andcommitted
Range Analysis: Compute range of Binary with >> operator
This patch computes the range of a `Binary` with `>>` (shift-right) operator when the `lhs` is a non-negative integer. Bug: 348701956 Test: tint_unittests Change-Id: I42d0e4ff542a6feb7b6e1f929c6fffa8338b2bed Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/245776 Commit-Queue: Jiawei Shao <[email protected]> Reviewed-by: James Price <[email protected]>
1 parent 7f2e648 commit b0a81d5

File tree

2 files changed

+838
-0
lines changed

2 files changed

+838
-0
lines changed

src/tint/lang/core/ir/analysis/integer_range_analysis.cc

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ struct IntegerRangeAnalysisImpl {
284284
case BinaryOp::kShiftLeft:
285285
return ComputeAndCacheIntegerRangeForBinaryShiftLeft(binary, range_lhs, range_rhs);
286286

287+
case BinaryOp::kShiftRight:
288+
return ComputeAndCacheIntegerRangeForBinaryShiftRight(binary, range_lhs, range_rhs);
289+
287290
default:
288291
return nullptr;
289292
}
@@ -1095,6 +1098,45 @@ struct IntegerRangeAnalysisImpl {
10951098
}
10961099
}
10971100

1101+
const IntegerRangeInfo* ComputeAndCacheIntegerRangeForBinaryShiftRight(
1102+
const Binary* binary,
1103+
const IntegerRangeInfo* lhs,
1104+
const IntegerRangeInfo* rhs) {
1105+
auto rhs_u32 = std::get<IntegerRangeInfo::UnsignedIntegerRange>(rhs->range);
1106+
1107+
// rhs_u32 must be less than the bit width of i32 and u32 (32):
1108+
// rhs_u32.min_bound <= rhs_u32.max_bound < 32
1109+
if (rhs_u32.max_bound >= 32) {
1110+
return nullptr;
1111+
}
1112+
1113+
if (std::holds_alternative<IntegerRangeInfo::SignedIntegerRange>(lhs->range)) {
1114+
auto lhs_i32 = std::get<IntegerRangeInfo::SignedIntegerRange>(lhs->range);
1115+
1116+
// Currently we require `lhs` must be non-negative.
1117+
// 0 <= lhs.min_bound <= lhs.max_bound
1118+
if (lhs_i32.min_bound < 0) {
1119+
return nullptr;
1120+
}
1121+
1122+
// [min1, max1] >> [min2, max2] => [min1 >> max2, max1 >> min2]
1123+
int64_t min_bound = lhs_i32.min_bound >> rhs_u32.max_bound;
1124+
int64_t max_bound = lhs_i32.max_bound >> rhs_u32.min_bound;
1125+
1126+
auto result =
1127+
integer_binary_range_info_map_.Add(binary, IntegerRangeInfo(min_bound, max_bound));
1128+
return &result.value;
1129+
} else {
1130+
auto lhs_u32 = std::get<IntegerRangeInfo::UnsignedIntegerRange>(lhs->range);
1131+
1132+
uint64_t min_bound = lhs_u32.min_bound >> rhs_u32.max_bound;
1133+
uint64_t max_bound = lhs_u32.max_bound >> rhs_u32.min_bound;
1134+
auto result =
1135+
integer_binary_range_info_map_.Add(binary, IntegerRangeInfo(min_bound, max_bound));
1136+
return &result.value;
1137+
}
1138+
}
1139+
10981140
Hashmap<const FunctionParam*, Vector<IntegerRangeInfo, 3>, 4>
10991141
integer_function_param_range_info_map_;
11001142
Hashmap<const Var*, IntegerRangeInfo, 8> integer_var_range_info_map_;

0 commit comments

Comments
 (0)