aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-10-24 14:41:22 +0300
committerVeikka Tuominen <git@vexu.eu>2022-10-27 01:31:17 +0300
commitdd437ae39948031dc04836f245c8b77d459a428a (patch)
treeea2cf8ea5dce382549deaf9a2c8801ec1c7403d1 /src
parent9db293492bbbc5b8d70638bd9c59dea19d13596c (diff)
downloadzig-dd437ae39948031dc04836f245c8b77d459a428a.tar.gz
zig-dd437ae39948031dc04836f245c8b77d459a428a.zip
stage2: optimize size of optional slices
Diffstat (limited to 'src')
-rw-r--r--src/codegen/c.zig14
-rw-r--r--src/codegen/llvm.zig10
-rw-r--r--src/type.zig46
3 files changed, 25 insertions, 45 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index d6584d75ae..5f6f2fd6d5 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -726,7 +726,11 @@ pub const DeclGen = struct {
}
if (ty.optionalReprIsPayload()) {
- return dg.renderValue(writer, payload_ty, val, location);
+ if (val.castTag(.opt_payload)) |payload| {
+ return dg.renderValue(writer, payload_ty, payload.data, location);
+ } else {
+ return dg.renderValue(writer, payload_ty, val, location);
+ }
}
try writer.writeByte('(');
@@ -3263,11 +3267,9 @@ fn airIsNull(
try f.writeCValue(writer, operand);
const ty = f.air.typeOf(un_op);
+ const opt_ty = if (deref_suffix[0] != 0) ty.childType() else ty;
var opt_buf: Type.Payload.ElemType = undefined;
- const payload_ty = if (deref_suffix[0] != 0)
- ty.childType().optionalChild(&opt_buf)
- else
- ty.optionalChild(&opt_buf);
+ const payload_ty = opt_ty.optionalChild(&opt_buf);
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
try writer.print("){s} {s} true;\n", .{ deref_suffix, operator });
@@ -3276,6 +3278,8 @@ fn airIsNull(
try writer.print("){s} {s} NULL;\n", .{ deref_suffix, operator });
} else if (payload_ty.zigTypeTag() == .ErrorSet) {
try writer.print("){s} {s} 0;\n", .{ deref_suffix, operator });
+ } else if (payload_ty.isSlice() and opt_ty.optionalReprIsPayload()) {
+ try writer.print("){s}.ptr {s} NULL;\n", .{ deref_suffix, operator });
} else {
try writer.print("){s}.is_null {s} true;\n", .{ deref_suffix, operator });
}
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index ffc19cb6f6..d4a94d1308 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -6316,18 +6316,24 @@ pub const FuncGen = struct {
const operand_ty = self.air.typeOf(un_op);
const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
const optional_llvm_ty = try self.dg.lowerType(optional_ty);
+ var buf: Type.Payload.ElemType = undefined;
+ const payload_ty = optional_ty.optionalChild(&buf);
if (optional_ty.optionalReprIsPayload()) {
const loaded = if (operand_is_ptr)
self.builder.buildLoad(optional_llvm_ty, operand, "")
else
operand;
+ if (payload_ty.isSlice()) {
+ const slice_ptr = self.builder.buildExtractValue(loaded, 0, "");
+ var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined;
+ const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(&slice_buf));
+ return self.builder.buildICmp(pred, slice_ptr, ptr_ty.constNull(), "");
+ }
return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), "");
}
comptime assert(optional_layout_version == 3);
- var buf: Type.Payload.ElemType = undefined;
- const payload_ty = optional_ty.optionalChild(&buf);
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
const loaded = if (operand_is_ptr)
self.builder.buildLoad(optional_llvm_ty, operand, "")
diff --git a/src/type.zig b/src/type.zig
index a2f0bb9e8f..8904b3178d 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -3469,20 +3469,8 @@ pub const Type = extern union {
if (!child_type.hasRuntimeBits()) return AbiSizeAdvanced{ .scalar = 1 };
- switch (child_type.zigTypeTag()) {
- .Pointer => {
- const ptr_info = child_type.ptrInfo().data;
- const has_null = switch (ptr_info.size) {
- .Slice, .C => true,
- else => ptr_info.@"allowzero",
- };
- if (!has_null) {
- const ptr_size_bytes = @divExact(target.cpu.arch.ptrBitWidth(), 8);
- return AbiSizeAdvanced{ .scalar = ptr_size_bytes };
- }
- },
- .ErrorSet => return abiSizeAdvanced(Type.anyerror, target, strat),
- else => {},
+ if (ty.optionalReprIsPayload()) {
+ return abiSizeAdvanced(child_type, target, strat);
}
const payload_size = switch (try child_type.abiSizeAdvanced(target, strat)) {
@@ -3747,28 +3735,10 @@ pub const Type = extern union {
.int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data,
- .optional => {
- var buf: Payload.ElemType = undefined;
- const child_type = ty.optionalChild(&buf);
- if (!child_type.hasRuntimeBits()) return 8;
-
- if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr() and !child_type.isSlice())
- return target.cpu.arch.ptrBitWidth();
-
- // Optional types are represented as a struct with the child type as the first
- // field and a boolean as the second. Since the child type's abi alignment is
- // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
- // to the child type's ABI alignment.
- const child_bit_size = try bitSizeAdvanced(child_type, target, sema_kit);
- return child_bit_size + 1;
- },
-
- .error_union => {
- const payload = ty.castTag(.error_union).?.data;
- if (!payload.payload.hasRuntimeBits()) {
- return payload.error_set.bitSizeAdvanced(target, sema_kit);
- }
- @panic("TODO bitSize error union");
+ .optional, .error_union => {
+ // Optionals and error unions are not packed so their bitsize
+ // includes padding bits.
+ return (try abiSizeAdvanced(ty, target, if (sema_kit) |sk| .{ .sema_kit = sk } else .eager)).scalar * 8;
},
.atomic_order,
@@ -4045,8 +4015,8 @@ pub const Type = extern union {
.Pointer => {
const info = child_ty.ptrInfo().data;
switch (info.size) {
- .Slice, .C => return false,
- .Many, .One => return !info.@"allowzero",
+ .C => return false,
+ .Slice, .Many, .One => return !info.@"allowzero",
}
},
.ErrorSet => return true,