1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 3; RUN: | FileCheck %s -check-prefix=RV32I 4 5declare void @notdead(i8*) 6 7; These tests must ensure the stack pointer is restored using the frame 8; pointer 9 10define void @simple_alloca(i32 %n) nounwind { 11; RV32I-LABEL: simple_alloca: 12; RV32I: # %bb.0: 13; RV32I-NEXT: addi sp, sp, -16 14; RV32I-NEXT: sw ra, 12(sp) 15; RV32I-NEXT: sw s0, 8(sp) 16; RV32I-NEXT: addi s0, sp, 16 17; RV32I-NEXT: addi a0, a0, 15 18; RV32I-NEXT: andi a0, a0, -16 19; RV32I-NEXT: sub a0, sp, a0 20; RV32I-NEXT: mv sp, a0 21; RV32I-NEXT: call notdead 22; RV32I-NEXT: addi sp, s0, -16 23; RV32I-NEXT: lw s0, 8(sp) 24; RV32I-NEXT: lw ra, 12(sp) 25; RV32I-NEXT: addi sp, sp, 16 26; RV32I-NEXT: ret 27 %1 = alloca i8, i32 %n 28 call void @notdead(i8* %1) 29 ret void 30} 31 32declare i8* @llvm.stacksave() 33declare void @llvm.stackrestore(i8*) 34 35define void @scoped_alloca(i32 %n) nounwind { 36; RV32I-LABEL: scoped_alloca: 37; RV32I: # %bb.0: 38; RV32I-NEXT: addi sp, sp, -16 39; RV32I-NEXT: sw ra, 12(sp) 40; RV32I-NEXT: sw s0, 8(sp) 41; RV32I-NEXT: sw s1, 4(sp) 42; RV32I-NEXT: addi s0, sp, 16 43; RV32I-NEXT: mv s1, sp 44; RV32I-NEXT: addi a0, a0, 15 45; RV32I-NEXT: andi a0, a0, -16 46; RV32I-NEXT: sub a0, sp, a0 47; RV32I-NEXT: mv sp, a0 48; RV32I-NEXT: call notdead 49; RV32I-NEXT: mv sp, s1 50; RV32I-NEXT: addi sp, s0, -16 51; RV32I-NEXT: lw s1, 4(sp) 52; RV32I-NEXT: lw s0, 8(sp) 53; RV32I-NEXT: lw ra, 12(sp) 54; RV32I-NEXT: addi sp, sp, 16 55; RV32I-NEXT: ret 56 %sp = call i8* @llvm.stacksave() 57 %addr = alloca i8, i32 %n 58 call void @notdead(i8* %addr) 59 call void @llvm.stackrestore(i8* %sp) 60 ret void 61} 62 63declare void @func(i8*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) 64 65; Check that outgoing arguments passed on the stack do not corrupt a 66; variable-sized stack object. 67define void @alloca_callframe(i32 %n) nounwind { 68; RV32I-LABEL: alloca_callframe: 69; RV32I: # %bb.0: 70; RV32I-NEXT: addi sp, sp, -16 71; RV32I-NEXT: sw ra, 12(sp) 72; RV32I-NEXT: sw s0, 8(sp) 73; RV32I-NEXT: addi s0, sp, 16 74; RV32I-NEXT: addi a0, a0, 15 75; RV32I-NEXT: andi a0, a0, -16 76; RV32I-NEXT: sub a0, sp, a0 77; RV32I-NEXT: mv sp, a0 78; RV32I-NEXT: addi sp, sp, -16 79; RV32I-NEXT: addi a1, zero, 12 80; RV32I-NEXT: sw a1, 12(sp) 81; RV32I-NEXT: addi a1, zero, 11 82; RV32I-NEXT: sw a1, 8(sp) 83; RV32I-NEXT: addi a1, zero, 10 84; RV32I-NEXT: sw a1, 4(sp) 85; RV32I-NEXT: addi t0, zero, 9 86; RV32I-NEXT: addi a1, zero, 2 87; RV32I-NEXT: addi a2, zero, 3 88; RV32I-NEXT: addi a3, zero, 4 89; RV32I-NEXT: addi a4, zero, 5 90; RV32I-NEXT: addi a5, zero, 6 91; RV32I-NEXT: addi a6, zero, 7 92; RV32I-NEXT: addi a7, zero, 8 93; RV32I-NEXT: sw t0, 0(sp) 94; RV32I-NEXT: call func 95; RV32I-NEXT: addi sp, sp, 16 96; RV32I-NEXT: addi sp, s0, -16 97; RV32I-NEXT: lw s0, 8(sp) 98; RV32I-NEXT: lw ra, 12(sp) 99; RV32I-NEXT: addi sp, sp, 16 100; RV32I-NEXT: ret 101 %1 = alloca i8, i32 %n 102 call void @func(i8* %1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, 103 i32 9, i32 10, i32 11, i32 12) 104 ret void 105} 106