Skip to content

Commit

Permalink
Merge pull request #1510 from ptersilie/loop_peeling
Browse files Browse the repository at this point in the history
Implement loop peeling.
  • Loading branch information
ltratt authored Dec 19, 2024
2 parents 23505ef + 3dfe285 commit 889dbdc
Show file tree
Hide file tree
Showing 14 changed files with 1,049 additions and 469 deletions.
9 changes: 5 additions & 4 deletions tests/c/nested_sidetrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,17 @@
// 18
// yk-jit-event: enter-jit-code
// yk-jit-event: deoptimise
// yk-jit-event: start-side-tracing
// 20
// yk-jit-event: enter-jit-code
// yk-jit-event: deoptimise
// yk-jit-event: start-side-tracing
// 22
// yk-jit-event: stop-tracing
// --- Begin jit-pre-opt ---
// ...
// --- End jit-pre-opt ---
// 22
// yk-jit-event: enter-jit-code
// yk-jit-event: execute-side-trace
// 24
// yk-jit-event: enter-jit-code
// yk-jit-event: execute-side-trace
// 26
// yk-jit-event: execute-side-trace
Expand Down
2 changes: 1 addition & 1 deletion tests/c/side-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ int foo(int i) {
int main(int argc, char **argv) {
YkMT *mt = yk_mt_new(NULL);
yk_mt_hot_threshold_set(mt, 0);
yk_mt_sidetrace_threshold_set(mt, 5);
yk_mt_sidetrace_threshold_set(mt, 4);
YkLocation loc = yk_location_new();

int res = 0;
Expand Down
49 changes: 49 additions & 0 deletions tests/c/simple_peeling.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Run-time:
// env-var: YKD_LOG_IR=jit-post-opt
// env-var: YKD_SERIALISE_COMPILATION=1
// env-var: YK_LOG=4
// stderr:
// ...
// --- Begin jit-post-opt ---
// ...
// header_start ...
// ...
// header_end [%{{0}}, %{{1}}, %{{2}}, %{{3}}, %{{4}}, %{{25}}]
// ...
// body_start [%{{30}}, %{{31}}, %{{32}}, %{{33}}, %{{34}}, %{{35}}]
// ...
// body_end ...
// ...
// --- End jit-post-opt ---
// ...

// Check that basic trace compilation works.

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <yk.h>
#include <yk_testing.h>

int main(int argc, char **argv) {
YkMT *mt = yk_mt_new(NULL);
yk_mt_hot_threshold_set(mt, 0);
YkLocation loc = yk_location_new();

int res = 9998;
int i = 4;
NOOPT_VAL(loc);
NOOPT_VAL(res);
NOOPT_VAL(i);
while (i > 0) {
yk_mt_control_point(mt, &loc);
fprintf(stderr, "%d\n", i);
i--;
}
fprintf(stderr, "exit\n");
NOOPT_VAL(res);
yk_location_drop(loc);
yk_mt_shutdown(mt);
return (EXIT_SUCCESS);
}
55 changes: 48 additions & 7 deletions ykrt/src/compile/jitc_yk/codegen/x64/lsregalloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,26 @@ impl<'a> LSRegAlloc<'a> {
}
}

/// Reset the register allocator. We use this when moving from the trace header into the trace
/// body.
pub(crate) fn reset(&mut self) {
for rs in self.gp_reg_states.iter_mut() {
*rs = RegState::Empty;
}
for reg in RESERVED_GP_REGS {
self.gp_reg_states[usize::from(reg.code())] = RegState::Reserved;
}
self.gp_regset = RegSet::with_gp_reserved();

for rs in self.fp_reg_states.iter_mut() {
*rs = RegState::Empty;
}
for reg in RESERVED_FP_REGS {
self.fp_reg_states[usize::from(reg.code())] = RegState::Reserved;
}
self.fp_regset = RegSet::with_fp_reserved();
}

/// Before generating code for the instruction at `iidx`, see which registers are no longer
/// needed and mark them as [RegState::Empty]. Calling this allows the register allocator to
/// use the set of available registers more efficiently.
Expand Down Expand Up @@ -379,7 +399,8 @@ impl LSRegAlloc<'_> {
| RegConstraint::OutputCanBeSameAsInput(_)
| RegConstraint::OutputFromReg(_)
| RegConstraint::InputOutput(_) => true,
RegConstraint::Clobber(_) | RegConstraint::Temporary => false,
RegConstraint::Clobber(_) | RegConstraint::Temporary | RegConstraint::None =>
false,
})
.count()
<= 1
Expand Down Expand Up @@ -409,7 +430,8 @@ impl LSRegAlloc<'_> {
| RegConstraint::Output
| RegConstraint::OutputCanBeSameAsInput(_)
| RegConstraint::Input(_)
| RegConstraint::Temporary => {}
| RegConstraint::Temporary
| RegConstraint::None => {}
}
}

Expand Down Expand Up @@ -506,6 +528,9 @@ impl LSRegAlloc<'_> {
| RegConstraint::OutputCanBeSameAsInput(_)
| RegConstraint::OutputFromReg(_)
| RegConstraint::Temporary => (),
RegConstraint::None => {
asgn[i] = Some(GP_REGS[0]);
}
}
}

Expand Down Expand Up @@ -595,7 +620,8 @@ impl LSRegAlloc<'_> {
| RegConstraint::OutputCanBeSameAsInput(_)
| RegConstraint::OutputFromReg(_)
| RegConstraint::Clobber(_)
| RegConstraint::Temporary => (),
| RegConstraint::Temporary
| RegConstraint::None => (),
}
}

Expand Down Expand Up @@ -641,6 +667,7 @@ impl LSRegAlloc<'_> {
self.gp_regset.unset(reg);
self.gp_reg_states[usize::from(reg.code())] = RegState::Empty;
}
RegConstraint::None => (),
}
}
asgn.map(|x| x.unwrap())
Expand Down Expand Up @@ -891,14 +918,17 @@ impl LSRegAlloc<'_> {
match inst {
Inst::Copy(_) => panic!(),
Inst::Const(cidx) => match self.m.const_(cidx) {
Const::Float(_, _) => todo!(),
Const::Float(_, v) => VarLocation::ConstFloat(*v),
Const::Int(tyidx, v) => {
let Ty::Integer(bits) = self.m.type_(*tyidx) else {
panic!()
};
VarLocation::ConstInt { bits: *bits, v: *v }
}
Const::Ptr(_) => todo!(),
Const::Ptr(p) => VarLocation::ConstInt {
bits: 64,
v: u64::try_from(*p).unwrap(),
},
},
_ => match self.spills[usize::from(iidx)] {
SpillState::Empty => panic!(),
Expand Down Expand Up @@ -946,7 +976,8 @@ impl LSRegAlloc<'_> {
| RegConstraint::OutputCanBeSameAsInput(_)
| RegConstraint::OutputFromReg(_)
| RegConstraint::InputOutput(_) => true,
RegConstraint::Clobber(_) | RegConstraint::Temporary => false,
RegConstraint::Clobber(_) | RegConstraint::Temporary | RegConstraint::None =>
false,
})
.count()
<= 1
Expand Down Expand Up @@ -977,6 +1008,9 @@ impl LSRegAlloc<'_> {
| RegConstraint::OutputCanBeSameAsInput(_)
| RegConstraint::Output
| RegConstraint::Temporary => {}
RegConstraint::None => {
asgn[i] = Some(FP_REGS[0]);
}
}
}

Expand Down Expand Up @@ -1023,6 +1057,7 @@ impl LSRegAlloc<'_> {
| RegConstraint::OutputFromReg(_)
| RegConstraint::Temporary => (),
RegConstraint::OutputCanBeSameAsInput(_) => todo!(),
RegConstraint::None => (),
}
}

Expand Down Expand Up @@ -1113,6 +1148,7 @@ impl LSRegAlloc<'_> {
| RegConstraint::Clobber(_)
| RegConstraint::Temporary => (),
RegConstraint::OutputCanBeSameAsInput(_) => todo!(),
RegConstraint::None => (),
}
}

Expand Down Expand Up @@ -1157,6 +1193,7 @@ impl LSRegAlloc<'_> {
self.fp_reg_states[usize::from(reg.code())] = RegState::Empty;
}
RegConstraint::OutputCanBeSameAsInput(_) => todo!(),
RegConstraint::None => (),
}
}
asgn.map(|x| x.unwrap())
Expand Down Expand Up @@ -1400,6 +1437,9 @@ pub(crate) enum RegConstraint<R: Register> {
Clobber(R),
/// A temporary register *x* that the instruction will clobber.
Temporary,
/// A no-op register constraint. A random register will be assigned to this: using this
/// register for any purposes leads to undefined behaviour.
None,
}

#[cfg(debug_assertions)]
Expand All @@ -1416,7 +1456,8 @@ impl<R: dynasmrt::Register> RegConstraint<R> {
| Self::OutputCanBeSameAsInput(_)
| Self::OutputFromReg(_)
| Self::Clobber(_)
| Self::Temporary => None,
| Self::Temporary
| Self::None => None,
}
}
}
Expand Down
Loading

0 comments on commit 889dbdc

Please sign in to comment.