Skip to content

Commit dc8362c

Browse files
authored
x64: Finish migrating brz and brnz to ISLE (#4614)
#4614
1 parent ed8908e commit dc8362c

File tree

6 files changed

+39
-201
lines changed

6 files changed

+39
-201
lines changed

cranelift/codegen/src/isa/x64/inst.isle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3274,6 +3274,12 @@
32743274
;; Same flags as `UnorderedOrLessThanOrEqual`.
32753275
(FcmpCondResult.Condition (x64_ucomis a b) (CC.BE)))
32763276

3277+
;;;; Type Guards ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3278+
3279+
;; A type guard for matching ints and bools up to 64 bits, or 64 bit references.
3280+
(decl ty_int_bool_or_ref () Type)
3281+
(extern extractor ty_int_bool_or_ref ty_int_bool_or_ref)
3282+
32773283
;;;; Atomics ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32783284

32793285
(decl x64_mfence () SideEffectNoResult)

cranelift/codegen/src/isa/x64/inst/emit_tests.rs

Lines changed: 0 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -3261,109 +3261,6 @@ fn test_x64_emit() {
32613261
"cmpb %r13b, %r14b",
32623262
));
32633263

3264-
// ========================================================
3265-
// TestRmiR
3266-
insns.push((
3267-
Inst::test_rmi_r(OperandSize::Size64, RegMemImm::reg(r15), rdx),
3268-
"4C85FA",
3269-
"testq %r15, %rdx",
3270-
));
3271-
insns.push((
3272-
Inst::test_rmi_r(
3273-
OperandSize::Size64,
3274-
RegMemImm::mem(Amode::imm_reg(99, rdi)),
3275-
rdx,
3276-
),
3277-
"48855763",
3278-
"testq 99(%rdi), %rdx",
3279-
));
3280-
insns.push((
3281-
Inst::test_rmi_r(OperandSize::Size64, RegMemImm::imm(127), rdx),
3282-
"48F7C27F000000",
3283-
"testq $127, %rdx",
3284-
));
3285-
insns.push((
3286-
Inst::test_rmi_r(OperandSize::Size64, RegMemImm::imm(76543210), rdx),
3287-
"48F7C2EAF48F04",
3288-
"testq $76543210, %rdx",
3289-
));
3290-
//
3291-
insns.push((
3292-
Inst::test_rmi_r(OperandSize::Size32, RegMemImm::reg(r15), rdx),
3293-
"4485FA",
3294-
"testl %r15d, %edx",
3295-
));
3296-
insns.push((
3297-
Inst::test_rmi_r(
3298-
OperandSize::Size32,
3299-
RegMemImm::mem(Amode::imm_reg(99, rdi)),
3300-
rdx,
3301-
),
3302-
"855763",
3303-
"testl 99(%rdi), %edx",
3304-
));
3305-
insns.push((
3306-
Inst::test_rmi_r(OperandSize::Size32, RegMemImm::imm(76543210), rdx),
3307-
"F7C2EAF48F04",
3308-
"testl $76543210, %edx",
3309-
));
3310-
//
3311-
insns.push((
3312-
Inst::test_rmi_r(OperandSize::Size16, RegMemImm::reg(r15), rdx),
3313-
"664485FA",
3314-
"testw %r15w, %dx",
3315-
));
3316-
insns.push((
3317-
Inst::test_rmi_r(
3318-
OperandSize::Size16,
3319-
RegMemImm::mem(Amode::imm_reg(99, rdi)),
3320-
rdx,
3321-
),
3322-
"66855763",
3323-
"testw 99(%rdi), %dx",
3324-
));
3325-
insns.push((
3326-
Inst::test_rmi_r(OperandSize::Size16, RegMemImm::imm(23210), rdx),
3327-
"66F7C2AA5A",
3328-
"testw $23210, %dx",
3329-
));
3330-
//
3331-
insns.push((
3332-
Inst::test_rmi_r(OperandSize::Size8, RegMemImm::reg(r15), rdx),
3333-
"4484FA",
3334-
"testb %r15b, %dl",
3335-
));
3336-
insns.push((
3337-
Inst::test_rmi_r(
3338-
OperandSize::Size8,
3339-
RegMemImm::mem(Amode::imm_reg(99, rdi)),
3340-
rdx,
3341-
),
3342-
"845763",
3343-
"testb 99(%rdi), %dl",
3344-
));
3345-
insns.push((
3346-
Inst::test_rmi_r(OperandSize::Size8, RegMemImm::imm(70), rdx),
3347-
"F6C246",
3348-
"testb $70, %dl",
3349-
));
3350-
// Extra byte-cases (paranoia!) for test_rmi_r for first operand = R
3351-
insns.push((
3352-
Inst::test_rmi_r(OperandSize::Size8, RegMemImm::reg(rax), rbx),
3353-
"84C3",
3354-
"testb %al, %bl",
3355-
));
3356-
insns.push((
3357-
Inst::test_rmi_r(OperandSize::Size8, RegMemImm::reg(rcx), rsi),
3358-
"4084CE",
3359-
"testb %cl, %sil",
3360-
));
3361-
insns.push((
3362-
Inst::test_rmi_r(OperandSize::Size8, RegMemImm::reg(rcx), r10),
3363-
"4184CA",
3364-
"testb %cl, %r10b",
3365-
));
3366-
33673264
// ========================================================
33683265
// SetCC
33693266
insns.push((Inst::setcc(CC::O, w_rsi), "400F90C6", "seto %sil"));

cranelift/codegen/src/isa/x64/inst/mod.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -619,18 +619,6 @@ impl Inst {
619619
}
620620
}
621621

622-
/// Does a comparison of dst & src for operands of size `size`.
623-
pub(crate) fn test_rmi_r(size: OperandSize, src: RegMemImm, dst: Reg) -> Inst {
624-
src.assert_regclass_is(RegClass::Int);
625-
debug_assert_eq!(dst.class(), RegClass::Int);
626-
Inst::CmpRmiR {
627-
size,
628-
src: GprMemImm::new(src).unwrap(),
629-
dst: Gpr::new(dst).unwrap(),
630-
opcode: CmpOpcode::Test,
631-
}
632-
}
633-
634622
pub(crate) fn trap(trap_code: TrapCode) -> Inst {
635623
Inst::Ud2 { trap_code }
636624
}
@@ -729,14 +717,6 @@ impl Inst {
729717
Inst::JmpKnown { dst }
730718
}
731719

732-
pub(crate) fn jmp_cond(cc: CC, taken: MachLabel, not_taken: MachLabel) -> Inst {
733-
Inst::JmpCond {
734-
cc,
735-
taken,
736-
not_taken,
737-
}
738-
}
739-
740720
pub(crate) fn jmp_unknown(target: RegMem) -> Inst {
741721
target.assert_regclass_is(RegClass::Int);
742722
Inst::JmpUnknown { target }

cranelift/codegen/src/isa/x64/lower.isle

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2890,6 +2890,12 @@
28902890
(rule (lower_branch (brz val @ (value_type $I128) _ _) (two_targets taken not_taken))
28912891
(side_effect (jmp_cond_icmp (cmp_zero_i128 (CC.NZ) val) taken not_taken)))
28922892

2893+
(rule (lower_branch (brz val @ (value_type (ty_int_bool_or_ref)) _ _) (two_targets taken not_taken))
2894+
(side_effect
2895+
(with_flags_side_effect (cmp_zero_int_bool_ref val)
2896+
(jmp_cond (CC.Z) taken not_taken))))
2897+
2898+
28932899
(rule (lower_branch (brnz (icmp cc a b) _ _) (two_targets taken not_taken))
28942900
(side_effect (jmp_cond_icmp (emit_cmp cc a b) taken not_taken)))
28952901

@@ -2900,6 +2906,12 @@
29002906
(rule (lower_branch (brnz val @ (value_type $I128) _ _) (two_targets taken not_taken))
29012907
(side_effect (jmp_cond_icmp (cmp_zero_i128 (CC.Z) val) taken not_taken)))
29022908

2909+
(rule (lower_branch (brnz val @ (value_type (ty_int_bool_or_ref)) _ _) (two_targets taken not_taken))
2910+
(side_effect
2911+
(with_flags_side_effect (cmp_zero_int_bool_ref val)
2912+
(jmp_cond (CC.NZ) taken not_taken))))
2913+
2914+
29032915
;; Compare an I128 value to zero, returning a flags result suitable for making a
29042916
;; jump decision. The comparison is implemented as `(hi == 0) && (low == 0)`,
29052917
;; and the result can be interpreted as follows
@@ -2916,6 +2928,14 @@
29162928
(x64_setcc (CC.Z)))))
29172929
(icmp_cond_result (x64_test (OperandSize.Size8) lo_z hi_z) cc)))
29182930

2931+
2932+
(decl cmp_zero_int_bool_ref (Value) ProducesFlags)
2933+
(rule (cmp_zero_int_bool_ref val @ (value_type $B1))
2934+
(x64_test (OperandSize.Size8) (RegMemImm.Imm 1) val))
2935+
(rule (cmp_zero_int_bool_ref val @ (value_type ty))
2936+
(let ((size OperandSize (raw_operand_size_of_type ty)))
2937+
(x64_test size val val)))
2938+
29192939
;; Rules for `bricmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29202940

29212941
(rule (lower_branch (br_icmp cc a b _ _) (two_targets taken not_taken))

cranelift/codegen/src/isa/x64/lower.rs

Lines changed: 2 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ use crate::isa::x64::inst::args::*;
1313
use crate::isa::x64::inst::*;
1414
use crate::isa::{x64::settings as x64_settings, x64::X64Backend, CallConv};
1515
use crate::machinst::lower::*;
16+
use crate::machinst::*;
1617
use crate::result::CodegenResult;
1718
use crate::settings::{Flags, TlsModel};
18-
use crate::{machinst::*, trace};
1919
use alloc::boxed::Box;
2020
use smallvec::SmallVec;
2121
use std::convert::TryFrom;
@@ -33,14 +33,6 @@ fn is_int_or_ref_ty(ty: Type) -> bool {
3333
}
3434
}
3535

36-
fn is_bool_ty(ty: Type) -> bool {
37-
match ty {
38-
types::B1 | types::B8 | types::B16 | types::B32 | types::B64 => true,
39-
types::R32 => panic!("shouldn't have 32-bits refs on x64"),
40-
_ => false,
41-
}
42-
}
43-
4436
/// Returns whether the given specified `input` is a result produced by an instruction with Opcode
4537
/// `op`.
4638
// TODO investigate failures with checking against the result index.
@@ -2758,75 +2750,7 @@ impl LowerBackend for X64Backend {
27582750
};
27592751

27602752
if branches.len() == 2 {
2761-
// Must be a conditional branch followed by an unconditional branch.
2762-
let op0 = ctx.data(branches[0]).opcode();
2763-
let op1 = ctx.data(branches[1]).opcode();
2764-
2765-
trace!(
2766-
"lowering two-branch group: opcodes are {:?} and {:?}",
2767-
op0,
2768-
op1
2769-
);
2770-
assert!(op1 == Opcode::Jump);
2771-
2772-
let taken = targets[0];
2773-
// not_taken target is the target of the second branch.
2774-
let not_taken = targets[1];
2775-
2776-
match op0 {
2777-
Opcode::Brz | Opcode::Brnz => {
2778-
let flag_input = InsnInput {
2779-
insn: branches[0],
2780-
input: 0,
2781-
};
2782-
2783-
let src_ty = ctx.input_ty(branches[0], 0);
2784-
2785-
if let Some(_icmp) = matches_input(ctx, flag_input, Opcode::Icmp) {
2786-
implemented_in_isle(ctx)
2787-
} else if let Some(_fcmp) = matches_input(ctx, flag_input, Opcode::Fcmp) {
2788-
implemented_in_isle(ctx)
2789-
} else if src_ty == types::I128 {
2790-
implemented_in_isle(ctx);
2791-
} else if is_int_or_ref_ty(src_ty) || is_bool_ty(src_ty) {
2792-
let src = put_input_in_reg(
2793-
ctx,
2794-
InsnInput {
2795-
insn: branches[0],
2796-
input: 0,
2797-
},
2798-
);
2799-
let cc = match op0 {
2800-
Opcode::Brz => CC::Z,
2801-
Opcode::Brnz => CC::NZ,
2802-
_ => unreachable!(),
2803-
};
2804-
// See case for `Opcode::Select` above re: testing the
2805-
// boolean input.
2806-
let test_input = if src_ty == types::B1 {
2807-
// test src, 1
2808-
RegMemImm::imm(1)
2809-
} else {
2810-
assert!(!is_bool_ty(src_ty));
2811-
// test src, src
2812-
RegMemImm::reg(src)
2813-
};
2814-
2815-
ctx.emit(Inst::test_rmi_r(
2816-
OperandSize::from_ty(src_ty),
2817-
test_input,
2818-
src,
2819-
));
2820-
ctx.emit(Inst::jmp_cond(cc, taken, not_taken));
2821-
} else {
2822-
unimplemented!("brz/brnz with non-int type {:?}", src_ty);
2823-
}
2824-
}
2825-
2826-
Opcode::BrIcmp | Opcode::Brif | Opcode::Brff => implemented_in_isle(ctx),
2827-
2828-
_ => panic!("unexpected branch opcode: {:?}", op0),
2829-
}
2753+
implemented_in_isle(ctx)
28302754
} else {
28312755
assert_eq!(branches.len(), 1);
28322756

cranelift/codegen/src/isa/x64/lower/isle.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Pull in the ISLE generated code.
44
pub(crate) mod generated_code;
55
use crate::{
6+
ir::types,
67
ir::AtomicRmwOp,
78
machinst::{InputSourceInst, Reg, Writable},
89
};
@@ -561,6 +562,16 @@ where
561562
}
562563
}
563564

565+
#[inline]
566+
fn ty_int_bool_or_ref(&mut self, ty: Type) -> Option<()> {
567+
match ty {
568+
types::I8 | types::I16 | types::I32 | types::I64 | types::R64 => Some(()),
569+
types::B1 | types::B8 | types::B16 | types::B32 | types::B64 => Some(()),
570+
types::R32 => panic!("shouldn't have 32-bits refs on x64"),
571+
_ => None,
572+
}
573+
}
574+
564575
#[inline]
565576
fn intcc_neq(&mut self, x: &IntCC, y: &IntCC) -> Option<IntCC> {
566577
if x != y {

0 commit comments

Comments
 (0)