@@ -20,6 +20,13 @@ Expr Simplify::visit(const Cast *op, ExprInfo *info) {
2020 int64_t old_min = value_info.bounds .min ;
2121 bool old_min_defined = value_info.bounds .min_defined ;
2222 value_info.cast_to (op->type );
23+ if (value.type ().is_float () && op->type .is_int_or_uint ()) {
24+ // ExprInfo::cast_to handles integer casts, where narrowing wraps
25+ // and preserves alignment modulo the destination width. Float to
26+ // integer casts saturate instead, so the old alignment can be
27+ // wrong after the cast.
28+ value_info.alignment = ModulusRemainder ();
29+ }
2330 if (op->type .is_uint () && op->type .bits () == 64 && old_min_defined && old_min > 0 ) {
2431 // It's impossible for a cast *to* a uint64 in Halide to lower the
2532 // min. Casts to uint64_t don't overflow for any source type.
@@ -110,13 +117,14 @@ Expr Simplify::visit(const Cast *op, ExprInfo *info) {
110117 } else if (cast &&
111118 op->type .is_int_or_uint () &&
112119 cast->type .is_int_or_uint () &&
120+ cast->value .type ().is_int_or_uint () &&
113121 op->type .bits () <= cast->type .bits () &&
114122 op->type .bits () <= op->value .type ().bits ()) {
115123 // If this is a cast between integer types, where the
116124 // outer cast is narrower than the inner cast and the
117125 // inner cast's argument, the inner cast can be
118- // eliminated. The inner cast is either a sign extend
119- // or a zero extend, and the outer cast truncates the extended bits
126+ // eliminated. The inner cast is either a sign- extend
127+ // or a zero- extend, and the outer cast truncates the extended bits.
120128 if (op->type == cast->value .type ()) {
121129 return mutate (cast->value , info);
122130 } else {
0 commit comments