Skip to content

x86 floating point regalloc, calls, load/store, select, eq - #88

Merged
can-lehmann merged 13 commits into
mainfrom
can-float-register-allocation
Sep 30, 2026
Merged

can-lehmann merged 13 commits into
mainfrom
can-float-register-allocation

Conversation

@can-lehmann

Copy link
Copy Markdown
Owner

No description provided.

@github-actions

Copy link
Copy Markdown

Coverage

File Lines Functions Regions Branches
genext.hpp 🔴 59.44% 🟡 80.95% 🟡 79.65% 🟡 79.34%
jitir.hpp 🔴 54.28% 🔴 67.28% 🔴 58.61% 🔴 57.30%
jitir_llvmapi.hpp 🔴 54.86% 🟡 80.00% 🟢 98.21% 🔴 50.00%
llvmgen.hpp 🔴 66.38% 🟡 70.00% 🟡 85.81% 🟡 87.18%
lowerllvm.hpp 🔴 63.60% 🟡 75.00% 🔴 41.32% 🔴 56.49%
x86gen.hpp 🟡 73.23% 🟡 80.65% 🟡 77.66% 🟡 84.32%
x86insts.inc.hpp - - - -
TOTAL 🔴 58.64% 🟡 70.25% 🔴 67.46% 🔴 68.59%
Diff Coverage

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • x86gen.hpp (88.2%): Missing lines 45,811,1627,1631-1636,1669
  • x86insts.inc.hpp (100%)

Summary

  • Total: 86 lines
  • Missing: 10 lines
  • Coverage: 88%

x86gen.hpp

Lines 41-49

  41     static constexpr Reg phys(size_t id) {
  42       return Reg(Kind::Physical, id);
  43     }
  44 
! 45     static constexpr Reg xmm(size_t id) { return phys(16 + id); }
  46 
  47     Class reg_class() const {
  48       assert(is_physical());
  49       return _id < 16 ? Class::GP : Class::FP;

Lines 807-815

  807     void isel(Inst* inst, Block* block) {
  808       if (dynmatch(FreezeInst, freeze, inst)) {
  809         copy(vreg(inst), vreg(freeze->arg(0)));
  810       } else if (dynmatch(PromoteInst, promote, inst)) {
! 811         copy(vreg(inst), vreg(promote->arg(0)));
  812       } else if (dynmatch(AssumeConstInst, assume_const, inst)) {
  813         copy(vreg(inst), vreg(assume_const->arg(0)));
  814       } else if (dynmatch(PtrToIntInst, ptr_to_int, inst)) {
  815         switch (type_size(ptr_to_int->type())) {

Lines 1623-1640

  1623       assert(vreg.is_virtual());
  1624       VRegInfo& info = _vreg_info[vreg.id()];
  1625       if (info.current_reg.is_physical()) {
  1626         // No need to unspill, just move from current reg
! 1627         copy(preg, info.current_reg);
  1628         reg_file.free(info.current_reg);
  1629       } else {
  1630         assert(info.stack_offset != ~size_t(0));
! 1631         X86Inst::Mem mem(Reg::X86_RSP(), (int32_t) info.stack_offset);
! 1632         if (info.reg_class == Reg::Class::FP) {
! 1633           _builder.movsd(preg, mem);
! 1634         } else {
! 1635           _builder.mov64(preg, mem);
! 1636         }
  1637       }
  1638       info.current_reg = preg;
  1639       reg_file.set(preg, vreg);
  1640     }

Lines 1665-1673

  1665              std::holds_alternative<Reg>(inst->rm());
  1666     }
  1667 
  1668     bool is_foldable_mov(X86Inst* inst) {
! 1669       if (is_reg_mov(inst)) {
  1670         Reg src = std::get<Reg>(inst->rm());
  1671         Reg dst = inst->reg();
  1672         assert(src.is_virtual() && dst.is_virtual());
  1673         if (_vreg_info[src.id()].current_reg.is_physical() &&

@github-actions

Copy link
Copy Markdown

Coverage

File Lines Functions Regions Branches
genext.hpp 🔴 59.44% 🟡 80.95% 🟡 79.65% 🟡 79.34%
jitir.hpp 🔴 54.30% 🔴 67.32% 🔴 58.62% 🔴 57.30%
jitir_llvmapi.hpp 🔴 54.86% 🟡 80.00% 🟢 98.21% 🔴 50.00%
llvmgen.hpp 🔴 66.38% 🟡 70.00% 🟡 85.81% 🟡 87.18%
lowerllvm.hpp 🔴 63.60% 🟡 75.00% 🔴 41.32% 🔴 56.49%
x86gen.hpp 🟡 73.26% 🟡 81.08% 🟡 77.61% 🟡 84.25%
x86insts.inc.hpp - - - -
TOTAL 🔴 58.66% 🟡 70.33% 🔴 67.44% 🔴 68.55%
Diff Coverage

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • jitir.hpp (100%)
  • x86gen.hpp (89.2%): Missing lines 809,1625,1629-1634,1667
  • x86insts.inc.hpp (100%)

Summary

  • Total: 95 lines
  • Missing: 9 lines
  • Coverage: 90%

x86gen.hpp

Lines 805-813

  805     void isel(Inst* inst, Block* block) {
  806       if (dynmatch(FreezeInst, freeze, inst)) {
  807         move(vreg(inst), vreg(freeze->arg(0)));
  808       } else if (dynmatch(PromoteInst, promote, inst)) {
! 809         move(vreg(inst), vreg(promote->arg(0)));
  810       } else if (dynmatch(AssumeConstInst, assume_const, inst)) {
  811         move(vreg(inst), vreg(assume_const->arg(0)));
  812       } else if (dynmatch(PtrToIntInst, ptr_to_int, inst)) {
  813         switch (type_size(ptr_to_int->type())) {

Lines 1621-1638

  1621       assert(vreg.is_virtual());
  1622       VRegInfo& info = _vreg_info[vreg.id()];
  1623       if (info.current_reg.is_physical()) {
  1624         // No need to unspill, just move from current reg
! 1625         move(preg, info.current_reg);
  1626         reg_file.free(info.current_reg);
  1627       } else {
  1628         assert(info.stack_offset != ~size_t(0));
! 1629         X86Inst::Mem mem(Reg::X86_RSP(), (int32_t) info.stack_offset);
! 1630         if (info.reg_class == RegClass::FP) {
! 1631           _builder.movsd(preg, mem);
! 1632         } else {
! 1633           _builder.mov64(preg, mem);
! 1634         }
  1635       }
  1636       info.current_reg = preg;
  1637       reg_file.set(preg, vreg);
  1638     }

Lines 1663-1671

  1663              std::holds_alternative<Reg>(inst->rm());
  1664     }
  1665 
  1666     bool is_foldable_mov(X86Inst* inst) {
! 1667       if (is_reg_mov(inst)) {
  1668         Reg src = std::get<Reg>(inst->rm());
  1669         Reg dst = inst->reg();
  1670         assert(src.is_virtual() && dst.is_virtual());
  1671         if (_vreg_info[src.id()].current_reg.is_physical() &&

@can-lehmann can-lehmann changed the title separate x86 floating point register allocation x86 floating point regalloc, calls Sep 30, 2026
@github-actions

Copy link
Copy Markdown

Coverage

File Lines Functions Regions Branches
genext.hpp 🔴 59.44% 🟡 80.95% 🟡 79.65% 🟡 79.34%
jitir.hpp 🔴 54.40% 🔴 67.32% 🔴 58.81% 🔴 57.51%
jitir_llvmapi.hpp 🔴 54.86% 🟡 80.00% 🟢 98.21% 🔴 50.00%
llvmgen.hpp 🔴 66.38% 🟡 70.00% 🟡 85.81% 🟡 87.18%
lowerllvm.hpp 🔴 63.60% 🟡 75.00% 🔴 41.32% 🔴 56.49%
x86gen.hpp 🟡 73.32% 🟡 80.98% 🟡 77.69% 🟡 84.46%
x86insts.inc.hpp - - - -
TOTAL 🔴 58.73% 🟡 70.31% 🔴 67.57% 🔴 68.74%
Diff Coverage

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • jitir.hpp (100%)
  • x86gen.hpp (86.9%): Missing lines 812,1632,1636-1641,1674,1804,1826-1829
  • x86insts.inc.hpp (100%)

Summary

  • Total: 119 lines
  • Missing: 14 lines
  • Coverage: 88%

x86gen.hpp

Lines 808-816

  808     void isel(Inst* inst, Block* block) {
  809       if (dynmatch(FreezeInst, freeze, inst)) {
  810         move(vreg(inst), vreg(freeze->arg(0)));
  811       } else if (dynmatch(PromoteInst, promote, inst)) {
! 812         move(vreg(inst), vreg(promote->arg(0)));
  813       } else if (dynmatch(AssumeConstInst, assume_const, inst)) {
  814         move(vreg(inst), vreg(assume_const->arg(0)));
  815       } else if (dynmatch(PtrToIntInst, ptr_to_int, inst)) {
  816         switch (type_size(ptr_to_int->type())) {

Lines 1628-1645

  1628       assert(vreg.is_virtual());
  1629       VRegInfo& info = _vreg_info[vreg.id()];
  1630       if (info.current_reg.is_physical()) {
  1631         // No need to unspill, just move from current reg
! 1632         move(preg, info.current_reg);
  1633         reg_file.free(info.current_reg);
  1634       } else {
  1635         assert(info.stack_offset != ~size_t(0));
! 1636         X86Inst::Mem mem(Reg::X86_RSP(), (int32_t) info.stack_offset);
! 1637         if (info.reg_class == RegClass::FP) {
! 1638           _builder.movsd(preg, mem);
! 1639         } else {
! 1640           _builder.mov64(preg, mem);
! 1641         }
  1642       }
  1643       info.current_reg = preg;
  1644       reg_file.set(preg, vreg);
  1645     }

Lines 1670-1678

  1670              std::holds_alternative<Reg>(inst->rm());
  1671     }
  1672 
  1673     bool is_foldable_mov(X86Inst* inst) {
! 1674       if (is_reg_mov(inst)) {
  1675         Reg src = std::get<Reg>(inst->rm());
  1676         Reg dst = inst->reg();
  1677         assert(src.is_virtual() && dst.is_virtual());
  1678         if (_vreg_info[src.id()].current_reg.is_physical() &&

Lines 1800-1808

  1800             for (size_t it = 0; it < reg_file.size(); it++) {
  1801               Reg preg = Reg::phys(it);
  1802               if (!reg_file.is_free(preg) &&
  1803                   !info.is_preserved(preg) &&
! 1804                   std::find(data->args.begin(), data->args.end(), reg_file[preg]) == data->args.end() &&
  1805                   reg_file[preg] != std::get<Reg>(inst->rm())) {
  1806                 spill(reg_file, preg, false);
  1807               }
  1808             }

Lines 1822-1833

  1822                 _vreg_info[vreg.id()].current_reg = Reg();
  1823               }
  1824             }
  1825 
! 1826             VRegInfo& ret_info = _vreg_info[data->ret.id()];
! 1827             ret_info.current_reg = ret_info.fixed;
! 1828             reg_file.set(ret_info.fixed, data->ret);
! 1829             reg_file.touch(ret_info.fixed);
  1830 
  1831             it++;
  1832             continue;
  1833           } else {

@github-actions

Copy link
Copy Markdown

Coverage

File Lines Functions Regions Branches
genext.hpp 🔴 59.44% 🟡 80.95% 🟡 79.65% 🟡 79.34%
jitir.hpp 🔴 54.30% 🔴 67.32% 🔴 58.62% 🔴 57.30%
jitir_llvmapi.hpp 🔴 54.86% 🟡 80.00% 🟢 98.21% 🔴 50.00%
llvmgen.hpp 🔴 66.38% 🟡 70.00% 🟡 85.81% 🟡 87.18%
lowerllvm.hpp 🔴 63.60% 🟡 75.00% 🔴 41.32% 🔴 56.49%
x86gen.hpp 🟡 73.41% 🟡 81.08% 🟡 77.72% 🟡 84.51%
x86insts.inc.hpp - - - -
TOTAL 🔴 58.69% 🟡 70.33% 🔴 67.48% 🔴 68.65%
Diff Coverage

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • jitir.hpp (100%)
  • x86gen.hpp (87.0%): Missing lines 813,1633,1637-1642,1675,1805,1827-1830
  • x86insts.inc.hpp (100%)

Summary

  • Total: 120 lines
  • Missing: 14 lines
  • Coverage: 88%

x86gen.hpp

Lines 809-817

  809     void isel(Inst* inst, Block* block) {
  810       if (dynmatch(FreezeInst, freeze, inst)) {
  811         move(vreg(inst), vreg(freeze->arg(0)));
  812       } else if (dynmatch(PromoteInst, promote, inst)) {
! 813         move(vreg(inst), vreg(promote->arg(0)));
  814       } else if (dynmatch(AssumeConstInst, assume_const, inst)) {
  815         move(vreg(inst), vreg(assume_const->arg(0)));
  816       } else if (dynmatch(PtrToIntInst, ptr_to_int, inst)) {
  817         switch (type_size(ptr_to_int->type())) {

Lines 1629-1646

  1629       assert(vreg.is_virtual());
  1630       VRegInfo& info = _vreg_info[vreg.id()];
  1631       if (info.current_reg.is_physical()) {
  1632         // No need to unspill, just move from current reg
! 1633         move(preg, info.current_reg);
  1634         reg_file.free(info.current_reg);
  1635       } else {
  1636         assert(info.stack_offset != ~size_t(0));
! 1637         X86Inst::Mem mem(Reg::X86_RSP(), (int32_t) info.stack_offset);
! 1638         if (info.reg_class == RegClass::FP) {
! 1639           _builder.movsd(preg, mem);
! 1640         } else {
! 1641           _builder.mov64(preg, mem);
! 1642         }
  1643       }
  1644       info.current_reg = preg;
  1645       reg_file.set(preg, vreg);
  1646     }

Lines 1671-1679

  1671              std::holds_alternative<Reg>(inst->rm());
  1672     }
  1673 
  1674     bool is_foldable_mov(X86Inst* inst) {
! 1675       if (is_reg_mov(inst)) {
  1676         Reg src = std::get<Reg>(inst->rm());
  1677         Reg dst = inst->reg();
  1678         assert(src.is_virtual() && dst.is_virtual());
  1679         if (_vreg_info[src.id()].current_reg.is_physical() &&

Lines 1801-1809

  1801             for (size_t it = 0; it < reg_file.size(); it++) {
  1802               Reg preg = Reg::phys(it);
  1803               if (!reg_file.is_free(preg) &&
  1804                   !info.is_preserved(preg) &&
! 1805                   std::find(data->args.begin(), data->args.end(), reg_file[preg]) == data->args.end() &&
  1806                   reg_file[preg] != std::get<Reg>(inst->rm())) {
  1807                 spill(reg_file, preg, false);
  1808               }
  1809             }

Lines 1823-1834

  1823                 _vreg_info[vreg.id()].current_reg = Reg();
  1824               }
  1825             }
  1826 
! 1827             VRegInfo& ret_info = _vreg_info[data->ret.id()];
! 1828             ret_info.current_reg = ret_info.fixed;
! 1829             reg_file.set(ret_info.fixed, data->ret);
! 1830             reg_file.touch(ret_info.fixed);
  1831 
  1832             it++;
  1833             continue;
  1834           } else {

@github-actions

Copy link
Copy Markdown

Coverage

File Lines Functions Regions Branches
genext.hpp 🔴 59.44% 🟡 80.95% 🟡 79.65% 🟡 79.34%
jitir.hpp 🔴 54.40% 🔴 67.32% 🔴 58.81% 🔴 57.51%
jitir_llvmapi.hpp 🔴 54.86% 🟡 80.00% 🟢 98.21% 🔴 50.00%
llvmgen.hpp 🔴 66.38% 🟡 70.00% 🟡 85.81% 🟡 87.18%
lowerllvm.hpp 🔴 63.60% 🟡 75.00% 🔴 41.32% 🔴 56.49%
x86gen.hpp 🟡 72.66% 🟡 80.54% 🟡 77.62% 🟡 84.24%
x86insts.inc.hpp - - - -
TOTAL 🔴 58.65% 🟡 70.25% 🔴 67.53% 🔴 68.63%
Diff Coverage

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • jitir.hpp (100%)
  • x86gen.hpp (75.7%): Missing lines 732-751,840,1666,1670-1675,1708,1838,1860-1863
  • x86insts.inc.hpp (100%)

Summary

  • Total: 152 lines
  • Missing: 34 lines
  • Coverage: 77%

x86gen.hpp

Lines 728-755

  728         return Reg();
  729       }
  730     }
  731 
! 732     void move(Reg dst, Reg src) {
! 733       RegClass dst_class;
! 734       if (dst.is_virtual()) {
! 735         dst_class = _vreg_info[dst.id()].reg_class;
! 736       } else {
! 737         dst_class = reg_class(dst);
! 738       }
! 739       RegClass src_class;
! 740       if (src.is_virtual()) {
! 741         src_class = _vreg_info[src.id()].reg_class;
! 742       } else {
! 743         src_class = reg_class(src);
! 744       }
! 745       assert(dst_class == src_class);
! 746       if (dst_class == RegClass::Float) {
! 747         _builder.movsd(dst, src);
! 748       } else {
! 749         _builder.mov64(dst, src);
! 750       }
! 751     }
  752 
  753     void build_add(Reg dst, Value* a, Value* b) {
  754       X86Inst::Mem mem;
  755       if (dynmatch(Const, constant_b, b)) {

Lines 836-844

  836     void isel(Inst* inst, Block* block) {
  837       if (dynmatch(FreezeInst, freeze, inst)) {
  838         move(vreg(inst), vreg(freeze->arg(0)));
  839       } else if (dynmatch(PromoteInst, promote, inst)) {
! 840         move(vreg(inst), vreg(promote->arg(0)));
  841       } else if (dynmatch(AssumeConstInst, assume_const, inst)) {
  842         move(vreg(inst), vreg(assume_const->arg(0)));
  843       } else if (dynmatch(PtrToIntInst, ptr_to_int, inst)) {
  844         switch (type_size(ptr_to_int->type())) {

Lines 1662-1679

  1662       assert(vreg.is_virtual());
  1663       VRegInfo& info = _vreg_info[vreg.id()];
  1664       if (info.current_reg.is_physical()) {
  1665         // No need to unspill, just move from current reg
! 1666         move(preg, info.current_reg);
  1667         reg_file.free(info.current_reg);
  1668       } else {
  1669         assert(info.stack_offset != ~size_t(0));
! 1670         X86Inst::Mem mem(Reg::X86_RSP(), (int32_t) info.stack_offset);
! 1671         if (info.reg_class == RegClass::Float) {
! 1672           _builder.movsd(preg, mem);
! 1673         } else {
! 1674           _builder.mov64(preg, mem);
! 1675         }
  1676       }
  1677       info.current_reg = preg;
  1678       reg_file.set(preg, vreg);
  1679     }

Lines 1704-1712

  1704              std::holds_alternative<Reg>(inst->rm());
  1705     }
  1706 
  1707     bool is_foldable_mov(X86Inst* inst) {
! 1708       if (is_reg_mov(inst)) {
  1709         Reg src = std::get<Reg>(inst->rm());
  1710         Reg dst = inst->reg();
  1711         assert(src.is_virtual() && dst.is_virtual());
  1712         if (_vreg_info[src.id()].current_reg.is_physical() &&

Lines 1834-1842

  1834             for (size_t it = 0; it < reg_file.size(); it++) {
  1835               Reg preg = Reg::phys(it);
  1836               if (!reg_file.is_free(preg) &&
  1837                   !info.is_preserved(preg) &&
! 1838                   std::find(data->args.begin(), data->args.end(), reg_file[preg]) == data->args.end() &&
  1839                   reg_file[preg] != std::get<Reg>(inst->rm())) {
  1840                 spill(reg_file, preg, false);
  1841               }
  1842             }

Lines 1856-1867

  1856                 _vreg_info[vreg.id()].current_reg = Reg();
  1857               }
  1858             }
  1859 
! 1860             VRegInfo& ret_info = _vreg_info[data->ret.id()];
! 1861             ret_info.current_reg = ret_info.fixed;
! 1862             reg_file.set(ret_info.fixed, data->ret);
! 1863             reg_file.touch(ret_info.fixed);
  1864 
  1865             it++;
  1866             continue;
  1867           } else {

@can-lehmann can-lehmann changed the title x86 floating point regalloc, calls x86 floating point regalloc, calls, load/store, select Sep 30, 2026
@github-actions

Copy link
Copy Markdown

Coverage

File Lines Functions Regions Branches
genext.hpp 🔴 59.44% 🟡 80.95% 🟡 79.65% 🟡 79.34%
jitir.hpp 🔴 54.30% 🔴 67.32% 🔴 58.62% 🔴 57.30%
jitir_llvmapi.hpp 🔴 54.86% 🟡 80.00% 🟢 98.21% 🔴 50.00%
llvmgen.hpp 🔴 66.38% 🟡 70.00% 🟡 85.81% 🟡 87.18%
lowerllvm.hpp 🔴 63.60% 🟡 75.00% 🔴 41.32% 🔴 56.49%
x86gen.hpp 🟡 73.33% 🟡 80.54% 🟡 77.74% 🟡 84.31%
x86insts.inc.hpp - - - -
TOTAL 🔴 58.70% 🟡 70.25% 🔴 67.49% 🔴 68.57%
Diff Coverage

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • jitir.hpp (100%)
  • x86gen.hpp (77.5%): Missing lines 732-751,840,1675,1679-1684,1717,1847,1869-1872
  • x86insts.inc.hpp (100%)

Summary

  • Total: 164 lines
  • Missing: 34 lines
  • Coverage: 79%

x86gen.hpp

Lines 728-755

  728         return Reg();
  729       }
  730     }
  731 
! 732     void move(Reg dst, Reg src) {
! 733       RegClass dst_class;
! 734       if (dst.is_virtual()) {
! 735         dst_class = _vreg_info[dst.id()].reg_class;
! 736       } else {
! 737         dst_class = reg_class(dst);
! 738       }
! 739       RegClass src_class;
! 740       if (src.is_virtual()) {
! 741         src_class = _vreg_info[src.id()].reg_class;
! 742       } else {
! 743         src_class = reg_class(src);
! 744       }
! 745       assert(dst_class == src_class);
! 746       if (dst_class == RegClass::Float) {
! 747         _builder.movsd(dst, src);
! 748       } else {
! 749         _builder.mov64(dst, src);
! 750       }
! 751     }
  752 
  753     void build_add(Reg dst, Value* a, Value* b) {
  754       X86Inst::Mem mem;
  755       if (dynmatch(Const, constant_b, b)) {

Lines 836-844

  836     void isel(Inst* inst, Block* block) {
  837       if (dynmatch(FreezeInst, freeze, inst)) {
  838         move(vreg(inst), vreg(freeze->arg(0)));
  839       } else if (dynmatch(PromoteInst, promote, inst)) {
! 840         move(vreg(inst), vreg(promote->arg(0)));
  841       } else if (dynmatch(AssumeConstInst, assume_const, inst)) {
  842         move(vreg(inst), vreg(assume_const->arg(0)));
  843       } else if (dynmatch(PtrToIntInst, ptr_to_int, inst)) {
  844         switch (type_size(ptr_to_int->type())) {

Lines 1671-1688

  1671       assert(vreg.is_virtual());
  1672       VRegInfo& info = _vreg_info[vreg.id()];
  1673       if (info.current_reg.is_physical()) {
  1674         // No need to unspill, just move from current reg
! 1675         move(preg, info.current_reg);
  1676         reg_file.free(info.current_reg);
  1677       } else {
  1678         assert(info.stack_offset != ~size_t(0));
! 1679         X86Inst::Mem mem(Reg::X86_RSP(), (int32_t) info.stack_offset);
! 1680         if (info.reg_class == RegClass::Float) {
! 1681           _builder.movsd(preg, mem);
! 1682         } else {
! 1683           _builder.mov64(preg, mem);
! 1684         }
  1685       }
  1686       info.current_reg = preg;
  1687       reg_file.set(preg, vreg);
  1688     }

Lines 1713-1721

  1713              std::holds_alternative<Reg>(inst->rm());
  1714     }
  1715 
  1716     bool is_foldable_mov(X86Inst* inst) {
! 1717       if (is_reg_mov(inst)) {
  1718         Reg src = std::get<Reg>(inst->rm());
  1719         Reg dst = inst->reg();
  1720         assert(src.is_virtual() && dst.is_virtual());
  1721         if (_vreg_info[src.id()].current_reg.is_physical() &&

Lines 1843-1851

  1843             for (size_t it = 0; it < reg_file.size(); it++) {
  1844               Reg preg = Reg::phys(it);
  1845               if (!reg_file.is_free(preg) &&
  1846                   !info.is_preserved(preg) &&
! 1847                   std::find(data->args.begin(), data->args.end(), reg_file[preg]) == data->args.end() &&
  1848                   reg_file[preg] != std::get<Reg>(inst->rm())) {
  1849                 spill(reg_file, preg, false);
  1850               }
  1851             }

Lines 1865-1876

  1865                 _vreg_info[vreg.id()].current_reg = Reg();
  1866               }
  1867             }
  1868 
! 1869             VRegInfo& ret_info = _vreg_info[data->ret.id()];
! 1870             ret_info.current_reg = ret_info.fixed;
! 1871             reg_file.set(ret_info.fixed, data->ret);
! 1872             reg_file.touch(ret_info.fixed);
  1873 
  1874             it++;
  1875             continue;
  1876           } else {

@github-actions

Copy link
Copy Markdown

Coverage

File Lines Functions Regions Branches
genext.hpp 🔴 59.44% 🟡 80.95% 🟡 79.65% 🟡 79.34%
jitir.hpp 🔴 54.30% 🔴 67.32% 🔴 58.62% 🔴 57.30%
jitir_llvmapi.hpp 🔴 54.86% 🟡 80.00% 🟢 98.21% 🔴 50.00%
llvmgen.hpp 🔴 67.63% 🟡 70.00% 🟡 86.13% 🟡 88.03%
lowerllvm.hpp 🔴 63.60% 🟡 75.00% 🔴 41.32% 🔴 56.49%
x86gen.hpp 🟡 72.93% 🟡 81.48% 🟡 77.60% 🟡 84.17%
x86insts.inc.hpp - - - -
TOTAL 🔴 58.73% 🟡 70.43% 🔴 67.49% 🔴 68.59%
Diff Coverage

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • jitir.hpp (100%)
  • llvmgen.hpp (100%)
  • x86gen.hpp (89.1%): Missing lines 858,1665,1668,1676-1681,1735,1818-1819,1822,1866,1888-1891,2364-2365
  • x86insts.inc.hpp (100%)

Summary

  • Total: 201 lines
  • Missing: 20 lines
  • Coverage: 90%

x86gen.hpp

Lines 854-862

  854     void isel(Inst* inst, Block* block) {
  855       if (dynmatch(FreezeInst, freeze, inst)) {
  856         move(vreg(inst), vreg(freeze->arg(0)));
  857       } else if (dynmatch(PromoteInst, promote, inst)) {
! 858         move(vreg(inst), vreg(promote->arg(0)));
  859       } else if (dynmatch(AssumeConstInst, assume_const, inst)) {
  860         move(vreg(inst), vreg(assume_const->arg(0)));
  861       } else if (dynmatch(PtrToIntInst, ptr_to_int, inst)) {
  862         switch (type_size(ptr_to_int->type())) {

Lines 1661-1672

  1661     void spill(RegFileState& reg_file, Reg preg, bool allow_spill_to_reg = true) {
  1662       Reg vreg = reg_file[preg];
  1663       if (vreg.is_virtual()) {
  1664         VRegInfo& info = _vreg_info[vreg.id()];
! 1665         Reg free_reg = reg_file.get_free_reg(info.reg_class);
  1666         if (allow_spill_to_reg && free_reg.is_physical()) {
  1667           // No need to spill, just move to free reg
! 1668           move(free_reg, preg);
  1669           reg_file.free(preg);
  1670           info.current_reg = free_reg;
  1671           reg_file.set(free_reg, vreg);
  1672         } else {

Lines 1672-1685

  1672         } else {
  1673           if (info.stack_offset == ~size_t(0)) {
  1674             info.stack_offset = _stack_offset_alloc.alloc();
  1675           }
! 1676           X86Inst::Mem mem(Reg::X86_RSP(), (int32_t) info.stack_offset);
! 1677           if (info.reg_class == RegClass::X86_FLOAT()) {
! 1678             _builder.movsd_mem(mem, preg);
! 1679           } else {
! 1680             _builder.mov64_mem(mem, preg);
! 1681           }
  1682           reg_file.free(preg);
  1683           info.current_reg = Reg();
  1684         }
  1685       }

Lines 1731-1739

  1731              std::holds_alternative<Reg>(inst->rm());
  1732     }
  1733 
  1734     bool is_foldable_mov(X86Inst* inst) {
! 1735       if (is_reg_mov(inst)) {
  1736         Reg src = std::get<Reg>(inst->rm());
  1737         Reg dst = inst->reg();
  1738         assert(src.is_virtual() && dst.is_virtual());
  1739         if (_vreg_info[src.id()].current_reg.is_physical() &&

Lines 1814-1826

  1814       Reg* initial_state = (Reg*) _allocator.alloc(sizeof(Reg) * reg_file.size(), alignof(Reg));
  1815       std::fill(initial_state, initial_state + reg_file.size(), Reg());
  1816 
  1817       for (Arg* arg : _section->entry()->args()) {
! 1818         Reg input = Reg::virt(arg->index());
! 1819         VRegInfo& info = _vreg_info[input.id()];
  1820         info.interval.incl(0);
  1821         assert(info.fixed.is_physical() && "Entry arguments must be in fixed registers");
! 1822         initial_state[info.fixed.id()] = input;
  1823       }
  1824       _blocks[0]->set_regalloc(initial_state);
  1825 
  1826       for (size_t block_index = 0; block_index < _blocks.size(); block_index++) {

Lines 1862-1870

  1862             for (size_t it = 0; it < reg_file.size(); it++) {
  1863               Reg preg = Reg::phys(it);
  1864               if (!reg_file.is_free(preg) &&
  1865                   !info.is_preserved(preg) &&
! 1866                   std::find(data->args.begin(), data->args.end(), reg_file[preg]) == data->args.end() &&
  1867                   reg_file[preg] != std::get<Reg>(inst->rm())) {
  1868                 spill(reg_file, preg, false);
  1869               }
  1870             }

Lines 1884-1895

  1884                 _vreg_info[vreg.id()].current_reg = Reg();
  1885               }
  1886             }
  1887 
! 1888             VRegInfo& ret_info = _vreg_info[data->ret.id()];
! 1889             ret_info.current_reg = ret_info.fixed;
! 1890             reg_file.set(ret_info.fixed, data->ret);
! 1891             reg_file.touch(ret_info.fixed);
  1892 
  1893             it++;
  1894             continue;
  1895           } else {

Lines 2360-2369

  2360         if (!(input == vreg(arg))) {
  2361           if (is_float(arg->type())) {
  2362             _builder.movq(vreg(arg), input);
  2363           } else {
! 2364             _builder.movq_to_int(vreg(arg), input);
! 2365           }
  2366         }
  2367       }
  2368       autoname_insts();

@github-actions

Copy link
Copy Markdown

Coverage

File Lines Functions Regions Branches
genext.hpp 🔴 59.44% 🟡 80.95% 🟡 79.65% 🟡 79.34%
jitir.hpp 🔴 54.30% 🔴 67.32% 🔴 58.62% 🔴 57.30%
jitir_llvmapi.hpp 🔴 54.86% 🟡 80.00% 🟢 98.21% 🔴 50.00%
llvmgen.hpp 🔴 67.63% 🟡 70.00% 🟡 86.13% 🟡 88.03%
lowerllvm.hpp 🔴 63.60% 🟡 75.00% 🔴 41.32% 🔴 56.49%
x86gen.hpp 🟡 72.89% 🟡 81.58% 🟡 77.65% 🟡 84.22%
x86insts.inc.hpp - - - -
TOTAL 🔴 58.72% 🟡 70.46% 🔴 67.50% 🔴 68.58%
Diff Coverage

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • jitir.hpp (100%)
  • llvmgen.hpp (100%)
  • x86gen.hpp (89.0%): Missing lines 857,1663,1666,1674-1679,1733,1816-1817,1820,1864,1886-1889,2362-2363
  • x86insts.inc.hpp (100%)

Summary

  • Total: 198 lines
  • Missing: 20 lines
  • Coverage: 89%

x86gen.hpp

Lines 853-861

  853     void isel(Inst* inst, Block* block) {
  854       if (dynmatch(FreezeInst, freeze, inst)) {
  855         move(vreg(inst), vreg(freeze->arg(0)));
  856       } else if (dynmatch(PromoteInst, promote, inst)) {
! 857         move(vreg(inst), vreg(promote->arg(0)));
  858       } else if (dynmatch(AssumeConstInst, assume_const, inst)) {
  859         move(vreg(inst), vreg(assume_const->arg(0)));
  860       } else if (dynmatch(PtrToIntInst, ptr_to_int, inst)) {
  861         switch (type_size(ptr_to_int->type())) {

Lines 1659-1670

  1659     void spill(RegFileState& reg_file, Reg preg, bool allow_spill_to_reg = true) {
  1660       Reg vreg = reg_file[preg];
  1661       if (vreg.is_virtual()) {
  1662         VRegInfo& info = _vreg_info[vreg.id()];
! 1663         Reg free_reg = reg_file.get_free_reg(info.reg_class);
  1664         if (allow_spill_to_reg && free_reg.is_physical()) {
  1665           // No need to spill, just move to free reg
! 1666           move(free_reg, preg);
  1667           reg_file.free(preg);
  1668           info.current_reg = free_reg;
  1669           reg_file.set(free_reg, vreg);
  1670         } else {

Lines 1670-1683

  1670         } else {
  1671           if (info.stack_offset == ~size_t(0)) {
  1672             info.stack_offset = _stack_offset_alloc.alloc();
  1673           }
! 1674           X86Inst::Mem mem(Reg::X86_RSP(), (int32_t) info.stack_offset);
! 1675           if (info.reg_class == RegClass::X86_FLOAT()) {
! 1676             _builder.movsd_mem(mem, preg);
! 1677           } else {
! 1678             _builder.mov64_mem(mem, preg);
! 1679           }
  1680           reg_file.free(preg);
  1681           info.current_reg = Reg();
  1682         }
  1683       }

Lines 1729-1737

  1729              std::holds_alternative<Reg>(inst->rm());
  1730     }
  1731 
  1732     bool is_foldable_mov(X86Inst* inst) {
! 1733       if (is_reg_mov(inst)) {
  1734         Reg src = std::get<Reg>(inst->rm());
  1735         Reg dst = inst->reg();
  1736         assert(src.is_virtual() && dst.is_virtual());
  1737         if (_vreg_info[src.id()].current_reg.is_physical() &&

Lines 1812-1824

  1812       Reg* initial_state = (Reg*) _allocator.alloc(sizeof(Reg) * reg_file.size(), alignof(Reg));
  1813       std::fill(initial_state, initial_state + reg_file.size(), Reg());
  1814 
  1815       for (Arg* arg : _section->entry()->args()) {
! 1816         Reg input = Reg::virt(arg->index());
! 1817         VRegInfo& info = _vreg_info[input.id()];
  1818         info.interval.incl(0);
  1819         assert(info.fixed.is_physical() && "Entry arguments must be in fixed registers");
! 1820         initial_state[info.fixed.id()] = input;
  1821       }
  1822       _blocks[0]->set_regalloc(initial_state);
  1823 
  1824       for (size_t block_index = 0; block_index < _blocks.size(); block_index++) {

Lines 1860-1868

  1860             for (size_t it = 0; it < reg_file.size(); it++) {
  1861               Reg preg = Reg::phys(it);
  1862               if (!reg_file.is_free(preg) &&
  1863                   !info.is_preserved(preg) &&
! 1864                   std::find(data->args.begin(), data->args.end(), reg_file[preg]) == data->args.end() &&
  1865                   reg_file[preg] != std::get<Reg>(inst->rm())) {
  1866                 spill(reg_file, preg, false);
  1867               }
  1868             }

Lines 1882-1893

  1882                 _vreg_info[vreg.id()].current_reg = Reg();
  1883               }
  1884             }
  1885 
! 1886             VRegInfo& ret_info = _vreg_info[data->ret.id()];
! 1887             ret_info.current_reg = ret_info.fixed;
! 1888             reg_file.set(ret_info.fixed, data->ret);
! 1889             reg_file.touch(ret_info.fixed);
  1890 
  1891             it++;
  1892             continue;
  1893           } else {

Lines 2358-2367

  2358         if (!(input == vreg(arg))) {
  2359           if (is_float(arg->type())) {
  2360             _builder.movq(vreg(arg), input);
  2361           } else {
! 2362             _builder.movq_to_int(vreg(arg), input);
! 2363           }
  2364         }
  2365       }
  2366       autoname_insts();

@github-actions

Copy link
Copy Markdown

Coverage

File Lines Functions Regions Branches
genext.hpp 🔴 59.44% 🟡 80.95% 🟡 79.65% 🟡 79.34%
jitir.hpp 🔴 54.40% 🔴 67.32% 🔴 58.81% 🔴 57.51%
jitir_llvmapi.hpp 🔴 54.86% 🟡 80.00% 🟢 98.21% 🔴 50.00%
llvmgen.hpp 🔴 67.63% 🟡 70.00% 🟡 86.13% 🟡 88.03%
lowerllvm.hpp 🔴 63.60% 🟡 75.00% 🔴 41.32% 🔴 56.49%
x86gen.hpp 🟡 73.00% 🟡 81.58% 🟡 77.60% 🟡 84.22%
x86insts.inc.hpp - - - -
TOTAL 🔴 58.80% 🟡 70.46% 🔴 67.58% 🔴 68.69%
Diff Coverage

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • jitir.hpp (100%)
  • llvmgen.hpp (100%)
  • x86gen.hpp (90.2%): Missing lines 858,1665,1668,1676-1681,1735,1818-1819,1822,1866,1888-1891
  • x86insts.inc.hpp (100%)

Summary

  • Total: 200 lines
  • Missing: 18 lines
  • Coverage: 91%

x86gen.hpp

Lines 854-862

  854     void isel(Inst* inst, Block* block) {
  855       if (dynmatch(FreezeInst, freeze, inst)) {
  856         move(vreg(inst), vreg(freeze->arg(0)));
  857       } else if (dynmatch(PromoteInst, promote, inst)) {
! 858         move(vreg(inst), vreg(promote->arg(0)));
  859       } else if (dynmatch(AssumeConstInst, assume_const, inst)) {
  860         move(vreg(inst), vreg(assume_const->arg(0)));
  861       } else if (dynmatch(PtrToIntInst, ptr_to_int, inst)) {
  862         switch (type_size(ptr_to_int->type())) {

Lines 1661-1672

  1661     void spill(RegFileState& reg_file, Reg preg, bool allow_spill_to_reg = true) {
  1662       Reg vreg = reg_file[preg];
  1663       if (vreg.is_virtual()) {
  1664         VRegInfo& info = _vreg_info[vreg.id()];
! 1665         Reg free_reg = reg_file.get_free_reg(info.reg_class);
  1666         if (allow_spill_to_reg && free_reg.is_physical()) {
  1667           // No need to spill, just move to free reg
! 1668           move(free_reg, preg);
  1669           reg_file.free(preg);
  1670           info.current_reg = free_reg;
  1671           reg_file.set(free_reg, vreg);
  1672         } else {

Lines 1672-1685

  1672         } else {
  1673           if (info.stack_offset == ~size_t(0)) {
  1674             info.stack_offset = _stack_offset_alloc.alloc();
  1675           }
! 1676           X86Inst::Mem mem(Reg::X86_RSP(), (int32_t) info.stack_offset);
! 1677           if (info.reg_class == RegClass::X86_FLOAT()) {
! 1678             _builder.movsd_mem(mem, preg);
! 1679           } else {
! 1680             _builder.mov64_mem(mem, preg);
! 1681           }
  1682           reg_file.free(preg);
  1683           info.current_reg = Reg();
  1684         }
  1685       }

Lines 1731-1739

  1731              std::holds_alternative<Reg>(inst->rm());
  1732     }
  1733 
  1734     bool is_foldable_mov(X86Inst* inst) {
! 1735       if (is_reg_mov(inst)) {
  1736         Reg src = std::get<Reg>(inst->rm());
  1737         Reg dst = inst->reg();
  1738         assert(src.is_virtual() && dst.is_virtual());
  1739         if (_vreg_info[src.id()].current_reg.is_physical() &&

Lines 1814-1826

  1814       Reg* initial_state = (Reg*) _allocator.alloc(sizeof(Reg) * reg_file.size(), alignof(Reg));
  1815       std::fill(initial_state, initial_state + reg_file.size(), Reg());
  1816 
  1817       for (Arg* arg : _section->entry()->args()) {
! 1818         Reg input = _input_vregs.at(arg->index());
! 1819         VRegInfo& info = _vreg_info[input.id()];
  1820         info.interval.incl(0);
  1821         assert(info.fixed.is_physical() && "Entry arguments must be in fixed registers");
! 1822         initial_state[info.fixed.id()] = input;
  1823       }
  1824       _blocks[0]->set_regalloc(initial_state);
  1825 
  1826       for (size_t block_index = 0; block_index < _blocks.size(); block_index++) {

Lines 1862-1870

  1862             for (size_t it = 0; it < reg_file.size(); it++) {
  1863               Reg preg = Reg::phys(it);
  1864               if (!reg_file.is_free(preg) &&
  1865                   !info.is_preserved(preg) &&
! 1866                   std::find(data->args.begin(), data->args.end(), reg_file[preg]) == data->args.end() &&
  1867                   reg_file[preg] != std::get<Reg>(inst->rm())) {
  1868                 spill(reg_file, preg, false);
  1869               }
  1870             }

Lines 1884-1895

  1884                 _vreg_info[vreg.id()].current_reg = Reg();
  1885               }
  1886             }
  1887 
! 1888             VRegInfo& ret_info = _vreg_info[data->ret.id()];
! 1889             ret_info.current_reg = ret_info.fixed;
! 1890             reg_file.set(ret_info.fixed, data->ret);
! 1891             reg_file.touch(ret_info.fixed);
  1892 
  1893             it++;
  1894             continue;
  1895           } else {

@github-actions

Copy link
Copy Markdown

Coverage

File Lines Functions Regions Branches
genext.hpp 🔴 59.44% 🟡 80.95% 🟡 79.65% 🟡 79.34%
jitir.hpp 🔴 54.40% 🔴 67.32% 🔴 58.81% 🔴 57.51%
jitir_llvmapi.hpp 🔴 54.86% 🟡 80.00% 🟢 98.21% 🔴 50.00%
llvmgen.hpp 🔴 67.63% 🟡 70.00% 🟡 86.13% 🟡 88.03%
lowerllvm.hpp 🔴 63.60% 🟡 75.00% 🔴 41.32% 🔴 56.49%
x86gen.hpp 🟡 73.00% 🟡 81.58% 🟡 77.60% 🟡 84.22%
x86insts.inc.hpp - - - -
TOTAL 🔴 58.80% 🟡 70.46% 🔴 67.58% 🔴 68.69%
Diff Coverage

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • jitir.hpp (100%)
  • llvmgen.hpp (100%)
  • x86gen.hpp (90.2%): Missing lines 858,1665,1668,1676-1681,1735,1818-1819,1822,1866,1888-1891
  • x86insts.inc.hpp (100%)

Summary

  • Total: 200 lines
  • Missing: 18 lines
  • Coverage: 91%

x86gen.hpp

Lines 854-862

  854     void isel(Inst* inst, Block* block) {
  855       if (dynmatch(FreezeInst, freeze, inst)) {
  856         move(vreg(inst), vreg(freeze->arg(0)));
  857       } else if (dynmatch(PromoteInst, promote, inst)) {
! 858         move(vreg(inst), vreg(promote->arg(0)));
  859       } else if (dynmatch(AssumeConstInst, assume_const, inst)) {
  860         move(vreg(inst), vreg(assume_const->arg(0)));
  861       } else if (dynmatch(PtrToIntInst, ptr_to_int, inst)) {
  862         switch (type_size(ptr_to_int->type())) {

Lines 1661-1672

  1661     void spill(RegFileState& reg_file, Reg preg, bool allow_spill_to_reg = true) {
  1662       Reg vreg = reg_file[preg];
  1663       if (vreg.is_virtual()) {
  1664         VRegInfo& info = _vreg_info[vreg.id()];
! 1665         Reg free_reg = reg_file.get_free_reg(info.reg_class);
  1666         if (allow_spill_to_reg && free_reg.is_physical()) {
  1667           // No need to spill, just move to free reg
! 1668           move(free_reg, preg);
  1669           reg_file.free(preg);
  1670           info.current_reg = free_reg;
  1671           reg_file.set(free_reg, vreg);
  1672         } else {

Lines 1672-1685

  1672         } else {
  1673           if (info.stack_offset == ~size_t(0)) {
  1674             info.stack_offset = _stack_offset_alloc.alloc();
  1675           }
! 1676           X86Inst::Mem mem(Reg::X86_RSP(), (int32_t) info.stack_offset);
! 1677           if (info.reg_class == RegClass::X86_FLOAT()) {
! 1678             _builder.movsd_mem(mem, preg);
! 1679           } else {
! 1680             _builder.mov64_mem(mem, preg);
! 1681           }
  1682           reg_file.free(preg);
  1683           info.current_reg = Reg();
  1684         }
  1685       }

Lines 1731-1739

  1731              std::holds_alternative<Reg>(inst->rm());
  1732     }
  1733 
  1734     bool is_foldable_mov(X86Inst* inst) {
! 1735       if (is_reg_mov(inst)) {
  1736         Reg src = std::get<Reg>(inst->rm());
  1737         Reg dst = inst->reg();
  1738         assert(src.is_virtual() && dst.is_virtual());
  1739         if (_vreg_info[src.id()].current_reg.is_physical() &&

Lines 1814-1826

  1814       Reg* initial_state = (Reg*) _allocator.alloc(sizeof(Reg) * reg_file.size(), alignof(Reg));
  1815       std::fill(initial_state, initial_state + reg_file.size(), Reg());
  1816 
  1817       for (Arg* arg : _section->entry()->args()) {
! 1818         Reg input = _input_vregs.at(arg->index());
! 1819         VRegInfo& info = _vreg_info[input.id()];
  1820         info.interval.incl(0);
  1821         assert(info.fixed.is_physical() && "Entry arguments must be in fixed registers");
! 1822         initial_state[info.fixed.id()] = input;
  1823       }
  1824       _blocks[0]->set_regalloc(initial_state);
  1825 
  1826       for (size_t block_index = 0; block_index < _blocks.size(); block_index++) {

Lines 1862-1870

  1862             for (size_t it = 0; it < reg_file.size(); it++) {
  1863               Reg preg = Reg::phys(it);
  1864               if (!reg_file.is_free(preg) &&
  1865                   !info.is_preserved(preg) &&
! 1866                   std::find(data->args.begin(), data->args.end(), reg_file[preg]) == data->args.end() &&
  1867                   reg_file[preg] != std::get<Reg>(inst->rm())) {
  1868                 spill(reg_file, preg, false);
  1869               }
  1870             }

Lines 1884-1895

  1884                 _vreg_info[vreg.id()].current_reg = Reg();
  1885               }
  1886             }
  1887 
! 1888             VRegInfo& ret_info = _vreg_info[data->ret.id()];
! 1889             ret_info.current_reg = ret_info.fixed;
! 1890             reg_file.set(ret_info.fixed, data->ret);
! 1891             reg_file.touch(ret_info.fixed);
  1892 
  1893             it++;
  1894             continue;
  1895           } else {

@can-lehmann can-lehmann changed the title x86 floating point regalloc, calls, load/store, select x86 floating point regalloc, calls, load/store, select, eq Sep 30, 2026
@can-lehmann
can-lehmann merged commit 26c9131 into main Sep 30, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant