| ... | @@ -1196,7 +1196,7 @@ fn minMax( | ... | @@ -1196,7 +1196,7 @@ fn minMax( |
| 1196 | // register. | 1196 | // register. |
| 1197 | assert(lhs_reg != rhs_reg); // see note above | 1197 | assert(lhs_reg != rhs_reg); // see note above |
| 1198 | | 1198 | |
| 1199 | _ = try self.binOpRegister(.cmp_eq, null, .{ .register = lhs_reg }, .{ .register = rhs_reg }, lhs_ty, rhs_ty); | 1199 | _ = try self.binOpRegister(.cmp, null, .{ .register = lhs_reg }, .{ .register = rhs_reg }, lhs_ty, rhs_ty); |
| 1200 | | 1200 | |
| 1201 | const cond_choose_lhs: Condition = switch (tag) { | 1201 | const cond_choose_lhs: Condition = switch (tag) { |
| 1202 | .max => switch (int_info.signedness) { | 1202 | .max => switch (int_info.signedness) { |
| ... | @@ -2067,7 +2067,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2067,7 +2067,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2067 | /// Asserts that generating an instruction of that form is possible. | 2067 | /// Asserts that generating an instruction of that form is possible. |
| 2068 | fn binOpRegister( | 2068 | fn binOpRegister( |
| 2069 | self: *Self, | 2069 | self: *Self, |
| 2070 | tag: Air.Inst.Tag, | 2070 | mir_tag: Mir.Inst.Tag, |
| 2071 | maybe_inst: ?Air.Inst.Index, | 2071 | maybe_inst: ?Air.Inst.Index, |
| 2072 | lhs: MCValue, | 2072 | lhs: MCValue, |
| 2073 | rhs: MCValue, | 2073 | rhs: MCValue, |
| ... | @@ -2112,8 +2112,8 @@ fn binOpRegister( | ... | @@ -2112,8 +2112,8 @@ fn binOpRegister( |
| 2112 | }; | 2112 | }; |
| 2113 | defer self.register_manager.unfreezeRegs(&.{rhs_reg}); | 2113 | defer self.register_manager.unfreezeRegs(&.{rhs_reg}); |
| 2114 | | 2114 | |
| 2115 | const dest_reg = switch (tag) { | 2115 | const dest_reg = switch (mir_tag) { |
| 2116 | .cmp_eq => .r0, // cmp has no destination regardless | 2116 | .cmp => .r0, // cmp has no destination regardless |
| 2117 | else => if (maybe_inst) |inst| blk: { | 2117 | else => if (maybe_inst) |inst| blk: { |
| 2118 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 2118 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2119 | | 2119 | |
| ... | @@ -2130,41 +2130,21 @@ fn binOpRegister( | ... | @@ -2130,41 +2130,21 @@ fn binOpRegister( |
| 2130 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); | 2130 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| 2131 | if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); | 2131 | if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); |
| 2132 | | 2132 | |
| 2133 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2133 | const mir_data: Mir.Inst.Data = switch (mir_tag) { |
| 2134 | .add => .add, | | |
| 2135 | .sub => .sub, | | |
| 2136 | .cmp_eq => .cmp, | | |
| 2137 | .mul => .mul, | | |
| 2138 | .bit_and, | | |
| 2139 | .bool_and, | | |
| 2140 | => .@"and", | | |
| 2141 | .bit_or, | | |
| 2142 | .bool_or, | | |
| 2143 | => .orr, | | |
| 2144 | .shl_exact => .lsl, | | |
| 2145 | .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) { | | |
| 2146 | .signed => Mir.Inst.Tag.asr, | | |
| 2147 | .unsigned => Mir.Inst.Tag.lsr, | | |
| 2148 | }, | | |
| 2149 | .xor => .eor, | | |
| 2150 | else => unreachable, | | |
| 2151 | }; | | |
| 2152 | const mir_data: Mir.Inst.Data = switch (tag) { | | |
| 2153 | .add, | 2134 | .add, |
| 2154 | .sub, | 2135 | .sub, |
| 2155 | .cmp_eq, | 2136 | .cmp, |
| 2156 | .bit_and, | 2137 | .@"and", |
| 2157 | .bool_and, | 2138 | .orr, |
| 2158 | .bit_or, | 2139 | .eor, |
| 2159 | .bool_or, | | |
| 2160 | .xor, | | |
| 2161 | => .{ .rr_op = .{ | 2140 | => .{ .rr_op = .{ |
| 2162 | .rd = dest_reg, | 2141 | .rd = dest_reg, |
| 2163 | .rn = lhs_reg, | 2142 | .rn = lhs_reg, |
| 2164 | .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none), | 2143 | .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none), |
| 2165 | } }, | 2144 | } }, |
| 2166 | .shl_exact, | 2145 | .lsl, |
| 2167 | .shr_exact, | 2146 | .asr, |
| | 2147 | .lsr, |
| 2168 | => .{ .rr_shift = .{ | 2148 | => .{ .rr_shift = .{ |
| 2169 | .rd = dest_reg, | 2149 | .rd = dest_reg, |
| 2170 | .rm = lhs_reg, | 2150 | .rm = lhs_reg, |
| ... | @@ -2200,7 +2180,7 @@ fn binOpRegister( | ... | @@ -2200,7 +2180,7 @@ fn binOpRegister( |
| 2200 | /// Asserts that generating an instruction of that form is possible. | 2180 | /// Asserts that generating an instruction of that form is possible. |
| 2201 | fn binOpImmediate( | 2181 | fn binOpImmediate( |
| 2202 | self: *Self, | 2182 | self: *Self, |
| 2203 | tag: Air.Inst.Tag, | 2183 | mir_tag: Mir.Inst.Tag, |
| 2204 | maybe_inst: ?Air.Inst.Index, | 2184 | maybe_inst: ?Air.Inst.Index, |
| 2205 | lhs: MCValue, | 2185 | lhs: MCValue, |
| 2206 | rhs: MCValue, | 2186 | rhs: MCValue, |
| ... | @@ -2230,8 +2210,8 @@ fn binOpImmediate( | ... | @@ -2230,8 +2210,8 @@ fn binOpImmediate( |
| 2230 | }; | 2210 | }; |
| 2231 | defer self.register_manager.unfreezeRegs(&.{lhs_reg}); | 2211 | defer self.register_manager.unfreezeRegs(&.{lhs_reg}); |
| 2232 | | 2212 | |
| 2233 | const dest_reg = switch (tag) { | 2213 | const dest_reg = switch (mir_tag) { |
| 2234 | .cmp_eq => .r0, // cmp has no destination reg | 2214 | .cmp => .r0, // cmp has no destination reg |
| 2235 | else => if (maybe_inst) |inst| blk: { | 2215 | else => if (maybe_inst) |inst| blk: { |
| 2236 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 2216 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2237 | | 2217 | |
| ... | @@ -2250,40 +2230,21 @@ fn binOpImmediate( | ... | @@ -2250,40 +2230,21 @@ fn binOpImmediate( |
| 2250 | | 2230 | |
| 2251 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); | 2231 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| 2252 | | 2232 | |
| 2253 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2233 | const mir_data: Mir.Inst.Data = switch (mir_tag) { |
| 2254 | .add => .add, | | |
| 2255 | .sub => .sub, | | |
| 2256 | .cmp_eq => .cmp, | | |
| 2257 | .bit_and, | | |
| 2258 | .bool_and, | | |
| 2259 | => .@"and", | | |
| 2260 | .bit_or, | | |
| 2261 | .bool_or, | | |
| 2262 | => .orr, | | |
| 2263 | .shl_exact => .lsl, | | |
| 2264 | .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) { | | |
| 2265 | .signed => Mir.Inst.Tag.asr, | | |
| 2266 | .unsigned => Mir.Inst.Tag.lsr, | | |
| 2267 | }, | | |
| 2268 | .xor => .eor, | | |
| 2269 | else => unreachable, | | |
| 2270 | }; | | |
| 2271 | const mir_data: Mir.Inst.Data = switch (tag) { | | |
| 2272 | .add, | 2234 | .add, |
| 2273 | .sub, | 2235 | .sub, |
| 2274 | .cmp_eq, | 2236 | .cmp, |
| 2275 | .bit_and, | 2237 | .@"and", |
| 2276 | .bool_and, | 2238 | .orr, |
| 2277 | .bit_or, | 2239 | .eor, |
| 2278 | .bool_or, | | |
| 2279 | .xor, | | |
| 2280 | => .{ .rr_op = .{ | 2240 | => .{ .rr_op = .{ |
| 2281 | .rd = dest_reg, | 2241 | .rd = dest_reg, |
| 2282 | .rn = lhs_reg, | 2242 | .rn = lhs_reg, |
| 2283 | .op = Instruction.Operand.fromU32(rhs.immediate).?, | 2243 | .op = Instruction.Operand.fromU32(rhs.immediate).?, |
| 2284 | } }, | 2244 | } }, |
| 2285 | .shl_exact, | 2245 | .lsl, |
| 2286 | .shr_exact, | 2246 | .asr, |
| | 2247 | .lsr, |
| 2287 | => .{ .rr_shift = .{ | 2248 | => .{ .rr_shift = .{ |
| 2288 | .rd = dest_reg, | 2249 | .rd = dest_reg, |
| 2289 | .rm = lhs_reg, | 2250 | .rm = lhs_reg, |
| ... | @@ -2352,13 +2313,20 @@ fn binOp( | ... | @@ -2352,13 +2313,20 @@ fn binOp( |
| 2352 | else => unreachable, | 2313 | else => unreachable, |
| 2353 | }; | 2314 | }; |
| 2354 | | 2315 | |
| | 2316 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| | 2317 | .add => .add, |
| | 2318 | .sub => .sub, |
| | 2319 | .cmp_eq => .cmp, |
| | 2320 | else => unreachable, |
| | 2321 | }; |
| | 2322 | |
| 2355 | if (rhs_immediate_ok) { | 2323 | if (rhs_immediate_ok) { |
| 2356 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); | 2324 | return try self.binOpImmediate(mir_tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| 2357 | } else if (lhs_immediate_ok) { | 2325 | } else if (lhs_immediate_ok) { |
| 2358 | // swap lhs and rhs | 2326 | // swap lhs and rhs |
| 2359 | return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); | 2327 | return try self.binOpImmediate(mir_tag, maybe_inst, rhs, lhs, rhs_ty, true); |
| 2360 | } else { | 2328 | } else { |
| 2361 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 2329 | return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2362 | } | 2330 | } |
| 2363 | } else { | 2331 | } else { |
| 2364 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); | 2332 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); |
| ... | @@ -2378,7 +2346,7 @@ fn binOp( | ... | @@ -2378,7 +2346,7 @@ fn binOp( |
| 2378 | // TODO add optimisations for multiplication | 2346 | // TODO add optimisations for multiplication |
| 2379 | // with immediates, for example a * 2 can be | 2347 | // with immediates, for example a * 2 can be |
| 2380 | // lowered to a << 1 | 2348 | // lowered to a << 1 |
| 2381 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 2349 | return try self.binOpRegister(.mul, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2382 | } else { | 2350 | } else { |
| 2383 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); | 2351 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); |
| 2384 | } | 2352 | } |
| ... | @@ -2432,13 +2400,20 @@ fn binOp( | ... | @@ -2432,13 +2400,20 @@ fn binOp( |
| 2432 | const lhs_immediate_ok = lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null; | 2400 | const lhs_immediate_ok = lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null; |
| 2433 | const rhs_immediate_ok = rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null; | 2401 | const rhs_immediate_ok = rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null; |
| 2434 | | 2402 | |
| | 2403 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| | 2404 | .bit_and => .@"and", |
| | 2405 | .bit_or => .orr, |
| | 2406 | .xor => .eor, |
| | 2407 | else => unreachable, |
| | 2408 | }; |
| | 2409 | |
| 2435 | if (rhs_immediate_ok) { | 2410 | if (rhs_immediate_ok) { |
| 2436 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); | 2411 | return try self.binOpImmediate(mir_tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| 2437 | } else if (lhs_immediate_ok) { | 2412 | } else if (lhs_immediate_ok) { |
| 2438 | // swap lhs and rhs | 2413 | // swap lhs and rhs |
| 2439 | return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); | 2414 | return try self.binOpImmediate(mir_tag, maybe_inst, rhs, lhs, rhs_ty, true); |
| 2440 | } else { | 2415 | } else { |
| 2441 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 2416 | return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2442 | } | 2417 | } |
| 2443 | } else { | 2418 | } else { |
| 2444 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); | 2419 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); |
| ... | @@ -2457,10 +2432,19 @@ fn binOp( | ... | @@ -2457,10 +2432,19 @@ fn binOp( |
| 2457 | if (int_info.bits <= 32) { | 2432 | if (int_info.bits <= 32) { |
| 2458 | const rhs_immediate_ok = rhs == .immediate; | 2433 | const rhs_immediate_ok = rhs == .immediate; |
| 2459 | | 2434 | |
| | 2435 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| | 2436 | .shl_exact => .lsl, |
| | 2437 | .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) { |
| | 2438 | .signed => Mir.Inst.Tag.asr, |
| | 2439 | .unsigned => Mir.Inst.Tag.lsr, |
| | 2440 | }, |
| | 2441 | else => unreachable, |
| | 2442 | }; |
| | 2443 | |
| 2460 | if (rhs_immediate_ok) { | 2444 | if (rhs_immediate_ok) { |
| 2461 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); | 2445 | return try self.binOpImmediate(mir_tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| 2462 | } else { | 2446 | } else { |
| 2463 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 2447 | return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2464 | } | 2448 | } |
| 2465 | } else { | 2449 | } else { |
| 2466 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); | 2450 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); |
| ... | @@ -2512,13 +2496,19 @@ fn binOp( | ... | @@ -2512,13 +2496,19 @@ fn binOp( |
| 2512 | const lhs_immediate_ok = lhs == .immediate; | 2496 | const lhs_immediate_ok = lhs == .immediate; |
| 2513 | const rhs_immediate_ok = rhs == .immediate; | 2497 | const rhs_immediate_ok = rhs == .immediate; |
| 2514 | | 2498 | |
| | 2499 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| | 2500 | .bool_and => .@"and", |
| | 2501 | .bool_or => .orr, |
| | 2502 | else => unreachable, |
| | 2503 | }; |
| | 2504 | |
| 2515 | if (rhs_immediate_ok) { | 2505 | if (rhs_immediate_ok) { |
| 2516 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); | 2506 | return try self.binOpImmediate(mir_tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| 2517 | } else if (lhs_immediate_ok) { | 2507 | } else if (lhs_immediate_ok) { |
| 2518 | // swap lhs and rhs | 2508 | // swap lhs and rhs |
| 2519 | return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); | 2509 | return try self.binOpImmediate(mir_tag, maybe_inst, rhs, lhs, rhs_ty, true); |
| 2520 | } else { | 2510 | } else { |
| 2521 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 2511 | return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2522 | } | 2512 | } |
| 2523 | }, | 2513 | }, |
| 2524 | else => unreachable, | 2514 | else => unreachable, |
| ... | @@ -2537,7 +2527,7 @@ fn binOp( | ... | @@ -2537,7 +2527,7 @@ fn binOp( |
| 2537 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | 2527 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| 2538 | | 2528 | |
| 2539 | if (elem_size == 1) { | 2529 | if (elem_size == 1) { |
| 2540 | const base_tag: Air.Inst.Tag = switch (tag) { | 2530 | const base_tag: Mir.Inst.Tag = switch (tag) { |
| 2541 | .ptr_add => .add, | 2531 | .ptr_add => .add, |
| 2542 | .ptr_sub => .sub, | 2532 | .ptr_sub => .sub, |
| 2543 | else => unreachable, | 2533 | else => unreachable, |