@@ -24,6 +24,7 @@ use crate::data_value::DataValue;
2424use log:: { debug, trace} ;
2525use regalloc:: { Reg , Writable } ;
2626use smallvec:: SmallVec ;
27+ use std:: cmp;
2728
2829//============================================================================
2930// Result enum types.
@@ -156,6 +157,14 @@ impl NarrowValueMode {
156157 NarrowValueMode :: ZeroExtend64 | NarrowValueMode :: SignExtend64 => false ,
157158 }
158159 }
160+
161+ fn is_signed ( & self ) -> bool {
162+ match self {
163+ NarrowValueMode :: SignExtend32 | NarrowValueMode :: SignExtend64 => true ,
164+ NarrowValueMode :: ZeroExtend32 | NarrowValueMode :: ZeroExtend64 => false ,
165+ NarrowValueMode :: None => false ,
166+ }
167+ }
159168}
160169
161170/// 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>>(
438447) -> ResultRSEImm12 {
439448 if let Some ( imm_value) = input_to_const ( ctx, input) {
440449 if let Some ( i) = Imm12 :: maybe_from_u64 ( imm_value) {
441- return ResultRSEImm12 :: Imm12 ( i) ;
450+ let out_ty_bits = ty_bits ( ctx. input_ty ( input. insn , input. input ) ) ;
451+ let is_negative = ( i. bits as u64 ) & ( 1 << ( cmp:: max ( out_ty_bits, 1 ) - 1 ) ) != 0 ;
452+
453+ // This condition can happen if we matched a value that overflows the output type of
454+ // its `iconst` when viewed as a signed value (i.e. iconst.i8 200).
455+ // When that happens we need to lower as a negative value, which we cannot do here.
456+ if !( narrow_mode. is_signed ( ) && is_negative) {
457+ return ResultRSEImm12 :: Imm12 ( i) ;
458+ }
442459 }
443460 }
444461
0 commit comments