Merge pull request #3056 from afonso360/aarch64-fix-overflow-imm

aarch64: Fix incorrect encoding of large const values in icmp.
This commit is contained in:
Chris Fallin
2021-07-03 16:05:49 -07:00
committed by GitHub
2 changed files with 35 additions and 1 deletions

View File

@@ -24,6 +24,7 @@ use crate::data_value::DataValue;
use log::{debug, trace};
use regalloc::{Reg, Writable};
use smallvec::SmallVec;
use std::cmp;
//============================================================================
// Result enum types.
@@ -156,6 +157,14 @@ impl NarrowValueMode {
NarrowValueMode::ZeroExtend64 | NarrowValueMode::SignExtend64 => false,
}
}
fn is_signed(&self) -> bool {
match self {
NarrowValueMode::SignExtend32 | NarrowValueMode::SignExtend64 => true,
NarrowValueMode::ZeroExtend32 | NarrowValueMode::ZeroExtend64 => false,
NarrowValueMode::None => false,
}
}
}
/// Emits instruction(s) to generate the given constant value into newly-allocated
@@ -438,7 +447,15 @@ pub(crate) fn put_input_in_rse_imm12<C: LowerCtx<I = Inst>>(
) -> ResultRSEImm12 {
if let Some(imm_value) = input_to_const(ctx, input) {
if let Some(i) = Imm12::maybe_from_u64(imm_value) {
return ResultRSEImm12::Imm12(i);
let out_ty_bits = ty_bits(ctx.input_ty(input.insn, input.input));
let is_negative = (i.bits as u64) & (1 << (cmp::max(out_ty_bits, 1) - 1)) != 0;
// This condition can happen if we matched a value that overflows the output type of
// its `iconst` when viewed as a signed value (i.e. iconst.i8 200).
// When that happens we need to lower as a negative value, which we cannot do here.
if !(narrow_mode.is_signed() && is_negative) {
return ResultRSEImm12::Imm12(i);
}
}
}