authorgravatar for william@sengir.comWilliam Sengir <william@sengir.com> 2022-03-20 00:38:12-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-21 16:54:19-07:00
logafdcfb005ea32849f30e2abd7361ce1f33d0ee74
treeee60a029d0fd028bc17e65e84a0fe36877a7c1fb
parent3f4676901a8c02d9d7069b284aa848d685c3975c

Sema: make most instructions vector-agnostic

Made most `Value` functions require a `Type`. If the provided type is a vector, then automatically vectorize the operation and return with another vector. The Sema side can then automatically become vectorized with minimal changes. There are already a few manually vectorized instructions, but we can simplify those later.

2 files changed, 1006 insertions(+), 278 deletions(-)

src/Sema.zig+278-235
...@@ -2105,7 +2105,7 @@ fn zirEnumDecl(...@@ -2105,7 +2105,7 @@ fn zirEnumDecl(
2105 });2105 });
2106 } else if (any_values) {2106 } else if (any_values) {
2107 const tag_val = if (last_tag_val) |val|2107 const tag_val = if (last_tag_val) |val|
2108 try val.intAdd(Value.one, sema.arena)2108 try val.intAdd(Value.one, enum_obj.tag_ty, sema.arena)
2109 else2109 else
2110 Value.zero;2110 Value.zero;
2111 last_tag_val = tag_val;2111 last_tag_val = tag_val;
...@@ -8192,14 +8192,22 @@ fn zirShl(...@@ -8192,14 +8192,22 @@ fn zirShl(
8192 defer tracy.end();8192 defer tracy.end();
81938193
8194 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;8194 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
8195 const src = inst_data.src();
8195 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };8196 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
8196 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };8197 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
8197 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;8198 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
8198 const lhs = sema.resolveInst(extra.lhs);8199 const lhs = sema.resolveInst(extra.lhs);
8199 const rhs = sema.resolveInst(extra.rhs);8200 const rhs = sema.resolveInst(extra.rhs);
8201 const lhs_ty = sema.typeOf(lhs);
8202 const rhs_ty = sema.typeOf(rhs);
8203 const target = sema.mod.getTarget();
8204 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
8205
8206 const scalar_ty = lhs_ty.scalarType();
8207 const scalar_rhs_ty = rhs_ty.scalarType();
82008208
8201 // TODO coerce rhs if air_tag is not shl_sat8209 // TODO coerce rhs if air_tag is not shl_sat
8202 const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, sema.typeOf(rhs));8210 const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, scalar_rhs_ty);
82038211
8204 const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs);8212 const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs);
8205 const maybe_rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs);8213 const maybe_rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs);
...@@ -8213,35 +8221,31 @@ fn zirShl(...@@ -8213,35 +8221,31 @@ fn zirShl(
8213 }8221 }
8214 }8222 }
82158223
8216 const lhs_ty = sema.typeOf(lhs);
8217 const rhs_ty = sema.typeOf(rhs);
8218 const target = sema.mod.getTarget();
8219
8220 const runtime_src = if (maybe_lhs_val) |lhs_val| rs: {8224 const runtime_src = if (maybe_lhs_val) |lhs_val| rs: {
8221 if (lhs_val.isUndef()) return sema.addConstUndef(lhs_ty);8225 if (lhs_val.isUndef()) return sema.addConstUndef(lhs_ty);
8222 const rhs_val = maybe_rhs_val orelse break :rs rhs_src;8226 const rhs_val = maybe_rhs_val orelse break :rs rhs_src;
82238227
8224 const val = switch (air_tag) {8228 const val = switch (air_tag) {
8225 .shl_exact => val: {8229 .shl_exact => val: {
8226 const shifted = try lhs_val.shl(rhs_val, sema.arena);8230 const shifted = try lhs_val.shl(rhs_val, lhs_ty, sema.arena);
8227 if (lhs_ty.zigTypeTag() == .ComptimeInt) {8231 if (scalar_ty.zigTypeTag() == .ComptimeInt) {
8228 break :val shifted;8232 break :val shifted;
8229 }8233 }
8230 const int_info = lhs_ty.intInfo(target);8234 const int_info = scalar_ty.intInfo(target);
8231 const truncated = try shifted.intTrunc(sema.arena, int_info.signedness, int_info.bits);8235 const truncated = try shifted.intTrunc(lhs_ty, sema.arena, int_info.signedness, int_info.bits);
8232 if (truncated.compareHetero(.eq, shifted)) {8236 if (truncated.compare(.eq, shifted, lhs_ty)) {
8233 break :val shifted;8237 break :val shifted;
8234 }8238 }
8235 return sema.addConstUndef(lhs_ty);8239 return sema.addConstUndef(lhs_ty);
8236 },8240 },
82378241
8238 .shl_sat => if (lhs_ty.zigTypeTag() == .ComptimeInt)8242 .shl_sat => if (scalar_ty.zigTypeTag() == .ComptimeInt)
8239 try lhs_val.shl(rhs_val, sema.arena)8243 try lhs_val.shl(rhs_val, lhs_ty, sema.arena)
8240 else8244 else
8241 try lhs_val.shlSat(rhs_val, lhs_ty, sema.arena, target),8245 try lhs_val.shlSat(rhs_val, lhs_ty, sema.arena, target),
82428246
8243 .shl => if (lhs_ty.zigTypeTag() == .ComptimeInt)8247 .shl => if (scalar_ty.zigTypeTag() == .ComptimeInt)
8244 try lhs_val.shl(rhs_val, sema.arena)8248 try lhs_val.shl(rhs_val, lhs_ty, sema.arena)
8245 else8249 else
8246 try lhs_val.shlTrunc(rhs_val, lhs_ty, sema.arena, target),8250 try lhs_val.shlTrunc(rhs_val, lhs_ty, sema.arena, target),
82478251
...@@ -8256,7 +8260,7 @@ fn zirShl(...@@ -8256,7 +8260,7 @@ fn zirShl(
8256 const new_rhs = if (air_tag == .shl_sat) rhs: {8260 const new_rhs = if (air_tag == .shl_sat) rhs: {
8257 // Limit the RHS type for saturating shl to be an integer as small as the LHS.8261 // Limit the RHS type for saturating shl to be an integer as small as the LHS.
8258 if (rhs_is_comptime_int or8262 if (rhs_is_comptime_int or
8259 rhs_ty.intInfo(target).bits > lhs_ty.intInfo(target).bits)8263 scalar_rhs_ty.intInfo(target).bits > scalar_ty.intInfo(target).bits)
8260 {8264 {
8261 const max_int = try sema.addConstant(8265 const max_int = try sema.addConstant(
8262 lhs_ty,8266 lhs_ty,
...@@ -8283,15 +8287,18 @@ fn zirShr(...@@ -8283,15 +8287,18 @@ fn zirShr(
8283 defer tracy.end();8287 defer tracy.end();
82848288
8285 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;8289 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
8290 const src = inst_data.src();
8286 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };8291 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
8287 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };8292 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
8288 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;8293 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
8289 const lhs = sema.resolveInst(extra.lhs);8294 const lhs = sema.resolveInst(extra.lhs);
8290 const rhs = sema.resolveInst(extra.rhs);8295 const rhs = sema.resolveInst(extra.rhs);
8296 const lhs_ty = sema.typeOf(lhs);
8297 const rhs_ty = sema.typeOf(rhs);
8298 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
82918299
8292 const runtime_src = if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| rs: {8300 const runtime_src = if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| rs: {
8293 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {8301 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
8294 const lhs_ty = sema.typeOf(lhs);
8295 if (lhs_val.isUndef() or rhs_val.isUndef()) {8302 if (lhs_val.isUndef() or rhs_val.isUndef()) {
8296 return sema.addConstUndef(lhs_ty);8303 return sema.addConstUndef(lhs_ty);
8297 }8304 }
...@@ -8301,13 +8308,12 @@ fn zirShr(...@@ -8301,13 +8308,12 @@ fn zirShr(
8301 }8308 }
8302 if (air_tag == .shr_exact) {8309 if (air_tag == .shr_exact) {
8303 // Detect if any ones would be shifted out.8310 // Detect if any ones would be shifted out.
8304 const bits = @intCast(u16, rhs_val.toUnsignedInt());8311 const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val);
8305 const truncated = try lhs_val.intTrunc(sema.arena, .unsigned, bits);
8306 if (!truncated.compareWithZero(.eq)) {8312 if (!truncated.compareWithZero(.eq)) {
8307 return sema.addConstUndef(lhs_ty);8313 return sema.addConstUndef(lhs_ty);
8308 }8314 }
8309 }8315 }
8310 const val = try lhs_val.shr(rhs_val, sema.arena);8316 const val = try lhs_val.shr(rhs_val, lhs_ty, sema.arena);
8311 return sema.addConstant(lhs_ty, val);8317 return sema.addConstant(lhs_ty, val);
8312 } else {8318 } else {
8313 // Even if lhs is not comptime known, we can still deduce certain things based8319 // Even if lhs is not comptime known, we can still deduce certain things based
...@@ -8342,32 +8348,15 @@ fn zirBitwise(...@@ -8342,32 +8348,15 @@ fn zirBitwise(
8342 const rhs = sema.resolveInst(extra.rhs);8348 const rhs = sema.resolveInst(extra.rhs);
8343 const lhs_ty = sema.typeOf(lhs);8349 const lhs_ty = sema.typeOf(lhs);
8344 const rhs_ty = sema.typeOf(rhs);8350 const rhs_ty = sema.typeOf(rhs);
8351 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
83458352
8346 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };8353 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
8347 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });8354 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
8348 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);8355 const scalar_type = resolved_type.scalarType();
8349 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
8350
8351 const scalar_type = if (resolved_type.zigTypeTag() == .Vector)
8352 resolved_type.elemType()
8353 else
8354 resolved_type;
8355
8356 const scalar_tag = scalar_type.zigTypeTag();8356 const scalar_tag = scalar_type.zigTypeTag();
83578357
8358 if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) {8358 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
8359 if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) {8359 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
8360 return sema.fail(block, src, "vector length mismatch: {d} and {d}", .{
8361 lhs_ty.arrayLen(),
8362 rhs_ty.arrayLen(),
8363 });
8364 }
8365 } else if (lhs_ty.zigTypeTag() == .Vector or rhs_ty.zigTypeTag() == .Vector) {
8366 return sema.fail(block, src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{
8367 lhs_ty,
8368 rhs_ty,
8369 });
8370 }
83718360
8372 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;8361 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
83738362
...@@ -8377,16 +8366,13 @@ fn zirBitwise(...@@ -8377,16 +8366,13 @@ fn zirBitwise(
83778366
8378 if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| {8367 if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| {
8379 if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {8368 if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {
8380 if (resolved_type.zigTypeTag() == .Vector) {
8381 return sema.fail(block, src, "TODO implement zirBitwise for vectors at comptime", .{});
8382 }
8383 const result_val = switch (air_tag) {8369 const result_val = switch (air_tag) {
8384 .bit_and => try lhs_val.bitwiseAnd(rhs_val, sema.arena),8370 .bit_and => try lhs_val.bitwiseAnd(rhs_val, resolved_type, sema.arena),
8385 .bit_or => try lhs_val.bitwiseOr(rhs_val, sema.arena),8371 .bit_or => try lhs_val.bitwiseOr(rhs_val, resolved_type, sema.arena),
8386 .xor => try lhs_val.bitwiseXor(rhs_val, sema.arena),8372 .xor => try lhs_val.bitwiseXor(rhs_val, resolved_type, sema.arena),
8387 else => unreachable,8373 else => unreachable,
8388 };8374 };
8389 return sema.addConstant(scalar_type, result_val);8375 return sema.addConstant(resolved_type, result_val);
8390 }8376 }
8391 }8377 }
83928378
...@@ -8413,9 +8399,9 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -8413,9 +8399,9 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
8413 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {8399 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
8414 const target = sema.mod.getTarget();8400 const target = sema.mod.getTarget();
8415 if (val.isUndef()) {8401 if (val.isUndef()) {
8416 return sema.addConstUndef(scalar_type);8402 return sema.addConstUndef(operand_type);
8417 } else if (operand_type.zigTypeTag() == .Vector) {8403 } else if (operand_type.zigTypeTag() == .Vector) {
8418 const vec_len = try sema.usizeCast(block, operand_src, operand_type.arrayLen());8404 const vec_len = try sema.usizeCast(block, operand_src, operand_type.vectorLen());
8419 var elem_val_buf: Value.ElemValueBuffer = undefined;8405 var elem_val_buf: Value.ElemValueBuffer = undefined;
8420 const elems = try sema.arena.alloc(Value, vec_len);8406 const elems = try sema.arena.alloc(Value, vec_len);
8421 for (elems) |*elem, i| {8407 for (elems) |*elem, i| {
...@@ -8427,8 +8413,8 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -8427,8 +8413,8 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
8427 try Value.Tag.aggregate.create(sema.arena, elems),8413 try Value.Tag.aggregate.create(sema.arena, elems),
8428 );8414 );
8429 } else {8415 } else {
8430 const result_val = try val.bitwiseNot(scalar_type, sema.arena, target);8416 const result_val = try val.bitwiseNot(operand_type, sema.arena, target);
8431 return sema.addConstant(scalar_type, result_val);8417 return sema.addConstant(operand_type, result_val);
8432 }8418 }
8433 }8419 }
84348420
...@@ -8780,8 +8766,19 @@ fn zirNegate(...@@ -8780,8 +8766,19 @@ fn zirNegate(
8780 const src = inst_data.src();8766 const src = inst_data.src();
8781 const lhs_src = src;8767 const lhs_src = src;
8782 const rhs_src = src; // TODO better source location8768 const rhs_src = src; // TODO better source location
8783 const lhs = sema.resolveInst(.zero);8769
8784 const rhs = sema.resolveInst(inst_data.operand);8770 const rhs = sema.resolveInst(inst_data.operand);
8771 const rhs_ty = sema.typeOf(rhs);
8772 const rhs_scalar_ty = rhs_ty.scalarType();
8773
8774 if (tag_override == .sub and rhs_scalar_ty.isUnsignedInt()) {
8775 return sema.fail(block, src, "negation of type '{}'", .{rhs_ty});
8776 }
8777
8778 const lhs = if (rhs_ty.zigTypeTag() == .Vector)
8779 try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero))
8780 else
8781 sema.resolveInst(.zero);
87858782
8786 return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src);8783 return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src);
8787}8784}
...@@ -8999,18 +8996,8 @@ fn analyzeArithmetic(...@@ -8999,18 +8996,8 @@ fn analyzeArithmetic(
8999 const rhs_ty = sema.typeOf(rhs);8996 const rhs_ty = sema.typeOf(rhs);
9000 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();8997 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
9001 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();8998 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
9002 if (lhs_zig_ty_tag == .Vector and rhs_zig_ty_tag == .Vector) {8999 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
9003 if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) {9000
9004 return sema.fail(block, src, "vector length mismatch: {d} and {d}", .{
9005 lhs_ty.arrayLen(), rhs_ty.arrayLen(),
9006 });
9007 }
9008 return sema.fail(block, src, "TODO implement support for vectors in Sema.analyzeArithmetic", .{});
9009 } else if (lhs_zig_ty_tag == .Vector or rhs_zig_ty_tag == .Vector) {
9010 return sema.fail(block, src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{
9011 lhs_ty, rhs_ty,
9012 });
9013 }
9014 if (lhs_zig_ty_tag == .Pointer) switch (lhs_ty.ptrSize()) {9001 if (lhs_zig_ty_tag == .Pointer) switch (lhs_ty.ptrSize()) {
9015 .One, .Slice => {},9002 .One, .Slice => {},
9016 .Many, .C => {9003 .Many, .C => {
...@@ -9033,15 +9020,13 @@ fn analyzeArithmetic(...@@ -9033,15 +9020,13 @@ fn analyzeArithmetic(
9033 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{9020 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
9034 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },9021 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
9035 });9022 });
9023
9036 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);9024 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
9037 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);9025 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
90389026
9039 const scalar_type = if (resolved_type.zigTypeTag() == .Vector)9027 const lhs_scalar_ty = lhs_ty.scalarType();
9040 resolved_type.elemType()9028 const rhs_scalar_ty = rhs_ty.scalarType();
9041 else9029 const scalar_tag = resolved_type.scalarType().zigTypeTag();
9042 resolved_type;
9043
9044 const scalar_tag = scalar_type.zigTypeTag();
90459030
9046 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;9031 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
9047 const is_float = scalar_tag == .Float or scalar_tag == .ComptimeFloat;9032 const is_float = scalar_tag == .Float or scalar_tag == .ComptimeFloat;
...@@ -9075,7 +9060,7 @@ fn analyzeArithmetic(...@@ -9075,7 +9060,7 @@ fn analyzeArithmetic(
9075 if (is_int) {9060 if (is_int) {
9076 return sema.failWithUseOfUndef(block, rhs_src);9061 return sema.failWithUseOfUndef(block, rhs_src);
9077 } else {9062 } else {
9078 return sema.addConstUndef(scalar_type);9063 return sema.addConstUndef(resolved_type);
9079 }9064 }
9080 }9065 }
9081 if (rhs_val.compareWithZero(.eq)) {9066 if (rhs_val.compareWithZero(.eq)) {
...@@ -9087,19 +9072,19 @@ fn analyzeArithmetic(...@@ -9087,19 +9072,19 @@ fn analyzeArithmetic(
9087 if (is_int) {9072 if (is_int) {
9088 return sema.failWithUseOfUndef(block, lhs_src);9073 return sema.failWithUseOfUndef(block, lhs_src);
9089 } else {9074 } else {
9090 return sema.addConstUndef(scalar_type);9075 return sema.addConstUndef(resolved_type);
9091 }9076 }
9092 }9077 }
9093 if (maybe_rhs_val) |rhs_val| {9078 if (maybe_rhs_val) |rhs_val| {
9094 if (is_int) {9079 if (is_int) {
9095 return sema.addConstant(9080 return sema.addConstant(
9096 scalar_type,9081 resolved_type,
9097 try lhs_val.intAdd(rhs_val, sema.arena),9082 try lhs_val.intAdd(rhs_val, resolved_type, sema.arena),
9098 );9083 );
9099 } else {9084 } else {
9100 return sema.addConstant(9085 return sema.addConstant(
9101 scalar_type,9086 resolved_type,
9102 try lhs_val.floatAdd(rhs_val, scalar_type, sema.arena, target),9087 try lhs_val.floatAdd(rhs_val, resolved_type, sema.arena, target),
9103 );9088 );
9104 }9089 }
9105 } else break :rs .{ .src = rhs_src, .air_tag = .add };9090 } else break :rs .{ .src = rhs_src, .air_tag = .add };
...@@ -9116,15 +9101,15 @@ fn analyzeArithmetic(...@@ -9116,15 +9101,15 @@ fn analyzeArithmetic(
9116 }9101 }
9117 if (maybe_rhs_val) |rhs_val| {9102 if (maybe_rhs_val) |rhs_val| {
9118 if (rhs_val.isUndef()) {9103 if (rhs_val.isUndef()) {
9119 return sema.addConstUndef(scalar_type);9104 return sema.addConstUndef(resolved_type);
9120 }9105 }
9121 if (rhs_val.compareWithZero(.eq)) {9106 if (rhs_val.compareWithZero(.eq)) {
9122 return casted_lhs;9107 return casted_lhs;
9123 }9108 }
9124 if (maybe_lhs_val) |lhs_val| {9109 if (maybe_lhs_val) |lhs_val| {
9125 return sema.addConstant(9110 return sema.addConstant(
9126 scalar_type,9111 resolved_type,
9127 try lhs_val.numberAddWrap(rhs_val, scalar_type, sema.arena, target),9112 try lhs_val.numberAddWrap(rhs_val, resolved_type, sema.arena, target),
9128 );9113 );
9129 } else break :rs .{ .src = lhs_src, .air_tag = .addwrap };9114 } else break :rs .{ .src = lhs_src, .air_tag = .addwrap };
9130 } else break :rs .{ .src = rhs_src, .air_tag = .addwrap };9115 } else break :rs .{ .src = rhs_src, .air_tag = .addwrap };
...@@ -9140,18 +9125,18 @@ fn analyzeArithmetic(...@@ -9140,18 +9125,18 @@ fn analyzeArithmetic(
9140 }9125 }
9141 if (maybe_rhs_val) |rhs_val| {9126 if (maybe_rhs_val) |rhs_val| {
9142 if (rhs_val.isUndef()) {9127 if (rhs_val.isUndef()) {
9143 return sema.addConstUndef(scalar_type);9128 return sema.addConstUndef(resolved_type);
9144 }9129 }
9145 if (rhs_val.compareWithZero(.eq)) {9130 if (rhs_val.compareWithZero(.eq)) {
9146 return casted_lhs;9131 return casted_lhs;
9147 }9132 }
9148 if (maybe_lhs_val) |lhs_val| {9133 if (maybe_lhs_val) |lhs_val| {
9149 const val = if (scalar_tag == .ComptimeInt)9134 const val = if (scalar_tag == .ComptimeInt)
9150 try lhs_val.intAdd(rhs_val, sema.arena)9135 try lhs_val.intAdd(rhs_val, resolved_type, sema.arena)
9151 else9136 else
9152 try lhs_val.intAddSat(rhs_val, scalar_type, sema.arena, target);9137 try lhs_val.intAddSat(rhs_val, resolved_type, sema.arena, target);
91539138
9154 return sema.addConstant(scalar_type, val);9139 return sema.addConstant(resolved_type, val);
9155 } else break :rs .{ .src = lhs_src, .air_tag = .add_sat };9140 } else break :rs .{ .src = lhs_src, .air_tag = .add_sat };
9156 } else break :rs .{ .src = rhs_src, .air_tag = .add_sat };9141 } else break :rs .{ .src = rhs_src, .air_tag = .add_sat };
9157 },9142 },
...@@ -9168,7 +9153,7 @@ fn analyzeArithmetic(...@@ -9168,7 +9153,7 @@ fn analyzeArithmetic(
9168 if (is_int) {9153 if (is_int) {
9169 return sema.failWithUseOfUndef(block, rhs_src);9154 return sema.failWithUseOfUndef(block, rhs_src);
9170 } else {9155 } else {
9171 return sema.addConstUndef(scalar_type);9156 return sema.addConstUndef(resolved_type);
9172 }9157 }
9173 }9158 }
9174 if (rhs_val.compareWithZero(.eq)) {9159 if (rhs_val.compareWithZero(.eq)) {
...@@ -9180,19 +9165,19 @@ fn analyzeArithmetic(...@@ -9180,19 +9165,19 @@ fn analyzeArithmetic(
9180 if (is_int) {9165 if (is_int) {
9181 return sema.failWithUseOfUndef(block, lhs_src);9166 return sema.failWithUseOfUndef(block, lhs_src);
9182 } else {9167 } else {
9183 return sema.addConstUndef(scalar_type);9168 return sema.addConstUndef(resolved_type);
9184 }9169 }
9185 }9170 }
9186 if (maybe_rhs_val) |rhs_val| {9171 if (maybe_rhs_val) |rhs_val| {
9187 if (is_int) {9172 if (is_int) {
9188 return sema.addConstant(9173 return sema.addConstant(
9189 scalar_type,9174 resolved_type,
9190 try lhs_val.intSub(rhs_val, sema.arena),9175 try lhs_val.intSub(rhs_val, resolved_type, sema.arena),
9191 );9176 );
9192 } else {9177 } else {
9193 return sema.addConstant(9178 return sema.addConstant(
9194 scalar_type,9179 resolved_type,
9195 try lhs_val.floatSub(rhs_val, scalar_type, sema.arena, target),9180 try lhs_val.floatSub(rhs_val, resolved_type, sema.arena, target),
9196 );9181 );
9197 }9182 }
9198 } else break :rs .{ .src = rhs_src, .air_tag = .sub };9183 } else break :rs .{ .src = rhs_src, .air_tag = .sub };
...@@ -9204,7 +9189,7 @@ fn analyzeArithmetic(...@@ -9204,7 +9189,7 @@ fn analyzeArithmetic(
9204 // If either of the operands are undefined, the result is undefined.9189 // If either of the operands are undefined, the result is undefined.
9205 if (maybe_rhs_val) |rhs_val| {9190 if (maybe_rhs_val) |rhs_val| {
9206 if (rhs_val.isUndef()) {9191 if (rhs_val.isUndef()) {
9207 return sema.addConstUndef(scalar_type);9192 return sema.addConstUndef(resolved_type);
9208 }9193 }
9209 if (rhs_val.compareWithZero(.eq)) {9194 if (rhs_val.compareWithZero(.eq)) {
9210 return casted_lhs;9195 return casted_lhs;
...@@ -9212,12 +9197,12 @@ fn analyzeArithmetic(...@@ -9212,12 +9197,12 @@ fn analyzeArithmetic(
9212 }9197 }
9213 if (maybe_lhs_val) |lhs_val| {9198 if (maybe_lhs_val) |lhs_val| {
9214 if (lhs_val.isUndef()) {9199 if (lhs_val.isUndef()) {
9215 return sema.addConstUndef(scalar_type);9200 return sema.addConstUndef(resolved_type);
9216 }9201 }
9217 if (maybe_rhs_val) |rhs_val| {9202 if (maybe_rhs_val) |rhs_val| {
9218 return sema.addConstant(9203 return sema.addConstant(
9219 scalar_type,9204 resolved_type,
9220 try lhs_val.numberSubWrap(rhs_val, scalar_type, sema.arena, target),9205 try lhs_val.numberSubWrap(rhs_val, resolved_type, sema.arena, target),
9221 );9206 );
9222 } else break :rs .{ .src = rhs_src, .air_tag = .subwrap };9207 } else break :rs .{ .src = rhs_src, .air_tag = .subwrap };
9223 } else break :rs .{ .src = lhs_src, .air_tag = .subwrap };9208 } else break :rs .{ .src = lhs_src, .air_tag = .subwrap };
...@@ -9228,7 +9213,7 @@ fn analyzeArithmetic(...@@ -9228,7 +9213,7 @@ fn analyzeArithmetic(
9228 // If either of the operands are undefined, result is undefined.9213 // If either of the operands are undefined, result is undefined.
9229 if (maybe_rhs_val) |rhs_val| {9214 if (maybe_rhs_val) |rhs_val| {
9230 if (rhs_val.isUndef()) {9215 if (rhs_val.isUndef()) {
9231 return sema.addConstUndef(scalar_type);9216 return sema.addConstUndef(resolved_type);
9232 }9217 }
9233 if (rhs_val.compareWithZero(.eq)) {9218 if (rhs_val.compareWithZero(.eq)) {
9234 return casted_lhs;9219 return casted_lhs;
...@@ -9236,15 +9221,15 @@ fn analyzeArithmetic(...@@ -9236,15 +9221,15 @@ fn analyzeArithmetic(
9236 }9221 }
9237 if (maybe_lhs_val) |lhs_val| {9222 if (maybe_lhs_val) |lhs_val| {
9238 if (lhs_val.isUndef()) {9223 if (lhs_val.isUndef()) {
9239 return sema.addConstUndef(scalar_type);9224 return sema.addConstUndef(resolved_type);
9240 }9225 }
9241 if (maybe_rhs_val) |rhs_val| {9226 if (maybe_rhs_val) |rhs_val| {
9242 const val = if (scalar_tag == .ComptimeInt)9227 const val = if (scalar_tag == .ComptimeInt)
9243 try lhs_val.intSub(rhs_val, sema.arena)9228 try lhs_val.intSub(rhs_val, resolved_type, sema.arena)
9244 else9229 else
9245 try lhs_val.intSubSat(rhs_val, scalar_type, sema.arena, target);9230 try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, target);
92469231
9247 return sema.addConstant(scalar_type, val);9232 return sema.addConstant(resolved_type, val);
9248 } else break :rs .{ .src = rhs_src, .air_tag = .sub_sat };9233 } else break :rs .{ .src = rhs_src, .air_tag = .sub_sat };
9249 } else break :rs .{ .src = lhs_src, .air_tag = .sub_sat };9234 } else break :rs .{ .src = lhs_src, .air_tag = .sub_sat };
9250 },9235 },
...@@ -9274,7 +9259,7 @@ fn analyzeArithmetic(...@@ -9274,7 +9259,7 @@ fn analyzeArithmetic(
9274 if (maybe_lhs_val) |lhs_val| {9259 if (maybe_lhs_val) |lhs_val| {
9275 if (!lhs_val.isUndef()) {9260 if (!lhs_val.isUndef()) {
9276 if (lhs_val.compareWithZero(.eq)) {9261 if (lhs_val.compareWithZero(.eq)) {
9277 return sema.addConstant(scalar_type, Value.zero);9262 return sema.addConstant(resolved_type, Value.zero);
9278 }9263 }
9279 }9264 }
9280 }9265 }
...@@ -9288,27 +9273,27 @@ fn analyzeArithmetic(...@@ -9288,27 +9273,27 @@ fn analyzeArithmetic(
9288 }9273 }
9289 if (maybe_lhs_val) |lhs_val| {9274 if (maybe_lhs_val) |lhs_val| {
9290 if (lhs_val.isUndef()) {9275 if (lhs_val.isUndef()) {
9291 if (lhs_ty.isSignedInt() and rhs_ty.isSignedInt()) {9276 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
9292 if (maybe_rhs_val) |rhs_val| {9277 if (maybe_rhs_val) |rhs_val| {
9293 if (rhs_val.compare(.neq, Value.negative_one, scalar_type)) {9278 if (rhs_val.compare(.neq, Value.negative_one, rhs_ty)) {
9294 return sema.addConstUndef(scalar_type);9279 return sema.addConstUndef(resolved_type);
9295 }9280 }
9296 }9281 }
9297 return sema.failWithUseOfUndef(block, rhs_src);9282 return sema.failWithUseOfUndef(block, rhs_src);
9298 }9283 }
9299 return sema.addConstUndef(scalar_type);9284 return sema.addConstUndef(resolved_type);
9300 }9285 }
93019286
9302 if (maybe_rhs_val) |rhs_val| {9287 if (maybe_rhs_val) |rhs_val| {
9303 if (is_int) {9288 if (is_int) {
9304 return sema.addConstant(9289 return sema.addConstant(
9305 scalar_type,9290 resolved_type,
9306 try lhs_val.intDiv(rhs_val, sema.arena),9291 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena),
9307 );9292 );
9308 } else {9293 } else {
9309 return sema.addConstant(9294 return sema.addConstant(
9310 scalar_type,9295 resolved_type,
9311 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target),9296 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
9312 );9297 );
9313 }9298 }
9314 } else {9299 } else {
...@@ -9349,7 +9334,7 @@ fn analyzeArithmetic(...@@ -9349,7 +9334,7 @@ fn analyzeArithmetic(
9349 if (maybe_lhs_val) |lhs_val| {9334 if (maybe_lhs_val) |lhs_val| {
9350 if (!lhs_val.isUndef()) {9335 if (!lhs_val.isUndef()) {
9351 if (lhs_val.compareWithZero(.eq)) {9336 if (lhs_val.compareWithZero(.eq)) {
9352 return sema.addConstant(scalar_type, Value.zero);9337 return sema.addConstant(resolved_type, Value.zero);
9353 }9338 }
9354 }9339 }
9355 }9340 }
...@@ -9363,27 +9348,27 @@ fn analyzeArithmetic(...@@ -9363,27 +9348,27 @@ fn analyzeArithmetic(
9363 }9348 }
9364 if (maybe_lhs_val) |lhs_val| {9349 if (maybe_lhs_val) |lhs_val| {
9365 if (lhs_val.isUndef()) {9350 if (lhs_val.isUndef()) {
9366 if (lhs_ty.isSignedInt() and rhs_ty.isSignedInt()) {9351 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
9367 if (maybe_rhs_val) |rhs_val| {9352 if (maybe_rhs_val) |rhs_val| {
9368 if (rhs_val.compare(.neq, Value.negative_one, scalar_type)) {9353 if (rhs_val.compare(.neq, Value.negative_one, rhs_ty)) {
9369 return sema.addConstUndef(scalar_type);9354 return sema.addConstUndef(resolved_type);
9370 }9355 }
9371 }9356 }
9372 return sema.failWithUseOfUndef(block, rhs_src);9357 return sema.failWithUseOfUndef(block, rhs_src);
9373 }9358 }
9374 return sema.addConstUndef(scalar_type);9359 return sema.addConstUndef(resolved_type);
9375 }9360 }
93769361
9377 if (maybe_rhs_val) |rhs_val| {9362 if (maybe_rhs_val) |rhs_val| {
9378 if (is_int) {9363 if (is_int) {
9379 return sema.addConstant(9364 return sema.addConstant(
9380 scalar_type,9365 resolved_type,
9381 try lhs_val.intDiv(rhs_val, sema.arena),9366 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena),
9382 );9367 );
9383 } else {9368 } else {
9384 return sema.addConstant(9369 return sema.addConstant(
9385 scalar_type,9370 resolved_type,
9386 try lhs_val.floatDivTrunc(rhs_val, scalar_type, sema.arena, target),9371 try lhs_val.floatDivTrunc(rhs_val, resolved_type, sema.arena, target),
9387 );9372 );
9388 }9373 }
9389 } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };9374 } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
...@@ -9412,7 +9397,7 @@ fn analyzeArithmetic(...@@ -9412,7 +9397,7 @@ fn analyzeArithmetic(
9412 if (maybe_lhs_val) |lhs_val| {9397 if (maybe_lhs_val) |lhs_val| {
9413 if (!lhs_val.isUndef()) {9398 if (!lhs_val.isUndef()) {
9414 if (lhs_val.compareWithZero(.eq)) {9399 if (lhs_val.compareWithZero(.eq)) {
9415 return sema.addConstant(scalar_type, Value.zero);9400 return sema.addConstant(resolved_type, Value.zero);
9416 }9401 }
9417 }9402 }
9418 }9403 }
...@@ -9426,27 +9411,27 @@ fn analyzeArithmetic(...@@ -9426,27 +9411,27 @@ fn analyzeArithmetic(
9426 }9411 }
9427 if (maybe_lhs_val) |lhs_val| {9412 if (maybe_lhs_val) |lhs_val| {
9428 if (lhs_val.isUndef()) {9413 if (lhs_val.isUndef()) {
9429 if (lhs_ty.isSignedInt() and rhs_ty.isSignedInt()) {9414 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
9430 if (maybe_rhs_val) |rhs_val| {9415 if (maybe_rhs_val) |rhs_val| {
9431 if (rhs_val.compare(.neq, Value.negative_one, scalar_type)) {9416 if (rhs_val.compare(.neq, Value.negative_one, rhs_ty)) {
9432 return sema.addConstUndef(scalar_type);9417 return sema.addConstUndef(resolved_type);
9433 }9418 }
9434 }9419 }
9435 return sema.failWithUseOfUndef(block, rhs_src);9420 return sema.failWithUseOfUndef(block, rhs_src);
9436 }9421 }
9437 return sema.addConstUndef(scalar_type);9422 return sema.addConstUndef(resolved_type);
9438 }9423 }
94399424
9440 if (maybe_rhs_val) |rhs_val| {9425 if (maybe_rhs_val) |rhs_val| {
9441 if (is_int) {9426 if (is_int) {
9442 return sema.addConstant(9427 return sema.addConstant(
9443 scalar_type,9428 resolved_type,
9444 try lhs_val.intDivFloor(rhs_val, sema.arena),9429 try lhs_val.intDivFloor(rhs_val, resolved_type, sema.arena),
9445 );9430 );
9446 } else {9431 } else {
9447 return sema.addConstant(9432 return sema.addConstant(
9448 scalar_type,9433 resolved_type,
9449 try lhs_val.floatDivFloor(rhs_val, scalar_type, sema.arena, target),9434 try lhs_val.floatDivFloor(rhs_val, resolved_type, sema.arena, target),
9450 );9435 );
9451 }9436 }
9452 } else break :rs .{ .src = rhs_src, .air_tag = .div_floor };9437 } else break :rs .{ .src = rhs_src, .air_tag = .div_floor };
...@@ -9474,7 +9459,7 @@ fn analyzeArithmetic(...@@ -9474,7 +9459,7 @@ fn analyzeArithmetic(
9474 return sema.failWithUseOfUndef(block, rhs_src);9459 return sema.failWithUseOfUndef(block, rhs_src);
9475 } else {9460 } else {
9476 if (lhs_val.compareWithZero(.eq)) {9461 if (lhs_val.compareWithZero(.eq)) {
9477 return sema.addConstant(scalar_type, Value.zero);9462 return sema.addConstant(resolved_type, Value.zero);
9478 }9463 }
9479 }9464 }
9480 }9465 }
...@@ -9491,14 +9476,14 @@ fn analyzeArithmetic(...@@ -9491,14 +9476,14 @@ fn analyzeArithmetic(
9491 if (is_int) {9476 if (is_int) {
9492 // TODO: emit compile error if there is a remainder9477 // TODO: emit compile error if there is a remainder
9493 return sema.addConstant(9478 return sema.addConstant(
9494 scalar_type,9479 resolved_type,
9495 try lhs_val.intDiv(rhs_val, sema.arena),9480 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena),
9496 );9481 );
9497 } else {9482 } else {
9498 // TODO: emit compile error if there is a remainder9483 // TODO: emit compile error if there is a remainder
9499 return sema.addConstant(9484 return sema.addConstant(
9500 scalar_type,9485 resolved_type,
9501 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target),9486 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
9502 );9487 );
9503 }9488 }
9504 } else break :rs .{ .src = rhs_src, .air_tag = .div_exact };9489 } else break :rs .{ .src = rhs_src, .air_tag = .div_exact };
...@@ -9516,9 +9501,9 @@ fn analyzeArithmetic(...@@ -9516,9 +9501,9 @@ fn analyzeArithmetic(
9516 if (maybe_lhs_val) |lhs_val| {9501 if (maybe_lhs_val) |lhs_val| {
9517 if (!lhs_val.isUndef()) {9502 if (!lhs_val.isUndef()) {
9518 if (lhs_val.compareWithZero(.eq)) {9503 if (lhs_val.compareWithZero(.eq)) {
9519 return sema.addConstant(scalar_type, Value.zero);9504 return sema.addConstant(resolved_type, Value.zero);
9520 }9505 }
9521 if (lhs_val.compare(.eq, Value.one, scalar_type)) {9506 if (lhs_val.compare(.eq, Value.one, lhs_ty)) {
9522 return casted_rhs;9507 return casted_rhs;
9523 }9508 }
9524 }9509 }
...@@ -9528,13 +9513,13 @@ fn analyzeArithmetic(...@@ -9528,13 +9513,13 @@ fn analyzeArithmetic(
9528 if (is_int) {9513 if (is_int) {
9529 return sema.failWithUseOfUndef(block, rhs_src);9514 return sema.failWithUseOfUndef(block, rhs_src);
9530 } else {9515 } else {
9531 return sema.addConstUndef(scalar_type);9516 return sema.addConstUndef(resolved_type);
9532 }9517 }
9533 }9518 }
9534 if (rhs_val.compareWithZero(.eq)) {9519 if (rhs_val.compareWithZero(.eq)) {
9535 return sema.addConstant(scalar_type, Value.zero);9520 return sema.addConstant(resolved_type, Value.zero);
9536 }9521 }
9537 if (rhs_val.compare(.eq, Value.one, scalar_type)) {9522 if (rhs_val.compare(.eq, Value.one, rhs_ty)) {
9538 return casted_lhs;9523 return casted_lhs;
9539 }9524 }
9540 if (maybe_lhs_val) |lhs_val| {9525 if (maybe_lhs_val) |lhs_val| {
...@@ -9542,18 +9527,18 @@ fn analyzeArithmetic(...@@ -9542,18 +9527,18 @@ fn analyzeArithmetic(
9542 if (is_int) {9527 if (is_int) {
9543 return sema.failWithUseOfUndef(block, lhs_src);9528 return sema.failWithUseOfUndef(block, lhs_src);
9544 } else {9529 } else {
9545 return sema.addConstUndef(scalar_type);9530 return sema.addConstUndef(resolved_type);
9546 }9531 }
9547 }9532 }
9548 if (is_int) {9533 if (is_int) {
9549 return sema.addConstant(9534 return sema.addConstant(
9550 scalar_type,9535 resolved_type,
9551 try lhs_val.intMul(rhs_val, sema.arena),9536 try lhs_val.intMul(rhs_val, resolved_type, sema.arena),
9552 );9537 );
9553 } else {9538 } else {
9554 return sema.addConstant(9539 return sema.addConstant(
9555 scalar_type,9540 resolved_type,
9556 try lhs_val.floatMul(rhs_val, scalar_type, sema.arena, target),9541 try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, target),
9557 );9542 );
9558 }9543 }
9559 } else break :rs .{ .src = lhs_src, .air_tag = .mul };9544 } else break :rs .{ .src = lhs_src, .air_tag = .mul };
...@@ -9567,30 +9552,30 @@ fn analyzeArithmetic(...@@ -9567,30 +9552,30 @@ fn analyzeArithmetic(
9567 if (maybe_lhs_val) |lhs_val| {9552 if (maybe_lhs_val) |lhs_val| {
9568 if (!lhs_val.isUndef()) {9553 if (!lhs_val.isUndef()) {
9569 if (lhs_val.compareWithZero(.eq)) {9554 if (lhs_val.compareWithZero(.eq)) {
9570 return sema.addConstant(scalar_type, Value.zero);9555 return sema.addConstant(resolved_type, Value.zero);
9571 }9556 }
9572 if (lhs_val.compare(.eq, Value.one, scalar_type)) {9557 if (lhs_val.compare(.eq, Value.one, lhs_ty)) {
9573 return casted_rhs;9558 return casted_rhs;
9574 }9559 }
9575 }9560 }
9576 }9561 }
9577 if (maybe_rhs_val) |rhs_val| {9562 if (maybe_rhs_val) |rhs_val| {
9578 if (rhs_val.isUndef()) {9563 if (rhs_val.isUndef()) {
9579 return sema.addConstUndef(scalar_type);9564 return sema.addConstUndef(resolved_type);
9580 }9565 }
9581 if (rhs_val.compareWithZero(.eq)) {9566 if (rhs_val.compareWithZero(.eq)) {
9582 return sema.addConstant(scalar_type, Value.zero);9567 return sema.addConstant(resolved_type, Value.zero);
9583 }9568 }
9584 if (rhs_val.compare(.eq, Value.one, scalar_type)) {9569 if (rhs_val.compare(.eq, Value.one, rhs_ty)) {
9585 return casted_lhs;9570 return casted_lhs;
9586 }9571 }
9587 if (maybe_lhs_val) |lhs_val| {9572 if (maybe_lhs_val) |lhs_val| {
9588 if (lhs_val.isUndef()) {9573 if (lhs_val.isUndef()) {
9589 return sema.addConstUndef(scalar_type);9574 return sema.addConstUndef(resolved_type);
9590 }9575 }
9591 return sema.addConstant(9576 return sema.addConstant(
9592 scalar_type,9577 resolved_type,
9593 try lhs_val.numberMulWrap(rhs_val, scalar_type, sema.arena, target),9578 try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, target),
9594 );9579 );
9595 } else break :rs .{ .src = lhs_src, .air_tag = .mulwrap };9580 } else break :rs .{ .src = lhs_src, .air_tag = .mulwrap };
9596 } else break :rs .{ .src = rhs_src, .air_tag = .mulwrap };9581 } else break :rs .{ .src = rhs_src, .air_tag = .mulwrap };
...@@ -9603,34 +9588,34 @@ fn analyzeArithmetic(...@@ -9603,34 +9588,34 @@ fn analyzeArithmetic(
9603 if (maybe_lhs_val) |lhs_val| {9588 if (maybe_lhs_val) |lhs_val| {
9604 if (!lhs_val.isUndef()) {9589 if (!lhs_val.isUndef()) {
9605 if (lhs_val.compareWithZero(.eq)) {9590 if (lhs_val.compareWithZero(.eq)) {
9606 return sema.addConstant(scalar_type, Value.zero);9591 return sema.addConstant(resolved_type, Value.zero);
9607 }9592 }
9608 if (lhs_val.compare(.eq, Value.one, scalar_type)) {9593 if (lhs_val.compare(.eq, Value.one, lhs_ty)) {
9609 return casted_rhs;9594 return casted_rhs;
9610 }9595 }
9611 }9596 }
9612 }9597 }
9613 if (maybe_rhs_val) |rhs_val| {9598 if (maybe_rhs_val) |rhs_val| {
9614 if (rhs_val.isUndef()) {9599 if (rhs_val.isUndef()) {
9615 return sema.addConstUndef(scalar_type);9600 return sema.addConstUndef(resolved_type);
9616 }9601 }
9617 if (rhs_val.compareWithZero(.eq)) {9602 if (rhs_val.compareWithZero(.eq)) {
9618 return sema.addConstant(scalar_type, Value.zero);9603 return sema.addConstant(resolved_type, Value.zero);
9619 }9604 }
9620 if (rhs_val.compare(.eq, Value.one, scalar_type)) {9605 if (rhs_val.compare(.eq, Value.one, rhs_ty)) {
9621 return casted_lhs;9606 return casted_lhs;
9622 }9607 }
9623 if (maybe_lhs_val) |lhs_val| {9608 if (maybe_lhs_val) |lhs_val| {
9624 if (lhs_val.isUndef()) {9609 if (lhs_val.isUndef()) {
9625 return sema.addConstUndef(scalar_type);9610 return sema.addConstUndef(resolved_type);
9626 }9611 }
96279612
9628 const val = if (scalar_tag == .ComptimeInt)9613 const val = if (scalar_tag == .ComptimeInt)
9629 try lhs_val.intMul(rhs_val, sema.arena)9614 try lhs_val.intMul(rhs_val, resolved_type, sema.arena)
9630 else9615 else
9631 try lhs_val.intMulSat(rhs_val, scalar_type, sema.arena, target);9616 try lhs_val.intMulSat(rhs_val, resolved_type, sema.arena, target);
96329617
9633 return sema.addConstant(scalar_type, val);9618 return sema.addConstant(resolved_type, val);
9634 } else break :rs .{ .src = lhs_src, .air_tag = .mul_sat };9619 } else break :rs .{ .src = lhs_src, .air_tag = .mul_sat };
9635 } else break :rs .{ .src = rhs_src, .air_tag = .mul_sat };9620 } else break :rs .{ .src = rhs_src, .air_tag = .mul_sat };
9636 },9621 },
...@@ -9654,9 +9639,9 @@ fn analyzeArithmetic(...@@ -9654,9 +9639,9 @@ fn analyzeArithmetic(
9654 return sema.failWithUseOfUndef(block, lhs_src);9639 return sema.failWithUseOfUndef(block, lhs_src);
9655 }9640 }
9656 if (lhs_val.compareWithZero(.eq)) {9641 if (lhs_val.compareWithZero(.eq)) {
9657 return sema.addConstant(scalar_type, Value.zero);9642 return sema.addConstant(resolved_type, Value.zero);
9658 }9643 }
9659 } else if (lhs_ty.isSignedInt()) {9644 } else if (lhs_scalar_ty.isSignedInt()) {
9660 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);9645 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
9661 }9646 }
9662 if (maybe_rhs_val) |rhs_val| {9647 if (maybe_rhs_val) |rhs_val| {
...@@ -9667,7 +9652,7 @@ fn analyzeArithmetic(...@@ -9667,7 +9652,7 @@ fn analyzeArithmetic(
9667 return sema.failWithDivideByZero(block, rhs_src);9652 return sema.failWithDivideByZero(block, rhs_src);
9668 }9653 }
9669 if (maybe_lhs_val) |lhs_val| {9654 if (maybe_lhs_val) |lhs_val| {
9670 const rem_result = try lhs_val.intRem(rhs_val, sema.arena);9655 const rem_result = try lhs_val.intRem(rhs_val, resolved_type, sema.arena);
9671 // If this answer could possibly be different by doing `intMod`,9656 // If this answer could possibly be different by doing `intMod`,
9672 // we must emit a compile error. Otherwise, it's OK.9657 // we must emit a compile error. Otherwise, it's OK.
9673 if (rhs_val.compareWithZero(.lt) != lhs_val.compareWithZero(.lt) and9658 if (rhs_val.compareWithZero(.lt) != lhs_val.compareWithZero(.lt) and
...@@ -9681,12 +9666,12 @@ fn analyzeArithmetic(...@@ -9681,12 +9666,12 @@ fn analyzeArithmetic(
9681 }9666 }
9682 if (lhs_val.compareWithZero(.lt)) {9667 if (lhs_val.compareWithZero(.lt)) {
9683 // Negative9668 // Negative
9684 return sema.addConstant(scalar_type, Value.zero);9669 return sema.addConstant(resolved_type, Value.zero);
9685 }9670 }
9686 return sema.addConstant(scalar_type, rem_result);9671 return sema.addConstant(resolved_type, rem_result);
9687 }9672 }
9688 break :rs .{ .src = lhs_src, .air_tag = .rem };9673 break :rs .{ .src = lhs_src, .air_tag = .rem };
9689 } else if (rhs_ty.isSignedInt()) {9674 } else if (rhs_scalar_ty.isSignedInt()) {
9690 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);9675 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
9691 } else {9676 } else {
9692 break :rs .{ .src = rhs_src, .air_tag = .rem };9677 break :rs .{ .src = rhs_src, .air_tag = .rem };
...@@ -9708,8 +9693,8 @@ fn analyzeArithmetic(...@@ -9708,8 +9693,8 @@ fn analyzeArithmetic(
9708 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);9693 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
9709 }9694 }
9710 return sema.addConstant(9695 return sema.addConstant(
9711 scalar_type,9696 resolved_type,
9712 try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),9697 try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target),
9713 );9698 );
9714 } else {9699 } else {
9715 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);9700 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
...@@ -9745,8 +9730,8 @@ fn analyzeArithmetic(...@@ -9745,8 +9730,8 @@ fn analyzeArithmetic(
9745 }9730 }
9746 if (maybe_lhs_val) |lhs_val| {9731 if (maybe_lhs_val) |lhs_val| {
9747 return sema.addConstant(9732 return sema.addConstant(
9748 scalar_type,9733 resolved_type,
9749 try lhs_val.intRem(rhs_val, sema.arena),9734 try lhs_val.intRem(rhs_val, resolved_type, sema.arena),
9750 );9735 );
9751 }9736 }
9752 break :rs .{ .src = lhs_src, .air_tag = .rem };9737 break :rs .{ .src = lhs_src, .air_tag = .rem };
...@@ -9765,12 +9750,12 @@ fn analyzeArithmetic(...@@ -9765,12 +9750,12 @@ fn analyzeArithmetic(
9765 }9750 }
9766 if (maybe_lhs_val) |lhs_val| {9751 if (maybe_lhs_val) |lhs_val| {
9767 if (lhs_val.isUndef()) {9752 if (lhs_val.isUndef()) {
9768 return sema.addConstUndef(scalar_type);9753 return sema.addConstUndef(resolved_type);
9769 }9754 }
9770 if (maybe_rhs_val) |rhs_val| {9755 if (maybe_rhs_val) |rhs_val| {
9771 return sema.addConstant(9756 return sema.addConstant(
9772 scalar_type,9757 resolved_type,
9773 try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),9758 try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target),
9774 );9759 );
9775 } else break :rs .{ .src = rhs_src, .air_tag = .rem };9760 } else break :rs .{ .src = rhs_src, .air_tag = .rem };
9776 } else break :rs .{ .src = lhs_src, .air_tag = .rem };9761 } else break :rs .{ .src = lhs_src, .air_tag = .rem };
...@@ -9802,8 +9787,8 @@ fn analyzeArithmetic(...@@ -9802,8 +9787,8 @@ fn analyzeArithmetic(
9802 }9787 }
9803 if (maybe_lhs_val) |lhs_val| {9788 if (maybe_lhs_val) |lhs_val| {
9804 return sema.addConstant(9789 return sema.addConstant(
9805 scalar_type,9790 resolved_type,
9806 try lhs_val.intMod(rhs_val, sema.arena),9791 try lhs_val.intMod(rhs_val, resolved_type, sema.arena),
9807 );9792 );
9808 }9793 }
9809 break :rs .{ .src = lhs_src, .air_tag = .mod };9794 break :rs .{ .src = lhs_src, .air_tag = .mod };
...@@ -9822,12 +9807,12 @@ fn analyzeArithmetic(...@@ -9822,12 +9807,12 @@ fn analyzeArithmetic(
9822 }9807 }
9823 if (maybe_lhs_val) |lhs_val| {9808 if (maybe_lhs_val) |lhs_val| {
9824 if (lhs_val.isUndef()) {9809 if (lhs_val.isUndef()) {
9825 return sema.addConstUndef(scalar_type);9810 return sema.addConstUndef(resolved_type);
9826 }9811 }
9827 if (maybe_rhs_val) |rhs_val| {9812 if (maybe_rhs_val) |rhs_val| {
9828 return sema.addConstant(9813 return sema.addConstant(
9829 scalar_type,9814 resolved_type,
9830 try lhs_val.floatMod(rhs_val, scalar_type, sema.arena, target),9815 try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target),
9831 );9816 );
9832 } else break :rs .{ .src = rhs_src, .air_tag = .mod };9817 } else break :rs .{ .src = rhs_src, .air_tag = .mod };
9833 } else break :rs .{ .src = lhs_src, .air_tag = .mod };9818 } else break :rs .{ .src = lhs_src, .air_tag = .mod };
...@@ -10178,6 +10163,11 @@ fn analyzeCmp(...@@ -10178,6 +10163,11 @@ fn analyzeCmp(
10178) CompileError!Air.Inst.Ref {10163) CompileError!Air.Inst.Ref {
10179 const lhs_ty = sema.typeOf(lhs);10164 const lhs_ty = sema.typeOf(lhs);
10180 const rhs_ty = sema.typeOf(rhs);10165 const rhs_ty = sema.typeOf(rhs);
10166 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
10167
10168 if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) {
10169 return sema.cmpVector(block, src, lhs, rhs, op, lhs_src, rhs_src);
10170 }
10181 if (lhs_ty.isNumeric() and rhs_ty.isNumeric()) {10171 if (lhs_ty.isNumeric() and rhs_ty.isNumeric()) {
10182 // This operation allows any combination of integer and float types, regardless of the10172 // This operation allows any combination of integer and float types, regardless of the
10183 // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for10173 // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for
...@@ -10212,6 +10202,12 @@ fn cmpSelf(...@@ -10212,6 +10202,12 @@ fn cmpSelf(
10212 if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {10202 if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {
10213 if (rhs_val.isUndef()) return sema.addConstUndef(Type.bool);10203 if (rhs_val.isUndef()) return sema.addConstUndef(Type.bool);
1021410204
10205 if (resolved_type.zigTypeTag() == .Vector) {
10206 const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.@"bool");
10207 const cmp_val = try lhs_val.compareVector(op, rhs_val, resolved_type, sema.arena);
10208 return sema.addConstant(result_ty, cmp_val);
10209 }
10210
10215 if (lhs_val.compare(op, rhs_val, resolved_type)) {10211 if (lhs_val.compare(op, rhs_val, resolved_type)) {
10216 return Air.Inst.Ref.bool_true;10212 return Air.Inst.Ref.bool_true;
10217 } else {10213 } else {
...@@ -10237,16 +10233,12 @@ fn cmpSelf(...@@ -10237,16 +10233,12 @@ fn cmpSelf(
10237 }10233 }
10238 };10234 };
10239 try sema.requireRuntimeBlock(block, runtime_src);10235 try sema.requireRuntimeBlock(block, runtime_src);
1024010236 if (resolved_type.zigTypeTag() == .Vector) {
10241 const tag: Air.Inst.Tag = switch (op) {10237 const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.@"bool");
10242 .lt => .cmp_lt,10238 const result_ty_ref = try sema.addType(result_ty);
10243 .lte => .cmp_lte,10239 return block.addCmpVector(casted_lhs, casted_rhs, op, result_ty_ref);
10244 .eq => .cmp_eq,10240 }
10245 .gte => .cmp_gte,10241 const tag = Air.Inst.Tag.fromCmpOp(op);
10246 .gt => .cmp_gt,
10247 .neq => .cmp_neq,
10248 };
10249 // TODO handle vectors
10250 return block.addBinOp(tag, casted_lhs, casted_rhs);10242 return block.addBinOp(tag, casted_lhs, casted_rhs);
10251}10243}
1025210244
...@@ -11367,7 +11359,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi...@@ -11367,7 +11359,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
11367 const elem_ty = operand.elemType2();11359 const elem_ty = operand.elemType2();
11368 const log2_elem_ty = try sema.log2IntType(block, elem_ty, src);11360 const log2_elem_ty = try sema.log2IntType(block, elem_ty, src);
11369 return Type.Tag.vector.create(sema.arena, .{11361 return Type.Tag.vector.create(sema.arena, .{
11370 .len = operand.arrayLen(),11362 .len = operand.vectorLen(),
11371 .elem_type = log2_elem_ty,11363 .elem_type = log2_elem_ty,
11372 });11364 });
11373 },11365 },
...@@ -13298,7 +13290,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -13298,7 +13290,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1329813290
13299 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {13291 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
13300 const target = sema.mod.getTarget();13292 const target = sema.mod.getTarget();
13301 const result_val = val.floatToInt(sema.arena, dest_ty, target) catch |err| switch (err) {13293 const result_val = val.floatToInt(sema.arena, operand_ty, dest_ty, target) catch |err| switch (err) {
13302 error.FloatCannotFit => {13294 error.FloatCannotFit => {
13303 return sema.fail(block, operand_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty });13295 return sema.fail(block, operand_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty });
13304 },13296 },
...@@ -13325,7 +13317,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -13325,7 +13317,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1332513317
13326 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {13318 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
13327 const target = sema.mod.getTarget();13319 const target = sema.mod.getTarget();
13328 const result_val = try val.intToFloat(sema.arena, dest_ty, target);13320 const result_val = try val.intToFloat(sema.arena, operand_ty, dest_ty, target);
13329 return sema.addConstant(dest_ty, result_val);13321 return sema.addConstant(dest_ty, result_val);
13330 }13322 }
1333113323
...@@ -13535,14 +13527,14 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13535,14 +13527,14 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13535 if (!is_vector) {13527 if (!is_vector) {
13536 return sema.addConstant(13528 return sema.addConstant(
13537 dest_ty,13529 dest_ty,
13538 try val.intTrunc(sema.arena, dest_info.signedness, dest_info.bits),13530 try val.intTrunc(operand_ty, sema.arena, dest_info.signedness, dest_info.bits),
13539 );13531 );
13540 }13532 }
13541 var elem_buf: Value.ElemValueBuffer = undefined;13533 var elem_buf: Value.ElemValueBuffer = undefined;
13542 const elems = try sema.arena.alloc(Value, operand_ty.vectorLen());13534 const elems = try sema.arena.alloc(Value, operand_ty.vectorLen());
13543 for (elems) |*elem, i| {13535 for (elems) |*elem, i| {
13544 const elem_val = val.elemValueBuffer(i, &elem_buf);13536 const elem_val = val.elemValueBuffer(i, &elem_buf);
13545 elem.* = try elem_val.intTrunc(sema.arena, dest_info.signedness, dest_info.bits);13537 elem.* = try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits);
13546 }13538 }
13547 return sema.addConstant(13539 return sema.addConstant(
13548 dest_ty,13540 dest_ty,
...@@ -14097,13 +14089,40 @@ fn checkSimdBinOp(...@@ -14097,13 +14089,40 @@ fn checkSimdBinOp(
14097) CompileError!SimdBinOp {14089) CompileError!SimdBinOp {
14098 const lhs_ty = sema.typeOf(uncasted_lhs);14090 const lhs_ty = sema.typeOf(uncasted_lhs);
14099 const rhs_ty = sema.typeOf(uncasted_rhs);14091 const rhs_ty = sema.typeOf(uncasted_rhs);
14100 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
14101 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
1410214092
14103 var vec_len: ?usize = null;14093 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14094 var vec_len: ?usize = if (lhs_ty.zigTypeTag() == .Vector) lhs_ty.vectorLen() else null;
14095 const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{
14096 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
14097 });
14098 const lhs = try sema.coerce(block, result_ty, uncasted_lhs, lhs_src);
14099 const rhs = try sema.coerce(block, result_ty, uncasted_rhs, rhs_src);
14100
14101 return SimdBinOp{
14102 .len = vec_len,
14103 .lhs = lhs,
14104 .rhs = rhs,
14105 .lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs),
14106 .rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs),
14107 .result_ty = result_ty,
14108 .scalar_ty = result_ty.scalarType(),
14109 };
14110}
14111
14112fn checkVectorizableBinaryOperands(
14113 sema: *Sema,
14114 block: *Block,
14115 src: LazySrcLoc,
14116 lhs_ty: Type,
14117 rhs_ty: Type,
14118 lhs_src: LazySrcLoc,
14119 rhs_src: LazySrcLoc,
14120) CompileError!void {
14121 const lhs_zig_ty_tag = lhs_ty.zigTypeTag();
14122 const rhs_zig_ty_tag = rhs_ty.zigTypeTag();
14104 if (lhs_zig_ty_tag == .Vector and rhs_zig_ty_tag == .Vector) {14123 if (lhs_zig_ty_tag == .Vector and rhs_zig_ty_tag == .Vector) {
14105 const lhs_len = lhs_ty.arrayLen();14124 const lhs_len = lhs_ty.vectorLen();
14106 const rhs_len = rhs_ty.arrayLen();14125 const rhs_len = rhs_ty.vectorLen();
14107 if (lhs_len != rhs_len) {14126 if (lhs_len != rhs_len) {
14108 const msg = msg: {14127 const msg = msg: {
14109 const msg = try sema.errMsg(block, src, "vector length mismatch", .{});14128 const msg = try sema.errMsg(block, src, "vector length mismatch", .{});
...@@ -14114,7 +14133,6 @@ fn checkSimdBinOp(...@@ -14114,7 +14133,6 @@ fn checkSimdBinOp(
14114 };14133 };
14115 return sema.failWithOwnedErrorMsg(block, msg);14134 return sema.failWithOwnedErrorMsg(block, msg);
14116 }14135 }
14117 vec_len = try sema.usizeCast(block, lhs_src, lhs_len);
14118 } else if (lhs_zig_ty_tag == .Vector or rhs_zig_ty_tag == .Vector) {14136 } else if (lhs_zig_ty_tag == .Vector or rhs_zig_ty_tag == .Vector) {
14119 const msg = msg: {14137 const msg = msg: {
14120 const msg = try sema.errMsg(block, src, "mixed scalar and vector operands: {} and {}", .{14138 const msg = try sema.errMsg(block, src, "mixed scalar and vector operands: {} and {}", .{
...@@ -14132,21 +14150,6 @@ fn checkSimdBinOp(...@@ -14132,21 +14150,6 @@ fn checkSimdBinOp(
14132 };14150 };
14133 return sema.failWithOwnedErrorMsg(block, msg);14151 return sema.failWithOwnedErrorMsg(block, msg);
14134 }14152 }
14135 const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{
14136 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
14137 });
14138 const lhs = try sema.coerce(block, result_ty, uncasted_lhs, lhs_src);
14139 const rhs = try sema.coerce(block, result_ty, uncasted_rhs, rhs_src);
14140
14141 return SimdBinOp{
14142 .len = vec_len,
14143 .lhs = lhs,
14144 .rhs = rhs,
14145 .lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs),
14146 .rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs),
14147 .result_ty = result_ty,
14148 .scalar_ty = result_ty.scalarType(),
14149 };
14150}14153}
1415114154
14152fn resolveExportOptions(14155fn resolveExportOptions(
...@@ -14376,9 +14379,9 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -14376,9 +14379,9 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
14376 while (i < vec_len) : (i += 1) {14379 while (i < vec_len) : (i += 1) {
14377 const elem_val = operand_val.elemValueBuffer(i, &elem_buf);14380 const elem_val = operand_val.elemValueBuffer(i, &elem_buf);
14378 switch (operation) {14381 switch (operation) {
14379 .And => accum = try accum.bitwiseAnd(elem_val, sema.arena),14382 .And => accum = try accum.bitwiseAnd(elem_val, scalar_ty, sema.arena),
14380 .Or => accum = try accum.bitwiseOr(elem_val, sema.arena),14383 .Or => accum = try accum.bitwiseOr(elem_val, scalar_ty, sema.arena),
14381 .Xor => accum = try accum.bitwiseXor(elem_val, sema.arena),14384 .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena),
14382 .Min => accum = accum.numberMin(elem_val),14385 .Min => accum = accum.numberMin(elem_val),
14383 .Max => accum = accum.numberMax(elem_val),14386 .Max => accum = accum.numberMax(elem_val),
14384 .Add => accum = try accum.numberAddWrap(elem_val, scalar_ty, sema.arena, target),14387 .Add => accum = try accum.numberAddWrap(elem_val, scalar_ty, sema.arena, target),
...@@ -14697,10 +14700,10 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -14697,10 +14700,10 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
14697 .Xchg => operand_val,14700 .Xchg => operand_val,
14698 .Add => try stored_val.numberAddWrap(operand_val, operand_ty, sema.arena, target),14701 .Add => try stored_val.numberAddWrap(operand_val, operand_ty, sema.arena, target),
14699 .Sub => try stored_val.numberSubWrap(operand_val, operand_ty, sema.arena, target),14702 .Sub => try stored_val.numberSubWrap(operand_val, operand_ty, sema.arena, target),
14700 .And => try stored_val.bitwiseAnd (operand_val, sema.arena),14703 .And => try stored_val.bitwiseAnd (operand_val, operand_ty, sema.arena),
14701 .Nand => try stored_val.bitwiseNand (operand_val, operand_ty, sema.arena, target),14704 .Nand => try stored_val.bitwiseNand (operand_val, operand_ty, sema.arena, target),
14702 .Or => try stored_val.bitwiseOr (operand_val, sema.arena),14705 .Or => try stored_val.bitwiseOr (operand_val, operand_ty, sema.arena),
14703 .Xor => try stored_val.bitwiseXor (operand_val, sema.arena),14706 .Xor => try stored_val.bitwiseXor (operand_val, operand_ty, sema.arena),
14704 .Max => stored_val.numberMax (operand_val),14707 .Max => stored_val.numberMax (operand_val),
14705 .Min => stored_val.numberMin (operand_val),14708 .Min => stored_val.numberMin (operand_val),
14706 // zig fmt: on14709 // zig fmt: on
...@@ -17523,7 +17526,7 @@ fn coerce(...@@ -17523,7 +17526,7 @@ fn coerce(
17523 if (val.floatHasFraction()) {17526 if (val.floatHasFraction()) {
17524 return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val.fmtValue(inst_ty), dest_ty });17527 return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val.fmtValue(inst_ty), dest_ty });
17525 }17528 }
17526 const result_val = val.floatToInt(sema.arena, dest_ty, target) catch |err| switch (err) {17529 const result_val = val.floatToInt(sema.arena, inst_ty, dest_ty, target) catch |err| switch (err) {
17527 error.FloatCannotFit => {17530 error.FloatCannotFit => {
17528 return sema.fail(block, inst_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty });17531 return sema.fail(block, inst_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty });
17529 },17532 },
...@@ -17586,7 +17589,7 @@ fn coerce(...@@ -17586,7 +17589,7 @@ fn coerce(
17586 },17589 },
17587 .Int, .ComptimeInt => int: {17590 .Int, .ComptimeInt => int: {
17588 const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse break :int;17591 const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse break :int;
17589 const result_val = try val.intToFloat(sema.arena, dest_ty, target);17592 const result_val = try val.intToFloat(sema.arena, inst_ty, dest_ty, target);
17590 // TODO implement this compile error17593 // TODO implement this compile error
17591 //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty);17594 //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty);
17592 //if (!int_again_val.eql(val, inst_ty)) {17595 //if (!int_again_val.eql(val, inst_ty)) {
...@@ -17823,8 +17826,21 @@ fn coerceInMemoryAllowed(...@@ -17823,8 +17826,21 @@ fn coerceInMemoryAllowed(
17823 return .ok;17826 return .ok;
17824 }17827 }
1782517828
17829 // Vectors
17830 if (dest_tag == .Vector and src_tag == .Vector) vectors: {
17831 const dest_len = dest_ty.vectorLen();
17832 const src_len = src_ty.vectorLen();
17833 if (dest_len != src_len) break :vectors;
17834
17835 const dest_elem_ty = dest_ty.scalarType();
17836 const src_elem_ty = src_ty.scalarType();
17837 const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src);
17838 if (child == .no_match) break :vectors;
17839
17840 return .ok;
17841 }
17842
17826 // TODO: non-pointer-like optionals17843 // TODO: non-pointer-like optionals
17827 // TODO: vectors
1782817844
17829 return .no_match;17845 return .no_match;
17830}17846}
...@@ -19697,19 +19713,6 @@ fn cmpNumeric(...@@ -19697,19 +19713,6 @@ fn cmpNumeric(
19697 const lhs_ty_tag = lhs_ty.zigTypeTag();19713 const lhs_ty_tag = lhs_ty.zigTypeTag();
19698 const rhs_ty_tag = rhs_ty.zigTypeTag();19714 const rhs_ty_tag = rhs_ty.zigTypeTag();
1969919715
19700 if (lhs_ty_tag == .Vector and rhs_ty_tag == .Vector) {
19701 if (lhs_ty.vectorLen() != rhs_ty.vectorLen()) {
19702 return sema.fail(block, src, "vector length mismatch: {d} and {d}", .{
19703 lhs_ty.vectorLen(), rhs_ty.vectorLen(),
19704 });
19705 }
19706 return sema.fail(block, src, "TODO implement support for vectors in cmpNumeric", .{});
19707 } else if (lhs_ty_tag == .Vector or rhs_ty_tag == .Vector) {
19708 return sema.fail(block, src, "mixed scalar and vector operands to comparison operator: '{}' and '{}'", .{
19709 lhs_ty, rhs_ty,
19710 });
19711 }
19712
19713 const runtime_src: LazySrcLoc = src: {19716 const runtime_src: LazySrcLoc = src: {
19714 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {19717 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
19715 if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {19718 if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
...@@ -19895,6 +19898,46 @@ fn cmpNumeric(...@@ -19895,6 +19898,46 @@ fn cmpNumeric(
19895 return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);19898 return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);
19896}19899}
1989719900
19901/// Asserts that lhs and rhs types are both vectors.
19902fn cmpVector(
19903 sema: *Sema,
19904 block: *Block,
19905 src: LazySrcLoc,
19906 lhs: Air.Inst.Ref,
19907 rhs: Air.Inst.Ref,
19908 op: std.math.CompareOperator,
19909 lhs_src: LazySrcLoc,
19910 rhs_src: LazySrcLoc,
19911) CompileError!Air.Inst.Ref {
19912 const lhs_ty = sema.typeOf(lhs);
19913 const rhs_ty = sema.typeOf(rhs);
19914 assert(lhs_ty.zigTypeTag() == .Vector);
19915 assert(rhs_ty.zigTypeTag() == .Vector);
19916 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
19917
19918 const result_ty = try Type.vector(sema.arena, lhs_ty.vectorLen(), Type.@"bool");
19919
19920 const runtime_src: LazySrcLoc = src: {
19921 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
19922 if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
19923 if (lhs_val.isUndef() or rhs_val.isUndef()) {
19924 return sema.addConstUndef(result_ty);
19925 }
19926 const cmp_val = try lhs_val.compareVector(op, rhs_val, lhs_ty, sema.arena);
19927 return sema.addConstant(result_ty, cmp_val);
19928 } else {
19929 break :src rhs_src;
19930 }
19931 } else {
19932 break :src lhs_src;
19933 }
19934 };
19935
19936 try sema.requireRuntimeBlock(block, runtime_src);
19937 const result_ty_inst = try sema.addType(result_ty);
19938 return block.addCmpVector(lhs, rhs, op, result_ty_inst);
19939}
19940
19898fn wrapOptional(19941fn wrapOptional(
19899 sema: *Sema,19942 sema: *Sema,
19900 block: *Block,19943 block: *Block,
...@@ -21201,7 +21244,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -21201,7 +21244,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
21201 map.putAssumeCapacityContext(copied_val, {}, .{ .ty = int_tag_ty });21244 map.putAssumeCapacityContext(copied_val, {}, .{ .ty = int_tag_ty });
21202 } else {21245 } else {
21203 const val = if (last_tag_val) |val|21246 const val = if (last_tag_val) |val|
21204 try val.intAdd(Value.one, sema.arena)21247 try val.intAdd(Value.one, int_tag_ty, sema.arena)
21205 else21248 else
21206 Value.zero;21249 Value.zero;
21207 last_tag_val = val;21250 last_tag_val = val;
src/value.zig+728-43
...@@ -1846,8 +1846,23 @@ pub const Value = extern union {...@@ -1846,8 +1846,23 @@ pub const Value = extern union {
1846 return order(lhs, rhs).compare(op);1846 return order(lhs, rhs).compare(op);
1847 }1847 }
18481848
1849 /// Asserts the value is comparable. Both operands have type `ty`.1849 /// Asserts the values are comparable. Both operands have type `ty`.
1850 /// Vector results will be reduced with AND.
1850 pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type) bool {1851 pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type) bool {
1852 if (ty.zigTypeTag() == .Vector) {
1853 var i: usize = 0;
1854 while (i < ty.vectorLen()) : (i += 1) {
1855 if (!compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType())) {
1856 return false;
1857 }
1858 }
1859 return true;
1860 }
1861 return compareScalar(lhs, op, rhs, ty);
1862 }
1863
1864 /// Asserts the values are comparable. Both operands have type `ty`.
1865 pub fn compareScalar(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type) bool {
1851 return switch (op) {1866 return switch (op) {
1852 .eq => lhs.eql(rhs, ty),1867 .eq => lhs.eql(rhs, ty),
1853 .neq => !lhs.eql(rhs, ty),1868 .neq => !lhs.eql(rhs, ty),
...@@ -1855,18 +1870,25 @@ pub const Value = extern union {...@@ -1855,18 +1870,25 @@ pub const Value = extern union {
1855 };1870 };
1856 }1871 }
18571872
1873 /// Asserts the values are comparable vectors of type `ty`.
1874 pub fn compareVector(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, allocator: Allocator) !Value {
1875 assert(ty.zigTypeTag() == .Vector);
1876 const result_data = try allocator.alloc(Value, ty.vectorLen());
1877 for (result_data) |*scalar, i| {
1878 const res_bool = compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType());
1879 scalar.* = if (res_bool) Value.@"true" else Value.@"false";
1880 }
1881 return Value.Tag.aggregate.create(allocator, result_data);
1882 }
1883
1858 /// Asserts the value is comparable.1884 /// Asserts the value is comparable.
1859 /// For vectors this is only valid with op == .eq.1885 /// Vector results will be reduced with AND.
1860 pub fn compareWithZero(lhs: Value, op: std.math.CompareOperator) bool {1886 pub fn compareWithZero(lhs: Value, op: std.math.CompareOperator) bool {
1861 switch (lhs.tag()) {1887 switch (lhs.tag()) {
1862 .repeated => {1888 .repeated => return lhs.castTag(.repeated).?.data.compareWithZero(op),
1863 assert(op == .eq);
1864 return lhs.castTag(.repeated).?.data.compareWithZero(.eq);
1865 },
1866 .aggregate => {1889 .aggregate => {
1867 assert(op == .eq);
1868 for (lhs.castTag(.aggregate).?.data) |elem_val| {1890 for (lhs.castTag(.aggregate).?.data) |elem_val| {
1869 if (!elem_val.compareWithZero(.eq)) return false;1891 if (!elem_val.compareWithZero(op)) return false;
1870 }1892 }
1871 return true;1893 return true;
1872 },1894 },
...@@ -2404,6 +2426,27 @@ pub const Value = extern union {...@@ -2404,6 +2426,27 @@ pub const Value = extern union {
2404 };2426 };
2405 }2427 }
24062428
2429 /// Index into a vector-like `Value`. Asserts `index` is a valid index for `val`.
2430 /// Some scalar values are considered vector-like to avoid needing to allocate
2431 /// a new `repeated` each time a constant is used.
2432 pub fn indexVectorlike(val: Value, index: usize) Value {
2433 return switch (val.tag()) {
2434 .aggregate => val.castTag(.aggregate).?.data[index],
2435
2436 .repeated => val.castTag(.repeated).?.data,
2437 // These values will implicitly be treated as `repeated`.
2438 .zero,
2439 .one,
2440 .bool_false,
2441 .bool_true,
2442 .int_i64,
2443 .int_u64,
2444 => val,
2445
2446 else => unreachable,
2447 };
2448 }
2449
2407 /// Asserts the value is a single-item pointer to an array, or an array,2450 /// Asserts the value is a single-item pointer to an array, or an array,
2408 /// or an unknown-length pointer, and returns the element value at the index.2451 /// or an unknown-length pointer, and returns the element value at the index.
2409 pub fn elemValue(val: Value, arena: Allocator, index: usize) !Value {2452 pub fn elemValue(val: Value, arena: Allocator, index: usize) !Value {
...@@ -2646,25 +2689,38 @@ pub const Value = extern union {...@@ -2646,25 +2689,38 @@ pub const Value = extern union {
2646 };2689 };
2647 }2690 }
26482691
2649 pub fn intToFloat(val: Value, arena: Allocator, dest_ty: Type, target: Target) !Value {2692 pub fn intToFloat(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target) !Value {
2693 if (int_ty.zigTypeTag() == .Vector) {
2694 const result_data = try arena.alloc(Value, int_ty.vectorLen());
2695 for (result_data) |*scalar, i| {
2696 scalar.* = try intToFloatScalar(val.indexVectorlike(i), arena, int_ty.scalarType(), float_ty.scalarType(), target);
2697 }
2698 return Value.Tag.aggregate.create(arena, result_data);
2699 }
2700 return intToFloatScalar(val, arena, int_ty, float_ty, target);
2701 }
2702
2703 pub fn intToFloatScalar(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target) !Value {
2704 assert(int_ty.isNumeric() and !int_ty.isAnyFloat());
2705 assert(float_ty.isAnyFloat());
2650 switch (val.tag()) {2706 switch (val.tag()) {
2651 .undef, .zero, .one => return val,2707 .undef, .zero, .one => return val,
2652 .the_only_possible_value => return Value.initTag(.zero), // for i0, u02708 .the_only_possible_value => return Value.initTag(.zero), // for i0, u0
2653 .int_u64 => {2709 .int_u64 => {
2654 return intToFloatInner(val.castTag(.int_u64).?.data, arena, dest_ty, target);2710 return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target);
2655 },2711 },
2656 .int_i64 => {2712 .int_i64 => {
2657 return intToFloatInner(val.castTag(.int_i64).?.data, arena, dest_ty, target);2713 return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target);
2658 },2714 },
2659 .int_big_positive => {2715 .int_big_positive => {
2660 const limbs = val.castTag(.int_big_positive).?.data;2716 const limbs = val.castTag(.int_big_positive).?.data;
2661 const float = bigIntToFloat(limbs, true);2717 const float = bigIntToFloat(limbs, true);
2662 return floatToValue(float, arena, dest_ty, target);2718 return floatToValue(float, arena, float_ty, target);
2663 },2719 },
2664 .int_big_negative => {2720 .int_big_negative => {
2665 const limbs = val.castTag(.int_big_negative).?.data;2721 const limbs = val.castTag(.int_big_negative).?.data;
2666 const float = bigIntToFloat(limbs, false);2722 const float = bigIntToFloat(limbs, false);
2667 return floatToValue(float, arena, dest_ty, target);2723 return floatToValue(float, arena, float_ty, target);
2668 },2724 },
2669 else => unreachable,2725 else => unreachable,
2670 }2726 }
...@@ -2694,7 +2750,20 @@ pub const Value = extern union {...@@ -2694,7 +2750,20 @@ pub const Value = extern union {
2694 }2750 }
2695 }2751 }
26962752
2697 pub fn floatToInt(val: Value, arena: Allocator, dest_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value {2753 pub fn floatToInt(val: Value, arena: Allocator, float_ty: Type, int_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value {
2754 if (float_ty.zigTypeTag() == .Vector) {
2755 const result_data = try arena.alloc(Value, float_ty.vectorLen());
2756 for (result_data) |*scalar, i| {
2757 scalar.* = try floatToIntScalar(val.indexVectorlike(i), arena, float_ty.scalarType(), int_ty.scalarType(), target);
2758 }
2759 return Value.Tag.aggregate.create(arena, result_data);
2760 }
2761 return floatToIntScalar(val, arena, float_ty, int_ty, target);
2762 }
2763
2764 pub fn floatToIntScalar(val: Value, arena: Allocator, float_ty: Type, int_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value {
2765 assert(float_ty.isAnyFloat());
2766 assert(int_ty.isInt());
2698 const Limb = std.math.big.Limb;2767 const Limb = std.math.big.Limb;
26992768
2700 var value = val.toFloat(f64); // TODO: f128 ?2769 var value = val.toFloat(f64); // TODO: f128 ?
...@@ -2724,7 +2793,7 @@ pub const Value = extern union {...@@ -2724,7 +2793,7 @@ pub const Value = extern union {
2724 else2793 else
2725 try Value.Tag.int_big_positive.create(arena, result_limbs);2794 try Value.Tag.int_big_positive.create(arena, result_limbs);
27262795
2727 if (result.intFitsInType(dest_ty, target)) {2796 if (result.intFitsInType(int_ty, target)) {
2728 return result;2797 return result;
2729 } else {2798 } else {
2730 return error.FloatCannotFit;2799 return error.FloatCannotFit;
...@@ -2771,18 +2840,36 @@ pub const Value = extern union {...@@ -2771,18 +2840,36 @@ pub const Value = extern union {
2771 };2840 };
2772 }2841 }
27732842
2774 /// Supports both floats and ints; handles undefined.2843 /// Supports both (vectors of) floats and ints; handles undefined scalars.
2775 pub fn numberAddWrap(2844 pub fn numberAddWrap(
2776 lhs: Value,2845 lhs: Value,
2777 rhs: Value,2846 rhs: Value,
2778 ty: Type,2847 ty: Type,
2779 arena: Allocator,2848 arena: Allocator,
2780 target: Target,2849 target: Target,
2850 ) !Value {
2851 if (ty.zigTypeTag() == .Vector) {
2852 const result_data = try arena.alloc(Value, ty.vectorLen());
2853 for (result_data) |*scalar, i| {
2854 scalar.* = try numberAddWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
2855 }
2856 return Value.Tag.aggregate.create(arena, result_data);
2857 }
2858 return numberAddWrapScalar(lhs, rhs, ty, arena, target);
2859 }
2860
2861 /// Supports both floats and ints; handles undefined.
2862 pub fn numberAddWrapScalar(
2863 lhs: Value,
2864 rhs: Value,
2865 ty: Type,
2866 arena: Allocator,
2867 target: Target,
2781 ) !Value {2868 ) !Value {
2782 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);2869 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
27832870
2784 if (ty.zigTypeTag() == .ComptimeInt) {2871 if (ty.zigTypeTag() == .ComptimeInt) {
2785 return intAdd(lhs, rhs, arena);2872 return intAdd(lhs, rhs, ty, arena);
2786 }2873 }
27872874
2788 if (ty.isAnyFloat()) {2875 if (ty.isAnyFloat()) {
...@@ -2809,13 +2896,31 @@ pub const Value = extern union {...@@ -2809,13 +2896,31 @@ pub const Value = extern union {
2809 }2896 }
2810 }2897 }
28112898
2812 /// Supports integers only; asserts neither operand is undefined.2899 /// Supports (vectors of) integers only; asserts neither operand is undefined.
2813 pub fn intAddSat(2900 pub fn intAddSat(
2814 lhs: Value,2901 lhs: Value,
2815 rhs: Value,2902 rhs: Value,
2816 ty: Type,2903 ty: Type,
2817 arena: Allocator,2904 arena: Allocator,
2818 target: Target,2905 target: Target,
2906 ) !Value {
2907 if (ty.zigTypeTag() == .Vector) {
2908 const result_data = try arena.alloc(Value, ty.vectorLen());
2909 for (result_data) |*scalar, i| {
2910 scalar.* = try intAddSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
2911 }
2912 return Value.Tag.aggregate.create(arena, result_data);
2913 }
2914 return intAddSatScalar(lhs, rhs, ty, arena, target);
2915 }
2916
2917 /// Supports integers only; asserts neither operand is undefined.
2918 pub fn intAddSatScalar(
2919 lhs: Value,
2920 rhs: Value,
2921 ty: Type,
2922 arena: Allocator,
2923 target: Target,
2819 ) !Value {2924 ) !Value {
2820 assert(!lhs.isUndef());2925 assert(!lhs.isUndef());
2821 assert(!rhs.isUndef());2926 assert(!rhs.isUndef());
...@@ -2861,18 +2966,36 @@ pub const Value = extern union {...@@ -2861,18 +2966,36 @@ pub const Value = extern union {
2861 };2966 };
2862 }2967 }
28632968
2864 /// Supports both floats and ints; handles undefined.2969 /// Supports both (vectors of) floats and ints; handles undefined scalars.
2865 pub fn numberSubWrap(2970 pub fn numberSubWrap(
2866 lhs: Value,2971 lhs: Value,
2867 rhs: Value,2972 rhs: Value,
2868 ty: Type,2973 ty: Type,
2869 arena: Allocator,2974 arena: Allocator,
2870 target: Target,2975 target: Target,
2976 ) !Value {
2977 if (ty.zigTypeTag() == .Vector) {
2978 const result_data = try arena.alloc(Value, ty.vectorLen());
2979 for (result_data) |*scalar, i| {
2980 scalar.* = try numberSubWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
2981 }
2982 return Value.Tag.aggregate.create(arena, result_data);
2983 }
2984 return numberSubWrapScalar(lhs, rhs, ty, arena, target);
2985 }
2986
2987 /// Supports both floats and ints; handles undefined.
2988 pub fn numberSubWrapScalar(
2989 lhs: Value,
2990 rhs: Value,
2991 ty: Type,
2992 arena: Allocator,
2993 target: Target,
2871 ) !Value {2994 ) !Value {
2872 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);2995 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
28732996
2874 if (ty.zigTypeTag() == .ComptimeInt) {2997 if (ty.zigTypeTag() == .ComptimeInt) {
2875 return intSub(lhs, rhs, arena);2998 return intSub(lhs, rhs, ty, arena);
2876 }2999 }
28773000
2878 if (ty.isAnyFloat()) {3001 if (ty.isAnyFloat()) {
...@@ -2883,13 +3006,31 @@ pub const Value = extern union {...@@ -2883,13 +3006,31 @@ pub const Value = extern union {
2883 return overflow_result.wrapped_result;3006 return overflow_result.wrapped_result;
2884 }3007 }
28853008
2886 /// Supports integers only; asserts neither operand is undefined.3009 /// Supports (vectors of) integers only; asserts neither operand is undefined.
2887 pub fn intSubSat(3010 pub fn intSubSat(
2888 lhs: Value,3011 lhs: Value,
2889 rhs: Value,3012 rhs: Value,
2890 ty: Type,3013 ty: Type,
2891 arena: Allocator,3014 arena: Allocator,
2892 target: Target,3015 target: Target,
3016 ) !Value {
3017 if (ty.zigTypeTag() == .Vector) {
3018 const result_data = try arena.alloc(Value, ty.vectorLen());
3019 for (result_data) |*scalar, i| {
3020 scalar.* = try intSubSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
3021 }
3022 return Value.Tag.aggregate.create(arena, result_data);
3023 }
3024 return intSubSatScalar(lhs, rhs, ty, arena, target);
3025 }
3026
3027 /// Supports integers only; asserts neither operand is undefined.
3028 pub fn intSubSatScalar(
3029 lhs: Value,
3030 rhs: Value,
3031 ty: Type,
3032 arena: Allocator,
3033 target: Target,
2893 ) !Value {3034 ) !Value {
2894 assert(!lhs.isUndef());3035 assert(!lhs.isUndef());
2895 assert(!rhs.isUndef());3036 assert(!rhs.isUndef());
...@@ -2944,18 +3085,36 @@ pub const Value = extern union {...@@ -2944,18 +3085,36 @@ pub const Value = extern union {
2944 };3085 };
2945 }3086 }
29463087
2947 /// Supports both floats and ints; handles undefined.3088 /// Supports both (vectors of) floats and ints; handles undefined scalars.
2948 pub fn numberMulWrap(3089 pub fn numberMulWrap(
2949 lhs: Value,3090 lhs: Value,
2950 rhs: Value,3091 rhs: Value,
2951 ty: Type,3092 ty: Type,
2952 arena: Allocator,3093 arena: Allocator,
2953 target: Target,3094 target: Target,
3095 ) !Value {
3096 if (ty.zigTypeTag() == .Vector) {
3097 const result_data = try arena.alloc(Value, ty.vectorLen());
3098 for (result_data) |*scalar, i| {
3099 scalar.* = try numberMulWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
3100 }
3101 return Value.Tag.aggregate.create(arena, result_data);
3102 }
3103 return numberMulWrapScalar(lhs, rhs, ty, arena, target);
3104 }
3105
3106 /// Supports both floats and ints; handles undefined.
3107 pub fn numberMulWrapScalar(
3108 lhs: Value,
3109 rhs: Value,
3110 ty: Type,
3111 arena: Allocator,
3112 target: Target,
2954 ) !Value {3113 ) !Value {
2955 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);3114 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
29563115
2957 if (ty.zigTypeTag() == .ComptimeInt) {3116 if (ty.zigTypeTag() == .ComptimeInt) {
2958 return intMul(lhs, rhs, arena);3117 return intMul(lhs, rhs, ty, arena);
2959 }3118 }
29603119
2961 if (ty.isAnyFloat()) {3120 if (ty.isAnyFloat()) {
...@@ -2966,13 +3125,31 @@ pub const Value = extern union {...@@ -2966,13 +3125,31 @@ pub const Value = extern union {
2966 return overflow_result.wrapped_result;3125 return overflow_result.wrapped_result;
2967 }3126 }
29683127
2969 /// Supports integers only; asserts neither operand is undefined.3128 /// Supports (vectors of) integers only; asserts neither operand is undefined.
2970 pub fn intMulSat(3129 pub fn intMulSat(
2971 lhs: Value,3130 lhs: Value,
2972 rhs: Value,3131 rhs: Value,
2973 ty: Type,3132 ty: Type,
2974 arena: Allocator,3133 arena: Allocator,
2975 target: Target,3134 target: Target,
3135 ) !Value {
3136 if (ty.zigTypeTag() == .Vector) {
3137 const result_data = try arena.alloc(Value, ty.vectorLen());
3138 for (result_data) |*scalar, i| {
3139 scalar.* = try intMulSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
3140 }
3141 return Value.Tag.aggregate.create(arena, result_data);
3142 }
3143 return intMulSatScalar(lhs, rhs, ty, arena, target);
3144 }
3145
3146 /// Supports (vectors of) integers only; asserts neither operand is undefined.
3147 pub fn intMulSatScalar(
3148 lhs: Value,
3149 rhs: Value,
3150 ty: Type,
3151 arena: Allocator,
3152 target: Target,
2976 ) !Value {3153 ) !Value {
2977 assert(!lhs.isUndef());3154 assert(!lhs.isUndef());
2978 assert(!rhs.isUndef());3155 assert(!rhs.isUndef());
...@@ -3025,8 +3202,20 @@ pub const Value = extern union {...@@ -3025,8 +3202,20 @@ pub const Value = extern union {
3025 };3202 };
3026 }3203 }
30273204
3028 /// operands must be integers; handles undefined.3205 /// operands must be (vectors of) integers; handles undefined scalars.
3029 pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, target: Target) !Value {3206 pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, target: Target) !Value {
3207 if (ty.zigTypeTag() == .Vector) {
3208 const result_data = try arena.alloc(Value, ty.vectorLen());
3209 for (result_data) |*scalar, i| {
3210 scalar.* = try bitwiseNotScalar(val.indexVectorlike(i), ty.scalarType(), arena, target);
3211 }
3212 return Value.Tag.aggregate.create(arena, result_data);
3213 }
3214 return bitwiseNotScalar(val, ty, arena, target);
3215 }
3216
3217 /// operands must be integers; handles undefined.
3218 pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, target: Target) !Value {
3030 if (val.isUndef()) return Value.initTag(.undef);3219 if (val.isUndef()) return Value.initTag(.undef);
30313220
3032 const info = ty.intInfo(target);3221 const info = ty.intInfo(target);
...@@ -3050,8 +3239,20 @@ pub const Value = extern union {...@@ -3050,8 +3239,20 @@ pub const Value = extern union {
3050 return fromBigInt(arena, result_bigint.toConst());3239 return fromBigInt(arena, result_bigint.toConst());
3051 }3240 }
30523241
3242 /// operands must be (vectors of) integers; handles undefined scalars.
3243 pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3244 if (ty.zigTypeTag() == .Vector) {
3245 const result_data = try allocator.alloc(Value, ty.vectorLen());
3246 for (result_data) |*scalar, i| {
3247 scalar.* = try bitwiseAndScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3248 }
3249 return Value.Tag.aggregate.create(allocator, result_data);
3250 }
3251 return bitwiseAndScalar(lhs, rhs, allocator);
3252 }
3253
3053 /// operands must be integers; handles undefined.3254 /// operands must be integers; handles undefined.
3054 pub fn bitwiseAnd(lhs: Value, rhs: Value, arena: Allocator) !Value {3255 pub fn bitwiseAndScalar(lhs: Value, rhs: Value, arena: Allocator) !Value {
3055 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);3256 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
30563257
3057 // TODO is this a performance issue? maybe we should try the operation without3258 // TODO is this a performance issue? maybe we should try the operation without
...@@ -3070,22 +3271,46 @@ pub const Value = extern union {...@@ -3070,22 +3271,46 @@ pub const Value = extern union {
3070 return fromBigInt(arena, result_bigint.toConst());3271 return fromBigInt(arena, result_bigint.toConst());
3071 }3272 }
30723273
3073 /// operands must be integers; handles undefined.3274 /// operands must be (vectors of) integers; handles undefined scalars.
3074 pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, target: Target) !Value {3275 pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, target: Target) !Value {
3276 if (ty.zigTypeTag() == .Vector) {
3277 const result_data = try arena.alloc(Value, ty.vectorLen());
3278 for (result_data) |*scalar, i| {
3279 scalar.* = try bitwiseNandScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
3280 }
3281 return Value.Tag.aggregate.create(arena, result_data);
3282 }
3283 return bitwiseNandScalar(lhs, rhs, ty, arena, target);
3284 }
3285
3286 /// operands must be integers; handles undefined.
3287 pub fn bitwiseNandScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, target: Target) !Value {
3075 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);3288 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
30763289
3077 const anded = try bitwiseAnd(lhs, rhs, arena);3290 const anded = try bitwiseAnd(lhs, rhs, ty, arena);
30783291
3079 const all_ones = if (ty.isSignedInt())3292 const all_ones = if (ty.isSignedInt())
3080 try Value.Tag.int_i64.create(arena, -1)3293 try Value.Tag.int_i64.create(arena, -1)
3081 else3294 else
3082 try ty.maxInt(arena, target);3295 try ty.maxInt(arena, target);
30833296
3084 return bitwiseXor(anded, all_ones, arena);3297 return bitwiseXor(anded, all_ones, ty, arena);
3298 }
3299
3300 /// operands must be (vectors of) integers; handles undefined scalars.
3301 pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3302 if (ty.zigTypeTag() == .Vector) {
3303 const result_data = try allocator.alloc(Value, ty.vectorLen());
3304 for (result_data) |*scalar, i| {
3305 scalar.* = try bitwiseOrScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3306 }
3307 return Value.Tag.aggregate.create(allocator, result_data);
3308 }
3309 return bitwiseOrScalar(lhs, rhs, allocator);
3085 }3310 }
30863311
3087 /// operands must be integers; handles undefined.3312 /// operands must be integers; handles undefined.
3088 pub fn bitwiseOr(lhs: Value, rhs: Value, arena: Allocator) !Value {3313 pub fn bitwiseOrScalar(lhs: Value, rhs: Value, arena: Allocator) !Value {
3089 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);3314 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
30903315
3091 // TODO is this a performance issue? maybe we should try the operation without3316 // TODO is this a performance issue? maybe we should try the operation without
...@@ -3103,8 +3328,20 @@ pub const Value = extern union {...@@ -3103,8 +3328,20 @@ pub const Value = extern union {
3103 return fromBigInt(arena, result_bigint.toConst());3328 return fromBigInt(arena, result_bigint.toConst());
3104 }3329 }
31053330
3331 /// operands must be (vectors of) integers; handles undefined scalars.
3332 pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3333 if (ty.zigTypeTag() == .Vector) {
3334 const result_data = try allocator.alloc(Value, ty.vectorLen());
3335 for (result_data) |*scalar, i| {
3336 scalar.* = try bitwiseXorScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3337 }
3338 return Value.Tag.aggregate.create(allocator, result_data);
3339 }
3340 return bitwiseXorScalar(lhs, rhs, allocator);
3341 }
3342
3106 /// operands must be integers; handles undefined.3343 /// operands must be integers; handles undefined.
3107 pub fn bitwiseXor(lhs: Value, rhs: Value, arena: Allocator) !Value {3344 pub fn bitwiseXorScalar(lhs: Value, rhs: Value, arena: Allocator) !Value {
3108 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);3345 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
31093346
3110 // TODO is this a performance issue? maybe we should try the operation without3347 // TODO is this a performance issue? maybe we should try the operation without
...@@ -3123,7 +3360,18 @@ pub const Value = extern union {...@@ -3123,7 +3360,18 @@ pub const Value = extern union {
3123 return fromBigInt(arena, result_bigint.toConst());3360 return fromBigInt(arena, result_bigint.toConst());
3124 }3361 }
31253362
3126 pub fn intAdd(lhs: Value, rhs: Value, allocator: Allocator) !Value {3363 pub fn intAdd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3364 if (ty.zigTypeTag() == .Vector) {
3365 const result_data = try allocator.alloc(Value, ty.vectorLen());
3366 for (result_data) |*scalar, i| {
3367 scalar.* = try intAddScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3368 }
3369 return Value.Tag.aggregate.create(allocator, result_data);
3370 }
3371 return intAddScalar(lhs, rhs, allocator);
3372 }
3373
3374 pub fn intAddScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
3127 // TODO is this a performance issue? maybe we should try the operation without3375 // TODO is this a performance issue? maybe we should try the operation without
3128 // resorting to BigInt first.3376 // resorting to BigInt first.
3129 var lhs_space: Value.BigIntSpace = undefined;3377 var lhs_space: Value.BigIntSpace = undefined;
...@@ -3139,7 +3387,18 @@ pub const Value = extern union {...@@ -3139,7 +3387,18 @@ pub const Value = extern union {
3139 return fromBigInt(allocator, result_bigint.toConst());3387 return fromBigInt(allocator, result_bigint.toConst());
3140 }3388 }
31413389
3142 pub fn intSub(lhs: Value, rhs: Value, allocator: Allocator) !Value {3390 pub fn intSub(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3391 if (ty.zigTypeTag() == .Vector) {
3392 const result_data = try allocator.alloc(Value, ty.vectorLen());
3393 for (result_data) |*scalar, i| {
3394 scalar.* = try intSubScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3395 }
3396 return Value.Tag.aggregate.create(allocator, result_data);
3397 }
3398 return intSubScalar(lhs, rhs, allocator);
3399 }
3400
3401 pub fn intSubScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
3143 // TODO is this a performance issue? maybe we should try the operation without3402 // TODO is this a performance issue? maybe we should try the operation without
3144 // resorting to BigInt first.3403 // resorting to BigInt first.
3145 var lhs_space: Value.BigIntSpace = undefined;3404 var lhs_space: Value.BigIntSpace = undefined;
...@@ -3155,7 +3414,18 @@ pub const Value = extern union {...@@ -3155,7 +3414,18 @@ pub const Value = extern union {
3155 return fromBigInt(allocator, result_bigint.toConst());3414 return fromBigInt(allocator, result_bigint.toConst());
3156 }3415 }
31573416
3158 pub fn intDiv(lhs: Value, rhs: Value, allocator: Allocator) !Value {3417 pub fn intDiv(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3418 if (ty.zigTypeTag() == .Vector) {
3419 const result_data = try allocator.alloc(Value, ty.vectorLen());
3420 for (result_data) |*scalar, i| {
3421 scalar.* = try intDivScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3422 }
3423 return Value.Tag.aggregate.create(allocator, result_data);
3424 }
3425 return intDivScalar(lhs, rhs, allocator);
3426 }
3427
3428 pub fn intDivScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
3159 // TODO is this a performance issue? maybe we should try the operation without3429 // TODO is this a performance issue? maybe we should try the operation without
3160 // resorting to BigInt first.3430 // resorting to BigInt first.
3161 var lhs_space: Value.BigIntSpace = undefined;3431 var lhs_space: Value.BigIntSpace = undefined;
...@@ -3180,7 +3450,18 @@ pub const Value = extern union {...@@ -3180,7 +3450,18 @@ pub const Value = extern union {
3180 return fromBigInt(allocator, result_q.toConst());3450 return fromBigInt(allocator, result_q.toConst());
3181 }3451 }
31823452
3183 pub fn intDivFloor(lhs: Value, rhs: Value, allocator: Allocator) !Value {3453 pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3454 if (ty.zigTypeTag() == .Vector) {
3455 const result_data = try allocator.alloc(Value, ty.vectorLen());
3456 for (result_data) |*scalar, i| {
3457 scalar.* = try intDivFloorScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3458 }
3459 return Value.Tag.aggregate.create(allocator, result_data);
3460 }
3461 return intDivFloorScalar(lhs, rhs, allocator);
3462 }
3463
3464 pub fn intDivFloorScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
3184 // TODO is this a performance issue? maybe we should try the operation without3465 // TODO is this a performance issue? maybe we should try the operation without
3185 // resorting to BigInt first.3466 // resorting to BigInt first.
3186 var lhs_space: Value.BigIntSpace = undefined;3467 var lhs_space: Value.BigIntSpace = undefined;
...@@ -3205,7 +3486,18 @@ pub const Value = extern union {...@@ -3205,7 +3486,18 @@ pub const Value = extern union {
3205 return fromBigInt(allocator, result_q.toConst());3486 return fromBigInt(allocator, result_q.toConst());
3206 }3487 }
32073488
3208 pub fn intRem(lhs: Value, rhs: Value, allocator: Allocator) !Value {3489 pub fn intRem(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3490 if (ty.zigTypeTag() == .Vector) {
3491 const result_data = try allocator.alloc(Value, ty.vectorLen());
3492 for (result_data) |*scalar, i| {
3493 scalar.* = try intRemScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3494 }
3495 return Value.Tag.aggregate.create(allocator, result_data);
3496 }
3497 return intRemScalar(lhs, rhs, allocator);
3498 }
3499
3500 pub fn intRemScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
3209 // TODO is this a performance issue? maybe we should try the operation without3501 // TODO is this a performance issue? maybe we should try the operation without
3210 // resorting to BigInt first.3502 // resorting to BigInt first.
3211 var lhs_space: Value.BigIntSpace = undefined;3503 var lhs_space: Value.BigIntSpace = undefined;
...@@ -3232,7 +3524,18 @@ pub const Value = extern union {...@@ -3232,7 +3524,18 @@ pub const Value = extern union {
3232 return fromBigInt(allocator, result_r.toConst());3524 return fromBigInt(allocator, result_r.toConst());
3233 }3525 }
32343526
3235 pub fn intMod(lhs: Value, rhs: Value, allocator: Allocator) !Value {3527 pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3528 if (ty.zigTypeTag() == .Vector) {
3529 const result_data = try allocator.alloc(Value, ty.vectorLen());
3530 for (result_data) |*scalar, i| {
3531 scalar.* = try intModScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3532 }
3533 return Value.Tag.aggregate.create(allocator, result_data);
3534 }
3535 return intModScalar(lhs, rhs, allocator);
3536 }
3537
3538 pub fn intModScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
3236 // TODO is this a performance issue? maybe we should try the operation without3539 // TODO is this a performance issue? maybe we should try the operation without
3237 // resorting to BigInt first.3540 // resorting to BigInt first.
3238 var lhs_space: Value.BigIntSpace = undefined;3541 var lhs_space: Value.BigIntSpace = undefined;
...@@ -3270,6 +3573,17 @@ pub const Value = extern union {...@@ -3270,6 +3573,17 @@ pub const Value = extern union {
3270 }3573 }
32713574
3272 pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {3575 pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
3576 if (float_type.zigTypeTag() == .Vector) {
3577 const result_data = try arena.alloc(Value, float_type.vectorLen());
3578 for (result_data) |*scalar, i| {
3579 scalar.* = try floatRemScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
3580 }
3581 return Value.Tag.aggregate.create(arena, result_data);
3582 }
3583 return floatRemScalar(lhs, rhs, float_type, arena, target);
3584 }
3585
3586 pub fn floatRemScalar(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
3273 switch (float_type.floatBits(target)) {3587 switch (float_type.floatBits(target)) {
3274 16 => {3588 16 => {
3275 const lhs_val = lhs.toFloat(f16);3589 const lhs_val = lhs.toFloat(f16);
...@@ -3304,6 +3618,17 @@ pub const Value = extern union {...@@ -3304,6 +3618,17 @@ pub const Value = extern union {
3304 }3618 }
33053619
3306 pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {3620 pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
3621 if (float_type.zigTypeTag() == .Vector) {
3622 const result_data = try arena.alloc(Value, float_type.vectorLen());
3623 for (result_data) |*scalar, i| {
3624 scalar.* = try floatModScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
3625 }
3626 return Value.Tag.aggregate.create(arena, result_data);
3627 }
3628 return floatModScalar(lhs, rhs, float_type, arena, target);
3629 }
3630
3631 pub fn floatModScalar(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
3307 switch (float_type.floatBits(target)) {3632 switch (float_type.floatBits(target)) {
3308 16 => {3633 16 => {
3309 const lhs_val = lhs.toFloat(f16);3634 const lhs_val = lhs.toFloat(f16);
...@@ -3337,7 +3662,18 @@ pub const Value = extern union {...@@ -3337,7 +3662,18 @@ pub const Value = extern union {
3337 }3662 }
3338 }3663 }
33393664
3340 pub fn intMul(lhs: Value, rhs: Value, allocator: Allocator) !Value {3665 pub fn intMul(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3666 if (ty.zigTypeTag() == .Vector) {
3667 const result_data = try allocator.alloc(Value, ty.vectorLen());
3668 for (result_data) |*scalar, i| {
3669 scalar.* = try intMulScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3670 }
3671 return Value.Tag.aggregate.create(allocator, result_data);
3672 }
3673 return intMulScalar(lhs, rhs, allocator);
3674 }
3675
3676 pub fn intMulScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
3341 // TODO is this a performance issue? maybe we should try the operation without3677 // TODO is this a performance issue? maybe we should try the operation without
3342 // resorting to BigInt first.3678 // resorting to BigInt first.
3343 var lhs_space: Value.BigIntSpace = undefined;3679 var lhs_space: Value.BigIntSpace = undefined;
...@@ -3358,7 +3694,30 @@ pub const Value = extern union {...@@ -3358,7 +3694,30 @@ pub const Value = extern union {
3358 return fromBigInt(allocator, result_bigint.toConst());3694 return fromBigInt(allocator, result_bigint.toConst());
3359 }3695 }
33603696
3361 pub fn intTrunc(val: Value, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16) !Value {3697 pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16) !Value {
3698 if (ty.zigTypeTag() == .Vector) {
3699 const result_data = try allocator.alloc(Value, ty.vectorLen());
3700 for (result_data) |*scalar, i| {
3701 scalar.* = try intTruncScalar(val.indexVectorlike(i), allocator, signedness, bits);
3702 }
3703 return Value.Tag.aggregate.create(allocator, result_data);
3704 }
3705 return intTruncScalar(val, allocator, signedness, bits);
3706 }
3707
3708 /// This variant may vectorize on `bits`. Asserts that `bits` is a (vector of) `u16`.
3709 pub fn intTruncBitsAsValue(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: Value) !Value {
3710 if (ty.zigTypeTag() == .Vector) {
3711 const result_data = try allocator.alloc(Value, ty.vectorLen());
3712 for (result_data) |*scalar, i| {
3713 scalar.* = try intTruncScalar(val.indexVectorlike(i), allocator, signedness, @intCast(u16, bits.indexVectorlike(i).toUnsignedInt()));
3714 }
3715 return Value.Tag.aggregate.create(allocator, result_data);
3716 }
3717 return intTruncScalar(val, allocator, signedness, @intCast(u16, bits.toUnsignedInt()));
3718 }
3719
3720 pub fn intTruncScalar(val: Value, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16) !Value {
3362 if (bits == 0) return Value.zero;3721 if (bits == 0) return Value.zero;
33633722
3364 var val_space: Value.BigIntSpace = undefined;3723 var val_space: Value.BigIntSpace = undefined;
...@@ -3374,7 +3733,18 @@ pub const Value = extern union {...@@ -3374,7 +3733,18 @@ pub const Value = extern union {
3374 return fromBigInt(allocator, result_bigint.toConst());3733 return fromBigInt(allocator, result_bigint.toConst());
3375 }3734 }
33763735
3377 pub fn shl(lhs: Value, rhs: Value, allocator: Allocator) !Value {3736 pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3737 if (ty.zigTypeTag() == .Vector) {
3738 const result_data = try allocator.alloc(Value, ty.vectorLen());
3739 for (result_data) |*scalar, i| {
3740 scalar.* = try shlScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3741 }
3742 return Value.Tag.aggregate.create(allocator, result_data);
3743 }
3744 return shlScalar(lhs, rhs, allocator);
3745 }
3746
3747 pub fn shlScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
3378 // TODO is this a performance issue? maybe we should try the operation without3748 // TODO is this a performance issue? maybe we should try the operation without
3379 // resorting to BigInt first.3749 // resorting to BigInt first.
3380 var lhs_space: Value.BigIntSpace = undefined;3750 var lhs_space: Value.BigIntSpace = undefined;
...@@ -3430,6 +3800,23 @@ pub const Value = extern union {...@@ -3430,6 +3800,23 @@ pub const Value = extern union {
3430 ty: Type,3800 ty: Type,
3431 arena: Allocator,3801 arena: Allocator,
3432 target: Target,3802 target: Target,
3803 ) !Value {
3804 if (ty.zigTypeTag() == .Vector) {
3805 const result_data = try arena.alloc(Value, ty.vectorLen());
3806 for (result_data) |*scalar, i| {
3807 scalar.* = try shlSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
3808 }
3809 return Value.Tag.aggregate.create(arena, result_data);
3810 }
3811 return shlSatScalar(lhs, rhs, ty, arena, target);
3812 }
3813
3814 pub fn shlSatScalar(
3815 lhs: Value,
3816 rhs: Value,
3817 ty: Type,
3818 arena: Allocator,
3819 target: Target,
3433 ) !Value {3820 ) !Value {
3434 // TODO is this a performance issue? maybe we should try the operation without3821 // TODO is this a performance issue? maybe we should try the operation without
3435 // resorting to BigInt first.3822 // resorting to BigInt first.
...@@ -3458,13 +3845,41 @@ pub const Value = extern union {...@@ -3458,13 +3845,41 @@ pub const Value = extern union {
3458 arena: Allocator,3845 arena: Allocator,
3459 target: Target,3846 target: Target,
3460 ) !Value {3847 ) !Value {
3461 const shifted = try lhs.shl(rhs, arena);3848 if (ty.zigTypeTag() == .Vector) {
3849 const result_data = try arena.alloc(Value, ty.vectorLen());
3850 for (result_data) |*scalar, i| {
3851 scalar.* = try shlTruncScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
3852 }
3853 return Value.Tag.aggregate.create(arena, result_data);
3854 }
3855 return shlTruncScalar(lhs, rhs, ty, arena, target);
3856 }
3857
3858 pub fn shlTruncScalar(
3859 lhs: Value,
3860 rhs: Value,
3861 ty: Type,
3862 arena: Allocator,
3863 target: Target,
3864 ) !Value {
3865 const shifted = try lhs.shl(rhs, ty, arena);
3462 const int_info = ty.intInfo(target);3866 const int_info = ty.intInfo(target);
3463 const truncated = try shifted.intTrunc(arena, int_info.signedness, int_info.bits);3867 const truncated = try shifted.intTrunc(ty, arena, int_info.signedness, int_info.bits);
3464 return truncated;3868 return truncated;
3465 }3869 }
34663870
3467 pub fn shr(lhs: Value, rhs: Value, allocator: Allocator) !Value {3871 pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
3872 if (ty.zigTypeTag() == .Vector) {
3873 const result_data = try allocator.alloc(Value, ty.vectorLen());
3874 for (result_data) |*scalar, i| {
3875 scalar.* = try shrScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
3876 }
3877 return Value.Tag.aggregate.create(allocator, result_data);
3878 }
3879 return shrScalar(lhs, rhs, allocator);
3880 }
3881
3882 pub fn shrScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
3468 // TODO is this a performance issue? maybe we should try the operation without3883 // TODO is this a performance issue? maybe we should try the operation without
3469 // resorting to BigInt first.3884 // resorting to BigInt first.
3470 var lhs_space: Value.BigIntSpace = undefined;3885 var lhs_space: Value.BigIntSpace = undefined;
...@@ -3497,6 +3912,23 @@ pub const Value = extern union {...@@ -3497,6 +3912,23 @@ pub const Value = extern union {
3497 float_type: Type,3912 float_type: Type,
3498 arena: Allocator,3913 arena: Allocator,
3499 target: Target,3914 target: Target,
3915 ) !Value {
3916 if (float_type.zigTypeTag() == .Vector) {
3917 const result_data = try arena.alloc(Value, float_type.vectorLen());
3918 for (result_data) |*scalar, i| {
3919 scalar.* = try floatAddScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
3920 }
3921 return Value.Tag.aggregate.create(arena, result_data);
3922 }
3923 return floatAddScalar(lhs, rhs, float_type, arena, target);
3924 }
3925
3926 pub fn floatAddScalar(
3927 lhs: Value,
3928 rhs: Value,
3929 float_type: Type,
3930 arena: Allocator,
3931 target: Target,
3500 ) !Value {3932 ) !Value {
3501 switch (float_type.floatBits(target)) {3933 switch (float_type.floatBits(target)) {
3502 16 => {3934 16 => {
...@@ -3534,6 +3966,23 @@ pub const Value = extern union {...@@ -3534,6 +3966,23 @@ pub const Value = extern union {
3534 float_type: Type,3966 float_type: Type,
3535 arena: Allocator,3967 arena: Allocator,
3536 target: Target,3968 target: Target,
3969 ) !Value {
3970 if (float_type.zigTypeTag() == .Vector) {
3971 const result_data = try arena.alloc(Value, float_type.vectorLen());
3972 for (result_data) |*scalar, i| {
3973 scalar.* = try floatSubScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
3974 }
3975 return Value.Tag.aggregate.create(arena, result_data);
3976 }
3977 return floatSubScalar(lhs, rhs, float_type, arena, target);
3978 }
3979
3980 pub fn floatSubScalar(
3981 lhs: Value,
3982 rhs: Value,
3983 float_type: Type,
3984 arena: Allocator,
3985 target: Target,
3537 ) !Value {3986 ) !Value {
3538 switch (float_type.floatBits(target)) {3987 switch (float_type.floatBits(target)) {
3539 16 => {3988 16 => {
...@@ -3571,6 +4020,23 @@ pub const Value = extern union {...@@ -3571,6 +4020,23 @@ pub const Value = extern union {
3571 float_type: Type,4020 float_type: Type,
3572 arena: Allocator,4021 arena: Allocator,
3573 target: Target,4022 target: Target,
4023 ) !Value {
4024 if (float_type.zigTypeTag() == .Vector) {
4025 const result_data = try arena.alloc(Value, float_type.vectorLen());
4026 for (result_data) |*scalar, i| {
4027 scalar.* = try floatDivScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
4028 }
4029 return Value.Tag.aggregate.create(arena, result_data);
4030 }
4031 return floatDivScalar(lhs, rhs, float_type, arena, target);
4032 }
4033
4034 pub fn floatDivScalar(
4035 lhs: Value,
4036 rhs: Value,
4037 float_type: Type,
4038 arena: Allocator,
4039 target: Target,
3574 ) !Value {4040 ) !Value {
3575 switch (float_type.floatBits(target)) {4041 switch (float_type.floatBits(target)) {
3576 16 => {4042 16 => {
...@@ -3611,6 +4077,23 @@ pub const Value = extern union {...@@ -3611,6 +4077,23 @@ pub const Value = extern union {
3611 float_type: Type,4077 float_type: Type,
3612 arena: Allocator,4078 arena: Allocator,
3613 target: Target,4079 target: Target,
4080 ) !Value {
4081 if (float_type.zigTypeTag() == .Vector) {
4082 const result_data = try arena.alloc(Value, float_type.vectorLen());
4083 for (result_data) |*scalar, i| {
4084 scalar.* = try floatDivFloorScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
4085 }
4086 return Value.Tag.aggregate.create(arena, result_data);
4087 }
4088 return floatDivFloorScalar(lhs, rhs, float_type, arena, target);
4089 }
4090
4091 pub fn floatDivFloorScalar(
4092 lhs: Value,
4093 rhs: Value,
4094 float_type: Type,
4095 arena: Allocator,
4096 target: Target,
3614 ) !Value {4097 ) !Value {
3615 switch (float_type.floatBits(target)) {4098 switch (float_type.floatBits(target)) {
3616 16 => {4099 16 => {
...@@ -3651,6 +4134,23 @@ pub const Value = extern union {...@@ -3651,6 +4134,23 @@ pub const Value = extern union {
3651 float_type: Type,4134 float_type: Type,
3652 arena: Allocator,4135 arena: Allocator,
3653 target: Target,4136 target: Target,
4137 ) !Value {
4138 if (float_type.zigTypeTag() == .Vector) {
4139 const result_data = try arena.alloc(Value, float_type.vectorLen());
4140 for (result_data) |*scalar, i| {
4141 scalar.* = try floatDivTruncScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
4142 }
4143 return Value.Tag.aggregate.create(arena, result_data);
4144 }
4145 return floatDivTruncScalar(lhs, rhs, float_type, arena, target);
4146 }
4147
4148 pub fn floatDivTruncScalar(
4149 lhs: Value,
4150 rhs: Value,
4151 float_type: Type,
4152 arena: Allocator,
4153 target: Target,
3654 ) !Value {4154 ) !Value {
3655 switch (float_type.floatBits(target)) {4155 switch (float_type.floatBits(target)) {
3656 16 => {4156 16 => {
...@@ -3691,6 +4191,23 @@ pub const Value = extern union {...@@ -3691,6 +4191,23 @@ pub const Value = extern union {
3691 float_type: Type,4191 float_type: Type,
3692 arena: Allocator,4192 arena: Allocator,
3693 target: Target,4193 target: Target,
4194 ) !Value {
4195 if (float_type.zigTypeTag() == .Vector) {
4196 const result_data = try arena.alloc(Value, float_type.vectorLen());
4197 for (result_data) |*scalar, i| {
4198 scalar.* = try floatMulScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
4199 }
4200 return Value.Tag.aggregate.create(arena, result_data);
4201 }
4202 return floatMulScalar(lhs, rhs, float_type, arena, target);
4203 }
4204
4205 pub fn floatMulScalar(
4206 lhs: Value,
4207 rhs: Value,
4208 float_type: Type,
4209 arena: Allocator,
4210 target: Target,
3694 ) !Value {4211 ) !Value {
3695 switch (float_type.floatBits(target)) {4212 switch (float_type.floatBits(target)) {
3696 16 => {4213 16 => {
...@@ -3726,6 +4243,17 @@ pub const Value = extern union {...@@ -3726,6 +4243,17 @@ pub const Value = extern union {
3726 }4243 }
37274244
3728 pub fn sqrt(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4245 pub fn sqrt(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4246 if (float_type.zigTypeTag() == .Vector) {
4247 const result_data = try arena.alloc(Value, float_type.vectorLen());
4248 for (result_data) |*scalar, i| {
4249 scalar.* = try sqrtScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4250 }
4251 return Value.Tag.aggregate.create(arena, result_data);
4252 }
4253 return sqrtScalar(val, float_type, arena, target);
4254 }
4255
4256 pub fn sqrtScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
3729 switch (float_type.floatBits(target)) {4257 switch (float_type.floatBits(target)) {
3730 16 => {4258 16 => {
3731 const f = val.toFloat(f16);4259 const f = val.toFloat(f16);
...@@ -3758,6 +4286,17 @@ pub const Value = extern union {...@@ -3758,6 +4286,17 @@ pub const Value = extern union {
3758 }4286 }
37594287
3760 pub fn sin(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4288 pub fn sin(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4289 if (float_type.zigTypeTag() == .Vector) {
4290 const result_data = try arena.alloc(Value, float_type.vectorLen());
4291 for (result_data) |*scalar, i| {
4292 scalar.* = try sinScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4293 }
4294 return Value.Tag.aggregate.create(arena, result_data);
4295 }
4296 return sinScalar(val, float_type, arena, target);
4297 }
4298
4299 pub fn sinScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
3761 switch (float_type.floatBits(target)) {4300 switch (float_type.floatBits(target)) {
3762 16 => {4301 16 => {
3763 const f = val.toFloat(f16);4302 const f = val.toFloat(f16);
...@@ -3790,6 +4329,17 @@ pub const Value = extern union {...@@ -3790,6 +4329,17 @@ pub const Value = extern union {
3790 }4329 }
37914330
3792 pub fn cos(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4331 pub fn cos(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4332 if (float_type.zigTypeTag() == .Vector) {
4333 const result_data = try arena.alloc(Value, float_type.vectorLen());
4334 for (result_data) |*scalar, i| {
4335 scalar.* = try cosScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4336 }
4337 return Value.Tag.aggregate.create(arena, result_data);
4338 }
4339 return cosScalar(val, float_type, arena, target);
4340 }
4341
4342 pub fn cosScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
3793 switch (float_type.floatBits(target)) {4343 switch (float_type.floatBits(target)) {
3794 16 => {4344 16 => {
3795 const f = val.toFloat(f16);4345 const f = val.toFloat(f16);
...@@ -3822,6 +4372,17 @@ pub const Value = extern union {...@@ -3822,6 +4372,17 @@ pub const Value = extern union {
3822 }4372 }
38234373
3824 pub fn exp(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4374 pub fn exp(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4375 if (float_type.zigTypeTag() == .Vector) {
4376 const result_data = try arena.alloc(Value, float_type.vectorLen());
4377 for (result_data) |*scalar, i| {
4378 scalar.* = try expScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4379 }
4380 return Value.Tag.aggregate.create(arena, result_data);
4381 }
4382 return expScalar(val, float_type, arena, target);
4383 }
4384
4385 pub fn expScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
3825 switch (float_type.floatBits(target)) {4386 switch (float_type.floatBits(target)) {
3826 16 => {4387 16 => {
3827 const f = val.toFloat(f16);4388 const f = val.toFloat(f16);
...@@ -3854,6 +4415,17 @@ pub const Value = extern union {...@@ -3854,6 +4415,17 @@ pub const Value = extern union {
3854 }4415 }
38554416
3856 pub fn exp2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4417 pub fn exp2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4418 if (float_type.zigTypeTag() == .Vector) {
4419 const result_data = try arena.alloc(Value, float_type.vectorLen());
4420 for (result_data) |*scalar, i| {
4421 scalar.* = try exp2Scalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4422 }
4423 return Value.Tag.aggregate.create(arena, result_data);
4424 }
4425 return exp2Scalar(val, float_type, arena, target);
4426 }
4427
4428 pub fn exp2Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
3857 switch (float_type.floatBits(target)) {4429 switch (float_type.floatBits(target)) {
3858 16 => {4430 16 => {
3859 const f = val.toFloat(f16);4431 const f = val.toFloat(f16);
...@@ -3886,6 +4458,17 @@ pub const Value = extern union {...@@ -3886,6 +4458,17 @@ pub const Value = extern union {
3886 }4458 }
38874459
3888 pub fn log(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4460 pub fn log(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4461 if (float_type.zigTypeTag() == .Vector) {
4462 const result_data = try arena.alloc(Value, float_type.vectorLen());
4463 for (result_data) |*scalar, i| {
4464 scalar.* = try logScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4465 }
4466 return Value.Tag.aggregate.create(arena, result_data);
4467 }
4468 return logScalar(val, float_type, arena, target);
4469 }
4470
4471 pub fn logScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
3889 switch (float_type.floatBits(target)) {4472 switch (float_type.floatBits(target)) {
3890 16 => {4473 16 => {
3891 const f = val.toFloat(f16);4474 const f = val.toFloat(f16);
...@@ -3918,6 +4501,17 @@ pub const Value = extern union {...@@ -3918,6 +4501,17 @@ pub const Value = extern union {
3918 }4501 }
39194502
3920 pub fn log2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4503 pub fn log2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4504 if (float_type.zigTypeTag() == .Vector) {
4505 const result_data = try arena.alloc(Value, float_type.vectorLen());
4506 for (result_data) |*scalar, i| {
4507 scalar.* = try log2Scalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4508 }
4509 return Value.Tag.aggregate.create(arena, result_data);
4510 }
4511 return log2Scalar(val, float_type, arena, target);
4512 }
4513
4514 pub fn log2Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
3921 switch (float_type.floatBits(target)) {4515 switch (float_type.floatBits(target)) {
3922 16 => {4516 16 => {
3923 const f = val.toFloat(f16);4517 const f = val.toFloat(f16);
...@@ -3950,6 +4544,17 @@ pub const Value = extern union {...@@ -3950,6 +4544,17 @@ pub const Value = extern union {
3950 }4544 }
39514545
3952 pub fn log10(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4546 pub fn log10(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4547 if (float_type.zigTypeTag() == .Vector) {
4548 const result_data = try arena.alloc(Value, float_type.vectorLen());
4549 for (result_data) |*scalar, i| {
4550 scalar.* = try log10Scalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4551 }
4552 return Value.Tag.aggregate.create(arena, result_data);
4553 }
4554 return log10Scalar(val, float_type, arena, target);
4555 }
4556
4557 pub fn log10Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
3953 switch (float_type.floatBits(target)) {4558 switch (float_type.floatBits(target)) {
3954 16 => {4559 16 => {
3955 const f = val.toFloat(f16);4560 const f = val.toFloat(f16);
...@@ -3982,6 +4587,17 @@ pub const Value = extern union {...@@ -3982,6 +4587,17 @@ pub const Value = extern union {
3982 }4587 }
39834588
3984 pub fn fabs(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4589 pub fn fabs(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4590 if (float_type.zigTypeTag() == .Vector) {
4591 const result_data = try arena.alloc(Value, float_type.vectorLen());
4592 for (result_data) |*scalar, i| {
4593 scalar.* = try fabsScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4594 }
4595 return Value.Tag.aggregate.create(arena, result_data);
4596 }
4597 return fabsScalar(val, float_type, arena, target);
4598 }
4599
4600 pub fn fabsScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
3985 switch (float_type.floatBits(target)) {4601 switch (float_type.floatBits(target)) {
3986 16 => {4602 16 => {
3987 const f = val.toFloat(f16);4603 const f = val.toFloat(f16);
...@@ -4011,6 +4627,17 @@ pub const Value = extern union {...@@ -4011,6 +4627,17 @@ pub const Value = extern union {
4011 }4627 }
40124628
4013 pub fn floor(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4629 pub fn floor(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4630 if (float_type.zigTypeTag() == .Vector) {
4631 const result_data = try arena.alloc(Value, float_type.vectorLen());
4632 for (result_data) |*scalar, i| {
4633 scalar.* = try floorScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4634 }
4635 return Value.Tag.aggregate.create(arena, result_data);
4636 }
4637 return floorScalar(val, float_type, arena, target);
4638 }
4639
4640 pub fn floorScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4014 switch (float_type.floatBits(target)) {4641 switch (float_type.floatBits(target)) {
4015 16 => {4642 16 => {
4016 const f = val.toFloat(f16);4643 const f = val.toFloat(f16);
...@@ -4040,6 +4667,17 @@ pub const Value = extern union {...@@ -4040,6 +4667,17 @@ pub const Value = extern union {
4040 }4667 }
40414668
4042 pub fn ceil(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4669 pub fn ceil(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4670 if (float_type.zigTypeTag() == .Vector) {
4671 const result_data = try arena.alloc(Value, float_type.vectorLen());
4672 for (result_data) |*scalar, i| {
4673 scalar.* = try ceilScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4674 }
4675 return Value.Tag.aggregate.create(arena, result_data);
4676 }
4677 return ceilScalar(val, float_type, arena, target);
4678 }
4679
4680 pub fn ceilScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4043 switch (float_type.floatBits(target)) {4681 switch (float_type.floatBits(target)) {
4044 16 => {4682 16 => {
4045 const f = val.toFloat(f16);4683 const f = val.toFloat(f16);
...@@ -4069,6 +4707,17 @@ pub const Value = extern union {...@@ -4069,6 +4707,17 @@ pub const Value = extern union {
4069 }4707 }
40704708
4071 pub fn round(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4709 pub fn round(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4710 if (float_type.zigTypeTag() == .Vector) {
4711 const result_data = try arena.alloc(Value, float_type.vectorLen());
4712 for (result_data) |*scalar, i| {
4713 scalar.* = try roundScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4714 }
4715 return Value.Tag.aggregate.create(arena, result_data);
4716 }
4717 return roundScalar(val, float_type, arena, target);
4718 }
4719
4720 pub fn roundScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4072 switch (float_type.floatBits(target)) {4721 switch (float_type.floatBits(target)) {
4073 16 => {4722 16 => {
4074 const f = val.toFloat(f16);4723 const f = val.toFloat(f16);
...@@ -4098,6 +4747,17 @@ pub const Value = extern union {...@@ -4098,6 +4747,17 @@ pub const Value = extern union {
4098 }4747 }
40994748
4100 pub fn trunc(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4749 pub fn trunc(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4750 if (float_type.zigTypeTag() == .Vector) {
4751 const result_data = try arena.alloc(Value, float_type.vectorLen());
4752 for (result_data) |*scalar, i| {
4753 scalar.* = try truncScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
4754 }
4755 return Value.Tag.aggregate.create(arena, result_data);
4756 }
4757 return truncScalar(val, float_type, arena, target);
4758 }
4759
4760 pub fn truncScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4101 switch (float_type.floatBits(target)) {4761 switch (float_type.floatBits(target)) {
4102 16 => {4762 16 => {
4103 const f = val.toFloat(f16);4763 const f = val.toFloat(f16);
...@@ -4133,6 +4793,31 @@ pub const Value = extern union {...@@ -4133,6 +4793,31 @@ pub const Value = extern union {
4133 addend: Value,4793 addend: Value,
4134 arena: Allocator,4794 arena: Allocator,
4135 target: Target,4795 target: Target,
4796 ) Allocator.Error!Value {
4797 if (float_type.zigTypeTag() == .Vector) {
4798 const result_data = try arena.alloc(Value, float_type.vectorLen());
4799 for (result_data) |*scalar, i| {
4800 scalar.* = try mulAddScalar(
4801 float_type.scalarType(),
4802 mulend1.indexVectorlike(i),
4803 mulend2.indexVectorlike(i),
4804 addend.indexVectorlike(i),
4805 arena,
4806 target,
4807 );
4808 }
4809 return Value.Tag.aggregate.create(arena, result_data);
4810 }
4811 return mulAddScalar(float_type, mulend1, mulend2, addend, arena, target);
4812 }
4813
4814 pub fn mulAddScalar(
4815 float_type: Type,
4816 mulend1: Value,
4817 mulend2: Value,
4818 addend: Value,
4819 arena: Allocator,
4820 target: Target,
4136 ) Allocator.Error!Value {4821 ) Allocator.Error!Value {
4137 switch (float_type.floatBits(target)) {4822 switch (float_type.floatBits(target)) {
4138 16 => {4823 16 => {