Skip to content

Commit

Permalink
YJIT: Avoid register allocation conflict with a higher stack_idx (#9143)
Browse files Browse the repository at this point in the history
YJIT: Avoid register allocation conflict

with a higher stack_idx
  • Loading branch information
k0kubun committed Dec 6, 2023
1 parent 9336bbb commit a439fc2
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
18 changes: 18 additions & 0 deletions bootstraptest/test_yjit.rb
Expand Up @@ -4273,3 +4273,21 @@ def entry = yield
Foo.class_eval "def initialize() #{ivars} end"
Foo.new
}

assert_equal '0', %q{
def spill
1.to_i # not inlined
end
def inline(_stack1, _stack2, _stack3, _stack4, _stack5)
0 # inlined
end
def entry
# RegTemps is 00111110 prior to the #inline call.
# Its return value goes to stack_idx=0, which conflicts with stack_idx=5.
inline(spill, 2, 3, 4, 5)
end
entry
}
21 changes: 16 additions & 5 deletions yjit/src/core.rs
Expand Up @@ -428,12 +428,12 @@ impl RegTemps {

/// Return true if there's a register that conflicts with a given stack_idx.
pub fn conflicts_with(&self, stack_idx: u8) -> bool {
let mut other_idx = stack_idx as isize - get_option!(num_temp_regs) as isize;
while other_idx >= 0 {
if self.get(other_idx as u8) {
let mut other_idx = stack_idx as usize % get_option!(num_temp_regs);
while other_idx < MAX_REG_TEMPS as usize {
if stack_idx as usize != other_idx && self.get(other_idx as u8) {
return true;
}
other_idx -= get_option!(num_temp_regs) as isize;
other_idx += get_option!(num_temp_regs);
}
false
}
Expand Down Expand Up @@ -3450,7 +3450,7 @@ mod tests {
assert_eq!(reg_temps.get(stack_idx), false);
}

// Set 0, 2, 7
// Set 0, 2, 7 (RegTemps: 10100001)
reg_temps.set(0, true);
reg_temps.set(2, true);
reg_temps.set(3, true);
Expand All @@ -3466,6 +3466,17 @@ mod tests {
assert_eq!(reg_temps.get(5), false);
assert_eq!(reg_temps.get(6), false);
assert_eq!(reg_temps.get(7), true);

// Test conflicts
assert_eq!(5, get_option!(num_temp_regs));
assert_eq!(reg_temps.conflicts_with(0), false); // already set, but no conflict
assert_eq!(reg_temps.conflicts_with(1), false);
assert_eq!(reg_temps.conflicts_with(2), true); // already set, and conflicts with 7
assert_eq!(reg_temps.conflicts_with(3), false);
assert_eq!(reg_temps.conflicts_with(4), false);
assert_eq!(reg_temps.conflicts_with(5), true); // not set, and will conflict with 0
assert_eq!(reg_temps.conflicts_with(6), false);
assert_eq!(reg_temps.conflicts_with(7), true); // already set, and conflicts with 2
}

#[test]
Expand Down

0 comments on commit a439fc2

Please sign in to comment.