YJIT: Branch directly when truthyness is known

This commit is contained in:
John Hawthorn 2022-09-05 15:20:08 -07:00
parent 79f50b9d02
commit d319184390
Notes: git 2022-09-10 12:30:03 +09:00

View File

@ -3197,12 +3197,6 @@ fn gen_branchif(
gen_check_ints(asm, side_exit); gen_check_ints(asm, side_exit);
} }
// Test if any bit (outside of the Qnil bit) is on
// RUBY_Qfalse /* ...0000 0000 */
// RUBY_Qnil /* ...0000 1000 */
let val_opnd = ctx.stack_pop(1);
asm.test(val_opnd, Opnd::Imm(!Qnil.as_i64()));
// Get the branch target instruction offsets // Get the branch target instruction offsets
let next_idx = jit_next_insn_idx(jit); let next_idx = jit_next_insn_idx(jit);
let jump_idx = (next_idx as i32) + jump_offset; let jump_idx = (next_idx as i32) + jump_offset;
@ -3215,18 +3209,31 @@ fn gen_branchif(
idx: jump_idx as u32, idx: jump_idx as u32,
}; };
// Generate the branch instructions // Test if any bit (outside of the Qnil bit) is on
gen_branch( // RUBY_Qfalse /* ...0000 0000 */
jit, // RUBY_Qnil /* ...0000 1000 */
ctx, let val_type = ctx.get_opnd_type(StackOpnd(0));
asm, let val_opnd = ctx.stack_pop(1);
ocb,
jump_block, if let Some(result) = val_type.known_truthy() {
ctx, let target = if result { jump_block } else { next_block };
Some(next_block), gen_direct_jump(jit, ctx, target, asm);
Some(ctx), } else {
gen_branchif_branch, asm.test(val_opnd.into(), Opnd::Imm(!Qnil.as_i64()));
);
// Generate the branch instructions
gen_branch(
jit,
ctx,
asm,
ocb,
jump_block,
ctx,
Some(next_block),
Some(ctx),
gen_branchif_branch,
);
}
EndBlock EndBlock
} }
@ -3261,13 +3268,6 @@ fn gen_branchunless(
gen_check_ints(asm, side_exit); gen_check_ints(asm, side_exit);
} }
// Test if any bit (outside of the Qnil bit) is on
// RUBY_Qfalse /* ...0000 0000 */
// RUBY_Qnil /* ...0000 1000 */
let val_opnd = ctx.stack_pop(1);
let not_qnil = !Qnil.as_i64();
asm.test(val_opnd, not_qnil.into());
// Get the branch target instruction offsets // Get the branch target instruction offsets
let next_idx = jit_next_insn_idx(jit) as i32; let next_idx = jit_next_insn_idx(jit) as i32;
let jump_idx = next_idx + jump_offset; let jump_idx = next_idx + jump_offset;
@ -3280,18 +3280,32 @@ fn gen_branchunless(
idx: jump_idx.try_into().unwrap(), idx: jump_idx.try_into().unwrap(),
}; };
// Generate the branch instructions let val_type = ctx.get_opnd_type(StackOpnd(0));
gen_branch( let val_opnd = ctx.stack_pop(1);
jit,
ctx, if let Some(result) = val_type.known_truthy() {
asm, let target = if result { next_block } else { jump_block };
ocb, gen_direct_jump(jit, ctx, target, asm);
jump_block, } else {
ctx, // Test if any bit (outside of the Qnil bit) is on
Some(next_block), // RUBY_Qfalse /* ...0000 0000 */
Some(ctx), // RUBY_Qnil /* ...0000 1000 */
gen_branchunless_branch, let not_qnil = !Qnil.as_i64();
); asm.test(val_opnd.into(), not_qnil.into());
// Generate the branch instructions
gen_branch(
jit,
ctx,
asm,
ocb,
jump_block,
ctx,
Some(next_block),
Some(ctx),
gen_branchunless_branch,
);
}
EndBlock EndBlock
} }