; Pin: SIGN_EXTEND_INREG with i32 result and inner type i1 / i8 / i16
; must Custom-lower to per-half ops.  Without the Custom hook, the
; combiner emits `sext_inreg(REG_SEQUENCE(...), i1)` which has no
; tablegen pattern and isel aborts with "Cannot select".
;
; The i1 case shows up in CRC32 loops (`-(crc & 1ul)` reduces to
; sign_extend_inreg with i1).  See feedback_sext_inreg_i32_isel_gap.md.
;
; Note: -verify-machineinstrs intentionally omitted because i32 store
; lowering still trips the i32-store-pair `implicit killed $y`
; concern in some chains; orthogonal to this fix.
;
; RUN: llc -mtriple=w65816 -O2 < %s | FileCheck %s

; The CRC32 idiom: -(x & 1) = sign_extend_inreg x, i1 (after combiner).
define i32 @neg_lowbit(i32 %x) {
; CHECK-LABEL: neg_lowbit:
; CHECK:       and #0x1
; CHECK:       rtl
  %a = and i32 %x, 1
  %b = sub i32 0, %a
  ret i32 %b
}

; (int32_t)(int8_t)x — sign-extend low byte to i32.
define i32 @sext_i8_to_i32(i32 %x) {
; CHECK-LABEL: sext_i8_to_i32:
; CHECK:       rtl
  %t = trunc i32 %x to i8
  %r = sext i8 %t to i32
  ret i32 %r
}

; (int32_t)(int16_t)x — sign-extend low halfword to i32.
define i32 @sext_i16_to_i32(i32 %x) {
; CHECK-LABEL: sext_i16_to_i32:
; CHECK:       rtl
  %t = trunc i32 %x to i16
  %r = sext i16 %t to i32
  ret i32 %r
}
