Skip to content

Commit 070b7d4

Browse files
authored
ZJIT: constant fold bitwise AND (&) operations (ruby#16226)
Following up ruby#16225, I'm implementing fold on AND (&) operations. - Ruby turns this operation into a C `&` in https://github.com/tomascco/ruby/blob/880eb3c76f09c44c85389ac5efbc555afafa3e6f/numeric.c#L5197-L5210 - Rustc compiler emits an `and` assembly instruction on x86: https://godbolt.org/z/Ee74vKTfb So the operations are equivalent. I tested manually some cases and the results match.
1 parent 2d8e24c commit 070b7d4

2 files changed

Lines changed: 66 additions & 0 deletions

File tree

zjit/src/hir.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4584,6 +4584,12 @@ impl Function {
45844584
_ => None,
45854585
})
45864586
}
4587+
Insn::FixnumAnd { left, right, .. } => {
4588+
self.fold_fixnum_bop(insn_id, left, right, |l, r| match (l, r) {
4589+
(Some(l), Some(r)) => Some(l & r),
4590+
_ => None,
4591+
})
4592+
}
45874593
Insn::FixnumEq { left, right, .. } => {
45884594
self.fold_fixnum_pred(insn_id, left, right, |l, r| match (l, r) {
45894595
(Some(l), Some(r)) => Some(l == r),

zjit/src/hir/opt_tests.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,66 @@ mod hir_opt_tests {
508508
");
509509
}
510510

511+
#[test]
512+
fn test_fold_fixnum_and() {
513+
eval("
514+
def test
515+
4 & -7
516+
end
517+
");
518+
519+
assert_snapshot!(inspect("test"), @"0");
520+
assert_snapshot!(hir_string("test"), @"
521+
fn test@<compiled>:3:
522+
bb1():
523+
EntryPoint interpreter
524+
v1:BasicObject = LoadSelf
525+
Jump bb3(v1)
526+
bb2():
527+
EntryPoint JIT(0)
528+
v4:BasicObject = LoadArg :self@0
529+
Jump bb3(v4)
530+
bb3(v6:BasicObject):
531+
v10:Fixnum[4] = Const Value(4)
532+
v12:Fixnum[-7] = Const Value(-7)
533+
PatchPoint MethodRedefined(Integer@0x1000, &@0x1008, cme:0x1010)
534+
v25:Fixnum[0] = Const Value(0)
535+
IncrCounter inline_cfunc_optimized_send_count
536+
CheckInterrupts
537+
Return v25
538+
");
539+
}
540+
541+
#[test]
542+
fn test_fold_fixnum_and_with_negative_self() {
543+
eval("
544+
def test
545+
-4 & 7
546+
end
547+
");
548+
549+
assert_snapshot!(inspect("test"), @"4");
550+
assert_snapshot!(hir_string("test"), @"
551+
fn test@<compiled>:3:
552+
bb1():
553+
EntryPoint interpreter
554+
v1:BasicObject = LoadSelf
555+
Jump bb3(v1)
556+
bb2():
557+
EntryPoint JIT(0)
558+
v4:BasicObject = LoadArg :self@0
559+
Jump bb3(v4)
560+
bb3(v6:BasicObject):
561+
v10:Fixnum[-4] = Const Value(-4)
562+
v12:Fixnum[7] = Const Value(7)
563+
PatchPoint MethodRedefined(Integer@0x1000, &@0x1008, cme:0x1010)
564+
v25:Fixnum[4] = Const Value(4)
565+
IncrCounter inline_cfunc_optimized_send_count
566+
CheckInterrupts
567+
Return v25
568+
");
569+
}
570+
511571
#[test]
512572
fn test_fold_fixnum_less() {
513573
eval("

0 commit comments

Comments
 (0)