Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement loop peeling. #1510

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
Draft

Conversation

ptersilie
Copy link
Contributor

@ptersilie ptersilie commented Dec 13, 2024

While this isn't ready yet, I'm raising this as a draft, so @ltratt may have a peek. Running simple.c we get the following trace, which shows the direction we want this to go.

%0: ptr = param Direct(6, -48, 8)
%1: ptr = param Direct(6, -40, 8)
%2: ptr = param Register(15, 8, 0, [])
%3: ptr = param Register(12, 8, 0, [])
header_start [%0, %1, %2, %3]
%5: ptr = lookup_global @stderr
%6: ptr = load %5
%7: i32 = load %3
%8: ptr = lookup_global @.str
%9: i32 = call @fprintf(%6, %8, %7)
%10: i32 = load %3
%11: i32 = add %10, 4294967295i32
*%3 = %11
%13: i32 = load %3
%14: i1 = sgt %13, 0i32
guard true, %14, [0:%0_6: %0, 0:%0_7: %1, 0:%0_8: %2, 0:%0_9: %3, 0:%8_1: 0i1]
header_end [%0, %1, %2, %3]
%18: ptr = param Direct(6, -48, 8)
%19: ptr = param Direct(6, -40, 8)
%20: ptr = param Register(15, 8, 0, [])
%21: ptr = param Register(12, 8, 0, [])
body_start [%18, %19, %20, %21]
%23: ptr = lookup_global @stderr
%24: ptr = load %23
%25: i32 = load %21
%26: ptr = lookup_global @.str
%27: i32 = call @fprintf(%24, %26, %25)
%28: i32 = load %21
%29: i32 = add %28, 4294967295i32
*%21 = %29
%31: i32 = load %21
%32: i1 = sgt %31, 0i32
guard true, %32, [0:%0_6: %18, 0:%0_7: %19, 0:%0_8: %20, 0:%0_9: %21, 0:%8_1: 0i1]
body_end [%18, %19, %20, %21]

I have taken this opportunity to rename the labels as their previous names consistently managed to confuse me. I'm not married to these names, so I'm open to discussion. But I do believe they need changing.

With the current PR, I'm getting the following error when running simple.c:

thread '<unnamed>' panicked at ykrt/src/compile/jitc_yk/codegen/x64/lsregalloc.rs:204:21:
assertion failed: !self.gp_regset.is_set(reg)

This is possibly due to the way we copy the VarLocations from the header_end to the body_start, which we do here: https://github.com/ykjit/yk/pull/1510/files#diff-b7513e8c31bfe56ee2b41fa041e8632d81f4bafc2e759b22b597f3867359269eR1938. I would also like to turn your attention the big comment there, which explains why we are doing things this way, and is related to what we discussed earlier.

@ptersilie ptersilie marked this pull request as draft December 13, 2024 14:18
@ltratt
Copy link
Contributor

ltratt commented Dec 16, 2024

On a fresh clone (and even if I merge in master), I see a different error:

thread '<unnamed>' panicked at ykrt/src/compile/jitc_yk/jit_ir/mod.rs:333:19:
index out of bounds: the len is 67 but the index is 69
stack backtrace:
   0: rust_begin_unwind
             at /rustc/5e1440ae514d98ddfcbf1607acb64d41e07ef616/library/std/src/panicking.rs:681:5
   1: core::panicking::panic_fmt
             at /rustc/5e1440ae514d98ddfcbf1607acb64d41e07ef616/library/core/src/panicking.rs:75:14
   2: core::panicking::panic_bounds_check
             at /rustc/5e1440ae514d98ddfcbf1607acb64d41e07ef616/library/core/src/panicking.rs:273:5
   3: <usize as core::slice::index::SliceIndex<[T]>>::index
             at /rustc/5e1440ae514d98ddfcbf1607acb64d41e07ef616/library/core/src/slice/index.rs:274:10
   4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
             at /rustc/5e1440ae514d98ddfcbf1607acb64d41e07ef616/library/core/src/slice/index.rs:16:9
   5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
             at /rustc/5e1440ae514d98ddfcbf1607acb64d41e07ef616/library/alloc/src/vec/mod.rs:3346:9
   6: ykrt::compile::jitc_yk::jit_ir::Module::inst_raw
             at /vol/extra/ltratt/yk/ykrt/src/compile/jitc_yk/jit_ir/mod.rs:333:19
   7: ykrt::compile::jitc_yk::jit_ir::PackedOperand::unpack
             at /vol/extra/ltratt/yk/ykrt/src/compile/jitc_yk/jit_ir/mod.rs:1104:23
   8: ykrt::compile::jitc_yk::jit_ir::Inst::map_operand_locals
             at /vol/extra/ltratt/yk/ykrt/src/compile/jitc_yk/jit_ir/mod.rs:1588:21
   9: ykrt::compile::jitc_yk::jit_ir::dead_code::<impl ykrt::compile::jitc_yk::jit_ir::Module>::dead_code_elimination
             at /vol/extra/ltratt/yk/ykrt/src/compile/jitc_yk/jit_ir/dead_code.rs:20:17
  10: ykrt::compile::jitc_yk::opt::Opt::opt
             at /vol/extra/ltratt/yk/ykrt/src/compile/jitc_yk/opt/mod.rs:426:9
  11: ykrt::compile::jitc_yk::opt::opt
             at /vol/extra/ltratt/yk/ykrt/src/compile/jitc_yk/opt/mod.rs:567:5

@@ -1844,14 +1853,18 @@ impl<'a> Assemble<'a> {
reg_alloc::Register::GP(r) => {
let [_] = self.ra.assign_gp_regs(
&mut self.asm,
iidx,
// This tells the register allocator to assign this register
// to the instruction at `iidx` so we can look it up later. Since
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "since we are at the end" bit is dangerous: the register allocator does (must!) take into account iidx when making decisions about what to spill etc. By passing in 0 here, I think weird things will happen. Is there any reason not to pass iidx here (and below)?

@@ -423,8 +429,10 @@ impl Module {
}

/// Push the location of a trace parameter.
pub(crate) fn push_param(&mut self, loc: yksmp::Location) {
pub(crate) fn push_param(&mut self, loc: yksmp::Location) -> usize {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should return a ParamIdx.

}),
Inst::Call(dc) => {
// Clone and map arguments.
let args = (0..(dc.num_args()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CallInst::iter_args_idx does this horror for you.

Inst::IndirectCall(iidx) => {
let ic = m.indirect_call(*iidx);
// Clone and map arguments.
let args = (0..(ic.num_args()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto IndirectCallInst::iter_args_idx.

where
F: Fn(InstIdx, &Module) -> Operand,
{
let mapper = |x: &PackedOperand, m: &Module| match x.unpack(m) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We always make m the first argument (it's a useful convention IMHO).

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.

2 participants