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(
21052105 });
21062106 } else if (any_values) {
21072107 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)
21092109 else
21102110 Value.zero;
21112111 last_tag_val = tag_val;
......@@ -8192,14 +8192,22 @@ fn zirShl(
81928192 defer tracy.end();
81938193
81948194 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
8195 const src = inst_data.src();
81958196 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
81968197 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
81978198 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
81988199 const lhs = sema.resolveInst(extra.lhs);
81998200 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
82018209 // 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
82048212 const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs);
82058213 const maybe_rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs);
......@@ -8213,35 +8221,31 @@ fn zirShl(
82138221 }
82148222 }
82158223
8216 const lhs_ty = sema.typeOf(lhs);
8217 const rhs_ty = sema.typeOf(rhs);
8218 const target = sema.mod.getTarget();
8219
82208224 const runtime_src = if (maybe_lhs_val) |lhs_val| rs: {
82218225 if (lhs_val.isUndef()) return sema.addConstUndef(lhs_ty);
82228226 const rhs_val = maybe_rhs_val orelse break :rs rhs_src;
82238227
82248228 const val = switch (air_tag) {
82258229 .shl_exact => val: {
8226 const shifted = try lhs_val.shl(rhs_val, sema.arena);
8227 if (lhs_ty.zigTypeTag() == .ComptimeInt) {
8230 const shifted = try lhs_val.shl(rhs_val, lhs_ty, sema.arena);
8231 if (scalar_ty.zigTypeTag() == .ComptimeInt) {
82288232 break :val shifted;
82298233 }
8230 const int_info = lhs_ty.intInfo(target);
8231 const truncated = try shifted.intTrunc(sema.arena, int_info.signedness, int_info.bits);
8232 if (truncated.compareHetero(.eq, shifted)) {
8234 const int_info = scalar_ty.intInfo(target);
8235 const truncated = try shifted.intTrunc(lhs_ty, sema.arena, int_info.signedness, int_info.bits);
8236 if (truncated.compare(.eq, shifted, lhs_ty)) {
82338237 break :val shifted;
82348238 }
82358239 return sema.addConstUndef(lhs_ty);
82368240 },
82378241
8238 .shl_sat => if (lhs_ty.zigTypeTag() == .ComptimeInt)
8239 try lhs_val.shl(rhs_val, sema.arena)
8242 .shl_sat => if (scalar_ty.zigTypeTag() == .ComptimeInt)
8243 try lhs_val.shl(rhs_val, lhs_ty, sema.arena)
82408244 else
82418245 try lhs_val.shlSat(rhs_val, lhs_ty, sema.arena, target),
82428246
8243 .shl => if (lhs_ty.zigTypeTag() == .ComptimeInt)
8244 try lhs_val.shl(rhs_val, sema.arena)
8247 .shl => if (scalar_ty.zigTypeTag() == .ComptimeInt)
8248 try lhs_val.shl(rhs_val, lhs_ty, sema.arena)
82458249 else
82468250 try lhs_val.shlTrunc(rhs_val, lhs_ty, sema.arena, target),
82478251
......@@ -8256,7 +8260,7 @@ fn zirShl(
82568260 const new_rhs = if (air_tag == .shl_sat) rhs: {
82578261 // Limit the RHS type for saturating shl to be an integer as small as the LHS.
82588262 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)
82608264 {
82618265 const max_int = try sema.addConstant(
82628266 lhs_ty,
......@@ -8283,15 +8287,18 @@ fn zirShr(
82838287 defer tracy.end();
82848288
82858289 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
8290 const src = inst_data.src();
82868291 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
82878292 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
82888293 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
82898294 const lhs = sema.resolveInst(extra.lhs);
82908295 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
82928300 const runtime_src = if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| rs: {
82938301 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
8294 const lhs_ty = sema.typeOf(lhs);
82958302 if (lhs_val.isUndef() or rhs_val.isUndef()) {
82968303 return sema.addConstUndef(lhs_ty);
82978304 }
......@@ -8301,13 +8308,12 @@ fn zirShr(
83018308 }
83028309 if (air_tag == .shr_exact) {
83038310 // Detect if any ones would be shifted out.
8304 const bits = @intCast(u16, rhs_val.toUnsignedInt());
8305 const truncated = try lhs_val.intTrunc(sema.arena, .unsigned, bits);
8311 const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val);
83068312 if (!truncated.compareWithZero(.eq)) {
83078313 return sema.addConstUndef(lhs_ty);
83088314 }
83098315 }
8310 const val = try lhs_val.shr(rhs_val, sema.arena);
8316 const val = try lhs_val.shr(rhs_val, lhs_ty, sema.arena);
83118317 return sema.addConstant(lhs_ty, val);
83128318 } else {
83138319 // Even if lhs is not comptime known, we can still deduce certain things based
......@@ -8342,32 +8348,15 @@ fn zirBitwise(
83428348 const rhs = sema.resolveInst(extra.rhs);
83438349 const lhs_ty = sema.typeOf(lhs);
83448350 const rhs_ty = sema.typeOf(rhs);
8351 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
83458352
83468353 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
83478354 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);
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
8355 const scalar_type = resolved_type.scalarType();
83568356 const scalar_tag = scalar_type.zigTypeTag();
83578357
8358 if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) {
8359 if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) {
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 }
8358 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
8359 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
83718360
83728361 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
83738362
......@@ -8377,16 +8366,13 @@ fn zirBitwise(
83778366
83788367 if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| {
83798368 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 }
83838369 const result_val = switch (air_tag) {
8384 .bit_and => try lhs_val.bitwiseAnd(rhs_val, sema.arena),
8385 .bit_or => try lhs_val.bitwiseOr(rhs_val, sema.arena),
8386 .xor => try lhs_val.bitwiseXor(rhs_val, sema.arena),
8370 .bit_and => try lhs_val.bitwiseAnd(rhs_val, resolved_type, sema.arena),
8371 .bit_or => try lhs_val.bitwiseOr(rhs_val, resolved_type, sema.arena),
8372 .xor => try lhs_val.bitwiseXor(rhs_val, resolved_type, sema.arena),
83878373 else => unreachable,
83888374 };
8389 return sema.addConstant(scalar_type, result_val);
8375 return sema.addConstant(resolved_type, result_val);
83908376 }
83918377 }
83928378
......@@ -8413,9 +8399,9 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
84138399 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
84148400 const target = sema.mod.getTarget();
84158401 if (val.isUndef()) {
8416 return sema.addConstUndef(scalar_type);
8402 return sema.addConstUndef(operand_type);
84178403 } 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());
84198405 var elem_val_buf: Value.ElemValueBuffer = undefined;
84208406 const elems = try sema.arena.alloc(Value, vec_len);
84218407 for (elems) |*elem, i| {
......@@ -8427,8 +8413,8 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
84278413 try Value.Tag.aggregate.create(sema.arena, elems),
84288414 );
84298415 } else {
8430 const result_val = try val.bitwiseNot(scalar_type, sema.arena, target);
8431 return sema.addConstant(scalar_type, result_val);
8416 const result_val = try val.bitwiseNot(operand_type, sema.arena, target);
8417 return sema.addConstant(operand_type, result_val);
84328418 }
84338419 }
84348420
......@@ -8780,8 +8766,19 @@ fn zirNegate(
87808766 const src = inst_data.src();
87818767 const lhs_src = src;
87828768 const rhs_src = src; // TODO better source location
8783 const lhs = sema.resolveInst(.zero);
8769
87848770 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
87868783 return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src);
87878784}
......@@ -8999,18 +8996,8 @@ fn analyzeArithmetic(
89998996 const rhs_ty = sema.typeOf(rhs);
90008997 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
90018998 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
9002 if (lhs_zig_ty_tag == .Vector and rhs_zig_ty_tag == .Vector) {
9003 if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) {
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 }
8999 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
9000
90149001 if (lhs_zig_ty_tag == .Pointer) switch (lhs_ty.ptrSize()) {
90159002 .One, .Slice => {},
90169003 .Many, .C => {
......@@ -9033,15 +9020,13 @@ fn analyzeArithmetic(
90339020 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
90349021 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
90359022 });
9023
90369024 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
90379025 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
90389026
9039 const scalar_type = if (resolved_type.zigTypeTag() == .Vector)
9040 resolved_type.elemType()
9041 else
9042 resolved_type;
9043
9044 const scalar_tag = scalar_type.zigTypeTag();
9027 const lhs_scalar_ty = lhs_ty.scalarType();
9028 const rhs_scalar_ty = rhs_ty.scalarType();
9029 const scalar_tag = resolved_type.scalarType().zigTypeTag();
90459030
90469031 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
90479032 const is_float = scalar_tag == .Float or scalar_tag == .ComptimeFloat;
......@@ -9075,7 +9060,7 @@ fn analyzeArithmetic(
90759060 if (is_int) {
90769061 return sema.failWithUseOfUndef(block, rhs_src);
90779062 } else {
9078 return sema.addConstUndef(scalar_type);
9063 return sema.addConstUndef(resolved_type);
90799064 }
90809065 }
90819066 if (rhs_val.compareWithZero(.eq)) {
......@@ -9087,19 +9072,19 @@ fn analyzeArithmetic(
90879072 if (is_int) {
90889073 return sema.failWithUseOfUndef(block, lhs_src);
90899074 } else {
9090 return sema.addConstUndef(scalar_type);
9075 return sema.addConstUndef(resolved_type);
90919076 }
90929077 }
90939078 if (maybe_rhs_val) |rhs_val| {
90949079 if (is_int) {
90959080 return sema.addConstant(
9096 scalar_type,
9097 try lhs_val.intAdd(rhs_val, sema.arena),
9081 resolved_type,
9082 try lhs_val.intAdd(rhs_val, resolved_type, sema.arena),
90989083 );
90999084 } else {
91009085 return sema.addConstant(
9101 scalar_type,
9102 try lhs_val.floatAdd(rhs_val, scalar_type, sema.arena, target),
9086 resolved_type,
9087 try lhs_val.floatAdd(rhs_val, resolved_type, sema.arena, target),
91039088 );
91049089 }
91059090 } else break :rs .{ .src = rhs_src, .air_tag = .add };
......@@ -9116,15 +9101,15 @@ fn analyzeArithmetic(
91169101 }
91179102 if (maybe_rhs_val) |rhs_val| {
91189103 if (rhs_val.isUndef()) {
9119 return sema.addConstUndef(scalar_type);
9104 return sema.addConstUndef(resolved_type);
91209105 }
91219106 if (rhs_val.compareWithZero(.eq)) {
91229107 return casted_lhs;
91239108 }
91249109 if (maybe_lhs_val) |lhs_val| {
91259110 return sema.addConstant(
9126 scalar_type,
9127 try lhs_val.numberAddWrap(rhs_val, scalar_type, sema.arena, target),
9111 resolved_type,
9112 try lhs_val.numberAddWrap(rhs_val, resolved_type, sema.arena, target),
91289113 );
91299114 } else break :rs .{ .src = lhs_src, .air_tag = .addwrap };
91309115 } else break :rs .{ .src = rhs_src, .air_tag = .addwrap };
......@@ -9140,18 +9125,18 @@ fn analyzeArithmetic(
91409125 }
91419126 if (maybe_rhs_val) |rhs_val| {
91429127 if (rhs_val.isUndef()) {
9143 return sema.addConstUndef(scalar_type);
9128 return sema.addConstUndef(resolved_type);
91449129 }
91459130 if (rhs_val.compareWithZero(.eq)) {
91469131 return casted_lhs;
91479132 }
91489133 if (maybe_lhs_val) |lhs_val| {
91499134 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)
91519136 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);
91559140 } else break :rs .{ .src = lhs_src, .air_tag = .add_sat };
91569141 } else break :rs .{ .src = rhs_src, .air_tag = .add_sat };
91579142 },
......@@ -9168,7 +9153,7 @@ fn analyzeArithmetic(
91689153 if (is_int) {
91699154 return sema.failWithUseOfUndef(block, rhs_src);
91709155 } else {
9171 return sema.addConstUndef(scalar_type);
9156 return sema.addConstUndef(resolved_type);
91729157 }
91739158 }
91749159 if (rhs_val.compareWithZero(.eq)) {
......@@ -9180,19 +9165,19 @@ fn analyzeArithmetic(
91809165 if (is_int) {
91819166 return sema.failWithUseOfUndef(block, lhs_src);
91829167 } else {
9183 return sema.addConstUndef(scalar_type);
9168 return sema.addConstUndef(resolved_type);
91849169 }
91859170 }
91869171 if (maybe_rhs_val) |rhs_val| {
91879172 if (is_int) {
91889173 return sema.addConstant(
9189 scalar_type,
9190 try lhs_val.intSub(rhs_val, sema.arena),
9174 resolved_type,
9175 try lhs_val.intSub(rhs_val, resolved_type, sema.arena),
91919176 );
91929177 } else {
91939178 return sema.addConstant(
9194 scalar_type,
9195 try lhs_val.floatSub(rhs_val, scalar_type, sema.arena, target),
9179 resolved_type,
9180 try lhs_val.floatSub(rhs_val, resolved_type, sema.arena, target),
91969181 );
91979182 }
91989183 } else break :rs .{ .src = rhs_src, .air_tag = .sub };
......@@ -9204,7 +9189,7 @@ fn analyzeArithmetic(
92049189 // If either of the operands are undefined, the result is undefined.
92059190 if (maybe_rhs_val) |rhs_val| {
92069191 if (rhs_val.isUndef()) {
9207 return sema.addConstUndef(scalar_type);
9192 return sema.addConstUndef(resolved_type);
92089193 }
92099194 if (rhs_val.compareWithZero(.eq)) {
92109195 return casted_lhs;
......@@ -9212,12 +9197,12 @@ fn analyzeArithmetic(
92129197 }
92139198 if (maybe_lhs_val) |lhs_val| {
92149199 if (lhs_val.isUndef()) {
9215 return sema.addConstUndef(scalar_type);
9200 return sema.addConstUndef(resolved_type);
92169201 }
92179202 if (maybe_rhs_val) |rhs_val| {
92189203 return sema.addConstant(
9219 scalar_type,
9220 try lhs_val.numberSubWrap(rhs_val, scalar_type, sema.arena, target),
9204 resolved_type,
9205 try lhs_val.numberSubWrap(rhs_val, resolved_type, sema.arena, target),
92219206 );
92229207 } else break :rs .{ .src = rhs_src, .air_tag = .subwrap };
92239208 } else break :rs .{ .src = lhs_src, .air_tag = .subwrap };
......@@ -9228,7 +9213,7 @@ fn analyzeArithmetic(
92289213 // If either of the operands are undefined, result is undefined.
92299214 if (maybe_rhs_val) |rhs_val| {
92309215 if (rhs_val.isUndef()) {
9231 return sema.addConstUndef(scalar_type);
9216 return sema.addConstUndef(resolved_type);
92329217 }
92339218 if (rhs_val.compareWithZero(.eq)) {
92349219 return casted_lhs;
......@@ -9236,15 +9221,15 @@ fn analyzeArithmetic(
92369221 }
92379222 if (maybe_lhs_val) |lhs_val| {
92389223 if (lhs_val.isUndef()) {
9239 return sema.addConstUndef(scalar_type);
9224 return sema.addConstUndef(resolved_type);
92409225 }
92419226 if (maybe_rhs_val) |rhs_val| {
92429227 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)
92449229 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);
92489233 } else break :rs .{ .src = rhs_src, .air_tag = .sub_sat };
92499234 } else break :rs .{ .src = lhs_src, .air_tag = .sub_sat };
92509235 },
......@@ -9274,7 +9259,7 @@ fn analyzeArithmetic(
92749259 if (maybe_lhs_val) |lhs_val| {
92759260 if (!lhs_val.isUndef()) {
92769261 if (lhs_val.compareWithZero(.eq)) {
9277 return sema.addConstant(scalar_type, Value.zero);
9262 return sema.addConstant(resolved_type, Value.zero);
92789263 }
92799264 }
92809265 }
......@@ -9288,27 +9273,27 @@ fn analyzeArithmetic(
92889273 }
92899274 if (maybe_lhs_val) |lhs_val| {
92909275 if (lhs_val.isUndef()) {
9291 if (lhs_ty.isSignedInt() and rhs_ty.isSignedInt()) {
9276 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
92929277 if (maybe_rhs_val) |rhs_val| {
9293 if (rhs_val.compare(.neq, Value.negative_one, scalar_type)) {
9294 return sema.addConstUndef(scalar_type);
9278 if (rhs_val.compare(.neq, Value.negative_one, rhs_ty)) {
9279 return sema.addConstUndef(resolved_type);
92959280 }
92969281 }
92979282 return sema.failWithUseOfUndef(block, rhs_src);
92989283 }
9299 return sema.addConstUndef(scalar_type);
9284 return sema.addConstUndef(resolved_type);
93009285 }
93019286
93029287 if (maybe_rhs_val) |rhs_val| {
93039288 if (is_int) {
93049289 return sema.addConstant(
9305 scalar_type,
9306 try lhs_val.intDiv(rhs_val, sema.arena),
9290 resolved_type,
9291 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena),
93079292 );
93089293 } else {
93099294 return sema.addConstant(
9310 scalar_type,
9311 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target),
9295 resolved_type,
9296 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
93129297 );
93139298 }
93149299 } else {
......@@ -9349,7 +9334,7 @@ fn analyzeArithmetic(
93499334 if (maybe_lhs_val) |lhs_val| {
93509335 if (!lhs_val.isUndef()) {
93519336 if (lhs_val.compareWithZero(.eq)) {
9352 return sema.addConstant(scalar_type, Value.zero);
9337 return sema.addConstant(resolved_type, Value.zero);
93539338 }
93549339 }
93559340 }
......@@ -9363,27 +9348,27 @@ fn analyzeArithmetic(
93639348 }
93649349 if (maybe_lhs_val) |lhs_val| {
93659350 if (lhs_val.isUndef()) {
9366 if (lhs_ty.isSignedInt() and rhs_ty.isSignedInt()) {
9351 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
93679352 if (maybe_rhs_val) |rhs_val| {
9368 if (rhs_val.compare(.neq, Value.negative_one, scalar_type)) {
9369 return sema.addConstUndef(scalar_type);
9353 if (rhs_val.compare(.neq, Value.negative_one, rhs_ty)) {
9354 return sema.addConstUndef(resolved_type);
93709355 }
93719356 }
93729357 return sema.failWithUseOfUndef(block, rhs_src);
93739358 }
9374 return sema.addConstUndef(scalar_type);
9359 return sema.addConstUndef(resolved_type);
93759360 }
93769361
93779362 if (maybe_rhs_val) |rhs_val| {
93789363 if (is_int) {
93799364 return sema.addConstant(
9380 scalar_type,
9381 try lhs_val.intDiv(rhs_val, sema.arena),
9365 resolved_type,
9366 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena),
93829367 );
93839368 } else {
93849369 return sema.addConstant(
9385 scalar_type,
9386 try lhs_val.floatDivTrunc(rhs_val, scalar_type, sema.arena, target),
9370 resolved_type,
9371 try lhs_val.floatDivTrunc(rhs_val, resolved_type, sema.arena, target),
93879372 );
93889373 }
93899374 } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
......@@ -9412,7 +9397,7 @@ fn analyzeArithmetic(
94129397 if (maybe_lhs_val) |lhs_val| {
94139398 if (!lhs_val.isUndef()) {
94149399 if (lhs_val.compareWithZero(.eq)) {
9415 return sema.addConstant(scalar_type, Value.zero);
9400 return sema.addConstant(resolved_type, Value.zero);
94169401 }
94179402 }
94189403 }
......@@ -9426,27 +9411,27 @@ fn analyzeArithmetic(
94269411 }
94279412 if (maybe_lhs_val) |lhs_val| {
94289413 if (lhs_val.isUndef()) {
9429 if (lhs_ty.isSignedInt() and rhs_ty.isSignedInt()) {
9414 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
94309415 if (maybe_rhs_val) |rhs_val| {
9431 if (rhs_val.compare(.neq, Value.negative_one, scalar_type)) {
9432 return sema.addConstUndef(scalar_type);
9416 if (rhs_val.compare(.neq, Value.negative_one, rhs_ty)) {
9417 return sema.addConstUndef(resolved_type);
94339418 }
94349419 }
94359420 return sema.failWithUseOfUndef(block, rhs_src);
94369421 }
9437 return sema.addConstUndef(scalar_type);
9422 return sema.addConstUndef(resolved_type);
94389423 }
94399424
94409425 if (maybe_rhs_val) |rhs_val| {
94419426 if (is_int) {
94429427 return sema.addConstant(
9443 scalar_type,
9444 try lhs_val.intDivFloor(rhs_val, sema.arena),
9428 resolved_type,
9429 try lhs_val.intDivFloor(rhs_val, resolved_type, sema.arena),
94459430 );
94469431 } else {
94479432 return sema.addConstant(
9448 scalar_type,
9449 try lhs_val.floatDivFloor(rhs_val, scalar_type, sema.arena, target),
9433 resolved_type,
9434 try lhs_val.floatDivFloor(rhs_val, resolved_type, sema.arena, target),
94509435 );
94519436 }
94529437 } else break :rs .{ .src = rhs_src, .air_tag = .div_floor };
......@@ -9474,7 +9459,7 @@ fn analyzeArithmetic(
94749459 return sema.failWithUseOfUndef(block, rhs_src);
94759460 } else {
94769461 if (lhs_val.compareWithZero(.eq)) {
9477 return sema.addConstant(scalar_type, Value.zero);
9462 return sema.addConstant(resolved_type, Value.zero);
94789463 }
94799464 }
94809465 }
......@@ -9491,14 +9476,14 @@ fn analyzeArithmetic(
94919476 if (is_int) {
94929477 // TODO: emit compile error if there is a remainder
94939478 return sema.addConstant(
9494 scalar_type,
9495 try lhs_val.intDiv(rhs_val, sema.arena),
9479 resolved_type,
9480 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena),
94969481 );
94979482 } else {
94989483 // TODO: emit compile error if there is a remainder
94999484 return sema.addConstant(
9500 scalar_type,
9501 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target),
9485 resolved_type,
9486 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
95029487 );
95039488 }
95049489 } else break :rs .{ .src = rhs_src, .air_tag = .div_exact };
......@@ -9516,9 +9501,9 @@ fn analyzeArithmetic(
95169501 if (maybe_lhs_val) |lhs_val| {
95179502 if (!lhs_val.isUndef()) {
95189503 if (lhs_val.compareWithZero(.eq)) {
9519 return sema.addConstant(scalar_type, Value.zero);
9504 return sema.addConstant(resolved_type, Value.zero);
95209505 }
9521 if (lhs_val.compare(.eq, Value.one, scalar_type)) {
9506 if (lhs_val.compare(.eq, Value.one, lhs_ty)) {
95229507 return casted_rhs;
95239508 }
95249509 }
......@@ -9528,13 +9513,13 @@ fn analyzeArithmetic(
95289513 if (is_int) {
95299514 return sema.failWithUseOfUndef(block, rhs_src);
95309515 } else {
9531 return sema.addConstUndef(scalar_type);
9516 return sema.addConstUndef(resolved_type);
95329517 }
95339518 }
95349519 if (rhs_val.compareWithZero(.eq)) {
9535 return sema.addConstant(scalar_type, Value.zero);
9520 return sema.addConstant(resolved_type, Value.zero);
95369521 }
9537 if (rhs_val.compare(.eq, Value.one, scalar_type)) {
9522 if (rhs_val.compare(.eq, Value.one, rhs_ty)) {
95389523 return casted_lhs;
95399524 }
95409525 if (maybe_lhs_val) |lhs_val| {
......@@ -9542,18 +9527,18 @@ fn analyzeArithmetic(
95429527 if (is_int) {
95439528 return sema.failWithUseOfUndef(block, lhs_src);
95449529 } else {
9545 return sema.addConstUndef(scalar_type);
9530 return sema.addConstUndef(resolved_type);
95469531 }
95479532 }
95489533 if (is_int) {
95499534 return sema.addConstant(
9550 scalar_type,
9551 try lhs_val.intMul(rhs_val, sema.arena),
9535 resolved_type,
9536 try lhs_val.intMul(rhs_val, resolved_type, sema.arena),
95529537 );
95539538 } else {
95549539 return sema.addConstant(
9555 scalar_type,
9556 try lhs_val.floatMul(rhs_val, scalar_type, sema.arena, target),
9540 resolved_type,
9541 try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, target),
95579542 );
95589543 }
95599544 } else break :rs .{ .src = lhs_src, .air_tag = .mul };
......@@ -9567,30 +9552,30 @@ fn analyzeArithmetic(
95679552 if (maybe_lhs_val) |lhs_val| {
95689553 if (!lhs_val.isUndef()) {
95699554 if (lhs_val.compareWithZero(.eq)) {
9570 return sema.addConstant(scalar_type, Value.zero);
9555 return sema.addConstant(resolved_type, Value.zero);
95719556 }
9572 if (lhs_val.compare(.eq, Value.one, scalar_type)) {
9557 if (lhs_val.compare(.eq, Value.one, lhs_ty)) {
95739558 return casted_rhs;
95749559 }
95759560 }
95769561 }
95779562 if (maybe_rhs_val) |rhs_val| {
95789563 if (rhs_val.isUndef()) {
9579 return sema.addConstUndef(scalar_type);
9564 return sema.addConstUndef(resolved_type);
95809565 }
95819566 if (rhs_val.compareWithZero(.eq)) {
9582 return sema.addConstant(scalar_type, Value.zero);
9567 return sema.addConstant(resolved_type, Value.zero);
95839568 }
9584 if (rhs_val.compare(.eq, Value.one, scalar_type)) {
9569 if (rhs_val.compare(.eq, Value.one, rhs_ty)) {
95859570 return casted_lhs;
95869571 }
95879572 if (maybe_lhs_val) |lhs_val| {
95889573 if (lhs_val.isUndef()) {
9589 return sema.addConstUndef(scalar_type);
9574 return sema.addConstUndef(resolved_type);
95909575 }
95919576 return sema.addConstant(
9592 scalar_type,
9593 try lhs_val.numberMulWrap(rhs_val, scalar_type, sema.arena, target),
9577 resolved_type,
9578 try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, target),
95949579 );
95959580 } else break :rs .{ .src = lhs_src, .air_tag = .mulwrap };
95969581 } else break :rs .{ .src = rhs_src, .air_tag = .mulwrap };
......@@ -9603,34 +9588,34 @@ fn analyzeArithmetic(
96039588 if (maybe_lhs_val) |lhs_val| {
96049589 if (!lhs_val.isUndef()) {
96059590 if (lhs_val.compareWithZero(.eq)) {
9606 return sema.addConstant(scalar_type, Value.zero);
9591 return sema.addConstant(resolved_type, Value.zero);
96079592 }
9608 if (lhs_val.compare(.eq, Value.one, scalar_type)) {
9593 if (lhs_val.compare(.eq, Value.one, lhs_ty)) {
96099594 return casted_rhs;
96109595 }
96119596 }
96129597 }
96139598 if (maybe_rhs_val) |rhs_val| {
96149599 if (rhs_val.isUndef()) {
9615 return sema.addConstUndef(scalar_type);
9600 return sema.addConstUndef(resolved_type);
96169601 }
96179602 if (rhs_val.compareWithZero(.eq)) {
9618 return sema.addConstant(scalar_type, Value.zero);
9603 return sema.addConstant(resolved_type, Value.zero);
96199604 }
9620 if (rhs_val.compare(.eq, Value.one, scalar_type)) {
9605 if (rhs_val.compare(.eq, Value.one, rhs_ty)) {
96219606 return casted_lhs;
96229607 }
96239608 if (maybe_lhs_val) |lhs_val| {
96249609 if (lhs_val.isUndef()) {
9625 return sema.addConstUndef(scalar_type);
9610 return sema.addConstUndef(resolved_type);
96269611 }
96279612
96289613 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)
96309615 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);
96349619 } else break :rs .{ .src = lhs_src, .air_tag = .mul_sat };
96359620 } else break :rs .{ .src = rhs_src, .air_tag = .mul_sat };
96369621 },
......@@ -9654,9 +9639,9 @@ fn analyzeArithmetic(
96549639 return sema.failWithUseOfUndef(block, lhs_src);
96559640 }
96569641 if (lhs_val.compareWithZero(.eq)) {
9657 return sema.addConstant(scalar_type, Value.zero);
9642 return sema.addConstant(resolved_type, Value.zero);
96589643 }
9659 } else if (lhs_ty.isSignedInt()) {
9644 } else if (lhs_scalar_ty.isSignedInt()) {
96609645 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
96619646 }
96629647 if (maybe_rhs_val) |rhs_val| {
......@@ -9667,7 +9652,7 @@ fn analyzeArithmetic(
96679652 return sema.failWithDivideByZero(block, rhs_src);
96689653 }
96699654 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);
96719656 // If this answer could possibly be different by doing `intMod`,
96729657 // we must emit a compile error. Otherwise, it's OK.
96739658 if (rhs_val.compareWithZero(.lt) != lhs_val.compareWithZero(.lt) and
......@@ -9681,12 +9666,12 @@ fn analyzeArithmetic(
96819666 }
96829667 if (lhs_val.compareWithZero(.lt)) {
96839668 // Negative
9684 return sema.addConstant(scalar_type, Value.zero);
9669 return sema.addConstant(resolved_type, Value.zero);
96859670 }
9686 return sema.addConstant(scalar_type, rem_result);
9671 return sema.addConstant(resolved_type, rem_result);
96879672 }
96889673 break :rs .{ .src = lhs_src, .air_tag = .rem };
9689 } else if (rhs_ty.isSignedInt()) {
9674 } else if (rhs_scalar_ty.isSignedInt()) {
96909675 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
96919676 } else {
96929677 break :rs .{ .src = rhs_src, .air_tag = .rem };
......@@ -9708,8 +9693,8 @@ fn analyzeArithmetic(
97089693 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
97099694 }
97109695 return sema.addConstant(
9711 scalar_type,
9712 try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),
9696 resolved_type,
9697 try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target),
97139698 );
97149699 } else {
97159700 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
......@@ -9745,8 +9730,8 @@ fn analyzeArithmetic(
97459730 }
97469731 if (maybe_lhs_val) |lhs_val| {
97479732 return sema.addConstant(
9748 scalar_type,
9749 try lhs_val.intRem(rhs_val, sema.arena),
9733 resolved_type,
9734 try lhs_val.intRem(rhs_val, resolved_type, sema.arena),
97509735 );
97519736 }
97529737 break :rs .{ .src = lhs_src, .air_tag = .rem };
......@@ -9765,12 +9750,12 @@ fn analyzeArithmetic(
97659750 }
97669751 if (maybe_lhs_val) |lhs_val| {
97679752 if (lhs_val.isUndef()) {
9768 return sema.addConstUndef(scalar_type);
9753 return sema.addConstUndef(resolved_type);
97699754 }
97709755 if (maybe_rhs_val) |rhs_val| {
97719756 return sema.addConstant(
9772 scalar_type,
9773 try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),
9757 resolved_type,
9758 try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target),
97749759 );
97759760 } else break :rs .{ .src = rhs_src, .air_tag = .rem };
97769761 } else break :rs .{ .src = lhs_src, .air_tag = .rem };
......@@ -9802,8 +9787,8 @@ fn analyzeArithmetic(
98029787 }
98039788 if (maybe_lhs_val) |lhs_val| {
98049789 return sema.addConstant(
9805 scalar_type,
9806 try lhs_val.intMod(rhs_val, sema.arena),
9790 resolved_type,
9791 try lhs_val.intMod(rhs_val, resolved_type, sema.arena),
98079792 );
98089793 }
98099794 break :rs .{ .src = lhs_src, .air_tag = .mod };
......@@ -9822,12 +9807,12 @@ fn analyzeArithmetic(
98229807 }
98239808 if (maybe_lhs_val) |lhs_val| {
98249809 if (lhs_val.isUndef()) {
9825 return sema.addConstUndef(scalar_type);
9810 return sema.addConstUndef(resolved_type);
98269811 }
98279812 if (maybe_rhs_val) |rhs_val| {
98289813 return sema.addConstant(
9829 scalar_type,
9830 try lhs_val.floatMod(rhs_val, scalar_type, sema.arena, target),
9814 resolved_type,
9815 try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target),
98319816 );
98329817 } else break :rs .{ .src = rhs_src, .air_tag = .mod };
98339818 } else break :rs .{ .src = lhs_src, .air_tag = .mod };
......@@ -10178,6 +10163,11 @@ fn analyzeCmp(
1017810163) CompileError!Air.Inst.Ref {
1017910164 const lhs_ty = sema.typeOf(lhs);
1018010165 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 }
1018110171 if (lhs_ty.isNumeric() and rhs_ty.isNumeric()) {
1018210172 // This operation allows any combination of integer and float types, regardless of the
1018310173 // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for
......@@ -10212,6 +10202,12 @@ fn cmpSelf(
1021210202 if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| {
1021310203 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
1021510211 if (lhs_val.compare(op, rhs_val, resolved_type)) {
1021610212 return Air.Inst.Ref.bool_true;
1021710213 } else {
......@@ -10237,16 +10233,12 @@ fn cmpSelf(
1023710233 }
1023810234 };
1023910235 try sema.requireRuntimeBlock(block, runtime_src);
10240
10241 const tag: Air.Inst.Tag = switch (op) {
10242 .lt => .cmp_lt,
10243 .lte => .cmp_lte,
10244 .eq => .cmp_eq,
10245 .gte => .cmp_gte,
10246 .gt => .cmp_gt,
10247 .neq => .cmp_neq,
10248 };
10249 // TODO handle vectors
10236 if (resolved_type.zigTypeTag() == .Vector) {
10237 const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.@"bool");
10238 const result_ty_ref = try sema.addType(result_ty);
10239 return block.addCmpVector(casted_lhs, casted_rhs, op, result_ty_ref);
10240 }
10241 const tag = Air.Inst.Tag.fromCmpOp(op);
1025010242 return block.addBinOp(tag, casted_lhs, casted_rhs);
1025110243}
1025210244
......@@ -11367,7 +11359,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
1136711359 const elem_ty = operand.elemType2();
1136811360 const log2_elem_ty = try sema.log2IntType(block, elem_ty, src);
1136911361 return Type.Tag.vector.create(sema.arena, .{
11370 .len = operand.arrayLen(),
11362 .len = operand.vectorLen(),
1137111363 .elem_type = log2_elem_ty,
1137211364 });
1137311365 },
......@@ -13298,7 +13290,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1329813290
1329913291 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
1330013292 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) {
1330213294 error.FloatCannotFit => {
1330313295 return sema.fail(block, operand_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty });
1330413296 },
......@@ -13325,7 +13317,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1332513317
1332613318 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
1332713319 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);
1332913321 return sema.addConstant(dest_ty, result_val);
1333013322 }
1333113323
......@@ -13535,14 +13527,14 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1353513527 if (!is_vector) {
1353613528 return sema.addConstant(
1353713529 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),
1353913531 );
1354013532 }
1354113533 var elem_buf: Value.ElemValueBuffer = undefined;
1354213534 const elems = try sema.arena.alloc(Value, operand_ty.vectorLen());
1354313535 for (elems) |*elem, i| {
1354413536 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);
1354613538 }
1354713539 return sema.addConstant(
1354813540 dest_ty,
......@@ -14097,13 +14089,40 @@ fn checkSimdBinOp(
1409714089) CompileError!SimdBinOp {
1409814090 const lhs_ty = sema.typeOf(uncasted_lhs);
1409914091 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();
1410414123 if (lhs_zig_ty_tag == .Vector and rhs_zig_ty_tag == .Vector) {
14105 const lhs_len = lhs_ty.arrayLen();
14106 const rhs_len = rhs_ty.arrayLen();
14124 const lhs_len = lhs_ty.vectorLen();
14125 const rhs_len = rhs_ty.vectorLen();
1410714126 if (lhs_len != rhs_len) {
1410814127 const msg = msg: {
1410914128 const msg = try sema.errMsg(block, src, "vector length mismatch", .{});
......@@ -14114,7 +14133,6 @@ fn checkSimdBinOp(
1411414133 };
1411514134 return sema.failWithOwnedErrorMsg(block, msg);
1411614135 }
14117 vec_len = try sema.usizeCast(block, lhs_src, lhs_len);
1411814136 } else if (lhs_zig_ty_tag == .Vector or rhs_zig_ty_tag == .Vector) {
1411914137 const msg = msg: {
1412014138 const msg = try sema.errMsg(block, src, "mixed scalar and vector operands: {} and {}", .{
......@@ -14132,21 +14150,6 @@ fn checkSimdBinOp(
1413214150 };
1413314151 return sema.failWithOwnedErrorMsg(block, msg);
1413414152 }
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 };
1415014153}
1415114154
1415214155fn resolveExportOptions(
......@@ -14376,9 +14379,9 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1437614379 while (i < vec_len) : (i += 1) {
1437714380 const elem_val = operand_val.elemValueBuffer(i, &elem_buf);
1437814381 switch (operation) {
14379 .And => accum = try accum.bitwiseAnd(elem_val, sema.arena),
14380 .Or => accum = try accum.bitwiseOr(elem_val, sema.arena),
14381 .Xor => accum = try accum.bitwiseXor(elem_val, sema.arena),
14382 .And => accum = try accum.bitwiseAnd(elem_val, scalar_ty, sema.arena),
14383 .Or => accum = try accum.bitwiseOr(elem_val, scalar_ty, sema.arena),
14384 .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena),
1438214385 .Min => accum = accum.numberMin(elem_val),
1438314386 .Max => accum = accum.numberMax(elem_val),
1438414387 .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
1469714700 .Xchg => operand_val,
1469814701 .Add => try stored_val.numberAddWrap(operand_val, operand_ty, sema.arena, target),
1469914702 .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),
1470114704 .Nand => try stored_val.bitwiseNand (operand_val, operand_ty, sema.arena, target),
14702 .Or => try stored_val.bitwiseOr (operand_val, sema.arena),
14703 .Xor => try stored_val.bitwiseXor (operand_val, sema.arena),
14705 .Or => try stored_val.bitwiseOr (operand_val, operand_ty, sema.arena),
14706 .Xor => try stored_val.bitwiseXor (operand_val, operand_ty, sema.arena),
1470414707 .Max => stored_val.numberMax (operand_val),
1470514708 .Min => stored_val.numberMin (operand_val),
1470614709 // zig fmt: on
......@@ -17523,7 +17526,7 @@ fn coerce(
1752317526 if (val.floatHasFraction()) {
1752417527 return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val.fmtValue(inst_ty), dest_ty });
1752517528 }
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) {
1752717530 error.FloatCannotFit => {
1752817531 return sema.fail(block, inst_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty });
1752917532 },
......@@ -17586,7 +17589,7 @@ fn coerce(
1758617589 },
1758717590 .Int, .ComptimeInt => int: {
1758817591 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);
1759017593 // TODO implement this compile error
1759117594 //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty);
1759217595 //if (!int_again_val.eql(val, inst_ty)) {
......@@ -17823,8 +17826,21 @@ fn coerceInMemoryAllowed(
1782317826 return .ok;
1782417827 }
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
1782617843 // TODO: non-pointer-like optionals
17827 // TODO: vectors
1782817844
1782917845 return .no_match;
1783017846}
......@@ -19697,19 +19713,6 @@ fn cmpNumeric(
1969719713 const lhs_ty_tag = lhs_ty.zigTypeTag();
1969819714 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
1971319716 const runtime_src: LazySrcLoc = src: {
1971419717 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
1971519718 if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
......@@ -19895,6 +19898,46 @@ fn cmpNumeric(
1989519898 return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);
1989619899}
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
1989819941fn wrapOptional(
1989919942 sema: *Sema,
1990019943 block: *Block,
......@@ -21201,7 +21244,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
2120121244 map.putAssumeCapacityContext(copied_val, {}, .{ .ty = int_tag_ty });
2120221245 } else {
2120321246 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)
2120521248 else
2120621249 Value.zero;
2120721250 last_tag_val = val;
src/value.zig+728-43
......@@ -1846,8 +1846,23 @@ pub const Value = extern union {
18461846 return order(lhs, rhs).compare(op);
18471847 }
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.
18501851 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 {
18511866 return switch (op) {
18521867 .eq => lhs.eql(rhs, ty),
18531868 .neq => !lhs.eql(rhs, ty),
......@@ -1855,18 +1870,25 @@ pub const Value = extern union {
18551870 };
18561871 }
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
18581884 /// Asserts the value is comparable.
1859 /// For vectors this is only valid with op == .eq.
1885 /// Vector results will be reduced with AND.
18601886 pub fn compareWithZero(lhs: Value, op: std.math.CompareOperator) bool {
18611887 switch (lhs.tag()) {
1862 .repeated => {
1863 assert(op == .eq);
1864 return lhs.castTag(.repeated).?.data.compareWithZero(.eq);
1865 },
1888 .repeated => return lhs.castTag(.repeated).?.data.compareWithZero(op),
18661889 .aggregate => {
1867 assert(op == .eq);
18681890 for (lhs.castTag(.aggregate).?.data) |elem_val| {
1869 if (!elem_val.compareWithZero(.eq)) return false;
1891 if (!elem_val.compareWithZero(op)) return false;
18701892 }
18711893 return true;
18721894 },
......@@ -2404,6 +2426,27 @@ pub const Value = extern union {
24042426 };
24052427 }
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
24072450 /// Asserts the value is a single-item pointer to an array, or an array,
24082451 /// or an unknown-length pointer, and returns the element value at the index.
24092452 pub fn elemValue(val: Value, arena: Allocator, index: usize) !Value {
......@@ -2646,25 +2689,38 @@ pub const Value = extern union {
26462689 };
26472690 }
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());
26502706 switch (val.tag()) {
26512707 .undef, .zero, .one => return val,
26522708 .the_only_possible_value => return Value.initTag(.zero), // for i0, u0
26532709 .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);
26552711 },
26562712 .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);
26582714 },
26592715 .int_big_positive => {
26602716 const limbs = val.castTag(.int_big_positive).?.data;
26612717 const float = bigIntToFloat(limbs, true);
2662 return floatToValue(float, arena, dest_ty, target);
2718 return floatToValue(float, arena, float_ty, target);
26632719 },
26642720 .int_big_negative => {
26652721 const limbs = val.castTag(.int_big_negative).?.data;
26662722 const float = bigIntToFloat(limbs, false);
2667 return floatToValue(float, arena, dest_ty, target);
2723 return floatToValue(float, arena, float_ty, target);
26682724 },
26692725 else => unreachable,
26702726 }
......@@ -2694,7 +2750,20 @@ pub const Value = extern union {
26942750 }
26952751 }
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());
26982767 const Limb = std.math.big.Limb;
26992768
27002769 var value = val.toFloat(f64); // TODO: f128 ?
......@@ -2724,7 +2793,7 @@ pub const Value = extern union {
27242793 else
27252794 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)) {
27282797 return result;
27292798 } else {
27302799 return error.FloatCannotFit;
......@@ -2771,18 +2840,36 @@ pub const Value = extern union {
27712840 };
27722841 }
27732842
2774 /// Supports both floats and ints; handles undefined.
2843 /// Supports both (vectors of) floats and ints; handles undefined scalars.
27752844 pub fn numberAddWrap(
27762845 lhs: Value,
27772846 rhs: Value,
27782847 ty: Type,
27792848 arena: Allocator,
27802849 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,
27812868 ) !Value {
27822869 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
27832870
27842871 if (ty.zigTypeTag() == .ComptimeInt) {
2785 return intAdd(lhs, rhs, arena);
2872 return intAdd(lhs, rhs, ty, arena);
27862873 }
27872874
27882875 if (ty.isAnyFloat()) {
......@@ -2809,13 +2896,31 @@ pub const Value = extern union {
28092896 }
28102897 }
28112898
2812 /// Supports integers only; asserts neither operand is undefined.
2899 /// Supports (vectors of) integers only; asserts neither operand is undefined.
28132900 pub fn intAddSat(
28142901 lhs: Value,
28152902 rhs: Value,
28162903 ty: Type,
28172904 arena: Allocator,
28182905 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,
28192924 ) !Value {
28202925 assert(!lhs.isUndef());
28212926 assert(!rhs.isUndef());
......@@ -2861,18 +2966,36 @@ pub const Value = extern union {
28612966 };
28622967 }
28632968
2864 /// Supports both floats and ints; handles undefined.
2969 /// Supports both (vectors of) floats and ints; handles undefined scalars.
28652970 pub fn numberSubWrap(
28662971 lhs: Value,
28672972 rhs: Value,
28682973 ty: Type,
28692974 arena: Allocator,
28702975 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,
28712994 ) !Value {
28722995 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
28732996
28742997 if (ty.zigTypeTag() == .ComptimeInt) {
2875 return intSub(lhs, rhs, arena);
2998 return intSub(lhs, rhs, ty, arena);
28762999 }
28773000
28783001 if (ty.isAnyFloat()) {
......@@ -2883,13 +3006,31 @@ pub const Value = extern union {
28833006 return overflow_result.wrapped_result;
28843007 }
28853008
2886 /// Supports integers only; asserts neither operand is undefined.
3009 /// Supports (vectors of) integers only; asserts neither operand is undefined.
28873010 pub fn intSubSat(
28883011 lhs: Value,
28893012 rhs: Value,
28903013 ty: Type,
28913014 arena: Allocator,
28923015 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,
28933034 ) !Value {
28943035 assert(!lhs.isUndef());
28953036 assert(!rhs.isUndef());
......@@ -2944,18 +3085,36 @@ pub const Value = extern union {
29443085 };
29453086 }
29463087
2947 /// Supports both floats and ints; handles undefined.
3088 /// Supports both (vectors of) floats and ints; handles undefined scalars.
29483089 pub fn numberMulWrap(
29493090 lhs: Value,
29503091 rhs: Value,
29513092 ty: Type,
29523093 arena: Allocator,
29533094 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,
29543113 ) !Value {
29553114 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
29563115
29573116 if (ty.zigTypeTag() == .ComptimeInt) {
2958 return intMul(lhs, rhs, arena);
3117 return intMul(lhs, rhs, ty, arena);
29593118 }
29603119
29613120 if (ty.isAnyFloat()) {
......@@ -2966,13 +3125,31 @@ pub const Value = extern union {
29663125 return overflow_result.wrapped_result;
29673126 }
29683127
2969 /// Supports integers only; asserts neither operand is undefined.
3128 /// Supports (vectors of) integers only; asserts neither operand is undefined.
29703129 pub fn intMulSat(
29713130 lhs: Value,
29723131 rhs: Value,
29733132 ty: Type,
29743133 arena: Allocator,
29753134 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,
29763153 ) !Value {
29773154 assert(!lhs.isUndef());
29783155 assert(!rhs.isUndef());
......@@ -3025,8 +3202,20 @@ pub const Value = extern union {
30253202 };
30263203 }
30273204
3028 /// operands must be integers; handles undefined.
3205 /// operands must be (vectors of) integers; handles undefined scalars.
30293206 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 {
30303219 if (val.isUndef()) return Value.initTag(.undef);
30313220
30323221 const info = ty.intInfo(target);
......@@ -3050,8 +3239,20 @@ pub const Value = extern union {
30503239 return fromBigInt(arena, result_bigint.toConst());
30513240 }
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
30533254 /// 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 {
30553256 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
30563257
30573258 // TODO is this a performance issue? maybe we should try the operation without
......@@ -3070,22 +3271,46 @@ pub const Value = extern union {
30703271 return fromBigInt(arena, result_bigint.toConst());
30713272 }
30723273
3073 /// operands must be integers; handles undefined.
3274 /// operands must be (vectors of) integers; handles undefined scalars.
30743275 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 {
30753288 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
30793292 const all_ones = if (ty.isSignedInt())
30803293 try Value.Tag.int_i64.create(arena, -1)
30813294 else
30823295 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);
30853310 }
30863311
30873312 /// 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 {
30893314 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
30903315
30913316 // TODO is this a performance issue? maybe we should try the operation without
......@@ -3103,8 +3328,20 @@ pub const Value = extern union {
31033328 return fromBigInt(arena, result_bigint.toConst());
31043329 }
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
31063343 /// 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 {
31083345 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
31093346
31103347 // TODO is this a performance issue? maybe we should try the operation without
......@@ -3123,7 +3360,18 @@ pub const Value = extern union {
31233360 return fromBigInt(arena, result_bigint.toConst());
31243361 }
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 {
31273375 // TODO is this a performance issue? maybe we should try the operation without
31283376 // resorting to BigInt first.
31293377 var lhs_space: Value.BigIntSpace = undefined;
......@@ -3139,7 +3387,18 @@ pub const Value = extern union {
31393387 return fromBigInt(allocator, result_bigint.toConst());
31403388 }
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 {
31433402 // TODO is this a performance issue? maybe we should try the operation without
31443403 // resorting to BigInt first.
31453404 var lhs_space: Value.BigIntSpace = undefined;
......@@ -3155,7 +3414,18 @@ pub const Value = extern union {
31553414 return fromBigInt(allocator, result_bigint.toConst());
31563415 }
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 {
31593429 // TODO is this a performance issue? maybe we should try the operation without
31603430 // resorting to BigInt first.
31613431 var lhs_space: Value.BigIntSpace = undefined;
......@@ -3180,7 +3450,18 @@ pub const Value = extern union {
31803450 return fromBigInt(allocator, result_q.toConst());
31813451 }
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 {
31843465 // TODO is this a performance issue? maybe we should try the operation without
31853466 // resorting to BigInt first.
31863467 var lhs_space: Value.BigIntSpace = undefined;
......@@ -3205,7 +3486,18 @@ pub const Value = extern union {
32053486 return fromBigInt(allocator, result_q.toConst());
32063487 }
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 {
32093501 // TODO is this a performance issue? maybe we should try the operation without
32103502 // resorting to BigInt first.
32113503 var lhs_space: Value.BigIntSpace = undefined;
......@@ -3232,7 +3524,18 @@ pub const Value = extern union {
32323524 return fromBigInt(allocator, result_r.toConst());
32333525 }
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 {
32363539 // TODO is this a performance issue? maybe we should try the operation without
32373540 // resorting to BigInt first.
32383541 var lhs_space: Value.BigIntSpace = undefined;
......@@ -3270,6 +3573,17 @@ pub const Value = extern union {
32703573 }
32713574
32723575 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 {
32733587 switch (float_type.floatBits(target)) {
32743588 16 => {
32753589 const lhs_val = lhs.toFloat(f16);
......@@ -3304,6 +3618,17 @@ pub const Value = extern union {
33043618 }
33053619
33063620 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 {
33073632 switch (float_type.floatBits(target)) {
33083633 16 => {
33093634 const lhs_val = lhs.toFloat(f16);
......@@ -3337,7 +3662,18 @@ pub const Value = extern union {
33373662 }
33383663 }
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 {
33413677 // TODO is this a performance issue? maybe we should try the operation without
33423678 // resorting to BigInt first.
33433679 var lhs_space: Value.BigIntSpace = undefined;
......@@ -3358,7 +3694,30 @@ pub const Value = extern union {
33583694 return fromBigInt(allocator, result_bigint.toConst());
33593695 }
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 {
33623721 if (bits == 0) return Value.zero;
33633722
33643723 var val_space: Value.BigIntSpace = undefined;
......@@ -3374,7 +3733,18 @@ pub const Value = extern union {
33743733 return fromBigInt(allocator, result_bigint.toConst());
33753734 }
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 {
33783748 // TODO is this a performance issue? maybe we should try the operation without
33793749 // resorting to BigInt first.
33803750 var lhs_space: Value.BigIntSpace = undefined;
......@@ -3430,6 +3800,23 @@ pub const Value = extern union {
34303800 ty: Type,
34313801 arena: Allocator,
34323802 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,
34333820 ) !Value {
34343821 // TODO is this a performance issue? maybe we should try the operation without
34353822 // resorting to BigInt first.
......@@ -3458,13 +3845,41 @@ pub const Value = extern union {
34583845 arena: Allocator,
34593846 target: Target,
34603847 ) !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);
34623866 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);
34643868 return truncated;
34653869 }
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 {
34683883 // TODO is this a performance issue? maybe we should try the operation without
34693884 // resorting to BigInt first.
34703885 var lhs_space: Value.BigIntSpace = undefined;
......@@ -3497,6 +3912,23 @@ pub const Value = extern union {
34973912 float_type: Type,
34983913 arena: Allocator,
34993914 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,
35003932 ) !Value {
35013933 switch (float_type.floatBits(target)) {
35023934 16 => {
......@@ -3534,6 +3966,23 @@ pub const Value = extern union {
35343966 float_type: Type,
35353967 arena: Allocator,
35363968 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,
35373986 ) !Value {
35383987 switch (float_type.floatBits(target)) {
35393988 16 => {
......@@ -3571,6 +4020,23 @@ pub const Value = extern union {
35714020 float_type: Type,
35724021 arena: Allocator,
35734022 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,
35744040 ) !Value {
35754041 switch (float_type.floatBits(target)) {
35764042 16 => {
......@@ -3611,6 +4077,23 @@ pub const Value = extern union {
36114077 float_type: Type,
36124078 arena: Allocator,
36134079 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,
36144097 ) !Value {
36154098 switch (float_type.floatBits(target)) {
36164099 16 => {
......@@ -3651,6 +4134,23 @@ pub const Value = extern union {
36514134 float_type: Type,
36524135 arena: Allocator,
36534136 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,
36544154 ) !Value {
36554155 switch (float_type.floatBits(target)) {
36564156 16 => {
......@@ -3691,6 +4191,23 @@ pub const Value = extern union {
36914191 float_type: Type,
36924192 arena: Allocator,
36934193 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,
36944211 ) !Value {
36954212 switch (float_type.floatBits(target)) {
36964213 16 => {
......@@ -3726,6 +4243,17 @@ pub const Value = extern union {
37264243 }
37274244
37284245 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 {
37294257 switch (float_type.floatBits(target)) {
37304258 16 => {
37314259 const f = val.toFloat(f16);
......@@ -3758,6 +4286,17 @@ pub const Value = extern union {
37584286 }
37594287
37604288 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 {
37614300 switch (float_type.floatBits(target)) {
37624301 16 => {
37634302 const f = val.toFloat(f16);
......@@ -3790,6 +4329,17 @@ pub const Value = extern union {
37904329 }
37914330
37924331 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 {
37934343 switch (float_type.floatBits(target)) {
37944344 16 => {
37954345 const f = val.toFloat(f16);
......@@ -3822,6 +4372,17 @@ pub const Value = extern union {
38224372 }
38234373
38244374 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 {
38254386 switch (float_type.floatBits(target)) {
38264387 16 => {
38274388 const f = val.toFloat(f16);
......@@ -3854,6 +4415,17 @@ pub const Value = extern union {
38544415 }
38554416
38564417 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 {
38574429 switch (float_type.floatBits(target)) {
38584430 16 => {
38594431 const f = val.toFloat(f16);
......@@ -3886,6 +4458,17 @@ pub const Value = extern union {
38864458 }
38874459
38884460 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 {
38894472 switch (float_type.floatBits(target)) {
38904473 16 => {
38914474 const f = val.toFloat(f16);
......@@ -3918,6 +4501,17 @@ pub const Value = extern union {
39184501 }
39194502
39204503 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 {
39214515 switch (float_type.floatBits(target)) {
39224516 16 => {
39234517 const f = val.toFloat(f16);
......@@ -3950,6 +4544,17 @@ pub const Value = extern union {
39504544 }
39514545
39524546 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 {
39534558 switch (float_type.floatBits(target)) {
39544559 16 => {
39554560 const f = val.toFloat(f16);
......@@ -3982,6 +4587,17 @@ pub const Value = extern union {
39824587 }
39834588
39844589 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 {
39854601 switch (float_type.floatBits(target)) {
39864602 16 => {
39874603 const f = val.toFloat(f16);
......@@ -4011,6 +4627,17 @@ pub const Value = extern union {
40114627 }
40124628
40134629 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 {
40144641 switch (float_type.floatBits(target)) {
40154642 16 => {
40164643 const f = val.toFloat(f16);
......@@ -4040,6 +4667,17 @@ pub const Value = extern union {
40404667 }
40414668
40424669 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 {
40434681 switch (float_type.floatBits(target)) {
40444682 16 => {
40454683 const f = val.toFloat(f16);
......@@ -4069,6 +4707,17 @@ pub const Value = extern union {
40694707 }
40704708
40714709 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 {
40724721 switch (float_type.floatBits(target)) {
40734722 16 => {
40744723 const f = val.toFloat(f16);
......@@ -4098,6 +4747,17 @@ pub const Value = extern union {
40984747 }
40994748
41004749 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 {
41014761 switch (float_type.floatBits(target)) {
41024762 16 => {
41034763 const f = val.toFloat(f16);
......@@ -4133,6 +4793,31 @@ pub const Value = extern union {
41334793 addend: Value,
41344794 arena: Allocator,
41354795 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,
41364821 ) Allocator.Error!Value {
41374822 switch (float_type.floatBits(target)) {
41384823 16 => {