Skip extra work when inferring REX prefixes
As explained in the added documentation and #1342, if we prevent `infer_rex()` and `w()` from being used together then we don't need to check whether the W bit is set when figuring out if a REX prefix is needed in `needs_rex()`. This should improve compile time for x86 very slightly since all `infer_rex()` instructions will no longer need this check.
This commit is contained in:
@@ -74,10 +74,15 @@ fn evex2(rm: RegUnit, reg: RegUnit) -> u8 {
|
||||
0x00 | r_ | (b << 1) | (x << 2) | (r << 3)
|
||||
}
|
||||
|
||||
/// Determines whether a REX prefix should be emitted.
|
||||
/// Determines whether a REX prefix should be emitted. A REX byte always has 0100 in bits 7:4; bits
|
||||
/// 3:0 correspond to WRXB. W allows certain instructions to declare a 64-bit operand size; because
|
||||
/// [needs_rex] is only used by [infer_rex] and we prevent [infer_rex] from using [w] in
|
||||
/// [Template::build], we do not need to check again whether [w] forces an inferred REX prefix--it
|
||||
/// always does and should be encoded like `.rex().w()`. The RXB are extension of ModR/M or SIB
|
||||
/// fields; see section 2.2.1.2 in the Intel Software Development Manual.
|
||||
#[inline]
|
||||
fn needs_rex(bits: u16, rex: u8) -> bool {
|
||||
rex != BASE_REX || EncodingBits::from(bits).rex_w() == 1
|
||||
fn needs_rex(rex: u8) -> bool {
|
||||
rex != BASE_REX
|
||||
}
|
||||
|
||||
// Emit a REX prefix.
|
||||
@@ -107,7 +112,7 @@ fn put_rexop1<CS: CodeSink + ?Sized>(bits: u16, rex: u8, sink: &mut CS) {
|
||||
/// Emit a single-byte opcode with inferred REX prefix.
|
||||
fn put_dynrexop1<CS: CodeSink + ?Sized>(bits: u16, rex: u8, sink: &mut CS) {
|
||||
debug_assert_eq!(bits & 0x0f00, 0, "Invalid encoding bits for DynRexOp1*");
|
||||
if needs_rex(bits, rex) {
|
||||
if needs_rex(rex) {
|
||||
rex_prefix(bits, rex, sink);
|
||||
}
|
||||
sink.put1(bits as u8);
|
||||
@@ -136,7 +141,7 @@ fn put_dynrexop2<CS: CodeSink + ?Sized>(bits: u16, rex: u8, sink: &mut CS) {
|
||||
0x0400,
|
||||
"Invalid encoding bits for DynRexOp2*"
|
||||
);
|
||||
if needs_rex(bits, rex) {
|
||||
if needs_rex(rex) {
|
||||
rex_prefix(bits, rex, sink);
|
||||
}
|
||||
sink.put1(0x0f);
|
||||
@@ -190,7 +195,7 @@ fn put_dynrexmp2<CS: CodeSink + ?Sized>(bits: u16, rex: u8, sink: &mut CS) {
|
||||
);
|
||||
let enc = EncodingBits::from(bits);
|
||||
sink.put1(PREFIX[(enc.pp() - 1) as usize]);
|
||||
if needs_rex(bits, rex) {
|
||||
if needs_rex(rex) {
|
||||
rex_prefix(bits, rex, sink);
|
||||
}
|
||||
sink.put1(0x0f);
|
||||
@@ -228,7 +233,7 @@ fn put_dynrexmp3<CS: CodeSink + ?Sized>(bits: u16, rex: u8, sink: &mut CS) {
|
||||
);
|
||||
let enc = EncodingBits::from(bits);
|
||||
sink.put1(PREFIX[(enc.pp() - 1) as usize]);
|
||||
if needs_rex(bits, rex) {
|
||||
if needs_rex(rex) {
|
||||
rex_prefix(bits, rex, sink);
|
||||
}
|
||||
sink.put1(0x0f);
|
||||
|
||||
Reference in New Issue
Block a user