Merge pull request #2395 from cfallin/lucet-x64-support

Add support for brff/brif and icmp_sp to new x64 backend to support Lucet.
This commit is contained in:
Chris Fallin
2020-11-12 12:10:52 -08:00
committed by GitHub
7 changed files with 167 additions and 33 deletions

View File

@@ -1185,9 +1185,8 @@ impl LowerBackend for AArch64Backend {
ctx: &mut C,
branches: &[IRInst],
targets: &[MachLabel],
fallthrough: Option<MachLabel>,
) -> CodegenResult<()> {
lower_inst::lower_branch(ctx, branches, targets, fallthrough)
lower_inst::lower_branch(ctx, branches, targets)
}
fn maybe_pinned_reg(&self) -> Option<Reg> {

View File

@@ -3115,7 +3115,6 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
ctx: &mut C,
branches: &[IRInst],
targets: &[MachLabel],
fallthrough: Option<MachLabel>,
) -> CodegenResult<()> {
// A block should end with at most two branches. The first may be a
// conditional branch; a conditional branch can be followed only by an
@@ -3132,11 +3131,11 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
assert!(op1 == Opcode::Jump || op1 == Opcode::Fallthrough);
let taken = BranchTarget::Label(targets[0]);
let not_taken = match op1 {
Opcode::Jump => BranchTarget::Label(targets[1]),
Opcode::Fallthrough => BranchTarget::Label(fallthrough.unwrap()),
_ => unreachable!(), // assert above.
};
// not_taken target is the target of the second branch, even if it is a Fallthrough
// instruction: because we reorder blocks while we lower, the fallthrough in the new
// order is not (necessarily) the same as the fallthrough in CLIF. So we use the
// explicitly-provided target.
let not_taken = BranchTarget::Label(targets[1]);
match op0 {
Opcode::Brz | Opcode::Brnz => {

View File

@@ -229,9 +229,8 @@ impl LowerBackend for Arm32Backend {
ctx: &mut C,
branches: &[IRInst],
targets: &[MachLabel],
fallthrough: Option<MachLabel>,
) -> CodegenResult<()> {
lower_inst::lower_branch(ctx, branches, targets, fallthrough)
lower_inst::lower_branch(ctx, branches, targets)
}
fn maybe_pinned_reg(&self) -> Option<Reg> {

View File

@@ -540,7 +540,6 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
ctx: &mut C,
branches: &[IRInst],
targets: &[MachLabel],
fallthrough: Option<MachLabel>,
) -> CodegenResult<()> {
// A block should end with at most two branches. The first may be a
// conditional branch; a conditional branch can be followed only by an
@@ -557,11 +556,8 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
assert!(op1 == Opcode::Jump || op1 == Opcode::Fallthrough);
let taken = BranchTarget::Label(targets[0]);
let not_taken = match op1 {
Opcode::Jump => BranchTarget::Label(targets[1]),
Opcode::Fallthrough => BranchTarget::Label(fallthrough.unwrap()),
_ => unreachable!(), // assert above.
};
let not_taken = BranchTarget::Label(targets[1]);
match op0 {
Opcode::Brz | Opcode::Brnz => {
let rn = input_to_reg(

View File

@@ -3566,7 +3566,6 @@ impl LowerBackend for X64Backend {
ctx: &mut C,
branches: &[IRInst],
targets: &[MachLabel],
fallthrough: Option<MachLabel>,
) -> CodegenResult<()> {
// A block should end with at most two branches. The first may be a
// conditional branch; a conditional branch can be followed only by an
@@ -3589,11 +3588,11 @@ impl LowerBackend for X64Backend {
assert!(op1 == Opcode::Jump || op1 == Opcode::Fallthrough);
let taken = targets[0];
let not_taken = match op1 {
Opcode::Jump => targets[1],
Opcode::Fallthrough => fallthrough.unwrap(),
_ => unreachable!(), // assert above.
};
// not_taken target is the target of the second branch, even if it is a Fallthrough
// instruction: because we reorder blocks while we lower, the fallthrough in the new
// order is not (necessarily) the same as the fallthrough in CLIF. So we use the
// explicitly-provided target.
let not_taken = targets[1];
match op0 {
Opcode::Brz | Opcode::Brnz => {
@@ -3686,6 +3685,67 @@ impl LowerBackend for X64Backend {
}
}
Opcode::Brif => {
let flag_input = InsnInput {
insn: branches[0],
input: 0,
};
if let Some(ifcmp) = matches_input(ctx, flag_input, Opcode::Ifcmp) {
emit_cmp(ctx, ifcmp);
let cond_code = ctx.data(branches[0]).cond_code().unwrap();
let cc = CC::from_intcc(cond_code);
ctx.emit(Inst::jmp_cond(cc, taken, not_taken));
} else if let Some(ifcmp_sp) = matches_input(ctx, flag_input, Opcode::IfcmpSp) {
let operand = put_input_in_reg(
ctx,
InsnInput {
insn: ifcmp_sp,
input: 0,
},
);
let ty = ctx.input_ty(ifcmp_sp, 0);
ctx.emit(Inst::cmp_rmi_r(
ty.bytes() as u8,
RegMemImm::reg(operand),
regs::rsp(),
));
let cond_code = ctx.data(branches[0]).cond_code().unwrap();
let cc = CC::from_intcc(cond_code);
ctx.emit(Inst::jmp_cond(cc, taken, not_taken));
} else {
// Should be disallowed by flags checks in verifier.
unimplemented!("Brif with non-ifcmp input");
}
}
Opcode::Brff => {
let flag_input = InsnInput {
insn: branches[0],
input: 0,
};
if let Some(ffcmp) = matches_input(ctx, flag_input, Opcode::Ffcmp) {
let cond_code = ctx.data(branches[0]).fp_cond_code().unwrap();
match emit_fcmp(ctx, ffcmp, cond_code, FcmpSpec::Normal) {
FcmpCondResult::Condition(cc) => {
ctx.emit(Inst::jmp_cond(cc, taken, not_taken));
}
FcmpCondResult::AndConditions(cc1, cc2) => {
ctx.emit(Inst::jmp_if(cc1.invert(), not_taken));
ctx.emit(Inst::jmp_cond(cc2.invert(), not_taken, taken));
}
FcmpCondResult::OrConditions(cc1, cc2) => {
ctx.emit(Inst::jmp_if(cc1, taken));
ctx.emit(Inst::jmp_cond(cc2, taken, not_taken));
}
FcmpCondResult::InvertedEqualOrConditions(_, _) => unreachable!(),
}
} else {
// Should be disallowed by flags checks in verifier.
unimplemented!("Brff with input not from ffcmp");
}
}
_ => panic!("unexpected branch opcode: {:?}", op0),
}
} else {