authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-05-31 23:14:48-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-06-01 08:24:01+01:00
log9edfccb9a7d23dbf02444023d042d5008a39462e
tree3eafb1c2bed9f2170d6861ca466dca9e6d74392a
parentec579aa0f372b2054ad659aaacd190c1a986d7f2
signaturelock-open Commit is signed but in an unrecognized format.

Legalize: implement scalarization of overflow intrinsics


19 files changed, 350 insertions(+), 98 deletions(-)

lib/std/simd.zig-1
......@@ -455,7 +455,6 @@ pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: a
455455}
456456
457457test "vector prefix scan" {
458 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
459458 if ((builtin.cpu.arch == .armeb or builtin.cpu.arch == .thumbeb) and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/22060
460459 if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21893
461460 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
src/Air/Legalize.zig+191-7
......@@ -33,6 +33,10 @@ pub const Feature = enum {
3333 scalarize_mod_optimized,
3434 scalarize_max,
3535 scalarize_min,
36 scalarize_add_with_overflow,
37 scalarize_sub_with_overflow,
38 scalarize_mul_with_overflow,
39 scalarize_shl_with_overflow,
3640 scalarize_bit_and,
3741 scalarize_bit_or,
3842 scalarize_shr,
......@@ -129,6 +133,10 @@ pub const Feature = enum {
129133 .mod_optimized => .scalarize_mod_optimized,
130134 .max => .scalarize_max,
131135 .min => .scalarize_min,
136 .add_with_overflow => .scalarize_add_with_overflow,
137 .sub_with_overflow => .scalarize_sub_with_overflow,
138 .mul_with_overflow => .scalarize_mul_with_overflow,
139 .shl_with_overflow => .scalarize_shl_with_overflow,
132140 .bit_and => .scalarize_bit_and,
133141 .bit_or => .scalarize_bit_or,
134142 .shr => .scalarize_shr,
......@@ -279,10 +287,15 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
279287 },
280288 .ptr_add,
281289 .ptr_sub,
282 .add_with_overflow,
290 => {},
291 inline .add_with_overflow,
283292 .sub_with_overflow,
284293 .mul_with_overflow,
285294 .shl_with_overflow,
295 => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) {
296 const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl;
297 if (ty_pl.ty.toType().fieldType(0, zcu).isVector(zcu)) continue :inst l.replaceInst(inst, .block, try l.scalarizeOverflowBlockPayload(inst));
298 },
286299 .alloc,
287300 => {},
288301 .inferred_alloc,
......@@ -518,7 +531,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
518531 switch (vector_ty.vectorLen(zcu)) {
519532 0 => unreachable,
520533 1 => continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{
521 .ty = Air.internedToRef(vector_ty.scalarType(zcu).toIntern()),
534 .ty = Air.internedToRef(vector_ty.childType(zcu).toIntern()),
522535 .operand = reduce.operand,
523536 } }),
524537 else => break :done,
......@@ -646,7 +659,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime form:
646659 .ty_op => loop.block.add(l, .{
647660 .tag = orig.tag,
648661 .data = .{ .ty_op = .{
649 .ty = Air.internedToRef(orig.data.ty_op.ty.toType().scalarType(zcu).toIntern()),
662 .ty = Air.internedToRef(res_ty.childType(zcu).toIntern()),
650663 .operand = loop.block.add(l, .{
651664 .tag = .array_elem_val,
652665 .data = .{ .bin_op = .{
......@@ -745,7 +758,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime form:
745758 .shuffle_two => unwrapped.operand_a,
746759 };
747760 const operand_a_len = l.typeOf(operand_a).vectorLen(zcu);
748 const elem_ty = unwrapped.result_ty.scalarType(zcu);
761 const elem_ty = res_ty.childType(zcu);
749762 var res_elem: Result = .init(l, elem_ty, &loop.block);
750763 res_elem.block = .init(loop.block.stealCapacity(extra_insts));
751764 {
......@@ -945,7 +958,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime form:
945958 },
946959 .select => {
947960 const extra = l.extraData(Air.Bin, orig.data.pl_op.payload).data;
948 var res_elem: Result = .init(l, l.typeOf(extra.lhs).scalarType(zcu), &loop.block);
961 var res_elem: Result = .init(l, l.typeOf(extra.lhs).childType(zcu), &loop.block);
949962 res_elem.block = .init(loop.block.stealCapacity(extra_insts));
950963 {
951964 var select_cond_br: CondBr = .init(l, res_elem.block.add(l, .{
......@@ -1043,6 +1056,176 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime form:
10431056 .payload = try l.addBlockBody(res_block.body()),
10441057 } };
10451058}
1059fn scalarizeOverflowBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.Inst.Data {
1060 const pt = l.pt;
1061 const zcu = pt.zcu;
1062
1063 const orig = l.air_instructions.get(@intFromEnum(orig_inst));
1064 const res_ty = l.typeOfIndex(orig_inst);
1065 const wrapped_res_ty = res_ty.fieldType(0, zcu);
1066 const wrapped_res_scalar_ty = wrapped_res_ty.childType(zcu);
1067 const res_len = wrapped_res_ty.vectorLen(zcu);
1068
1069 var inst_buf: [21]Air.Inst.Index = undefined;
1070 try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len);
1071
1072 var res_block: Block = .init(&inst_buf);
1073 {
1074 const res_alloc_inst = res_block.add(l, .{
1075 .tag = .alloc,
1076 .data = .{ .ty = try pt.singleMutPtrType(res_ty) },
1077 });
1078 const ptr_wrapped_res_inst = res_block.add(l, .{
1079 .tag = .struct_field_ptr_index_0,
1080 .data = .{ .ty_op = .{
1081 .ty = Air.internedToRef((try pt.singleMutPtrType(wrapped_res_ty)).toIntern()),
1082 .operand = res_alloc_inst.toRef(),
1083 } },
1084 });
1085 const ptr_overflow_res_inst = res_block.add(l, .{
1086 .tag = .struct_field_ptr_index_1,
1087 .data = .{ .ty_op = .{
1088 .ty = Air.internedToRef((try pt.singleMutPtrType(res_ty.fieldType(1, zcu))).toIntern()),
1089 .operand = res_alloc_inst.toRef(),
1090 } },
1091 });
1092 const index_alloc_inst = res_block.add(l, .{
1093 .tag = .alloc,
1094 .data = .{ .ty = .ptr_usize },
1095 });
1096 _ = res_block.add(l, .{
1097 .tag = .store,
1098 .data = .{ .bin_op = .{
1099 .lhs = index_alloc_inst.toRef(),
1100 .rhs = .zero_usize,
1101 } },
1102 });
1103
1104 var loop: Loop = .init(l, &res_block);
1105 loop.block = .init(res_block.stealRemainingCapacity());
1106 {
1107 const cur_index_inst = loop.block.add(l, .{
1108 .tag = .load,
1109 .data = .{ .ty_op = .{
1110 .ty = .usize_type,
1111 .operand = index_alloc_inst.toRef(),
1112 } },
1113 });
1114 const extra = l.extraData(Air.Bin, orig.data.ty_pl.payload).data;
1115 const res_elem = loop.block.add(l, .{
1116 .tag = orig.tag,
1117 .data = .{ .ty_pl = .{
1118 .ty = Air.internedToRef(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{
1119 .types = &.{ wrapped_res_scalar_ty.toIntern(), .u1_type },
1120 .values = &(.{.none} ** 2),
1121 })),
1122 .payload = try l.addExtra(Air.Bin, .{
1123 .lhs = loop.block.add(l, .{
1124 .tag = .array_elem_val,
1125 .data = .{ .bin_op = .{
1126 .lhs = extra.lhs,
1127 .rhs = cur_index_inst.toRef(),
1128 } },
1129 }).toRef(),
1130 .rhs = loop.block.add(l, .{
1131 .tag = .array_elem_val,
1132 .data = .{ .bin_op = .{
1133 .lhs = extra.rhs,
1134 .rhs = cur_index_inst.toRef(),
1135 } },
1136 }).toRef(),
1137 }),
1138 } },
1139 });
1140 _ = loop.block.add(l, .{
1141 .tag = .vector_store_elem,
1142 .data = .{ .vector_store_elem = .{
1143 .vector_ptr = ptr_overflow_res_inst.toRef(),
1144 .payload = try l.addExtra(Air.Bin, .{
1145 .lhs = cur_index_inst.toRef(),
1146 .rhs = loop.block.add(l, .{
1147 .tag = .struct_field_val,
1148 .data = .{ .ty_pl = .{
1149 .ty = .u1_type,
1150 .payload = try l.addExtra(Air.StructField, .{
1151 .struct_operand = res_elem.toRef(),
1152 .field_index = 1,
1153 }),
1154 } },
1155 }).toRef(),
1156 }),
1157 } },
1158 });
1159 _ = loop.block.add(l, .{
1160 .tag = .vector_store_elem,
1161 .data = .{ .vector_store_elem = .{
1162 .vector_ptr = ptr_wrapped_res_inst.toRef(),
1163 .payload = try l.addExtra(Air.Bin, .{
1164 .lhs = cur_index_inst.toRef(),
1165 .rhs = loop.block.add(l, .{
1166 .tag = .struct_field_val,
1167 .data = .{ .ty_pl = .{
1168 .ty = Air.internedToRef(wrapped_res_scalar_ty.toIntern()),
1169 .payload = try l.addExtra(Air.StructField, .{
1170 .struct_operand = res_elem.toRef(),
1171 .field_index = 0,
1172 }),
1173 } },
1174 }).toRef(),
1175 }),
1176 } },
1177 });
1178
1179 var loop_cond_br: CondBr = .init(l, (try loop.block.addCmp(
1180 l,
1181 .lt,
1182 cur_index_inst.toRef(),
1183 try pt.intRef(.usize, res_len - 1),
1184 .{},
1185 )).toRef(), &loop.block, .{});
1186 loop_cond_br.then_block = .init(loop.block.stealRemainingCapacity());
1187 {
1188 _ = loop_cond_br.then_block.add(l, .{
1189 .tag = .store,
1190 .data = .{ .bin_op = .{
1191 .lhs = index_alloc_inst.toRef(),
1192 .rhs = loop_cond_br.then_block.add(l, .{
1193 .tag = .add,
1194 .data = .{ .bin_op = .{
1195 .lhs = cur_index_inst.toRef(),
1196 .rhs = .one_usize,
1197 } },
1198 }).toRef(),
1199 } },
1200 });
1201 _ = loop_cond_br.then_block.add(l, .{
1202 .tag = .repeat,
1203 .data = .{ .repeat = .{ .loop_inst = loop.inst } },
1204 });
1205 }
1206 loop_cond_br.else_block = .init(loop_cond_br.then_block.stealRemainingCapacity());
1207 _ = loop_cond_br.else_block.add(l, .{
1208 .tag = .br,
1209 .data = .{ .br = .{
1210 .block_inst = orig_inst,
1211 .operand = loop_cond_br.else_block.add(l, .{
1212 .tag = .load,
1213 .data = .{ .ty_op = .{
1214 .ty = Air.internedToRef(res_ty.toIntern()),
1215 .operand = res_alloc_inst.toRef(),
1216 } },
1217 }).toRef(),
1218 } },
1219 });
1220 try loop_cond_br.finish(l);
1221 }
1222 try loop.finish(l);
1223 }
1224 return .{ .ty_pl = .{
1225 .ty = Air.internedToRef(res_ty.toIntern()),
1226 .payload = try l.addBlockBody(res_block.body()),
1227 } };
1228}
10461229
10471230fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.Inst.Data {
10481231 const pt = l.pt;
......@@ -1535,8 +1718,9 @@ fn addBlockBody(l: *Legalize, body: []const Air.Inst.Index) Error!u32 {
15351718 return @intCast(l.air_extra.items.len);
15361719}
15371720
1538// inline to propagate comptime `tag`s
1539inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag {
1721/// Returns `tag` to remind the caller to `continue :inst` the result.
1722/// This is inline to propagate the comptime-known `tag`.
1723inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, comptime tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag {
15401724 const orig_ty = if (std.debug.runtime_safety) l.typeOfIndex(inst) else {};
15411725 l.air_instructions.set(@intFromEnum(inst), .{ .tag = tag, .data = data });
15421726 if (std.debug.runtime_safety) assert(l.typeOfIndex(inst).toIntern() == orig_ty.toIntern());
src/arch/x86_64/CodeGen.zig+78-47
......@@ -53,6 +53,10 @@ pub fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features
5353 .scalarize_div_exact_optimized = use_old,
5454 .scalarize_max = use_old,
5555 .scalarize_min = use_old,
56 .scalarize_add_with_overflow = true,
57 .scalarize_sub_with_overflow = true,
58 .scalarize_mul_with_overflow = true,
59 .scalarize_shl_with_overflow = true,
5660 .scalarize_bit_and = use_old,
5761 .scalarize_bit_or = use_old,
5862 .scalarize_shr = true,
......@@ -283,7 +287,7 @@ pub const MCValue = union(enum) {
283287 /// Payload is a frame address.
284288 lea_frame: bits.FrameAddr,
285289 /// Supports integer_per_element abi
286 elementwise_regs_then_frame: packed struct { regs: u3, frame_off: i29, frame_index: FrameIndex },
290 elementwise_args: packed struct { regs: u3, frame_off: i29, frame_index: FrameIndex },
287291 /// This indicates that we have already allocated a frame index for this instruction,
288292 /// but it has not been spilled there yet in the current control flow.
289293 /// Payload is a frame index.
......@@ -305,7 +309,7 @@ pub const MCValue = union(enum) {
305309 .lea_direct,
306310 .lea_got,
307311 .lea_frame,
308 .elementwise_regs_then_frame,
312 .elementwise_args,
309313 .reserved_frame,
310314 .air_ref,
311315 => false,
......@@ -420,7 +424,7 @@ pub const MCValue = union(enum) {
420424 .lea_direct,
421425 .lea_got,
422426 .lea_frame,
423 .elementwise_regs_then_frame,
427 .elementwise_args,
424428 .reserved_frame,
425429 .air_ref,
426430 => unreachable, // not in memory
......@@ -454,7 +458,7 @@ pub const MCValue = union(enum) {
454458 .load_got,
455459 .load_frame,
456460 .load_symbol,
457 .elementwise_regs_then_frame,
461 .elementwise_args,
458462 .reserved_frame,
459463 .air_ref,
460464 => unreachable, // not dereferenceable
......@@ -474,7 +478,7 @@ pub const MCValue = union(enum) {
474478 .unreach,
475479 .dead,
476480 .undef,
477 .elementwise_regs_then_frame,
481 .elementwise_args,
478482 .reserved_frame,
479483 .air_ref,
480484 => unreachable, // not valid
......@@ -528,7 +532,7 @@ pub const MCValue = union(enum) {
528532 .load_got,
529533 .lea_got,
530534 .lea_frame,
531 .elementwise_regs_then_frame,
535 .elementwise_args,
532536 .reserved_frame,
533537 .lea_symbol,
534538 => unreachable,
......@@ -612,7 +616,7 @@ pub const MCValue = union(enum) {
612616 .load_got => |pl| try writer.print("[got:{d}]", .{pl}),
613617 .lea_got => |pl| try writer.print("got:{d}", .{pl}),
614618 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
615 .elementwise_regs_then_frame => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{
619 .elementwise_args => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{
616620 pl.regs, pl.frame_index, pl.frame_off,
617621 }),
618622 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),
......@@ -645,7 +649,7 @@ const InstTracking = struct {
645649 .lea_symbol,
646650 => result,
647651 .dead,
648 .elementwise_regs_then_frame,
652 .elementwise_args,
649653 .reserved_frame,
650654 .air_ref,
651655 => unreachable,
......@@ -754,7 +758,7 @@ const InstTracking = struct {
754758 .register_overflow,
755759 .register_mask,
756760 .indirect,
757 .elementwise_regs_then_frame,
761 .elementwise_args,
758762 .air_ref,
759763 => unreachable,
760764 }
......@@ -168424,7 +168428,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE
168424168428 .register_quadruple,
168425168429 .register_overflow,
168426168430 .register_mask,
168427 .elementwise_regs_then_frame,
168431 .elementwise_args,
168428168432 .reserved_frame,
168429168433 => unreachable, // not a valid pointer
168430168434 .immediate,
......@@ -168642,7 +168646,7 @@ fn store(
168642168646 .register_quadruple,
168643168647 .register_overflow,
168644168648 .register_mask,
168645 .elementwise_regs_then_frame,
168649 .elementwise_args,
168646168650 .reserved_frame,
168647168651 => unreachable, // not a valid pointer
168648168652 .immediate,
......@@ -169128,7 +169132,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv:
169128169132 .lea_direct,
169129169133 .lea_got,
169130169134 .lea_frame,
169131 .elementwise_regs_then_frame,
169135 .elementwise_args,
169132169136 .reserved_frame,
169133169137 .air_ref,
169134169138 => unreachable, // unmodifiable destination
......@@ -170799,7 +170803,7 @@ fn genBinOp(
170799170803 .load_got,
170800170804 .lea_got,
170801170805 .lea_frame,
170802 .elementwise_regs_then_frame,
170806 .elementwise_args,
170803170807 .reserved_frame,
170804170808 .air_ref,
170805170809 => unreachable,
......@@ -171982,7 +171986,7 @@ fn genBinOpMir(
171982171986 .lea_got,
171983171987 .lea_frame,
171984171988 .lea_symbol,
171985 .elementwise_regs_then_frame,
171989 .elementwise_args,
171986171990 .reserved_frame,
171987171991 .air_ref,
171988171992 => unreachable, // unmodifiable destination
......@@ -172018,7 +172022,7 @@ fn genBinOpMir(
172018172022 .undef,
172019172023 .register_overflow,
172020172024 .register_mask,
172021 .elementwise_regs_then_frame,
172025 .elementwise_args,
172022172026 .reserved_frame,
172023172027 => unreachable,
172024172028 .register,
......@@ -172178,7 +172182,7 @@ fn genBinOpMir(
172178172182 .undef,
172179172183 .register_overflow,
172180172184 .register_mask,
172181 .elementwise_regs_then_frame,
172185 .elementwise_args,
172182172186 .reserved_frame,
172183172187 .air_ref,
172184172188 => unreachable,
......@@ -172274,7 +172278,7 @@ fn genBinOpMir(
172274172278 .undef,
172275172279 .register_overflow,
172276172280 .register_mask,
172277 .elementwise_regs_then_frame,
172281 .elementwise_args,
172278172282 .reserved_frame,
172279172283 .air_ref,
172280172284 => unreachable,
......@@ -172405,7 +172409,7 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv
172405172409 .lea_direct,
172406172410 .lea_got,
172407172411 .lea_frame,
172408 .elementwise_regs_then_frame,
172412 .elementwise_args,
172409172413 .reserved_frame,
172410172414 .air_ref,
172411172415 => unreachable, // unmodifiable destination
......@@ -172437,7 +172441,7 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv
172437172441 .register_quadruple,
172438172442 .register_overflow,
172439172443 .register_mask,
172440 .elementwise_regs_then_frame,
172444 .elementwise_args,
172441172445 .reserved_frame,
172442172446 .air_ref,
172443172447 => unreachable,
......@@ -172557,7 +172561,7 @@ fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void {
172557172561 try self.genCopy(arg_ty, dst_mcv, src_mcv, .{});
172558172562 break :result dst_mcv;
172559172563 },
172560 .elementwise_regs_then_frame => |regs_frame_addr| {
172564 .elementwise_args => |regs_frame_addr| {
172561172565 try self.spillEflagsIfOccupied();
172562172566
172563172567 const fn_info = zcu.typeToFunc(self.fn_type).?;
......@@ -172661,7 +172665,7 @@ fn genLocalDebugInfo(
172661172665 .arg, .dbg_arg_inline, .dbg_var_val => |tag| {
172662172666 switch (mcv) {
172663172667 .none => try self.asmAir(.dbg_local, inst),
172664 .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
172668 .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
172665172669 .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, .u(imm)),
172666172670 .lea_frame => |frame_addr| try self.asmAirFrameAddress(.dbg_local, inst, frame_addr),
172667172671 .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, .rel(sym_off)),
......@@ -172684,7 +172688,7 @@ fn genLocalDebugInfo(
172684172688 },
172685172689 .dbg_var_ptr => switch (mcv) {
172686172690 else => unreachable,
172687 .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
172691 .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
172688172692 .lea_frame => |frame_addr| try self.asmAirMemory(.dbg_local, inst, .{
172689172693 .base = .{ .frame = frame_addr.index },
172690172694 .mod = .{ .rm = .{
......@@ -172853,7 +172857,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
172853172857 try self.genCopy(arg_ty, dst_arg, src_arg, opts);
172854172858 try self.freeValue(src_arg);
172855172859 },
172856 .elementwise_regs_then_frame => |regs_frame_addr| {
172860 .elementwise_args => |regs_frame_addr| {
172857172861 const index_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
172858172862 const index_lock = self.register_manager.lockRegAssumeUnused(index_reg);
172859172863 defer self.register_manager.unlockReg(index_lock);
......@@ -172962,7 +172966,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
172962172966 .indirect => |reg_off| try self.genSetReg(reg_off.reg, .usize, .{
172963172967 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
172964172968 }, .{}),
172965 .elementwise_regs_then_frame => |regs_frame_addr| {
172969 .elementwise_args => |regs_frame_addr| {
172966172970 const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(self, .{ .size = .dword }) else .{
172967172971 .base = .{ .reg = try self.copyToTmpRegister(
172968172972 .usize,
......@@ -173350,7 +173354,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
173350173354 .lea_got,
173351173355 .lea_frame,
173352173356 .lea_symbol,
173353 .elementwise_regs_then_frame,
173357 .elementwise_args,
173354173358 .reserved_frame,
173355173359 .air_ref,
173356173360 => unreachable,
......@@ -173405,7 +173409,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
173405173409 .lea_direct,
173406173410 .lea_got,
173407173411 .lea_frame,
173408 .elementwise_regs_then_frame,
173412 .elementwise_args,
173409173413 .reserved_frame,
173410173414 .air_ref,
173411173415 => unreachable,
......@@ -173810,7 +173814,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue)
173810173814 .lea_direct,
173811173815 .lea_got,
173812173816 .lea_symbol,
173813 .elementwise_regs_then_frame,
173817 .elementwise_args,
173814173818 .reserved_frame,
173815173819 .air_ref,
173816173820 => unreachable,
......@@ -175867,7 +175871,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
175867175871 .lea_got,
175868175872 .lea_frame,
175869175873 .lea_symbol,
175870 .elementwise_regs_then_frame,
175874 .elementwise_args,
175871175875 .reserved_frame,
175872175876 .air_ref,
175873175877 => unreachable, // unmodifiable destination
......@@ -175878,7 +175882,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
175878175882 .dead,
175879175883 .undef,
175880175884 .register_overflow,
175881 .elementwise_regs_then_frame,
175885 .elementwise_args,
175882175886 .reserved_frame,
175883175887 => unreachable,
175884175888 .immediate,
......@@ -176056,7 +176060,7 @@ fn genSetReg(
176056176060 .none,
176057176061 .unreach,
176058176062 .dead,
176059 .elementwise_regs_then_frame,
176063 .elementwise_args,
176060176064 .reserved_frame,
176061176065 => unreachable,
176062176066 .undef => if (opts.safety) switch (dst_reg.class()) {
......@@ -176593,7 +176597,7 @@ fn genSetMem(
176593176597 .none,
176594176598 .unreach,
176595176599 .dead,
176596 .elementwise_regs_then_frame,
176600 .elementwise_args,
176597176601 .reserved_frame,
176598176602 => unreachable,
176599176603 .undef => if (opts.safety) try self.genInlineMemset(
......@@ -180885,7 +180889,7 @@ fn resolveCallingConventionValues(
180885180889
180886180890 result.stack_byte_count =
180887180891 std.mem.alignForward(u31, result.stack_byte_count, frame_elem_align);
180888 arg_mcv[arg_mcv_i] = .{ .elementwise_regs_then_frame = .{
180892 arg_mcv[arg_mcv_i] = .{ .elementwise_args = .{
180889180893 .regs = remaining_param_int_regs,
180890180894 .frame_off = @intCast(result.stack_byte_count),
180891180895 .frame_index = stack_frame_base,
......@@ -181510,7 +181514,7 @@ const Temp = struct {
181510181514 .load_got,
181511181515 .lea_got,
181512181516 .lea_frame,
181513 .elementwise_regs_then_frame,
181517 .elementwise_args,
181514181518 .reserved_frame,
181515181519 .air_ref,
181516181520 => false,
......@@ -181945,7 +181949,7 @@ const Temp = struct {
181945181949 .register_quadruple,
181946181950 .register_overflow,
181947181951 .register_mask,
181948 .elementwise_regs_then_frame,
181952 .elementwise_args,
181949181953 .reserved_frame,
181950181954 .air_ref,
181951181955 => unreachable, // not a valid pointer
......@@ -186669,19 +186673,46 @@ const Temp = struct {
186669186673 if (cg.reused_operands.isSet(op_index)) continue;
186670186674 try cg.processDeath(op_ref.toIndexAllowNone() orelse continue);
186671186675 }
186672 if (cg.liveness.isUnused(inst)) try temp.die(cg) else switch (temp.unwrap(cg)) {
186673 .ref, .err_ret_trace => {
186674 const result = try cg.allocRegOrMem(inst, true);
186675 try cg.genCopy(cg.typeOfIndex(inst), result, temp.tracking(cg).short, .{});
186676 tracking_log.debug("{} => {} (birth)", .{ inst, result });
186677 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result));
186678 },
186679 .temp => |temp_index| {
186680 const temp_tracking = temp_index.tracking(cg);
186681 tracking_log.debug("{} => {} (birth)", .{ inst, temp_tracking.short });
186682 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(temp_tracking.short));
186683 assert(cg.reuseTemp(inst, temp_index.toIndex(), temp_tracking));
186684 },
186676 if (cg.liveness.isUnused(inst)) try temp.die(cg) else {
186677 switch (temp.unwrap(cg)) {
186678 .ref, .err_ret_trace => {
186679 const temp_mcv = temp.tracking(cg).short;
186680 const result = result: switch (temp_mcv) {
186681 .none, .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
186682 .undef, .immediate, .lea_frame => temp_mcv,
186683 .eflags,
186684 .register,
186685 .register_pair,
186686 .register_triple,
186687 .register_quadruple,
186688 .register_offset,
186689 .register_overflow,
186690 .register_mask,
186691 .memory,
186692 .load_symbol,
186693 .lea_symbol,
186694 .indirect,
186695 .load_direct,
186696 .lea_direct,
186697 .load_got,
186698 .lea_got,
186699 .load_frame,
186700 => {
186701 const result = try cg.allocRegOrMem(inst, true);
186702 try cg.genCopy(cg.typeOfIndex(inst), result, temp_mcv, .{});
186703 break :result result;
186704 },
186705 };
186706 tracking_log.debug("{} => {} (birth)", .{ inst, result });
186707 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result));
186708 },
186709 .temp => |temp_index| {
186710 const temp_tracking = temp_index.tracking(cg);
186711 tracking_log.debug("{} => {} (birth)", .{ inst, temp_tracking.short });
186712 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(temp_tracking.short));
186713 assert(cg.reuseTemp(inst, temp_index.toIndex(), temp_tracking));
186714 },
186715 }
186685186716 }
186686186717 for (0.., op_refs, op_temps) |op_index, op_ref, op_temp| {
186687186718 if (op_temp.index != temp.index) continue;
test/behavior/floatop.zig+36-12
......@@ -14,9 +14,11 @@ fn epsForType(comptime T: type) T {
1414}
1515
1616test "add f16" {
17 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1817 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1918
19 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
20 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest;
21
2022 try testAdd(f16);
2123 try comptime testAdd(f16);
2224}
......@@ -123,10 +125,12 @@ fn testMul(comptime T: type) !void {
123125
124126test "cmp f16" {
125127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
127128 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
128129 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
129130
131 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
132 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest;
133
130134 try testCmp(f16);
131135 try comptime testCmp(f16);
132136}
......@@ -338,9 +342,11 @@ test "different sized float comparisons" {
338342 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
339343 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
340344 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
341 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
342345 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
343346
347 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
348 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest;
349
344350 try testDifferentSizedFloatComparisons();
345351 try comptime testDifferentSizedFloatComparisons();
346352}
......@@ -386,10 +392,12 @@ test "@sqrt f16" {
386392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
387393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
388394 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
389 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
390395 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
391396 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
392397
398 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
399 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest;
400
393401 try testSqrt(f16);
394402 try comptime testSqrt(f16);
395403}
......@@ -1129,9 +1137,11 @@ test "@abs f16" {
11291137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11301138 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11311139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1132 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
11331140 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11341141
1142 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
1143 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest;
1144
11351145 try testFabs(f16);
11361146 try comptime testFabs(f16);
11371147}
......@@ -1263,9 +1273,11 @@ test "@floor f32/f64" {
12631273 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12641274 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12651275 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1266 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
12671276 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12681277
1278 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
1279 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
1280
12691281 try testFloor(f32);
12701282 try comptime testFloor(f32);
12711283 try testFloor(f64);
......@@ -1329,7 +1341,9 @@ test "@floor with vectors" {
13291341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13301342 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
13311343 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1332 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1344
1345 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
1346 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
13331347
13341348 try testFloorWithVectors();
13351349 try comptime testFloorWithVectors();
......@@ -1360,9 +1374,11 @@ test "@ceil f32/f64" {
13601374 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13611375 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13621376 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1363 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
13641377 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13651378
1379 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
1380 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
1381
13661382 try testCeil(f32);
13671383 try comptime testCeil(f32);
13681384 try testCeil(f64);
......@@ -1426,7 +1442,9 @@ test "@ceil with vectors" {
14261442 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14271443 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
14281444 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1429 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1445
1446 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
1447 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
14301448
14311449 try testCeilWithVectors();
14321450 try comptime testCeilWithVectors();
......@@ -1457,9 +1475,11 @@ test "@trunc f32/f64" {
14571475 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14581476 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14591477 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1460 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
14611478 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14621479
1480 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
1481 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
1482
14631483 try testTrunc(f32);
14641484 try comptime testTrunc(f32);
14651485 try testTrunc(f64);
......@@ -1523,7 +1543,9 @@ test "@trunc with vectors" {
15231543 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15241544 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
15251545 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1526 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1546
1547 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
1548 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
15271549
15281550 try testTruncWithVectors();
15291551 try comptime testTruncWithVectors();
......@@ -1543,9 +1565,11 @@ test "neg f16" {
15431565 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15441566 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15451567 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1546 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
15471568 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15481569
1570 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
1571 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest;
1572
15491573 if (builtin.os.tag == .freebsd) {
15501574 // TODO file issue to track this failure
15511575 return error.SkipZigTest;
test/behavior/math.zig+7-3
......@@ -471,10 +471,12 @@ test "division" {
471471 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
472472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
473473 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
474 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
475474 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
476475 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
477476
477 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
478 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest;
479
478480 try testIntDivision();
479481 try comptime testIntDivision();
480482
......@@ -1619,10 +1621,10 @@ test "vector integer addition" {
16191621 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16201622 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16211623 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1622 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
16231624 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16241625 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
16251626 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1627 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
16261628
16271629 const S = struct {
16281630 fn doTheTest() !void {
......@@ -1926,7 +1928,9 @@ test "float vector division of comptime zero by runtime nan is nan" {
19261928 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
19271929 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19281930 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1929 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1931
1932 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
1933 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
19301934
19311935 const ct_zero: @Vector(1, f32) = .{0};
19321936 var rt_nan: @Vector(1, f32) = .{math.nan(f32)};
test/behavior/maximum_minimum.zig-1
......@@ -204,7 +204,6 @@ test "@min/@max notices vector bounds" {
204204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
205205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
206206 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
207 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
208207
209208 var x: @Vector(2, u16) = .{ 140, 40 };
210209 const y: @Vector(2, u64) = .{ 5, 100 };
test/behavior/muladd.zig+9-3
......@@ -6,10 +6,12 @@ test "@mulAdd" {
66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
109 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1110 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1211
12 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
13 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .fma)) return error.SkipZigTest;
14
1315 try comptime testMulAdd();
1416 try testMulAdd();
1517}
......@@ -137,10 +139,12 @@ test "vector f32" {
137139 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
138140 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
139141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
141142 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
142143 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
143144
145 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
146 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .fma)) return error.SkipZigTest;
147
144148 try comptime vector32();
145149 try vector32();
146150}
......@@ -163,10 +167,12 @@ test "vector f64" {
163167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
164168 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
165169 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
166 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
167170 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
168171 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
169172
173 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
174 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .fma)) return error.SkipZigTest;
175
170176 try comptime vector64();
171177 try vector64();
172178}
test/behavior/vector.zig+8-10
......@@ -75,12 +75,12 @@ test "vector bin compares with mem.eql" {
7575
7676test "vector int operators" {
7777 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7978 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8079 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8180 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8281 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8382 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
8484
8585 const S = struct {
8686 fn doTheTest() !void {
......@@ -248,9 +248,11 @@ test "array to vector with element type coercion" {
248248 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
249249 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
250250 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
252251 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
253252
253 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and
254 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest;
255
254256 const S = struct {
255257 fn doTheTest() !void {
256258 var foo: f16 = 3.14;
......@@ -285,11 +287,11 @@ test "peer type resolution with coercible element types" {
285287
286288test "tuple to vector" {
287289 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
288 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
289290 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
290291 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
291292 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
292293 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
294 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
293295
294296 const S = struct {
295297 fn doTheTest() !void {
......@@ -682,12 +684,12 @@ test "vector bitwise not operator" {
682684
683685test "vector shift operators" {
684686 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
685 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
686687 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
687688 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
688689 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
689690 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
690691 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
692 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
691693
692694 const S = struct {
693695 fn doTheTestShift(x: anytype, y: anytype) !void {
......@@ -1036,12 +1038,12 @@ test "saturating shift-left" {
10361038
10371039test "multiplication-assignment operator with an array operand" {
10381040 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1039 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10401041 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10411042 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10421043 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10431044 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10441045 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1046 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
10451047
10461048 const S = struct {
10471049 fn doTheTest() !void {
......@@ -1058,7 +1060,6 @@ test "multiplication-assignment operator with an array operand" {
10581060
10591061test "@addWithOverflow" {
10601062 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1061 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10621063 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10631064 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10641065 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1109,7 +1110,6 @@ test "@addWithOverflow" {
11091110
11101111test "@subWithOverflow" {
11111112 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1112 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11131113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11141114 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11151115 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1144,7 +1144,6 @@ test "@subWithOverflow" {
11441144
11451145test "@mulWithOverflow" {
11461146 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1147 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11481147 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11491148 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11501149 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1168,7 +1167,6 @@ test "@mulWithOverflow" {
11681167
11691168test "@shlWithOverflow" {
11701169 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1171 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11721170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11731171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11741172 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1307,7 +1305,7 @@ test "zero multiplicand" {
13071305 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13081306 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13091307 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1310 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1308 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
13111309
13121310 const zeros = @Vector(2, u32){ 0.0, 0.0 };
13131311 var ones = @Vector(2, u32){ 1.0, 1.0 };
test/behavior/x86_64/binary.zig+8-4
......@@ -5244,31 +5244,34 @@ test min {
52445244 try test_min.testFloatVectors();
52455245}
52465246
5247inline fn addWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, u1 } {
5247inline fn addWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, ChangeScalar(Type, u1) } {
52485248 return @addWithOverflow(lhs, rhs);
52495249}
52505250test addWithOverflow {
52515251 const test_add_with_overflow = binary(addWithOverflow, .{});
52525252 try test_add_with_overflow.testInts();
5253 try test_add_with_overflow.testIntVectors();
52535254}
52545255
5255inline fn subWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, u1 } {
5256inline fn subWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, ChangeScalar(Type, u1) } {
52565257 return @subWithOverflow(lhs, rhs);
52575258}
52585259test subWithOverflow {
52595260 const test_sub_with_overflow = binary(subWithOverflow, .{});
52605261 try test_sub_with_overflow.testInts();
5262 try test_sub_with_overflow.testIntVectors();
52615263}
52625264
5263inline fn mulWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, u1 } {
5265inline fn mulWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, ChangeScalar(Type, u1) } {
52645266 return @mulWithOverflow(lhs, rhs);
52655267}
52665268test mulWithOverflow {
52675269 const test_mul_with_overflow = binary(mulWithOverflow, .{});
52685270 try test_mul_with_overflow.testInts();
5271 try test_mul_with_overflow.testIntVectors();
52695272}
52705273
5271inline fn shlWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, u1 } {
5274inline fn shlWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, ChangeScalar(Type, u1) } {
52725275 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);
52735276 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
52745277 return @shlWithOverflow(lhs, if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs);
......@@ -5276,6 +5279,7 @@ inline fn shlWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Ty
52765279test shlWithOverflow {
52775280 const test_shl_with_overflow = binary(shlWithOverflow, .{});
52785281 try test_shl_with_overflow.testInts();
5282 try test_shl_with_overflow.testIntVectors();
52795283}
52805284
52815285inline fn equal(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs == rhs) {
test/cases/safety/memmove_len_mismatch.zig+1-1
......@@ -15,5 +15,5 @@ pub fn main() !void {
1515 return error.TestFailed;
1616}
1717// run
18// backend=llvm
18// backend=stage2,llvm
1919// target=native
test/cases/safety/slice_cast_change_len_0.zig+2-1
......@@ -23,4 +23,5 @@ pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noretu
2323const std = @import("std");
2424
2525// run
26// backend=llvm
26// backend=stage2,llvm
27// target=x86_64-linux
test/cases/safety/slice_cast_change_len_1.zig+2-1
......@@ -23,4 +23,5 @@ pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noretu
2323const std = @import("std");
2424
2525// run
26// backend=llvm
26// backend=stage2,llvm
27// target=x86_64-linux
test/cases/safety/slice_cast_change_len_2.zig+2-1
......@@ -23,4 +23,5 @@ pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noretu
2323const std = @import("std");
2424
2525// run
26// backend=llvm
26// backend=stage2,llvm
27// target=x86_64-linux
test/cases/safety/truncating vector cast.zig +1-1
......@@ -17,5 +17,5 @@ pub fn main() !void {
1717}
1818
1919// run
20// backend=llvm
20// backend=stage2,llvm
2121// target=native
test/cases/safety/unsigned-signed vector cast.zig +1-1
......@@ -17,5 +17,5 @@ pub fn main() !void {
1717}
1818
1919// run
20// backend=llvm
20// backend=stage2,llvm
2121// target=native
test/cases/safety/vector integer addition overflow.zig +1-1
......@@ -18,5 +18,5 @@ fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
1818 return a + b;
1919}
2020// run
21// backend=llvm
21// backend=stage2,llvm
2222// target=native
test/cases/safety/vector integer multiplication overflow.zig +1-1
......@@ -18,5 +18,5 @@ fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) {
1818 return a * b;
1919}
2020// run
21// backend=llvm
21// backend=stage2,llvm
2222// target=native
test/cases/safety/vector integer negation overflow.zig +1-1
......@@ -18,5 +18,5 @@ fn neg(a: @Vector(4, i16)) @Vector(4, i16) {
1818 return -a;
1919}
2020// run
21// backend=llvm
21// backend=stage2,llvm
2222// target=native
test/cases/safety/vector integer subtraction overflow.zig +1-1
......@@ -18,5 +18,5 @@ fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) {
1818 return a - b;
1919}
2020// run
21// backend=llvm
21// backend=stage2,llvm
2222// target=native