aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-05-11 08:59:44 -0700
committerGitHub <noreply@github.com>2023-05-11 08:59:44 -0700
commit7f7bd206dc8309ca767b47fb97bb9e7c2dc882c3 (patch)
tree2d24acb80954ec2d33863befa9ce48ecd3075e72 /src/Sema.zig
parent5512455974a9dda5d2a86a81e4a5cc520cb7afa8 (diff)
parent4d296debefccbd80f2007685a27386b7434464dd (diff)
downloadzig-7f7bd206dc8309ca767b47fb97bb9e7c2dc882c3.tar.gz
zig-7f7bd206dc8309ca767b47fb97bb9e7c2dc882c3.zip
Merge pull request #15519 from dweiller/issue-15482
Optimize lowering of `s[start..][0..len]`
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig57
1 files changed, 48 insertions, 9 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 225a6c5bff..0834e6a50e 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -985,6 +985,7 @@ fn analyzeBodyInner(
.slice_end => try sema.zirSliceEnd(block, inst),
.slice_sentinel => try sema.zirSliceSentinel(block, inst),
.slice_start => try sema.zirSliceStart(block, inst),
+ .slice_length => try sema.zirSliceLength(block, inst),
.str => try sema.zirStr(block, inst),
.switch_block => try sema.zirSwitchBlock(block, inst),
.switch_cond => try sema.zirSwitchCond(block, inst, false),
@@ -9931,7 +9932,7 @@ fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
const start_src: LazySrcLoc = .{ .node_offset_slice_start = inst_data.src_node };
const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node };
- return sema.analyzeSlice(block, src, array_ptr, start, .none, .none, .unneeded, ptr_src, start_src, end_src);
+ return sema.analyzeSlice(block, src, array_ptr, start, .none, .none, .unneeded, ptr_src, start_src, end_src, false);
}
fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -9948,7 +9949,7 @@ fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const start_src: LazySrcLoc = .{ .node_offset_slice_start = inst_data.src_node };
const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node };
- return sema.analyzeSlice(block, src, array_ptr, start, end, .none, .unneeded, ptr_src, start_src, end_src);
+ return sema.analyzeSlice(block, src, array_ptr, start, end, .none, .unneeded, ptr_src, start_src, end_src, false);
}
fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -9967,7 +9968,29 @@ fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
const start_src: LazySrcLoc = .{ .node_offset_slice_start = inst_data.src_node };
const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node };
- return sema.analyzeSlice(block, src, array_ptr, start, end, sentinel, sentinel_src, ptr_src, start_src, end_src);
+ return sema.analyzeSlice(block, src, array_ptr, start, end, sentinel, sentinel_src, ptr_src, start_src, end_src, false);
+}
+
+fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+ const src = inst_data.src();
+ const extra = sema.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data;
+ const array_ptr = try sema.resolveInst(extra.lhs);
+ const start = try sema.resolveInst(extra.start);
+ const len = try sema.resolveInst(extra.len);
+ const sentinel = try sema.resolveInst(extra.sentinel);
+ const ptr_src: LazySrcLoc = .{ .node_offset_slice_ptr = inst_data.src_node };
+ const start_src: LazySrcLoc = .{ .node_offset_slice_start = extra.start_src_node_offset };
+ const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node };
+ const sentinel_src: LazySrcLoc = if (sentinel == .none)
+ .unneeded
+ else
+ .{ .node_offset_slice_sentinel = inst_data.src_node };
+
+ return sema.analyzeSlice(block, src, array_ptr, start, len, sentinel, sentinel_src, ptr_src, start_src, end_src, true);
}
fn zirSwitchCapture(
@@ -29193,6 +29216,7 @@ fn analyzeSlice(
ptr_src: LazySrcLoc,
start_src: LazySrcLoc,
end_src: LazySrcLoc,
+ by_length: bool,
) CompileError!Air.Inst.Ref {
// Slice expressions can operate on a variable whose type is an array. This requires
// the slice operand to be a pointer. In the case of a non-array, it will be a double pointer.
@@ -29271,7 +29295,11 @@ fn analyzeSlice(
const len_val = try Value.Tag.int_u64.create(sema.arena, array_ty.arrayLen());
if (!end_is_len) {
- const end = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
+ const end = if (by_length) end: {
+ const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
+ const uncasted_end = try sema.analyzeArithmetic(block, .add, start, len, src, start_src, end_src, false);
+ break :end try sema.coerce(block, Type.usize, uncasted_end, end_src);
+ } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
if (try sema.resolveMaybeUndefVal(end)) |end_val| {
const len_s_val = try Value.Tag.int_u64.create(
sema.arena,
@@ -29308,7 +29336,11 @@ fn analyzeSlice(
break :e try sema.addConstant(Type.usize, len_val);
} else if (slice_ty.isSlice()) {
if (!end_is_len) {
- const end = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
+ const end = if (by_length) end: {
+ const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
+ const uncasted_end = try sema.analyzeArithmetic(block, .add, start, len, src, start_src, end_src, false);
+ break :end try sema.coerce(block, Type.usize, uncasted_end, end_src);
+ } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
if (try sema.resolveMaybeUndefVal(ptr_or_slice)) |slice_val| {
if (slice_val.isUndef()) {
@@ -29355,7 +29387,11 @@ fn analyzeSlice(
break :e try sema.analyzeSliceLen(block, src, ptr_or_slice);
}
if (!end_is_len) {
- break :e try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
+ if (by_length) {
+ const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
+ const uncasted_end = try sema.analyzeArithmetic(block, .add, start, len, src, start_src, end_src, false);
+ break :e try sema.coerce(block, Type.usize, uncasted_end, end_src);
+ } else break :e try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
}
return sema.fail(block, src, "slice of pointer must include end value", .{});
};
@@ -29379,7 +29415,7 @@ fn analyzeSlice(
// requirement: start <= end
if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| {
- if (!(try sema.compareAll(start_val, .lte, end_val, Type.usize))) {
+ if (!by_length and !(try sema.compareAll(start_val, .lte, end_val, Type.usize))) {
return sema.fail(
block,
start_src,
@@ -29432,11 +29468,14 @@ fn analyzeSlice(
}
}
- if (block.wantSafety() and !block.is_comptime) {
+ if (!by_length and block.wantSafety() and !block.is_comptime) {
// requirement: start <= end
try sema.panicStartLargerThanEnd(block, start, end);
}
- const new_len = try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src, false);
+ const new_len = if (by_length)
+ try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)
+ else
+ try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src, false);
const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len);
const new_ptr_ty_info = sema.typeOf(new_ptr).ptrInfo().data;