Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/op/reduce.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,27 @@ ReduceOp::ReduceOp(Array<PrimExpr> args, BufferMap vmap) {
}

PrimExpr ReduceOp::MakeInitValue() const {
auto dst_dtype = dst->dtype;
auto is_int = dst_dtype.is_int();
auto bits = dst_dtype.bits();

switch (type) {
case ReduceType::kSum:
return make_zero(dst->dtype);
case ReduceType::kAbsSum:
return make_zero(dst->dtype);
case ReduceType::kMax:
return make_const(dst->dtype, -INFINITY);
if (is_int) {
return make_const(dst->dtype, -(1 << (bits - 1)));
} else {
return make_const(dst->dtype, -INFINITY);
}
Comment on lines +57 to +64

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The current logic for kMax has a few issues:

  • Undefined Behavior: -(1 << (bits - 1)) can lead to undefined behavior for bits >= 32 due to integer overflow on the 1 literal. For bits == 64, -(1LL << 63) is also undefined behavior due to negating the most negative number.
  • Missing Unsigned Integer Support: The logic doesn't handle unsigned integers (is_uint). For a kMax reduction, the initial value for an unsigned type should be 0.
Suggested change
if (is_int) {
return make_const(dst->dtype, -(1 << (bits - 1)));
} else {
return make_const(dst->dtype, -INFINITY);
}
if (is_int) {
// Handle 64-bit case separately to avoid overflow/UB.
if (bits == 64) {
// This is a portable way to represent INT64_MIN.
return make_const(dst_dtype, -9223372036854775807LL - 1);
}
return make_const(dst_dtype, -(1LL << (bits - 1)));
} else if (dst_dtype.is_uint()) {
return make_zero(dst_dtype);
} else {
return make_const(dst_dtype, -INFINITY);
}

case ReduceType::kMin:
return make_const(dst->dtype, INFINITY);
if (is_int) {
return make_const(dst->dtype, (1 << (bits - 1)) - 1);
} else {
return make_const(dst->dtype, INFINITY);
}
Comment on lines +63 to +72

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to the kMax case, this logic has issues:

  • Undefined Behavior: (1 << (bits - 1)) can be undefined behavior for bits >= 32. You should use a 64-bit literal like 1LL or 1ULL to avoid this.
  • Missing Unsigned Integer Support: Unsigned integers are not handled. The initial value for a kMin reduction on an unsigned type should be the maximum value for that type.
Suggested change
if (is_int) {
return make_const(dst->dtype, (1 << (bits - 1)) - 1);
} else {
return make_const(dst->dtype, INFINITY);
}
if (is_int) {
// Use unsigned long long for the shift to avoid signed overflow UB.
// The result is correctly cast to int64_t for make_const.
return make_const(dst_dtype, static_cast<int64_t>((1ULL << (bits - 1)) - 1));
} else if (dst_dtype.is_uint()) {
if (bits == 64) {
// This is UINT64_MAX.
return make_const(dst_dtype, 18446744073709551615ULL);
}
return make_const(dst_dtype, (1ULL << bits) - 1);
} else {
return make_const(dst_dtype, INFINITY);
}

case ReduceType::kAbsMax:
return make_const(dst->dtype, 0);
default:
Expand Down
Loading