Use 'xor r, r' to set registers to 0 instead of mov (#766)

This commit is contained in:
Andy Wortman
2019-09-16 14:35:55 +00:00
committed by Benjamin Bouvier
parent b95508c51a
commit 99380fad1a
9 changed files with 193 additions and 7 deletions

View File

@@ -614,6 +614,7 @@ pub(crate) fn define(
let rec_trapif = r.recipe("trapif");
let rec_trapff = r.recipe("trapff");
let rec_u_id = r.template("u_id");
let rec_u_id_z = r.template("u_id_z");
let rec_umr = r.template("umr");
let rec_umr_reg_to_ssa = r.template("umr_reg_to_ssa");
let rec_ur = r.template("ur");
@@ -750,6 +751,35 @@ pub(crate) fn define(
}
e.enc64(bconst.bind(B64), rec_pu_id_bool.opcodes(vec![0xb8]).rex());
let is_zero_int = InstructionPredicate::new_is_zero_int(f_unary_imm, "imm");
e.enc_both_instp(
iconst.bind(I8),
rec_u_id_z.opcodes(vec![0x30]),
is_zero_int.clone(),
);
// You may expect that i16 encodings would have an 0x66 prefix on the opcode to indicate that
// encodings should be on 16-bit operands (f.ex, "xor %ax, %ax"). Cranelift currently does not
// know that it can drop the 0x66 prefix and clear the upper half of a 32-bit register in these
// scenarios, so we explicitly select a wider but permissible opcode.
//
// This effectively formalizes the i16->i32 widening that Cranelift performs when there isn't
// an appropriate i16 encoding available.
e.enc_both_instp(
iconst.bind(I16),
rec_u_id_z.opcodes(vec![0x31]),
is_zero_int.clone(),
);
e.enc_both_instp(
iconst.bind(I32),
rec_u_id_z.opcodes(vec![0x31]),
is_zero_int.clone(),
);
e.enc_x86_64_instp(
iconst.bind(I64),
rec_u_id_z.opcodes(vec![0x31]),
is_zero_int,
);
// Shifts and rotates.
// Note that the dynamic shift amount is only masked by 5 or 6 bits; the 8-bit
// and 16-bit shifts would need explicit masking.