Skip to content

Commit 7c2144e

Browse files
authored
Promote narrow ints to floats in widening_mul (#8846)
1 parent ed156e7 commit 7c2144e

3 files changed

Lines changed: 47 additions & 4 deletions

File tree

src/IROperator.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,20 @@ Expr widening_add(Expr a, Expr b) {
11621162

11631163
Expr widening_mul(Expr a, Expr b) {
11641164
user_assert(a.defined() && b.defined()) << "widening_mul of undefined Expr\n";
1165+
// Promote float to int if lossless
1166+
if (a.type().is_float() && b.type().is_int_or_uint()) {
1167+
Expr float_b = lossless_cast(a.type(), b);
1168+
user_assert(float_b.defined())
1169+
<< "widening_mul: cannot promote RHS of type " << b.type() << " to " << a.type() << ".\n"
1170+
<< "Please use an explicit cast.\n";
1171+
b = float_b;
1172+
} else if (b.type().is_float() && a.type().is_int_or_uint()) {
1173+
Expr float_a = lossless_cast(b.type(), a);
1174+
user_assert(float_a.defined())
1175+
<< "widening_mul: cannot promote LHS of type " << a.type() << " to " << b.type() << ".\n"
1176+
<< "Please use an explicit cast.\n";
1177+
a = float_a;
1178+
}
11651179
// Widening multiplies can have different signs.
11661180
match_bits(a, b);
11671181
match_lanes(a, b);

src/Type.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,10 @@ bool Type::can_represent(Type other) const {
118118
if (other.is_bfloat()) {
119119
return bits() > other.bits();
120120
} else {
121-
return ((other.is_float() && other.bits() <= bits()) ||
122-
(bits() == 64 && other.bits() <= 32) ||
123-
(bits() == 32 && other.bits() <= 16));
121+
return (other.is_float() && other.bits() <= bits()) ||
122+
(bits() == 64 && other.bits() <= 32) ||
123+
(bits() == 32 && other.bits() <= 16) ||
124+
(bits() == 16 && other.bits() <= 8);
124125
}
125126
} else {
126127
return false;

test/correctness/intrinsics.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ void check(Expr test, Expr expected, Type required_type) {
1515

1616
// Make sure the pattern is robust to CSE. We only enforce this
1717
// for types with well-defined overflow for now.
18-
if (test.type().bits() < 32 || test.type().is_uint()) {
18+
if (test.type().can_overflow()) {
1919
auto bundle = [](const Expr &e) {
2020
return Call::make(e.type(), Call::bundle, {e, e}, Call::PureIntrinsic);
2121
};
@@ -131,7 +131,10 @@ int main(int argc, char **argv) {
131131
Expr u8y = make_leaf(UInt(8, 4), "u8y");
132132
Expr u8z = make_leaf(UInt(8, 4), "u8w");
133133
Expr u8w = make_leaf(UInt(8, 4), "u8z");
134+
Expr i16x = make_leaf(Int(16, 4), "i16x");
134135
Expr u16x = make_leaf(UInt(16, 4), "u16x");
136+
Expr i16y = make_leaf(Int(16, 4), "i16y");
137+
Expr u16y = make_leaf(UInt(16, 4), "u16y");
135138
Expr u32x = make_leaf(UInt(32, 4), "u32x");
136139
Expr u32y = make_leaf(UInt(32, 4), "u32y");
137140
Expr i32x = make_leaf(Int(32, 4), "i32x");
@@ -170,6 +173,21 @@ int main(int argc, char **argv) {
170173
check(u32(u8x) * u8y, u32(widening_mul(u8x, u8y)));
171174
check(f32(f16x) * f32(f16y), widening_mul(f16x, f16y));
172175

176+
// Check mixed float/int promotion
177+
check(widening_mul(i8x, f16y), widening_mul(f16(i8x), f16y));
178+
check(widening_mul(i8x, f32y), widening_mul(f32(i8x), f32y));
179+
check(widening_mul(u8x, f16y), widening_mul(f16(u8x), f16y));
180+
check(widening_mul(u8x, f32y), widening_mul(f32(u8x), f32y));
181+
check(widening_mul(i16x, f32y), widening_mul(f32(i16x), f32y));
182+
check(widening_mul(u16x, f32y), widening_mul(f32(u16x), f32y));
183+
184+
check(widening_mul(f16x, i8y), widening_mul(f16x, f16(i8y)));
185+
check(widening_mul(f32x, i8y), widening_mul(f32x, f32(i8y)));
186+
check(widening_mul(f16x, u8y), widening_mul(f16x, f16(u8y)));
187+
check(widening_mul(f32x, u8y), widening_mul(f32x, f32(u8y)));
188+
check(widening_mul(f32x, i16y), widening_mul(f32x, f32(i16y)));
189+
check(widening_mul(f32x, u16y), widening_mul(f32x, f32(u16y)));
190+
173191
// Widening mul allows mixed signs
174192
check(i16(i8x) * u8y, widening_mul(i8x, u8y), Int(16, 4));
175193
check(i32(i8x) * u8y, i32(widening_mul(i8x, u8y)));
@@ -377,6 +395,16 @@ int main(int argc, char **argv) {
377395
g.compile_jit();
378396
}
379397

398+
// Mixed integer-floating-point used to crash codegen
399+
{
400+
Func f, q, s;
401+
q(x) = cast<int8_t>(0);
402+
s(x) = cast(Float(16), 1.0f);
403+
f(x) = widening_mul(q(x), s(x));
404+
405+
f.compile_jit();
406+
}
407+
380408
printf("Success!\n");
381409
return 0;
382410
}

0 commit comments

Comments
 (0)