aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorMatthew Lugg <mlugg@mlugg.co.uk>2025-11-09 15:16:49 +0000
committerMatthew Lugg <mlugg@mlugg.co.uk>2025-11-12 16:00:16 +0000
commit69f39868b4125e79e4070a88bbdfcd3643dbc90d (patch)
tree7e90f08d2b5d1cb234957dbe0b6a48034afe4e30 /src/Sema.zig
parent99a7884308d288bd39df9192c9094439b179ff60 (diff)
downloadzig-69f39868b4125e79e4070a88bbdfcd3643dbc90d.tar.gz
zig-69f39868b4125e79e4070a88bbdfcd3643dbc90d.zip
Air.Legalize: revert to loops for scalarizations
I had tried unrolling the loops to avoid requiring the `vector_store_elem` instruction, but it's arguably a problem to generate O(N) code for an operation on `@Vector(N, T)`. In addition, that lowering emitted a lot of `.aggregate_init` instructions, which is itself a quite difficult operation to codegen. This requires reintroducing runtime vector indexing internally. However, I've put it in a couple of instructions which are intended only for use by `Air.Legalize`, named `legalize_vec_elem_val` (like `array_elem_val`, but for indexing a vector with a runtime-known index) and `legalize_vec_store_elem` (like the old `vector_store_elem` instruction). These are explicitly documented as *not* being emitted by Sema, so need only be implemented by backends if they actually use an `Air.Legalize.Feature` which emits them (otherwise they can be marked as `unreachable`).
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig23
1 files changed, 14 insertions, 9 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 8b5c7c5de2..7974b47913 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -15930,16 +15930,21 @@ fn zirOverflowArithmetic(
}
}
// If either of the arguments is one, the result is the other and no overflow occured.
- const scalar_one = try pt.intValue(dest_ty.scalarType(zcu), 1);
- const vec_one = try sema.splat(dest_ty, scalar_one);
- if (maybe_lhs_val) |lhs_val| {
- if (!lhs_val.isUndef(zcu) and try sema.compareAll(lhs_val, .eq, vec_one, dest_ty)) {
- break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs };
+ const dest_scalar_ty = dest_ty.scalarType(zcu);
+ const dest_scalar_int = dest_scalar_ty.intInfo(zcu);
+ // We could still be working with i1, where '1' is not a legal value!
+ if (!(dest_scalar_int.bits == 1 and dest_scalar_int.signedness == .signed)) {
+ const scalar_one = try pt.intValue(dest_scalar_ty, 1);
+ const vec_one = try sema.splat(dest_ty, scalar_one);
+ if (maybe_lhs_val) |lhs_val| {
+ if (!lhs_val.isUndef(zcu) and try sema.compareAll(lhs_val, .eq, vec_one, dest_ty)) {
+ break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs };
+ }
}
- }
- if (maybe_rhs_val) |rhs_val| {
- if (!rhs_val.isUndef(zcu) and try sema.compareAll(rhs_val, .eq, vec_one, dest_ty)) {
- break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs };
+ if (maybe_rhs_val) |rhs_val| {
+ if (!rhs_val.isUndef(zcu) and try sema.compareAll(rhs_val, .eq, vec_one, dest_ty)) {
+ break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs };
+ }
}
}