authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-07-09 16:04:26+07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-14 16:57:31-07:00
logde17fe66a541b3277579d351f7a362d3f07ea91d
tree00b4c14fb1cc6ec0d856fc3d387393928b567f7a
parentab3d3b260bc24d1a3e16329371d9a2438e043506

stage2: sparc64: Tidy up binOp and enable more operations

sub, mul, addwrap, subwrap, mulwrap, shr, shr_exact

1 files changed, 108 insertions(+), 125 deletions(-)

src/arch/sparc64/CodeGen.zig+108-125
......@@ -499,20 +499,29 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
499499 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),
500500
501501 .add => try self.airBinOp(inst, .add),
502 .addwrap => @panic("TODO try self.airAddWrap(inst)"),
502 .addwrap => try self.airBinOp(inst, .addwrap),
503 .sub => try self.airBinOp(inst, .sub),
504 .subwrap => try self.airBinOp(inst, .subwrap),
505 .mul => try self.airBinOp(inst, .mul),
506 .mulwrap => try self.airBinOp(inst, .mulwrap),
507 .shl => try self.airBinOp(inst, .shl),
508 .shl_exact => try self.airBinOp(inst, .shl_exact),
509 .shr => try self.airBinOp(inst, .shr),
510 .shr_exact => try self.airBinOp(inst, .shr_exact),
511 .bool_and => try self.airBinOp(inst, .bool_and),
512 .bool_or => try self.airBinOp(inst, .bool_or),
513 .bit_and => try self.airBinOp(inst, .bit_and),
514 .bit_or => try self.airBinOp(inst, .bit_or),
515 .xor => try self.airBinOp(inst, .xor),
516
503517 .add_sat => @panic("TODO try self.airAddSat(inst)"),
504 .sub => @panic("TODO try self.airBinOp(inst)"),
505 .subwrap => @panic("TODO try self.airSubWrap(inst)"),
506518 .sub_sat => @panic("TODO try self.airSubSat(inst)"),
507 .mul => @panic("TODO try self.airMul(inst)"),
508 .mulwrap => @panic("TODO try self.airMulWrap(inst)"),
509519 .mul_sat => @panic("TODO try self.airMulSat(inst)"),
510 .rem => try self.airRem(inst),
511 .mod => try self.airMod(inst),
512 .shl, .shl_exact => @panic("TODO try self.airShl(inst)"),
513520 .shl_sat => @panic("TODO try self.airShlSat(inst)"),
514521 .min => @panic("TODO try self.airMin(inst)"),
515522 .max => @panic("TODO try self.airMax(inst)"),
523 .rem => try self.airRem(inst),
524 .mod => try self.airMod(inst),
516525 .slice => try self.airSlice(inst),
517526
518527 .sqrt,
......@@ -548,13 +557,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
548557 .cmp_vector => @panic("TODO try self.airCmpVector(inst)"),
549558 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
550559
551 .bool_and => try self.airBinOp(inst, .bool_and),
552 .bool_or => try self.airBinOp(inst, .bool_or),
553 .bit_and => try self.airBinOp(inst, .bit_and),
554 .bit_or => try self.airBinOp(inst, .bit_or),
555 .xor => try self.airBinOp(inst, .xor),
556 .shr, .shr_exact => @panic("TODO try self.airShr(inst)"),
557
558560 .alloc => try self.airAlloc(inst),
559561 .ret_ptr => try self.airRetPtr(inst),
560562 .arg => try self.airArg(inst),
......@@ -2397,6 +2399,10 @@ fn binOp(
23972399 switch (tag) {
23982400 .add,
23992401 .sub,
2402 .mul,
2403 .bit_and,
2404 .bit_or,
2405 .xor,
24002406 .cmp_eq,
24012407 => {
24022408 switch (lhs_ty.zigTypeTag()) {
......@@ -2411,12 +2417,20 @@ fn binOp(
24112417 // operands
24122418 const lhs_immediate_ok = switch (tag) {
24132419 .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2420 .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2421 .bit_and => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2422 .bit_or => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2423 .xor => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
24142424 .sub, .cmp_eq => false,
24152425 else => unreachable,
24162426 };
24172427 const rhs_immediate_ok = switch (tag) {
24182428 .add,
24192429 .sub,
2430 .mul,
2431 .bit_and,
2432 .bit_or,
2433 .xor,
24202434 .cmp_eq,
24212435 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
24222436 else => unreachable,
......@@ -2425,6 +2439,10 @@ fn binOp(
24252439 const mir_tag: Mir.Inst.Tag = switch (tag) {
24262440 .add => .add,
24272441 .sub => .sub,
2442 .mul => .mulx,
2443 .bit_and => .@"and",
2444 .bit_or => .@"or",
2445 .xor => .xor,
24282446 .cmp_eq => .cmp,
24292447 else => unreachable,
24302448 };
......@@ -2446,72 +2464,60 @@ fn binOp(
24462464 }
24472465 },
24482466
2449 .div_trunc => {
2467 .addwrap,
2468 .subwrap,
2469 .mulwrap,
2470 => {
2471 const base_tag: Air.Inst.Tag = switch (tag) {
2472 .addwrap => .add,
2473 .subwrap => .sub,
2474 .mulwrap => .mul,
2475 else => unreachable,
2476 };
2477
2478 // Generate the base operation
2479 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2480
2481 // Truncate if necessary
24502482 switch (lhs_ty.zigTypeTag()) {
24512483 .Vector => return self.fail("TODO binary operations on vectors", .{}),
24522484 .Int => {
2453 assert(lhs_ty.eql(rhs_ty, mod));
24542485 const int_info = lhs_ty.intInfo(self.target.*);
24552486 if (int_info.bits <= 64) {
2456 const rhs_immediate_ok = switch (tag) {
2457 .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
2458 else => unreachable,
2459 };
2460
2461 const mir_tag: Mir.Inst.Tag = switch (tag) {
2462 .div_trunc => switch (int_info.signedness) {
2463 .signed => Mir.Inst.Tag.sdivx,
2464 .unsigned => Mir.Inst.Tag.udivx,
2465 },
2466 else => unreachable,
2467 };
2468
2469 if (rhs_immediate_ok) {
2470 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, true, metadata);
2471 } else {
2472 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2473 }
2487 const result_reg = result.register;
2488 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
2489 return result;
24742490 } else {
2475 return self.fail("TODO binary operations on int with bits > 64", .{});
2491 return self.fail("TODO binary operations on integers > u64/i64", .{});
24762492 }
24772493 },
24782494 else => unreachable,
24792495 }
24802496 },
24812497
2482 .mul => {
2498 .div_trunc => {
24832499 switch (lhs_ty.zigTypeTag()) {
24842500 .Vector => return self.fail("TODO binary operations on vectors", .{}),
24852501 .Int => {
24862502 assert(lhs_ty.eql(rhs_ty, mod));
24872503 const int_info = lhs_ty.intInfo(self.target.*);
24882504 if (int_info.bits <= 64) {
2489 // Only say yes if the operation is
2490 // commutative, i.e. we can swap both of the
2491 // operands
2492 const lhs_immediate_ok = switch (tag) {
2493 .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2494 else => unreachable,
2495 };
24962505 const rhs_immediate_ok = switch (tag) {
2497 .mul => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
2506 .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
24982507 else => unreachable,
24992508 };
25002509
25012510 const mir_tag: Mir.Inst.Tag = switch (tag) {
2502 .mul => .mulx,
2511 .div_trunc => switch (int_info.signedness) {
2512 .signed => Mir.Inst.Tag.sdivx,
2513 .unsigned => Mir.Inst.Tag.udivx,
2514 },
25032515 else => unreachable,
25042516 };
25052517
25062518 if (rhs_immediate_ok) {
2507 // At this point, rhs is an immediate
2508 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
2509 } else if (lhs_immediate_ok) {
2510 // swap lhs and rhs
2511 // At this point, lhs is an immediate
2512 return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata);
2519 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, true, metadata);
25132520 } else {
2514 // TODO convert large immediates to register before adding
25152521 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
25162522 }
25172523 } else {
......@@ -2552,58 +2558,6 @@ fn binOp(
25522558 }
25532559 },
25542560
2555 .bit_and,
2556 .bit_or,
2557 .xor,
2558 => {
2559 switch (lhs_ty.zigTypeTag()) {
2560 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2561 .Int => {
2562 assert(lhs_ty.eql(rhs_ty, mod));
2563 const int_info = lhs_ty.intInfo(self.target.*);
2564 if (int_info.bits <= 64) {
2565 // Only say yes if the operation is
2566 // commutative, i.e. we can swap both of the
2567 // operands
2568 const lhs_immediate_ok = switch (tag) {
2569 .bit_and,
2570 .bit_or,
2571 .xor,
2572 => lhs == .immediate and lhs.immediate <= std.math.maxInt(u13),
2573 else => unreachable,
2574 };
2575 const rhs_immediate_ok = switch (tag) {
2576 .bit_and,
2577 .bit_or,
2578 .xor,
2579 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u13),
2580 else => unreachable,
2581 };
2582
2583 const mir_tag: Mir.Inst.Tag = switch (tag) {
2584 .bit_and => .@"and",
2585 .bit_or => .@"or",
2586 .xor => .xor,
2587 else => unreachable,
2588 };
2589
2590 if (rhs_immediate_ok) {
2591 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
2592 } else if (lhs_immediate_ok) {
2593 // swap lhs and rhs
2594 return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata);
2595 } else {
2596 // TODO convert large immediates to register before adding
2597 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2598 }
2599 } else {
2600 return self.fail("TODO binary operations on int with bits > 64", .{});
2601 }
2602 },
2603 else => unreachable,
2604 }
2605 },
2606
26072561 .bool_and,
26082562 .bool_or,
26092563 => {
......@@ -2624,36 +2578,41 @@ fn binOp(
26242578 }
26252579 },
26262580
2627 .shl => {
2581 .shl,
2582 .shr,
2583 => {
26282584 const base_tag: Air.Inst.Tag = switch (tag) {
26292585 .shl => .shl_exact,
2586 .shr => .shr_exact,
26302587 else => unreachable,
26312588 };
26322589
2633 // Generate a shl_exact/shr_exact
2590 // Generate the base operation
26342591 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
26352592
26362593 // Truncate if necessary
2637 switch (tag) {
2638 .shl => switch (lhs_ty.zigTypeTag()) {
2639 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2640 .Int => {
2641 const int_info = lhs_ty.intInfo(self.target.*);
2642 if (int_info.bits <= 64) {
2643 const result_reg = result.register;
2644 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
2645 return result;
2646 } else {
2647 return self.fail("TODO binary operations on integers > u64/i64", .{});
2648 }
2649 },
2650 else => unreachable,
2594 switch (lhs_ty.zigTypeTag()) {
2595 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2596 .Int => {
2597 const int_info = lhs_ty.intInfo(self.target.*);
2598 if (int_info.bits <= 64) {
2599 // 32 and 64 bit operands doesn't need truncating
2600 if (int_info.bits == 32 or int_info.bits == 64) return result;
2601
2602 const result_reg = result.register;
2603 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
2604 return result;
2605 } else {
2606 return self.fail("TODO binary operations on integers > u64/i64", .{});
2607 }
26512608 },
26522609 else => unreachable,
26532610 }
26542611 },
26552612
2656 .shl_exact => {
2613 .shl_exact,
2614 .shr_exact,
2615 => {
26572616 switch (lhs_ty.zigTypeTag()) {
26582617 .Vector => return self.fail("TODO binary operations on vectors", .{}),
26592618 .Int => {
......@@ -2662,7 +2621,11 @@ fn binOp(
26622621 const rhs_immediate_ok = rhs == .immediate;
26632622
26642623 const mir_tag: Mir.Inst.Tag = switch (tag) {
2665 .shl_exact => .sllx,
2624 .shl_exact => if (int_info.bits <= 32) Mir.Inst.Tag.sll else Mir.Inst.Tag.sllx,
2625 .shr_exact => switch (int_info.signedness) {
2626 .signed => if (int_info.bits <= 32) Mir.Inst.Tag.sra else Mir.Inst.Tag.srax,
2627 .unsigned => if (int_info.bits <= 32) Mir.Inst.Tag.srl else Mir.Inst.Tag.srlx,
2628 },
26662629 else => unreachable,
26672630 };
26682631
......@@ -2769,7 +2732,21 @@ fn binOpImmediate(
27692732 .rs2_or_imm = .{ .imm = @intCast(u12, rhs.immediate) },
27702733 },
27712734 },
2772 .sllx => .{
2735 .sll,
2736 .srl,
2737 .sra,
2738 => .{
2739 .shift = .{
2740 .is_imm = true,
2741 .rd = dest_reg,
2742 .rs1 = lhs_reg,
2743 .rs2_or_imm = .{ .imm = @intCast(u5, rhs.immediate) },
2744 },
2745 },
2746 .sllx,
2747 .srlx,
2748 .srax,
2749 => .{
27732750 .shift = .{
27742751 .is_imm = true,
27752752 .rd = dest_reg,
......@@ -2893,7 +2870,13 @@ fn binOpRegister(
28932870 .rs2_or_imm = .{ .rs2 = rhs_reg },
28942871 },
28952872 },
2896 .sllx => .{
2873 .sll,
2874 .srl,
2875 .sra,
2876 .sllx,
2877 .srlx,
2878 .srax,
2879 => .{
28972880 .shift = .{
28982881 .is_imm = false,
28992882 .rd = dest_reg,