summaryrefslogtreecommitdiff
path: root/yjit
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2022-09-05 15:20:08 -0700
committerJohn Hawthorn <john@hawthorn.email>2022-09-09 20:29:40 -0700
commitd3191843909208477ada3b82db00fb6204696479 (patch)
tree9e451a1d6d0f9cd82eb98adf93322f0bb6f95ce7 /yjit
parent79f50b9d02b228aba2d8887422f00767046051a6 (diff)
YJIT: Branch directly when truthyness is known
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/6350
Diffstat (limited to 'yjit')
-rw-r--r--yjit/src/codegen.rs88
1 files changed, 51 insertions, 37 deletions
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 58b30d5c85..0551491bbb 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -3197,12 +3197,6 @@ fn gen_branchif(
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
let next_idx = jit_next_insn_idx(jit);
let jump_idx = (next_idx as i32) + jump_offset;
@@ -3215,18 +3209,31 @@ fn gen_branchif(
idx: jump_idx as u32,
};
- // Generate the branch instructions
- gen_branch(
- jit,
- ctx,
- asm,
- ocb,
- jump_block,
- ctx,
- Some(next_block),
- Some(ctx),
- gen_branchif_branch,
- );
+ // Test if any bit (outside of the Qnil bit) is on
+ // RUBY_Qfalse /* ...0000 0000 */
+ // RUBY_Qnil /* ...0000 1000 */
+ let val_type = ctx.get_opnd_type(StackOpnd(0));
+ let val_opnd = ctx.stack_pop(1);
+
+ if let Some(result) = val_type.known_truthy() {
+ let target = if result { jump_block } else { next_block };
+ gen_direct_jump(jit, ctx, target, asm);
+ } else {
+ 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
}
@@ -3261,13 +3268,6 @@ fn gen_branchunless(
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
let next_idx = jit_next_insn_idx(jit) as i32;
let jump_idx = next_idx + jump_offset;
@@ -3280,18 +3280,32 @@ fn gen_branchunless(
idx: jump_idx.try_into().unwrap(),
};
- // Generate the branch instructions
- gen_branch(
- jit,
- ctx,
- asm,
- ocb,
- jump_block,
- ctx,
- Some(next_block),
- Some(ctx),
- gen_branchunless_branch,
- );
+ let val_type = ctx.get_opnd_type(StackOpnd(0));
+ let val_opnd = ctx.stack_pop(1);
+
+ if let Some(result) = val_type.known_truthy() {
+ let target = if result { next_block } else { jump_block };
+ gen_direct_jump(jit, ctx, target, asm);
+ } else {
+ // Test if any bit (outside of the Qnil bit) is on
+ // RUBY_Qfalse /* ...0000 0000 */
+ // RUBY_Qnil /* ...0000 1000 */
+ 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
}