Skip to content

Commit 3aebaea

Browse files
committed
perf(jit): defer call-free fusion after confirmed search regressions
1 parent 087ac84 commit 3aebaea

2 files changed

Lines changed: 11 additions & 74 deletions

File tree

‎crates/neovm-core/src/emacs_core/runtime/jit/compile.rs‎

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3620,15 +3620,6 @@ fn build_leaf_fn<M: Module>(
36203620
// param instead of baking. 0 = plain function / AOT.
36213621
dynamic_prefix: usize,
36223622
) -> Result<cranelift_module::FuncId, CompileError> {
3623-
// Predicate fusion improves arithmetic loops, but measured call-containing
3624-
// bodies can regress under the altered branch form. Keep their established
3625-
// lowering until that tradeoff is resolved independently.
3626-
let fuse_integer_predicates = !ops.iter().any(|op| {
3627-
matches!(
3628-
op,
3629-
Op::Call(_) | Op::Apply(_) | Op::CallBuiltin(..) | Op::CallBuiltinSym(..)
3630-
)
3631-
});
36323623
lowering::imm_pool_reset();
36333624
LAST_IR_STATS.with(|c| c.set((0, 0, 0, 0)));
36343625
let frontend_config = module.target_config();
@@ -4067,29 +4058,21 @@ fn build_leaf_fn<M: Module>(
40674058
Op::GotoIfNil(t) | Op::GotoIfNotNil(t) => {
40684059
let cond = stack.pop().ok_or(CompileError::StackUnderflow)?;
40694060
write_stack_to_vars(&mut fb, &vars, &stack);
4061+
let is_nil =
4062+
fb.ins()
4063+
.icmp_imm_u(IntCC::Equal, cond, Value::NIL.bits() as i64);
40704064
let tu = *t as usize;
40714065
let mut target = block_for[&tu];
40724066
let fallthrough = block_for[&(i + 1)];
40734067
let backedge = (tu <= i).then(|| fb.create_block());
40744068
if let Some(tramp) = backedge {
40754069
target = tramp;
40764070
}
4071+
// brif takes the `then` block when the condition is true.
40774072
if matches!(op, Op::GotoIfNil(_)) {
4078-
emit_nil_branch(
4079-
&mut fb,
4080-
cond,
4081-
fuse_integer_predicates,
4082-
target,
4083-
fallthrough,
4084-
);
4073+
fb.ins().brif(is_nil, target, &[], fallthrough, &[]);
40854074
} else {
4086-
emit_nil_branch(
4087-
&mut fb,
4088-
cond,
4089-
fuse_integer_predicates,
4090-
fallthrough,
4091-
target,
4092-
);
4075+
fb.ins().brif(is_nil, fallthrough, &[], target, &[]);
40934076
}
40944077
if let Some(tramp) = backedge {
40954078
// Taken-edge trampoline carrying the back-edge poll.
@@ -4121,6 +4104,9 @@ fn build_leaf_fn<M: Module>(
41214104
// top slot — implementing the "ElsePop".
41224105
let cond = *stack.last().ok_or(CompileError::StackUnderflow)?;
41234106
write_stack_to_vars(&mut fb, &vars, &stack);
4107+
let is_nil =
4108+
fb.ins()
4109+
.icmp_imm_u(IntCC::Equal, cond, Value::NIL.bits() as i64);
41244110
let tu = *t as usize;
41254111
let mut target = block_for[&tu];
41264112
let fallthrough = block_for[&(i + 1)];
@@ -4129,21 +4115,9 @@ fn build_leaf_fn<M: Module>(
41294115
target = tramp;
41304116
}
41314117
if matches!(op, Op::GotoIfNilElsePop(_)) {
4132-
emit_nil_branch(
4133-
&mut fb,
4134-
cond,
4135-
fuse_integer_predicates,
4136-
target,
4137-
fallthrough,
4138-
);
4118+
fb.ins().brif(is_nil, target, &[], fallthrough, &[]);
41394119
} else {
4140-
emit_nil_branch(
4141-
&mut fb,
4142-
cond,
4143-
fuse_integer_predicates,
4144-
fallthrough,
4145-
target,
4146-
);
4120+
fb.ins().brif(is_nil, fallthrough, &[], target, &[]);
41474121
}
41484122
if let Some(tramp) = backedge {
41494123
fb.switch_to_block(tramp);

‎crates/neovm-core/src/emacs_core/runtime/jit/compile/lowering.rs‎

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -82,43 +82,6 @@ pub(crate) fn iconst_bits(fb: &FunctionBuilder, v: ClifValue) -> Option<i64> {
8282
}
8383
}
8484

85-
/// Branch on a tagged Lisp value, reusing an integer predicate with T/NIL arms.
86-
/// Complement the comparison to preserve nil/non-nil successor ordering without
87-
/// materializing the Lisp boolean. Other consumers retain the tagged value.
88-
/// The caller opts in only for bodies without explicit Lisp-call bytecodes.
89-
pub(crate) fn emit_nil_branch(
90-
fb: &mut FunctionBuilder,
91-
value: ClifValue,
92-
fuse_predicate: bool,
93-
if_nil: Block,
94-
if_non_nil: Block,
95-
) {
96-
use cranelift_codegen::ir::{InstructionData, Opcode, ValueDef, condcodes::CondCode};
97-
if fuse_predicate
98-
&& let ValueDef::Result(inst, _) = fb.func.dfg.value_def(value)
99-
&& let InstructionData::Ternary {
100-
opcode: Opcode::Select,
101-
args,
102-
} = fb.func.dfg.insts[inst]
103-
&& iconst_bits(fb, args[1]) == Some(Value::T.bits() as i64)
104-
&& iconst_bits(fb, args[2]) == Some(Value::NIL.bits() as i64)
105-
&& let ValueDef::Result(predicate, _) = fb.func.dfg.value_def(args[0])
106-
&& let InstructionData::IntCompare {
107-
opcode: Opcode::Icmp,
108-
args,
109-
cond,
110-
} = fb.func.dfg.insts[predicate]
111-
{
112-
let is_nil = fb.ins().icmp(cond.complement(), args[0], args[1]);
113-
fb.ins().brif(is_nil, if_nil, &[], if_non_nil, &[]);
114-
} else {
115-
let is_nil = fb
116-
.ins()
117-
.icmp_imm_u(IntCC::Equal, value, Value::NIL.bits() as i64);
118-
fb.ins().brif(is_nil, if_nil, &[], if_non_nil, &[]);
119-
}
120-
}
121-
12285
/// Return `(value, immediate)` for a binary instruction whose right operand is
12386
/// an `iconst`. This is the 0.134 IR shape produced by helpers such as
12487
/// `bor_imm_u` and `ishl_imm_u`.

0 commit comments

Comments
 (0)