Don't relax a branch to have different input constraints.

When relaxing a branch, restrict the set of candidate encodings to those which
have the same input constraints as the original encoding choice. This prevents
situations where relaxation prefers a non-REX-prefixed encoding over a REX
prefixed one because the end of the instruction can be one byte closer to the
destination, in a situation where the encoding needs to be REX-prefixed
because of one of the operand registers.

This also makes the Context class perform encoding verification after
relaxation, to catch similar problems in the future.

Fixes #256.
This commit is contained in:
Dan Gohman
2018-03-08 02:26:26 -08:00
parent 6cf9bf36b8
commit 40ec50d0b6
3 changed files with 39 additions and 11 deletions

View File

@@ -152,13 +152,23 @@ fn relax_branch(
if let Some(enc) = isa.legal_encodings(dfg, &dfg[inst], ctrl_type).find(
|&enc| {
let range = encinfo.branch_range(enc).expect("Branch with no range");
let in_range = range.contains(offset, dest_offset);
dbg!(
" trying [{}]: {}",
encinfo.display(enc),
if in_range { "OK" } else { "out of range" }
);
in_range
if !range.contains(offset, dest_offset) {
dbg!(" trying [{}]: out of range", encinfo.display(enc));
false
} else if encinfo.operand_constraints(enc) !=
encinfo.operand_constraints(cur.func.encodings[inst])
{
// Conservatively give up if the encoding has different constraints
// than the original, so that we don't risk picking a new encoding
// which the existing operands don't satisfy. We can't check for
// validity directly because we don't have a RegDiversions active so
// we don't know which registers are actually in use.
dbg!(" trying [{}]: constraints differ", encinfo.display(enc));
false
} else {
dbg!(" trying [{}]: OK", encinfo.display(enc));
true
}
},
)
{