| author | |
| committer | |
| log | c1e9ef9eaabb2219a3762c5957b1c63ad20bf1ed |
| tree | e7f1c0f1aa7dc8268283a0ef71ef15b888ce9173 |
| parent | c907866d55dd92352e26f7501e5a441210bedaba |
8 files changed, 635 insertions(+), 147 deletions(-)
src/Air/Legalize.zig+372-98| ... | ... | @@ -1,21 +1,48 @@ |
| 1 | zcu: *const Zcu, | |
| 2 | air: Air, | |
| 3 | features: std.enums.EnumSet(Feature), | |
| 1 | pt: Zcu.PerThread, | |
| 2 | air_instructions: std.MultiArrayList(Air.Inst), | |
| 3 | air_extra: std.ArrayListUnmanaged(u32), | |
| 4 | features: *const Features, | |
| 4 | 5 | |
| 5 | 6 | pub const Feature = enum { |
| 7 | scalarize_not, | |
| 8 | scalarize_clz, | |
| 9 | scalarize_ctz, | |
| 10 | scalarize_popcount, | |
| 11 | scalarize_byte_swap, | |
| 12 | scalarize_bit_reverse, | |
| 13 | scalarize_sqrt, | |
| 14 | scalarize_sin, | |
| 15 | scalarize_cos, | |
| 16 | scalarize_tan, | |
| 17 | scalarize_exp, | |
| 18 | scalarize_exp2, | |
| 19 | scalarize_log, | |
| 20 | scalarize_log2, | |
| 21 | scalarize_log10, | |
| 22 | scalarize_abs, | |
| 23 | scalarize_floor, | |
| 24 | scalarize_ceil, | |
| 25 | scalarize_round, | |
| 26 | scalarize_trunc_float, | |
| 27 | scalarize_neg, | |
| 28 | scalarize_neg_optimized, | |
| 29 | ||
| 6 | 30 | /// Legalize (shift lhs, (splat rhs)) -> (shift lhs, rhs) |
| 7 | 31 | remove_shift_vector_rhs_splat, |
| 8 | 32 | /// Legalize reduce of a one element vector to a bitcast |
| 9 | 33 | reduce_one_elem_to_bitcast, |
| 10 | 34 | }; |
| 11 | 35 | |
| 12 | pub const Features = std.enums.EnumFieldStruct(Feature, bool, false); | |
| 36 | pub const Features = std.enums.EnumSet(Feature); | |
| 37 | ||
| 38 | pub const Error = std.mem.Allocator.Error; | |
| 13 | 39 | |
| 14 | pub fn legalize(air: *Air, backend: std.builtin.CompilerBackend, zcu: *const Zcu) std.mem.Allocator.Error!void { | |
| 40 | pub fn legalize(air: *Air, backend: std.builtin.CompilerBackend, pt: Zcu.PerThread) Error!void { | |
| 15 | 41 | var l: Legalize = .{ |
| 16 | .zcu = zcu, | |
| 17 | .air = air.*, | |
| 18 | .features = features: switch (backend) { | |
| 42 | .pt = pt, | |
| 43 | .air_instructions = air.instructions.toMultiArrayList(), | |
| 44 | .air_extra = air.extra, | |
| 45 | .features = &features: switch (backend) { | |
| 19 | 46 | .other, .stage1 => unreachable, |
| 20 | 47 | inline .stage2_llvm, |
| 21 | 48 | .stage2_c, |
| ... | ... | @@ -30,118 +57,365 @@ pub fn legalize(air: *Air, backend: std.builtin.CompilerBackend, zcu: *const Zcu |
| 30 | 57 | .stage2_powerpc, |
| 31 | 58 | => |ct_backend| { |
| 32 | 59 | const Backend = codegen.importBackend(ct_backend) orelse break :features .initEmpty(); |
| 33 | break :features if (@hasDecl(Backend, "legalize_features")) | |
| 34 | .init(Backend.legalize_features) | |
| 35 | else | |
| 36 | .initEmpty(); | |
| 60 | break :features if (@hasDecl(Backend, "legalize_features")) Backend.legalize_features else .initEmpty(); | |
| 37 | 61 | }, |
| 38 | 62 | _ => unreachable, |
| 39 | 63 | }, |
| 40 | 64 | }; |
| 41 | defer air.* = l.air; | |
| 42 | if (!l.features.bits.eql(.initEmpty())) try l.legalizeBody(l.air.getMainBody()); | |
| 65 | if (l.features.bits.eql(.initEmpty())) return; | |
| 66 | defer air.* = l.getTmpAir(); | |
| 67 | const main_extra = l.extraData(Air.Block, l.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)]); | |
| 68 | try l.legalizeBody(main_extra.end, main_extra.data.body_len); | |
| 69 | } | |
| 70 | ||
| 71 | fn getTmpAir(l: *const Legalize) Air { | |
| 72 | return .{ | |
| 73 | .instructions = l.air_instructions.slice(), | |
| 74 | .extra = l.air_extra, | |
| 75 | }; | |
| 76 | } | |
| 77 | ||
| 78 | fn typeOf(l: *const Legalize, ref: Air.Inst.Ref) Type { | |
| 79 | return l.getTmpAir().typeOf(ref, &l.pt.zcu.intern_pool); | |
| 80 | } | |
| 81 | ||
| 82 | fn typeOfIndex(l: *const Legalize, inst: Air.Inst.Index) Type { | |
| 83 | return l.getTmpAir().typeOfIndex(inst, &l.pt.zcu.intern_pool); | |
| 43 | 84 | } |
| 44 | 85 | |
| 45 | fn legalizeBody(l: *Legalize, body: []const Air.Inst.Index) std.mem.Allocator.Error!void { | |
| 46 | const zcu = l.zcu; | |
| 86 | fn extraData(l: *const Legalize, comptime T: type, index: usize) @TypeOf(Air.extraData(undefined, T, undefined)) { | |
| 87 | return l.getTmpAir().extraData(T, index); | |
| 88 | } | |
| 89 | ||
| 90 | fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { | |
| 91 | const zcu = l.pt.zcu; | |
| 47 | 92 | const ip = &zcu.intern_pool; |
| 48 | const tags = l.air.instructions.items(.tag); | |
| 49 | const data = l.air.instructions.items(.data); | |
| 50 | for (body) |inst| inst: switch (tags[@intFromEnum(inst)]) { | |
| 51 | else => {}, | |
| 52 | ||
| 53 | .shl, | |
| 54 | .shl_exact, | |
| 55 | .shl_sat, | |
| 56 | .shr, | |
| 57 | .shr_exact, | |
| 58 | => |air_tag| if (l.features.contains(.remove_shift_vector_rhs_splat)) done: { | |
| 59 | const bin_op = data[@intFromEnum(inst)].bin_op; | |
| 60 | const ty = l.air.typeOf(bin_op.rhs, ip); | |
| 61 | if (!ty.isVector(zcu)) break :done; | |
| 62 | if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) { | |
| 63 | else => {}, | |
| 64 | .aggregate => |aggregate| switch (aggregate.storage) { | |
| 65 | else => {}, | |
| 66 | .repeated_elem => |splat| continue :inst l.replaceInst(inst, air_tag, .{ .bin_op = .{ | |
| 67 | .lhs = bin_op.lhs, | |
| 68 | .rhs = Air.internedToRef(splat), | |
| 69 | } }), | |
| 70 | }, | |
| 71 | } else { | |
| 72 | const rhs_inst = bin_op.rhs.toIndex().?; | |
| 73 | switch (tags[@intFromEnum(rhs_inst)]) { | |
| 93 | for (body_start..body_start + body_len) |inst_extra_index| { | |
| 94 | const inst: Air.Inst.Index = @enumFromInt(l.air_extra.items[inst_extra_index]); | |
| 95 | inst: switch (l.air_instructions.items(.tag)[@intFromEnum(inst)]) { | |
| 96 | else => {}, | |
| 97 | ||
| 98 | inline .not, | |
| 99 | .clz, | |
| 100 | .ctz, | |
| 101 | .popcount, | |
| 102 | .byte_swap, | |
| 103 | .bit_reverse, | |
| 104 | .abs, | |
| 105 | => |air_tag| if (l.features.contains(@field(Feature, "scalarize_" ++ @tagName(air_tag)))) done: { | |
| 106 | const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op; | |
| 107 | if (!ty_op.ty.toType().isVector(zcu)) break :done; | |
| 108 | continue :inst try l.scalarizeUnary(inst, .ty_op, ty_op.operand); | |
| 109 | }, | |
| 110 | inline .sqrt, | |
| 111 | .sin, | |
| 112 | .cos, | |
| 113 | .tan, | |
| 114 | .exp, | |
| 115 | .exp2, | |
| 116 | .log, | |
| 117 | .log2, | |
| 118 | .log10, | |
| 119 | .floor, | |
| 120 | .ceil, | |
| 121 | .round, | |
| 122 | .trunc_float, | |
| 123 | .neg, | |
| 124 | .neg_optimized, | |
| 125 | => |air_tag| if (l.features.contains(@field(Feature, "scalarize_" ++ @tagName(air_tag)))) done: { | |
| 126 | const un_op = l.air_instructions.items(.data)[@intFromEnum(inst)].un_op; | |
| 127 | if (!l.typeOf(un_op).isVector(zcu)) break :done; | |
| 128 | continue :inst try l.scalarizeUnary(inst, .un_op, un_op); | |
| 129 | }, | |
| 130 | ||
| 131 | .shl, | |
| 132 | .shl_exact, | |
| 133 | .shl_sat, | |
| 134 | .shr, | |
| 135 | .shr_exact, | |
| 136 | => |air_tag| if (l.features.contains(.remove_shift_vector_rhs_splat)) done: { | |
| 137 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op; | |
| 138 | const ty = l.typeOf(bin_op.rhs); | |
| 139 | if (!ty.isVector(zcu)) break :done; | |
| 140 | if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) { | |
| 74 | 141 | else => {}, |
| 75 | .splat => continue :inst l.replaceInst(inst, air_tag, .{ .bin_op = .{ | |
| 76 | .lhs = bin_op.lhs, | |
| 77 | .rhs = data[@intFromEnum(rhs_inst)].ty_op.operand, | |
| 142 | .aggregate => |aggregate| switch (aggregate.storage) { | |
| 143 | else => {}, | |
| 144 | .repeated_elem => |splat| continue :inst l.replaceInst(inst, air_tag, .{ .bin_op = .{ | |
| 145 | .lhs = bin_op.lhs, | |
| 146 | .rhs = Air.internedToRef(splat), | |
| 147 | } }), | |
| 148 | }, | |
| 149 | } else { | |
| 150 | const rhs_inst = bin_op.rhs.toIndex().?; | |
| 151 | switch (l.air_instructions.items(.tag)[@intFromEnum(rhs_inst)]) { | |
| 152 | else => {}, | |
| 153 | .splat => continue :inst l.replaceInst(inst, air_tag, .{ .bin_op = .{ | |
| 154 | .lhs = bin_op.lhs, | |
| 155 | .rhs = l.air_instructions.items(.data)[@intFromEnum(rhs_inst)].ty_op.operand, | |
| 156 | } }), | |
| 157 | } | |
| 158 | } | |
| 159 | }, | |
| 160 | ||
| 161 | .reduce, | |
| 162 | .reduce_optimized, | |
| 163 | => if (l.features.contains(.reduce_one_elem_to_bitcast)) done: { | |
| 164 | const reduce = l.air_instructions.items(.data)[@intFromEnum(inst)].reduce; | |
| 165 | const vector_ty = l.typeOf(reduce.operand); | |
| 166 | switch (vector_ty.vectorLen(zcu)) { | |
| 167 | 0 => unreachable, | |
| 168 | 1 => continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{ | |
| 169 | .ty = Air.internedToRef(vector_ty.scalarType(zcu).toIntern()), | |
| 170 | .operand = reduce.operand, | |
| 78 | 171 | } }), |
| 172 | else => break :done, | |
| 79 | 173 | } |
| 80 | } | |
| 81 | }, | |
| 174 | }, | |
| 82 | 175 | |
| 83 | .reduce, | |
| 84 | .reduce_optimized, | |
| 85 | => if (l.features.contains(.reduce_one_elem_to_bitcast)) done: { | |
| 86 | const reduce = data[@intFromEnum(inst)].reduce; | |
| 87 | const vector_ty = l.air.typeOf(reduce.operand, ip); | |
| 88 | switch (vector_ty.vectorLen(zcu)) { | |
| 89 | 0 => unreachable, | |
| 90 | 1 => continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{ | |
| 91 | .ty = Air.internedToRef(vector_ty.scalarType(zcu).toIntern()), | |
| 92 | .operand = reduce.operand, | |
| 93 | } }), | |
| 94 | else => break :done, | |
| 95 | } | |
| 96 | }, | |
| 176 | .@"try", .try_cold => { | |
| 177 | const pl_op = l.air_instructions.items(.data)[@intFromEnum(inst)].pl_op; | |
| 178 | const extra = l.extraData(Air.Try, pl_op.payload); | |
| 179 | try l.legalizeBody(extra.end, extra.data.body_len); | |
| 180 | }, | |
| 181 | .try_ptr, .try_ptr_cold => { | |
| 182 | const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 183 | const extra = l.extraData(Air.TryPtr, ty_pl.payload); | |
| 184 | try l.legalizeBody(extra.end, extra.data.body_len); | |
| 185 | }, | |
| 186 | .block, .loop => { | |
| 187 | const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 188 | const extra = l.extraData(Air.Block, ty_pl.payload); | |
| 189 | try l.legalizeBody(extra.end, extra.data.body_len); | |
| 190 | }, | |
| 191 | .dbg_inline_block => { | |
| 192 | const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 193 | const extra = l.extraData(Air.DbgInlineBlock, ty_pl.payload); | |
| 194 | try l.legalizeBody(extra.end, extra.data.body_len); | |
| 195 | }, | |
| 196 | .cond_br => { | |
| 197 | const pl_op = l.air_instructions.items(.data)[@intFromEnum(inst)].pl_op; | |
| 198 | const extra = l.extraData(Air.CondBr, pl_op.payload); | |
| 199 | try l.legalizeBody(extra.end, extra.data.then_body_len); | |
| 200 | try l.legalizeBody(extra.end + extra.data.then_body_len, extra.data.else_body_len); | |
| 201 | }, | |
| 202 | .switch_br, .loop_switch_br => { | |
| 203 | const pl_op = l.air_instructions.items(.data)[@intFromEnum(inst)].pl_op; | |
| 204 | const extra = l.extraData(Air.SwitchBr, pl_op.payload); | |
| 205 | const hint_bag_count = std.math.divCeil(usize, extra.data.cases_len + 1, 10) catch unreachable; | |
| 206 | var extra_index = extra.end + hint_bag_count; | |
| 207 | for (0..extra.data.cases_len) |_| { | |
| 208 | const case_extra = l.extraData(Air.SwitchBr.Case, extra_index); | |
| 209 | const case_body_start = case_extra.end + case_extra.data.items_len + case_extra.data.ranges_len * 2; | |
| 210 | try l.legalizeBody(case_body_start, case_extra.data.body_len); | |
| 211 | extra_index = case_body_start + case_extra.data.body_len; | |
| 212 | } | |
| 213 | try l.legalizeBody(extra_index, extra.data.else_body_len); | |
| 214 | }, | |
| 215 | } | |
| 216 | } | |
| 217 | } | |
| 97 | 218 | |
| 98 | .@"try", .try_cold => { | |
| 99 | const pl_op = data[@intFromEnum(inst)].pl_op; | |
| 100 | const extra = l.air.extraData(Air.Try, pl_op.payload); | |
| 101 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end..][0..extra.data.body_len])); | |
| 102 | }, | |
| 103 | .try_ptr, .try_ptr_cold => { | |
| 104 | const ty_pl = data[@intFromEnum(inst)].ty_pl; | |
| 105 | const extra = l.air.extraData(Air.TryPtr, ty_pl.payload); | |
| 106 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end..][0..extra.data.body_len])); | |
| 107 | }, | |
| 108 | .block, .loop => { | |
| 109 | const ty_pl = data[@intFromEnum(inst)].ty_pl; | |
| 110 | const extra = l.air.extraData(Air.Block, ty_pl.payload); | |
| 111 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end..][0..extra.data.body_len])); | |
| 112 | }, | |
| 113 | .dbg_inline_block => { | |
| 114 | const ty_pl = data[@intFromEnum(inst)].ty_pl; | |
| 115 | const extra = l.air.extraData(Air.DbgInlineBlock, ty_pl.payload); | |
| 116 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end..][0..extra.data.body_len])); | |
| 117 | }, | |
| 118 | .cond_br => { | |
| 119 | const pl_op = data[@intFromEnum(inst)].pl_op; | |
| 120 | const extra = l.air.extraData(Air.CondBr, pl_op.payload); | |
| 121 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end..][0..extra.data.then_body_len])); | |
| 122 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end + extra.data.then_body_len ..][0..extra.data.else_body_len])); | |
| 123 | }, | |
| 124 | .switch_br, .loop_switch_br => { | |
| 125 | const switch_br = l.air.unwrapSwitch(inst); | |
| 126 | var it = switch_br.iterateCases(); | |
| 127 | while (it.next()) |case| try l.legalizeBody(case.body); | |
| 128 | try l.legalizeBody(it.elseBody()); | |
| 219 | const UnaryDataTag = enum { un_op, ty_op }; | |
| 220 | inline fn scalarizeUnary(l: *Legalize, inst: Air.Inst.Index, data_tag: UnaryDataTag, un_op: Air.Inst.Ref) Error!Air.Inst.Tag { | |
| 221 | return l.replaceInst(inst, .block, try l.scalarizeUnaryBlockPayload(inst, data_tag, un_op)); | |
| 222 | } | |
| 223 | fn scalarizeUnaryBlockPayload( | |
| 224 | l: *Legalize, | |
| 225 | inst: Air.Inst.Index, | |
| 226 | data_tag: UnaryDataTag, | |
| 227 | un_op: Air.Inst.Ref, | |
| 228 | ) Error!Air.Inst.Data { | |
| 229 | const pt = l.pt; | |
| 230 | const zcu = pt.zcu; | |
| 231 | const gpa = zcu.gpa; | |
| 232 | ||
| 233 | const res_ty = l.typeOfIndex(inst); | |
| 234 | try l.air_instructions.ensureUnusedCapacity(gpa, 15); | |
| 235 | const res_alloc_inst = l.addInstAssumeCapacity(.{ | |
| 236 | .tag = .alloc, | |
| 237 | .data = .{ .ty = try pt.singleMutPtrType(res_ty) }, | |
| 238 | }); | |
| 239 | const index_alloc_inst = l.addInstAssumeCapacity(.{ | |
| 240 | .tag = .alloc, | |
| 241 | .data = .{ .ty = try pt.singleMutPtrType(.usize) }, | |
| 242 | }); | |
| 243 | const index_init_inst = l.addInstAssumeCapacity(.{ | |
| 244 | .tag = .store, | |
| 245 | .data = .{ .bin_op = .{ | |
| 246 | .lhs = index_alloc_inst.toRef(), | |
| 247 | .rhs = try pt.intRef(.usize, 0), | |
| 248 | } }, | |
| 249 | }); | |
| 250 | const cur_index_inst = l.addInstAssumeCapacity(.{ | |
| 251 | .tag = .load, | |
| 252 | .data = .{ .ty_op = .{ | |
| 253 | .ty = .usize_type, | |
| 254 | .operand = index_alloc_inst.toRef(), | |
| 255 | } }, | |
| 256 | }); | |
| 257 | const get_elem_inst = l.addInstAssumeCapacity(.{ | |
| 258 | .tag = .array_elem_val, | |
| 259 | .data = .{ .bin_op = .{ | |
| 260 | .lhs = un_op, | |
| 261 | .rhs = cur_index_inst.toRef(), | |
| 262 | } }, | |
| 263 | }); | |
| 264 | const op_elem_inst = l.addInstAssumeCapacity(.{ | |
| 265 | .tag = l.air_instructions.items(.tag)[@intFromEnum(inst)], | |
| 266 | .data = switch (data_tag) { | |
| 267 | .un_op => .{ .un_op = get_elem_inst.toRef() }, | |
| 268 | .ty_op => .{ .ty_op = .{ | |
| 269 | .ty = Air.internedToRef(res_ty.scalarType(zcu).toIntern()), | |
| 270 | .operand = get_elem_inst.toRef(), | |
| 271 | } }, | |
| 129 | 272 | }, |
| 130 | }; | |
| 273 | }); | |
| 274 | const set_elem_inst = l.addInstAssumeCapacity(.{ | |
| 275 | .tag = .vector_store_elem, | |
| 276 | .data = .{ .vector_store_elem = .{ | |
| 277 | .vector_ptr = res_alloc_inst.toRef(), | |
| 278 | .payload = try l.addExtra(Air.Bin, .{ | |
| 279 | .lhs = cur_index_inst.toRef(), | |
| 280 | .rhs = op_elem_inst.toRef(), | |
| 281 | }), | |
| 282 | } }, | |
| 283 | }); | |
| 284 | const not_done_inst = l.addInstAssumeCapacity(.{ | |
| 285 | .tag = .cmp_lt, | |
| 286 | .data = .{ .bin_op = .{ | |
| 287 | .lhs = cur_index_inst.toRef(), | |
| 288 | .rhs = try pt.intRef(.usize, res_ty.vectorLen(zcu)), | |
| 289 | } }, | |
| 290 | }); | |
| 291 | const next_index_inst = l.addInstAssumeCapacity(.{ | |
| 292 | .tag = .add, | |
| 293 | .data = .{ .bin_op = .{ | |
| 294 | .lhs = cur_index_inst.toRef(), | |
| 295 | .rhs = try pt.intRef(.usize, 1), | |
| 296 | } }, | |
| 297 | }); | |
| 298 | const set_index_inst = l.addInstAssumeCapacity(.{ | |
| 299 | .tag = .store, | |
| 300 | .data = .{ .bin_op = .{ | |
| 301 | .lhs = index_alloc_inst.toRef(), | |
| 302 | .rhs = next_index_inst.toRef(), | |
| 303 | } }, | |
| 304 | }); | |
| 305 | const loop_inst: Air.Inst.Index = @enumFromInt(l.air_instructions.len + 4); | |
| 306 | const repeat_inst = l.addInstAssumeCapacity(.{ | |
| 307 | .tag = .repeat, | |
| 308 | .data = .{ .repeat = .{ .loop_inst = loop_inst } }, | |
| 309 | }); | |
| 310 | const final_res_inst = l.addInstAssumeCapacity(.{ | |
| 311 | .tag = .load, | |
| 312 | .data = .{ .ty_op = .{ | |
| 313 | .ty = Air.internedToRef(res_ty.toIntern()), | |
| 314 | .operand = res_alloc_inst.toRef(), | |
| 315 | } }, | |
| 316 | }); | |
| 317 | const br_res_inst = l.addInstAssumeCapacity(.{ | |
| 318 | .tag = .br, | |
| 319 | .data = .{ .br = .{ | |
| 320 | .block_inst = inst, | |
| 321 | .operand = final_res_inst.toRef(), | |
| 322 | } }, | |
| 323 | }); | |
| 324 | const done_br_inst = l.addInstAssumeCapacity(.{ | |
| 325 | .tag = .cond_br, | |
| 326 | .data = .{ .pl_op = .{ | |
| 327 | .operand = not_done_inst.toRef(), | |
| 328 | .payload = try l.addCondBrBodies(&.{ | |
| 329 | next_index_inst, | |
| 330 | set_index_inst, | |
| 331 | repeat_inst, | |
| 332 | }, &.{ | |
| 333 | final_res_inst, | |
| 334 | br_res_inst, | |
| 335 | }), | |
| 336 | } }, | |
| 337 | }); | |
| 338 | assert(loop_inst == l.addInstAssumeCapacity(.{ | |
| 339 | .tag = .loop, | |
| 340 | .data = .{ .ty_pl = .{ | |
| 341 | .ty = .noreturn_type, | |
| 342 | .payload = try l.addBlockBody(&.{ | |
| 343 | cur_index_inst, | |
| 344 | get_elem_inst, | |
| 345 | op_elem_inst, | |
| 346 | set_elem_inst, | |
| 347 | not_done_inst, | |
| 348 | done_br_inst, | |
| 349 | }), | |
| 350 | } }, | |
| 351 | })); | |
| 352 | return .{ .ty_pl = .{ | |
| 353 | .ty = Air.internedToRef(res_ty.toIntern()), | |
| 354 | .payload = try l.addBlockBody(&.{ | |
| 355 | res_alloc_inst, | |
| 356 | index_alloc_inst, | |
| 357 | index_init_inst, | |
| 358 | loop_inst, | |
| 359 | }), | |
| 360 | } }; | |
| 361 | } | |
| 362 | ||
| 363 | fn addInstAssumeCapacity(l: *Legalize, inst: Air.Inst) Air.Inst.Index { | |
| 364 | defer l.air_instructions.appendAssumeCapacity(inst); | |
| 365 | return @enumFromInt(l.air_instructions.len); | |
| 366 | } | |
| 367 | ||
| 368 | fn addExtra(l: *Legalize, comptime Extra: type, extra: Extra) Error!u32 { | |
| 369 | const extra_fields = @typeInfo(Extra).@"struct".fields; | |
| 370 | try l.air_extra.ensureUnusedCapacity(l.pt.zcu.gpa, extra_fields.len); | |
| 371 | defer inline for (extra_fields) |field| l.air_extra.appendAssumeCapacity(switch (field.type) { | |
| 372 | u32 => @field(extra, field.name), | |
| 373 | Air.Inst.Ref => @intFromEnum(@field(extra, field.name)), | |
| 374 | else => @compileError(@typeName(field.type)), | |
| 375 | }); | |
| 376 | return @intCast(l.air_extra.items.len); | |
| 377 | } | |
| 378 | ||
| 379 | fn addBlockBody(l: *Legalize, body: []const Air.Inst.Index) Error!u32 { | |
| 380 | try l.air_extra.ensureUnusedCapacity(l.pt.zcu.gpa, 1 + body.len); | |
| 381 | defer { | |
| 382 | l.air_extra.appendAssumeCapacity(@intCast(body.len)); | |
| 383 | l.air_extra.appendSliceAssumeCapacity(@ptrCast(body)); | |
| 384 | } | |
| 385 | return @intCast(l.air_extra.items.len); | |
| 386 | } | |
| 387 | ||
| 388 | fn addCondBrBodies(l: *Legalize, then_body: []const Air.Inst.Index, else_body: []const Air.Inst.Index) Error!u32 { | |
| 389 | try l.air_extra.ensureUnusedCapacity(l.pt.zcu.gpa, 3 + then_body.len + else_body.len); | |
| 390 | defer { | |
| 391 | l.air_extra.appendSliceAssumeCapacity(&.{ | |
| 392 | @intCast(then_body.len), | |
| 393 | @intCast(else_body.len), | |
| 394 | @bitCast(Air.CondBr.BranchHints{ | |
| 395 | .true = .none, | |
| 396 | .false = .none, | |
| 397 | .then_cov = .none, | |
| 398 | .else_cov = .none, | |
| 399 | }), | |
| 400 | }); | |
| 401 | l.air_extra.appendSliceAssumeCapacity(@ptrCast(then_body)); | |
| 402 | l.air_extra.appendSliceAssumeCapacity(@ptrCast(else_body)); | |
| 403 | } | |
| 404 | return @intCast(l.air_extra.items.len); | |
| 131 | 405 | } |
| 132 | 406 | |
| 133 | 407 | // inline to propagate comptime `tag`s |
| 134 | 408 | inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag { |
| 135 | const ip = &l.zcu.intern_pool; | |
| 136 | const orig_ty = if (std.debug.runtime_safety) l.air.typeOfIndex(inst, ip) else {}; | |
| 137 | l.air.instructions.items(.tag)[@intFromEnum(inst)] = tag; | |
| 138 | l.air.instructions.items(.data)[@intFromEnum(inst)] = data; | |
| 139 | if (std.debug.runtime_safety) std.debug.assert(l.air.typeOfIndex(inst, ip).toIntern() == orig_ty.toIntern()); | |
| 409 | const orig_ty = if (std.debug.runtime_safety) l.typeOfIndex(inst) else {}; | |
| 410 | l.air_instructions.set(@intFromEnum(inst), .{ .tag = tag, .data = data }); | |
| 411 | if (std.debug.runtime_safety) assert(l.typeOfIndex(inst).toIntern() == orig_ty.toIntern()); | |
| 140 | 412 | return tag; |
| 141 | 413 | } |
| 142 | 414 | |
| 143 | 415 | const Air = @import("../Air.zig"); |
| 416 | const assert = std.debug.assert; | |
| 144 | 417 | const codegen = @import("../codegen.zig"); |
| 145 | 418 | const Legalize = @This(); |
| 146 | 419 | const std = @import("std"); |
| 420 | const Type = @import("../Type.zig"); | |
| 147 | 421 | const Zcu = @import("../Zcu.zig"); |
src/Zcu/PerThread.zig+1-1| ... | ... | @@ -1742,7 +1742,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A |
| 1742 | 1742 | } |
| 1743 | 1743 | |
| 1744 | 1744 | const backend = target_util.zigBackend(zcu.root_mod.resolved_target.result, zcu.comp.config.use_llvm); |
| 1745 | try air.legalize(backend, zcu); | |
| 1745 | try air.legalize(backend, pt); | |
| 1746 | 1746 | |
| 1747 | 1747 | var liveness = try Air.Liveness.analyze(gpa, air.*, ip); |
| 1748 | 1748 | defer liveness.deinit(gpa); |
src/arch/x86_64/CodeGen.zig+250-40| ... | ... | @@ -32,10 +32,15 @@ const FrameIndex = bits.FrameIndex; |
| 32 | 32 | |
| 33 | 33 | const InnerError = codegen.CodeGenError || error{OutOfRegisters}; |
| 34 | 34 | |
| 35 | pub const legalize_features: Air.Legalize.Features = .{ | |
| 35 | pub const legalize_features: Air.Legalize.Features = .init(.{ | |
| 36 | .scalarize_ctz = true, | |
| 37 | .scalarize_popcount = true, | |
| 38 | .scalarize_byte_swap = true, | |
| 39 | .scalarize_bit_reverse = true, | |
| 40 | ||
| 36 | 41 | .remove_shift_vector_rhs_splat = false, |
| 37 | 42 | .reduce_one_elem_to_bitcast = true, |
| 38 | }; | |
| 43 | }); | |
| 39 | 44 | |
| 40 | 45 | /// Set this to `false` to uncover Sema OPV bugs. |
| 41 | 46 | /// https://github.com/ziglang/zig/issues/22419 |
| ... | ... | @@ -63352,14 +63357,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 63352 | 63357 | defer assert(cg.loops.remove(inst)); |
| 63353 | 63358 | try cg.genBodyBlock(@ptrCast(cg.air.extra.items[block.end..][0..block.data.body_len])); |
| 63354 | 63359 | }, |
| 63355 | .repeat => if (use_old) try cg.airRepeat(inst) else { | |
| 63360 | .repeat => { | |
| 63356 | 63361 | const repeat = air_datas[@intFromEnum(inst)].repeat; |
| 63357 | 63362 | const loop = cg.loops.get(repeat.loop_inst).?; |
| 63358 | 63363 | try cg.restoreState(loop.state, &.{}, .{ |
| 63359 | 63364 | .emit_instructions = true, |
| 63360 | 63365 | .update_tracking = false, |
| 63361 | 63366 | .resurrect = false, |
| 63362 | .close_scope = true, | |
| 63367 | .close_scope = false, | |
| 63363 | 63368 | }); |
| 63364 | 63369 | _ = try cg.asmJmpReloc(loop.target); |
| 63365 | 63370 | }, |
| ... | ... | @@ -162356,6 +162361,136 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 162356 | 162361 | .each = .{ .once = &.{ |
| 162357 | 162362 | .{ ._, ._, .mov, .leasi(.src0w, .@"2", .src1), .src2w, ._, ._ }, |
| 162358 | 162363 | } }, |
| 162364 | }, .{ | |
| 162365 | .required_features = .{ .avx, null, null, null }, | |
| 162366 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162367 | .patterns = &.{ | |
| 162368 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162369 | }, | |
| 162370 | .each = .{ .once = &.{ | |
| 162371 | .{ ._, .vp_w, .extr, .leaa(.src0w, .add_src0_elem_size_mul_src1), .src2x, .ui(0), ._ }, | |
| 162372 | } }, | |
| 162373 | }, .{ | |
| 162374 | .required_features = .{ .sse4_1, null, null, null }, | |
| 162375 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162376 | .patterns = &.{ | |
| 162377 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162378 | }, | |
| 162379 | .each = .{ .once = &.{ | |
| 162380 | .{ ._, .p_w, .extr, .leaa(.src0w, .add_src0_elem_size_mul_src1), .src2x, .ui(0), ._ }, | |
| 162381 | } }, | |
| 162382 | }, .{ | |
| 162383 | .required_features = .{ .sse2, null, null, null }, | |
| 162384 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162385 | .patterns = &.{ | |
| 162386 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162387 | }, | |
| 162388 | .extra_temps = .{ | |
| 162389 | .{ .type = .f16, .kind = .{ .rc = .general_purpose } }, | |
| 162390 | .unused, | |
| 162391 | .unused, | |
| 162392 | .unused, | |
| 162393 | .unused, | |
| 162394 | .unused, | |
| 162395 | .unused, | |
| 162396 | .unused, | |
| 162397 | .unused, | |
| 162398 | .unused, | |
| 162399 | .unused, | |
| 162400 | }, | |
| 162401 | .each = .{ .once = &.{ | |
| 162402 | .{ ._, .p_w, .extr, .tmp0d, .src2x, .ui(0), ._ }, | |
| 162403 | .{ ._, ._, .mov, .leaa(.src0w, .add_src0_elem_size_mul_src1), .tmp0w, ._, ._ }, | |
| 162404 | } }, | |
| 162405 | }, .{ | |
| 162406 | .required_features = .{ .sse, null, null, null }, | |
| 162407 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162408 | .patterns = &.{ | |
| 162409 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162410 | }, | |
| 162411 | .extra_temps = .{ | |
| 162412 | .{ .type = .f32, .kind = .mem }, | |
| 162413 | .{ .type = .f16, .kind = .{ .rc = .general_purpose } }, | |
| 162414 | .unused, | |
| 162415 | .unused, | |
| 162416 | .unused, | |
| 162417 | .unused, | |
| 162418 | .unused, | |
| 162419 | .unused, | |
| 162420 | .unused, | |
| 162421 | .unused, | |
| 162422 | .unused, | |
| 162423 | }, | |
| 162424 | .each = .{ .once = &.{ | |
| 162425 | .{ ._, ._ss, .mov, .mem(.tmp1d), .src2x, ._, ._ }, | |
| 162426 | .{ ._, ._, .mov, .tmp1d, .mem(.tmp1d), ._, ._ }, | |
| 162427 | .{ ._, ._, .mov, .leaa(.src0w, .add_src0_elem_size_mul_src1), .tmp1w, ._, ._ }, | |
| 162428 | } }, | |
| 162429 | }, .{ | |
| 162430 | .required_features = .{ .avx, null, null, null }, | |
| 162431 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162432 | .patterns = &.{ | |
| 162433 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162434 | }, | |
| 162435 | .each = .{ .once = &.{ | |
| 162436 | .{ ._, .vp_w, .extr, .leasi(.src0w, .@"2", .src1), .src2x, .ui(0), ._ }, | |
| 162437 | } }, | |
| 162438 | }, .{ | |
| 162439 | .required_features = .{ .sse4_1, null, null, null }, | |
| 162440 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162441 | .patterns = &.{ | |
| 162442 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162443 | }, | |
| 162444 | .each = .{ .once = &.{ | |
| 162445 | .{ ._, .p_w, .extr, .leasi(.src0w, .@"2", .src1), .src2x, .ui(0), ._ }, | |
| 162446 | } }, | |
| 162447 | }, .{ | |
| 162448 | .required_features = .{ .sse2, null, null, null }, | |
| 162449 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162450 | .patterns = &.{ | |
| 162451 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162452 | }, | |
| 162453 | .extra_temps = .{ | |
| 162454 | .{ .type = .f16, .kind = .{ .rc = .general_purpose } }, | |
| 162455 | .unused, | |
| 162456 | .unused, | |
| 162457 | .unused, | |
| 162458 | .unused, | |
| 162459 | .unused, | |
| 162460 | .unused, | |
| 162461 | .unused, | |
| 162462 | .unused, | |
| 162463 | .unused, | |
| 162464 | .unused, | |
| 162465 | }, | |
| 162466 | .each = .{ .once = &.{ | |
| 162467 | .{ ._, .p_w, .extr, .tmp0d, .src2x, .ui(0), ._ }, | |
| 162468 | .{ ._, ._, .mov, .leasi(.src0w, .@"2", .src1), .tmp0w, ._, ._ }, | |
| 162469 | } }, | |
| 162470 | }, .{ | |
| 162471 | .required_features = .{ .sse, null, null, null }, | |
| 162472 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162473 | .patterns = &.{ | |
| 162474 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162475 | }, | |
| 162476 | .extra_temps = .{ | |
| 162477 | .{ .type = .f32, .kind = .mem }, | |
| 162478 | .{ .type = .f16, .kind = .{ .rc = .general_purpose } }, | |
| 162479 | .unused, | |
| 162480 | .unused, | |
| 162481 | .unused, | |
| 162482 | .unused, | |
| 162483 | .unused, | |
| 162484 | .unused, | |
| 162485 | .unused, | |
| 162486 | .unused, | |
| 162487 | .unused, | |
| 162488 | }, | |
| 162489 | .each = .{ .once = &.{ | |
| 162490 | .{ ._, ._ss, .mov, .mem(.tmp1d), .src2x, ._, ._ }, | |
| 162491 | .{ ._, ._, .mov, .tmp1d, .mem(.tmp1d), ._, ._ }, | |
| 162492 | .{ ._, ._, .mov, .leasi(.src0w, .@"2", .src1), .tmp1w, ._, ._ }, | |
| 162493 | } }, | |
| 162359 | 162494 | }, .{ |
| 162360 | 162495 | .src_constraints = .{ .any, .any, .{ .int = .dword } }, |
| 162361 | 162496 | .patterns = &.{ |
| ... | ... | @@ -162374,30 +162509,120 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 162374 | 162509 | .each = .{ .once = &.{ |
| 162375 | 162510 | .{ ._, ._, .mov, .leasi(.src0d, .@"4", .src1), .src2d, ._, ._ }, |
| 162376 | 162511 | } }, |
| 162512 | }, .{ | |
| 162513 | .required_features = .{ .avx, null, null, null }, | |
| 162514 | .src_constraints = .{ .any, .any, .{ .float = .dword } }, | |
| 162515 | .patterns = &.{ | |
| 162516 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162517 | }, | |
| 162518 | .each = .{ .once = &.{ | |
| 162519 | .{ ._, .v_ss, .mov, .leaa(.src0d, .add_src0_elem_size_mul_src1), .src2x, ._, ._ }, | |
| 162520 | } }, | |
| 162521 | }, .{ | |
| 162522 | .required_features = .{ .sse, null, null, null }, | |
| 162523 | .src_constraints = .{ .any, .any, .{ .float = .dword } }, | |
| 162524 | .patterns = &.{ | |
| 162525 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162526 | }, | |
| 162527 | .each = .{ .once = &.{ | |
| 162528 | .{ ._, ._ss, .mov, .leaa(.src0d, .add_src0_elem_size_mul_src1), .src2x, ._, ._ }, | |
| 162529 | } }, | |
| 162530 | }, .{ | |
| 162531 | .required_features = .{ .avx, null, null, null }, | |
| 162532 | .src_constraints = .{ .any, .any, .{ .float = .dword } }, | |
| 162533 | .patterns = &.{ | |
| 162534 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162535 | }, | |
| 162536 | .each = .{ .once = &.{ | |
| 162537 | .{ ._, .v_ss, .mov, .leasi(.src0d, .@"4", .src1), .src2x, ._, ._ }, | |
| 162538 | } }, | |
| 162539 | }, .{ | |
| 162540 | .required_features = .{ .sse, null, null, null }, | |
| 162541 | .src_constraints = .{ .any, .any, .{ .float = .dword } }, | |
| 162542 | .patterns = &.{ | |
| 162543 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162544 | }, | |
| 162545 | .each = .{ .once = &.{ | |
| 162546 | .{ ._, ._ss, .mov, .leasi(.src0d, .@"4", .src1), .src2x, ._, ._ }, | |
| 162547 | } }, | |
| 162377 | 162548 | }, .{ |
| 162378 | 162549 | .required_features = .{ .@"64bit", null, null, null }, |
| 162379 | .dst_constraints = .{ .{ .int = .qword }, .any }, | |
| 162550 | .src_constraints = .{ .any, .any, .{ .int = .qword } }, | |
| 162380 | 162551 | .patterns = &.{ |
| 162381 | .{ .src = .{ .to_mem, .simm32, .simm32 } }, | |
| 162382 | .{ .src = .{ .to_mem, .simm32, .to_gpr } }, | |
| 162552 | .{ .src = .{ .to_gpr, .simm32, .simm32 } }, | |
| 162553 | .{ .src = .{ .to_gpr, .simm32, .to_gpr } }, | |
| 162383 | 162554 | }, |
| 162384 | 162555 | .each = .{ .once = &.{ |
| 162385 | 162556 | .{ ._, ._, .mov, .leaa(.src0q, .add_src0_elem_size_mul_src1), .src2q, ._, ._ }, |
| 162386 | 162557 | } }, |
| 162387 | 162558 | }, .{ |
| 162388 | 162559 | .required_features = .{ .@"64bit", null, null, null }, |
| 162389 | .dst_constraints = .{ .{ .int = .qword }, .any }, | |
| 162560 | .src_constraints = .{ .any, .any, .{ .int = .qword } }, | |
| 162390 | 162561 | .patterns = &.{ |
| 162391 | .{ .src = .{ .to_mem, .to_gpr, .simm32 } }, | |
| 162392 | .{ .src = .{ .to_mem, .to_gpr, .to_gpr } }, | |
| 162562 | .{ .src = .{ .to_gpr, .to_gpr, .simm32 } }, | |
| 162563 | .{ .src = .{ .to_gpr, .to_gpr, .to_gpr } }, | |
| 162393 | 162564 | }, |
| 162394 | 162565 | .each = .{ .once = &.{ |
| 162395 | 162566 | .{ ._, ._, .mov, .leasi(.src0q, .@"8", .src1), .src2q, ._, ._ }, |
| 162396 | 162567 | } }, |
| 162568 | }, .{ | |
| 162569 | .required_features = .{ .avx, null, null, null }, | |
| 162570 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162571 | .patterns = &.{ | |
| 162572 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162573 | }, | |
| 162574 | .each = .{ .once = &.{ | |
| 162575 | .{ ._, .v_sd, .mov, .leaa(.src0q, .add_src0_elem_size_mul_src1), .src2x, ._, ._ }, | |
| 162576 | } }, | |
| 162577 | }, .{ | |
| 162578 | .required_features = .{ .sse2, null, null, null }, | |
| 162579 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162580 | .patterns = &.{ | |
| 162581 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162582 | }, | |
| 162583 | .each = .{ .once = &.{ | |
| 162584 | .{ ._, ._sd, .mov, .leaa(.src0q, .add_src0_elem_size_mul_src1), .src2x, ._, ._ }, | |
| 162585 | } }, | |
| 162586 | }, .{ | |
| 162587 | .required_features = .{ .sse, null, null, null }, | |
| 162588 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162589 | .patterns = &.{ | |
| 162590 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162591 | }, | |
| 162592 | .each = .{ .once = &.{ | |
| 162593 | .{ ._, ._ps, .movl, .leaa(.src0q, .add_src0_elem_size_mul_src1), .src2x, ._, ._ }, | |
| 162594 | } }, | |
| 162595 | }, .{ | |
| 162596 | .required_features = .{ .avx, null, null, null }, | |
| 162597 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162598 | .patterns = &.{ | |
| 162599 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162600 | }, | |
| 162601 | .each = .{ .once = &.{ | |
| 162602 | .{ ._, .v_sd, .mov, .leasi(.src0q, .@"8", .src1), .src2x, ._, ._ }, | |
| 162603 | } }, | |
| 162604 | }, .{ | |
| 162605 | .required_features = .{ .sse2, null, null, null }, | |
| 162606 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162607 | .patterns = &.{ | |
| 162608 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162609 | }, | |
| 162610 | .each = .{ .once = &.{ | |
| 162611 | .{ ._, ._sd, .mov, .leasi(.src0q, .@"8", .src1), .src2x, ._, ._ }, | |
| 162612 | } }, | |
| 162613 | }, .{ | |
| 162614 | .required_features = .{ .sse, null, null, null }, | |
| 162615 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162616 | .patterns = &.{ | |
| 162617 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162618 | }, | |
| 162619 | .each = .{ .once = &.{ | |
| 162620 | .{ ._, ._ps, .movl, .leasi(.src0q, .@"8", .src1), .src2x, ._, ._ }, | |
| 162621 | } }, | |
| 162397 | 162622 | } }) catch |err| switch (err) { |
| 162398 | 162623 | error.SelectFailed => { |
| 162399 | 162624 | const elem_size = cg.typeOf(bin_op.rhs).abiSize(zcu); |
| 162400 | while (try ops[0].toBase(false, cg) or | |
| 162625 | while (try ops[0].toRegClass(true, .general_purpose, cg) or | |
| 162401 | 162626 | try ops[1].toRegClass(true, .general_purpose, cg)) |
| 162402 | 162627 | {} |
| 162403 | 162628 | const base_reg = ops[0].tracking(cg).short.register.to64(); |
| ... | ... | @@ -162410,11 +162635,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 162410 | 162635 | rhs_reg, |
| 162411 | 162636 | .u(elem_size), |
| 162412 | 162637 | ); |
| 162413 | try cg.asmRegisterMemory( | |
| 162414 | .{ ._, .lea }, | |
| 162415 | base_reg, | |
| 162416 | try ops[0].tracking(cg).short.mem(cg, .{ .index = rhs_reg }), | |
| 162417 | ); | |
| 162638 | try cg.asmRegisterMemory(.{ ._, .lea }, base_reg, .{ | |
| 162639 | .base = .{ .reg = base_reg }, | |
| 162640 | .mod = .{ .rm = .{ .index = rhs_reg } }, | |
| 162641 | }); | |
| 162418 | 162642 | } else if (elem_size > 8) { |
| 162419 | 162643 | try cg.spillEflagsIfOccupied(); |
| 162420 | 162644 | try cg.asmRegisterImmediate( |
| ... | ... | @@ -162422,20 +162646,18 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 162422 | 162646 | rhs_reg, |
| 162423 | 162647 | .u(std.math.log2_int(u64, elem_size)), |
| 162424 | 162648 | ); |
| 162425 | try cg.asmRegisterMemory( | |
| 162426 | .{ ._, .lea }, | |
| 162427 | base_reg, | |
| 162428 | try ops[0].tracking(cg).short.mem(cg, .{ .index = rhs_reg }), | |
| 162429 | ); | |
| 162430 | } else try cg.asmRegisterMemory( | |
| 162431 | .{ ._, .lea }, | |
| 162432 | base_reg, | |
| 162433 | try ops[0].tracking(cg).short.mem(cg, .{ | |
| 162649 | try cg.asmRegisterMemory(.{ ._, .lea }, base_reg, .{ | |
| 162650 | .base = .{ .reg = base_reg }, | |
| 162651 | .mod = .{ .rm = .{ .index = rhs_reg } }, | |
| 162652 | }); | |
| 162653 | } else try cg.asmRegisterMemory(.{ ._, .lea }, base_reg, .{ | |
| 162654 | .base = .{ .reg = base_reg }, | |
| 162655 | .mod = .{ .rm = .{ | |
| 162434 | 162656 | .index = rhs_reg, |
| 162435 | 162657 | .scale = .fromFactor(@intCast(elem_size)), |
| 162436 | }), | |
| 162437 | ); | |
| 162438 | try ops[0].store(&ops[1], .{}, cg); | |
| 162658 | } }, | |
| 162659 | }); | |
| 162660 | try ops[0].store(&ops[2], .{}, cg); | |
| 162439 | 162661 | }, |
| 162440 | 162662 | else => |e| return e, |
| 162441 | 162663 | }; |
| ... | ... | @@ -174453,18 +174675,6 @@ fn airBr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 174453 | 174675 | try self.freeValue(block_tracking.short); |
| 174454 | 174676 | } |
| 174455 | 174677 | |
| 174456 | fn airRepeat(self: *CodeGen, inst: Air.Inst.Index) !void { | |
| 174457 | const loop_inst = self.air.instructions.items(.data)[@intFromEnum(inst)].repeat.loop_inst; | |
| 174458 | const repeat_info = self.loops.get(loop_inst).?; | |
| 174459 | try self.restoreState(repeat_info.state, &.{}, .{ | |
| 174460 | .emit_instructions = true, | |
| 174461 | .update_tracking = false, | |
| 174462 | .resurrect = false, | |
| 174463 | .close_scope = true, | |
| 174464 | }); | |
| 174465 | _ = try self.asmJmpReloc(repeat_info.target); | |
| 174466 | } | |
| 174467 | ||
| 174468 | 174678 | fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 174469 | 174679 | @setEvalBranchQuota(1_100); |
| 174470 | 174680 | const pt = self.pt; |
test/behavior/bitreverse.zig+3-3| ... | ... | @@ -123,12 +123,12 @@ fn vector8() !void { |
| 123 | 123 | |
| 124 | 124 | test "bitReverse vectors u8" { |
| 125 | 125 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 126 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 127 | 126 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 128 | 127 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 129 | 128 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 130 | 129 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 131 | 130 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 131 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 132 | 132 | |
| 133 | 133 | try comptime vector8(); |
| 134 | 134 | try vector8(); |
| ... | ... | @@ -144,12 +144,12 @@ fn vector16() !void { |
| 144 | 144 | |
| 145 | 145 | test "bitReverse vectors u16" { |
| 146 | 146 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 147 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 148 | 147 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 149 | 148 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 150 | 149 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 151 | 150 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 152 | 151 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 152 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 153 | 153 | |
| 154 | 154 | try comptime vector16(); |
| 155 | 155 | try vector16(); |
| ... | ... | @@ -165,12 +165,12 @@ fn vector24() !void { |
| 165 | 165 | |
| 166 | 166 | test "bitReverse vectors u24" { |
| 167 | 167 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 168 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 169 | 168 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 170 | 169 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 171 | 170 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 172 | 171 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 173 | 172 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 173 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 174 | 174 | |
| 175 | 175 | try comptime vector24(); |
| 176 | 176 | try vector24(); |
test/behavior/byteswap.zig+3-3| ... | ... | @@ -95,12 +95,12 @@ fn vector8() !void { |
| 95 | 95 | |
| 96 | 96 | test "@byteSwap vectors u8" { |
| 97 | 97 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 98 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 99 | 98 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 100 | 99 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 101 | 100 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 102 | 101 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 103 | 102 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 103 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 104 | 104 | |
| 105 | 105 | try comptime vector8(); |
| 106 | 106 | try vector8(); |
| ... | ... | @@ -116,12 +116,12 @@ fn vector16() !void { |
| 116 | 116 | |
| 117 | 117 | test "@byteSwap vectors u16" { |
| 118 | 118 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 119 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 120 | 119 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 121 | 120 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 122 | 121 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 123 | 122 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 124 | 123 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 124 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 125 | 125 | |
| 126 | 126 | try comptime vector16(); |
| 127 | 127 | try vector16(); |
| ... | ... | @@ -137,12 +137,12 @@ fn vector24() !void { |
| 137 | 137 | |
| 138 | 138 | test "@byteSwap vectors u24" { |
| 139 | 139 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 140 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 141 | 140 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 142 | 141 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 143 | 142 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 144 | 143 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 145 | 144 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 145 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 146 | 146 | |
| 147 | 147 | try comptime vector24(); |
| 148 | 148 | try vector24(); |
test/behavior/math.zig+1-1| ... | ... | @@ -193,12 +193,12 @@ fn testCtz128() !void { |
| 193 | 193 | |
| 194 | 194 | test "@ctz vectors" { |
| 195 | 195 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 196 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 197 | 196 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 198 | 197 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 199 | 198 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 200 | 199 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 201 | 200 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 201 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 202 | 202 | |
| 203 | 203 | try testCtzVectors(); |
| 204 | 204 | try comptime testCtzVectors(); |
test/behavior/popcount.zig+1-1| ... | ... | @@ -77,12 +77,12 @@ fn testPopCountIntegers() !void { |
| 77 | 77 | |
| 78 | 78 | test "@popCount vectors" { |
| 79 | 79 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 80 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 81 | 80 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 82 | 81 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 83 | 82 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 84 | 83 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 85 | 84 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 85 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 86 | 86 | |
| 87 | 87 | try comptime testPopCountVectors(); |
| 88 | 88 | try testPopCountVectors(); |
test/behavior/x86_64/unary.zig+4| ... | ... | @@ -4828,6 +4828,7 @@ inline fn ctz(comptime Type: type, rhs: Type) @TypeOf(@ctz(rhs)) { |
| 4828 | 4828 | test ctz { |
| 4829 | 4829 | const test_ctz = unary(ctz, .{}); |
| 4830 | 4830 | try test_ctz.testInts(); |
| 4831 | try test_ctz.testIntVectors(); | |
| 4831 | 4832 | } |
| 4832 | 4833 | |
| 4833 | 4834 | inline fn popCount(comptime Type: type, rhs: Type) @TypeOf(@popCount(rhs)) { |
| ... | ... | @@ -4836,6 +4837,7 @@ inline fn popCount(comptime Type: type, rhs: Type) @TypeOf(@popCount(rhs)) { |
| 4836 | 4837 | test popCount { |
| 4837 | 4838 | const test_pop_count = unary(popCount, .{}); |
| 4838 | 4839 | try test_pop_count.testInts(); |
| 4840 | try test_pop_count.testIntVectors(); | |
| 4839 | 4841 | } |
| 4840 | 4842 | |
| 4841 | 4843 | inline fn byteSwap(comptime Type: type, rhs: Type) RoundBitsUp(Type, 8) { |
| ... | ... | @@ -4844,6 +4846,7 @@ inline fn byteSwap(comptime Type: type, rhs: Type) RoundBitsUp(Type, 8) { |
| 4844 | 4846 | test byteSwap { |
| 4845 | 4847 | const test_byte_swap = unary(byteSwap, .{}); |
| 4846 | 4848 | try test_byte_swap.testInts(); |
| 4849 | try test_byte_swap.testIntVectors(); | |
| 4847 | 4850 | } |
| 4848 | 4851 | |
| 4849 | 4852 | inline fn bitReverse(comptime Type: type, rhs: Type) @TypeOf(@bitReverse(rhs)) { |
| ... | ... | @@ -4852,6 +4855,7 @@ inline fn bitReverse(comptime Type: type, rhs: Type) @TypeOf(@bitReverse(rhs)) { |
| 4852 | 4855 | test bitReverse { |
| 4853 | 4856 | const test_bit_reverse = unary(bitReverse, .{}); |
| 4854 | 4857 | try test_bit_reverse.testInts(); |
| 4858 | try test_bit_reverse.testIntVectors(); | |
| 4855 | 4859 | } |
| 4856 | 4860 | |
| 4857 | 4861 | inline fn sqrt(comptime Type: type, rhs: Type) @TypeOf(@sqrt(rhs)) { |