1; RUN: llc -mattr=+zcmp -verify-machineinstrs \ 2; RUN: -mtriple=riscv32 -target-abi=ilp32 < %s \ 3; RUN: | FileCheck %s -check-prefixes=RV32IZCMP 4; RUN: llc -mattr=+zcmp -verify-machineinstrs \ 5; RUN: -mtriple=riscv64 -target-abi=lp64 < %s \ 6; RUN: | FileCheck %s -check-prefixes=RV64IZCMP 7 8; This source code exposed a crash in the RISC-V Zcmp Push/Pop optimization 9; pass. The root cause was: Not doing a bounds check before using a returned 10; iterator. 11 12declare dso_local void @f1() local_unnamed_addr 13declare dso_local void @f2() local_unnamed_addr 14define dso_local void @f0() local_unnamed_addr { 15; RV32IZCMP-LABEL: f0: 16; RV32IZCMP: .cfi_startproc 17; RV32IZCMP-NEXT: # %bb.0: # %entry 18; RV32IZCMP-NEXT: bnez zero, .LBB0_2 19; RV32IZCMP-NEXT: # %bb.1: # %if.T 20; RV32IZCMP-NEXT: cm.push {ra}, -16 21; RV32IZCMP-NEXT: .cfi_def_cfa_offset 16 22; RV32IZCMP-NEXT: .cfi_offset ra, -4 23; RV32IZCMP-NEXT: call f1 24; RV32IZCMP-NEXT: cm.pop {ra}, 16 25; RV32IZCMP-NEXT: .cfi_restore ra 26; RV32IZCMP-NEXT: .cfi_def_cfa_offset 0 27; RV32IZCMP-NEXT: .LBB0_2: # %if.F 28; RV32IZCMP-NEXT: tail f2 29; RV32IZCMP-NEXT: .Lfunc_end0: 30 31; RV64IZCMP-LABEL: f0: 32; RV64IZCMP: .cfi_startproc 33; RV64IZCMP-NEXT: # %bb.0: # %entry 34; RV64IZCMP-NEXT: bnez zero, .LBB0_2 35; RV64IZCMP-NEXT: # %bb.1: # %if.T 36; RV64IZCMP-NEXT: cm.push {ra}, -16 37; RV64IZCMP-NEXT: .cfi_def_cfa_offset 16 38; RV64IZCMP-NEXT: .cfi_offset ra, -8 39; RV64IZCMP-NEXT: call f1 40; RV64IZCMP-NEXT: cm.pop {ra}, 16 41; RV64IZCMP-NEXT: .cfi_restore ra 42; RV64IZCMP-NEXT: .cfi_def_cfa_offset 0 43; RV64IZCMP-NEXT: .LBB0_2: # %if.F 44; RV64IZCMP-NEXT: tail f2 45; RV64IZCMP-NEXT: .Lfunc_end0: 46entry: 47 br i1 poison, label %if.T, label %if.F 48 49if.T: 50 tail call void @f1() 51 br label %if.F 52 53if.F: 54 tail call void @f2() 55 ret void 56} 57