; Pin: multi-cgoto threaded-interpreter pattern.  Several BRINDs in
; one function dispatching from a single `labels` array.  Pre-fix,
; LowerBRIND constructed the $00B8 store address as a plain i32
; ConstantSDNode — which then ran through Custom-lower-i32-Constant
; and became a REG_SEQUENCE(0xB8, 0).  LowerStore couldn't see a
; clean ConstantSDNode at Ptr, mis-routed the i16 store to the
; generic ST_PTR slow path ([E0],Y indirect-long with full Wide32
; address staging — ~10 instructions per dispatch), and the resulting
; Wide32 / IMG pressure across multiple BRINDs in one function
; over-pressured the register allocator at -O2.
;
; The fix is in LowerBRIND: use DAG.getTargetConstant(0x00B8, ...)
; instead of DAG.getConstant(...) so the i32 Constant skips the
; LowerI32Constant Custom lowering.  The (store Acc16, (iPTR timm))
; tablegen pattern at W65816InstrInfo.td then matches directly,
; emitting STAabs which AsmPrinter folds to the DP form `sta $b8`
; (1 instruction, no Wide32 vreg, no DPF0/DPF1 staging).
;
; CHECK that:
;   - Compilation succeeds at -O2 (no "ran out of registers"),
;   - The dispatch site is the clean one-byte form (sta $b8, jmp ($b8)),
;   - Exactly six BRINDpseudo dispatches are emitted (one per opcode +
;     the entry dispatch).

; RUN: llc -mtriple=w65816 -O2 < %s | FileCheck %s

target datalayout = "e-m:e-p:32:16-i16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S8"

@labels = internal constant [6 x ptr] [
  ptr blockaddress(@vmRun, %op_add),
  ptr blockaddress(@vmRun, %op_sub),
  ptr blockaddress(@vmRun, %op_mul),
  ptr blockaddress(@vmRun, %op_xor),
  ptr blockaddress(@vmRun, %op_dup),
  ptr blockaddress(@vmRun, %op_done)
]

; CHECK-LABEL: vmRun:
; Each BRIND dispatches via the clean `sta $b8 ; jmp ($b8)` pair (1 byte
; STA, no Wide32 / DPF0/DPF1 staging).  Six dispatches total (one per
; opcode handler + the entry-block dispatch).  Pre-fix the constant
; address 0x00B8 was Custom-lowered into a Wide32 REG_SEQUENCE, the
; store mis-routed through [E0],Y indirect-long (10 instructions per
; dispatch), and the resulting Wide32 pressure across 6 BRINDs in one
; function over-pressured the regalloc at -O2.
;
; CHECK:       sta	0xb8
; CHECK-NEXT:  jmp	(0xb8)
; CHECK:       sta	0xb8
; CHECK-NEXT:  jmp	(0xb8)
; CHECK:       sta	0xb8
; CHECK-NEXT:  jmp	(0xb8)
; CHECK:       sta	0xb8
; CHECK-NEXT:  jmp	(0xb8)
; CHECK:       sta	0xb8
; CHECK-NEXT:  jmp	(0xb8)
; CHECK:       sta	0xb8
; CHECK-NEXT:  jmp	(0xb8)
;
; And the slow path is gone: no [dp],Y STORES anywhere (loads of `labels[i]`
; still go via [E0],Y indirect-long for ptr-deref, but BRIND's i16 store
; should not).
; CHECK-NOT: sta	[0xe0], y
define i16 @vmRun(ptr %code, i16 %inA, i16 %inB) {
entry:
  %op0  = load i8, ptr %code
  %ix0  = zext i8 %op0 to i32
  %p0   = getelementptr inbounds [6 x ptr], ptr @labels, i32 0, i32 %ix0
  %t0   = load ptr, ptr %p0
  indirectbr ptr %t0, [label %op_add, label %op_sub, label %op_mul, label %op_xor, label %op_dup, label %op_done]

op_add:
  %a1  = add i16 %inA, %inB
  %g1p = getelementptr inbounds i8, ptr %code, i16 1
  %g1  = load i8, ptr %g1p
  %ix1 = zext i8 %g1 to i32
  %p1  = getelementptr inbounds [6 x ptr], ptr @labels, i32 0, i32 %ix1
  %t1  = load ptr, ptr %p1
  indirectbr ptr %t1, [label %op_add, label %op_sub, label %op_mul, label %op_xor, label %op_dup, label %op_done]

op_sub:
  %a2  = sub i16 %inA, %inB
  %g2p = getelementptr inbounds i8, ptr %code, i16 2
  %g2  = load i8, ptr %g2p
  %ix2 = zext i8 %g2 to i32
  %p2  = getelementptr inbounds [6 x ptr], ptr @labels, i32 0, i32 %ix2
  %t2  = load ptr, ptr %p2
  indirectbr ptr %t2, [label %op_add, label %op_sub, label %op_mul, label %op_xor, label %op_dup, label %op_done]

op_mul:
  %a3  = mul i16 %inA, %inB
  %g3p = getelementptr inbounds i8, ptr %code, i16 3
  %g3  = load i8, ptr %g3p
  %ix3 = zext i8 %g3 to i32
  %p3  = getelementptr inbounds [6 x ptr], ptr @labels, i32 0, i32 %ix3
  %t3  = load ptr, ptr %p3
  indirectbr ptr %t3, [label %op_add, label %op_sub, label %op_mul, label %op_xor, label %op_dup, label %op_done]

op_xor:
  %a4  = xor i16 %inA, %inB
  %g4p = getelementptr inbounds i8, ptr %code, i16 4
  %g4  = load i8, ptr %g4p
  %ix4 = zext i8 %g4 to i32
  %p4  = getelementptr inbounds [6 x ptr], ptr @labels, i32 0, i32 %ix4
  %t4  = load ptr, ptr %p4
  indirectbr ptr %t4, [label %op_add, label %op_sub, label %op_mul, label %op_xor, label %op_dup, label %op_done]

op_dup:
  %a5  = add i16 %inA, %inA
  %g5p = getelementptr inbounds i8, ptr %code, i16 5
  %g5  = load i8, ptr %g5p
  %ix5 = zext i8 %g5 to i32
  %p5  = getelementptr inbounds [6 x ptr], ptr @labels, i32 0, i32 %ix5
  %t5  = load ptr, ptr %p5
  indirectbr ptr %t5, [label %op_add, label %op_sub, label %op_mul, label %op_xor, label %op_dup, label %op_done]

op_done:
  ret i16 42
}
