diff --git a/src/Air.zig b/src/Air.zig index 7a8d3a7c9e..1b394ca1c1 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -166,19 +166,25 @@ pub const Inst = struct { mod, /// Same as `mod` with optimized float mode. mod_optimized, - /// Add an offset to a pointer, returning a new pointer. - /// The offset is in element type units, not bytes. - /// Wrapping is illegal behavior. - /// The lhs is the pointer, rhs is the offset. Result type is the same as lhs. - /// The pointer may be a slice. - /// Uses the `ty_pl` field. Payload is `Bin`. + /// Add an offset, in element type units, to a pointer, returning a new + /// pointer. Element type may not be zero bits. + /// + /// Wrapping is illegal behavior. If the newly computed address is + /// outside the provenance of the operand, the result is undefined. + /// + /// Uses the `ty_pl` field. Payload is `Bin`. The lhs is the pointer, + /// rhs is the offset. Result type is the same as lhs. The operand may + /// be a slice. ptr_add, - /// Subtract an offset from a pointer, returning a new pointer. - /// The offset is in element type units, not bytes. - /// Wrapping is illegal behavior. - /// The lhs is the pointer, rhs is the offset. Result type is the same as lhs. - /// The pointer may be a slice. - /// Uses the `ty_pl` field. Payload is `Bin`. + /// Subtract an offset, in element type units, from a pointer, + /// returning a new pointer. Element type may not be zero bits. + /// + /// Wrapping is illegal behavior. If the newly computed address is + /// outside the provenance of the operand, the result is undefined. + /// + /// Uses the `ty_pl` field. Payload is `Bin`. The lhs is the pointer, + /// rhs is the offset. Result type is the same as lhs. The operand may + /// be a slice. ptr_sub, /// Given two operands which can be floats, integers, or vectors, returns the /// greater of the operands. For vectors it operates element-wise. diff --git a/src/Sema.zig b/src/Sema.zig index 1ca5bb5a58..de5d202b87 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16002,7 +16002,6 @@ fn splat(sema: *Sema, ty: Type, val: Value) !Value { fn analyzeArithmetic( sema: *Sema, block: *Block, - /// TODO performance investigation: make this comptime? zir_tag: Zir.Inst.Tag, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, @@ -16201,6 +16200,11 @@ fn analyzePtrArithmetic( const ptr_info = ptr_ty.ptrInfo(zcu); assert(ptr_info.flags.size == .many or ptr_info.flags.size == .c); + if ((try sema.typeHasOnePossibleValue(.fromInterned(ptr_info.child))) != null) { + // Offset will be multiplied by zero, so result is the same as the base pointer. + return ptr; + } + const new_ptr_ty = t: { // Calculate the new pointer alignment. // This code is duplicated in `Type.elemPtrType`.