1; RUN: llc -mtriple=thumbv4t-none--eabi < %s | FileCheck %s --check-prefix=CHECK-V4T 2; RUN: llc -mtriple=thumbv5t-none--eabi < %s | FileCheck %s --check-prefix=CHECK-V5T 3 4; CHECK-V4T-LABEL: clobberframe 5; CHECK-V5T-LABEL: clobberframe 6define <4 x i32> @clobberframe(<6 x i32>* %p) #0 { 7entry: 8; Prologue 9; -------- 10; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr} 11; CHECK-V4T: sub sp, 12; Stack is realigned because of the <6 x i32> type 13; CHECK-V4T: mov sp, r4 14; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr} 15 16 %b = alloca <6 x i32>, align 16 17 %a = alloca <4 x i32>, align 16 18 %stuff = load <6 x i32>, <6 x i32>* %p, align 16 19 store <6 x i32> %stuff, <6 x i32>* %b, align 16 20 store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32>* %a, align 16 21 %0 = load <4 x i32>, <4 x i32>* %a, align 16 22 ret <4 x i32> %0 23 24; Epilogue 25; -------- 26; Stack realignment means sp is restored from frame pointer 27; CHECK-V4T: mov sp 28; CHECK-V4T-NEXT: ldr [[POP:r[4567]]], [sp, #16] 29; CHECK-V4T-NEXT: mov lr, [[POP]] 30; CHECK-V4T-NEXT: pop {[[SAVED]]} 31; CHECK-V4T-NEXT add sp, sp, #4 32; The ISA for v4 does not support pop pc, so make sure we do not emit 33; one even when we do not need to update SP. 34; CHECK-V4T-NOT: pop {pc} 35; CHECK-V4T: bx lr 36; CHECK-V5T: pop {[[SAVED]], pc} 37} 38 39; CHECK-V4T-LABEL: clobbervariadicframe 40; CHECK-V5T-LABEL: clobbervariadicframe 41define <4 x i32> @clobbervariadicframe(i32 %i, ...) #0 { 42entry: 43; Prologue 44; -------- 45; CHECK-V4T: sub sp, 46; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr} 47; CHECK-V5T: sub sp, 48; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr} 49 50 %b = alloca <4 x i32>, align 16 51 %a = alloca <4 x i32>, align 16 52 store <4 x i32> <i32 42, i32 42, i32 42, i32 42>, <4 x i32>* %b, align 16 53 store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32>* %a, align 16 54 %0 = load <4 x i32>, <4 x i32>* %a, align 16 55 call void @llvm.va_start(i8* null) 56 ret <4 x i32> %0 57 58; Epilogue 59; -------- 60; CHECK-V4T: ldr [[POP:r[4567]]], [sp, #12] 61; CHECK-V4T-NEXT: mov lr, [[POP]] 62; CHECK-V4T-NEXT: pop {[[SAVED]]} 63; CHECK-V4T-NEXT: add sp, #16 64; CHECK-V4T-NEXT: bx lr 65; CHECK-V5T: lsls r4 66; CHECK-V5T-NEXT: mov sp, r4 67; CHECK-V5T: ldr [[POP:r[4567]]], [sp, #12] 68; CHECK-V5T-NEXT: mov lr, [[POP]] 69; CHECK-V5T-NEXT: pop {[[SAVED]]} 70; CHECK-V5T-NEXT: add sp, #16 71; CHECK-V5T-NEXT: bx lr 72} 73 74; CHECK-V4T-LABEL: simpleframe 75; CHECK-V5T-LABEL: simpleframe 76define i32 @simpleframe(<6 x i32>* %p) #0 { 77entry: 78; Prologue 79; -------- 80; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr} 81; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr} 82 83 %0 = load <6 x i32>, <6 x i32>* %p, align 16 84 %1 = extractelement <6 x i32> %0, i32 0 85 %2 = extractelement <6 x i32> %0, i32 1 86 %3 = extractelement <6 x i32> %0, i32 2 87 %4 = extractelement <6 x i32> %0, i32 3 88 %5 = extractelement <6 x i32> %0, i32 4 89 %6 = extractelement <6 x i32> %0, i32 5 90 %add1 = add nsw i32 %1, %2 91 %add2 = add nsw i32 %add1, %3 92 %add3 = add nsw i32 %add2, %4 93 %add4 = add nsw i32 %add3, %5 94 %add5 = add nsw i32 %add4, %6 95 ret i32 %add5 96 97; Epilogue 98; -------- 99; CHECK-V4T: pop {[[SAVED]]} 100; The ISA for v4 does not support pop pc, so make sure we do not emit 101; one even when we do not need to update SP. 102; CHECK-V4T-NOT: pop {pc} 103; Pop the value of LR into a scratch lo register other than r0 (it is 104; used for the return value). 105; CHECK-V4T-NEXT: pop {[[POP_REG:r[1-3]]]} 106; CHECK-V4T-NEXT: bx [[POP_REG]] 107; CHECK-V5T: pop {[[SAVED]], pc} 108} 109 110; CHECK-V4T-LABEL: simplevariadicframe 111; CHECK-V5T-LABEL: simplevariadicframe 112define i32 @simplevariadicframe(i32 %i, ...) #0 { 113entry: 114; Prologue 115; -------- 116; CHECK-V4T: sub sp, 117; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr} 118; CHECK-V4T: sub sp, 119; CHECK-V5T: sub sp, 120; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr} 121; CHECK-V5T: sub sp, 122 123 %a = alloca i32, align 4 124 %b = alloca i32, align 4 125 %c = alloca i32, align 4 126 %d = alloca i32, align 4 127 store i32 1, i32* %a, align 4 128 store i32 2, i32* %b, align 4 129 store i32 3, i32* %c, align 4 130 store i32 4, i32* %d, align 4 131 %0 = load i32, i32* %a, align 4 132 %inc = add nsw i32 %0, 1 133 store i32 %inc, i32* %a, align 4 134 %1 = load i32, i32* %b, align 4 135 %inc1 = add nsw i32 %1, 1 136 store i32 %inc1, i32* %b, align 4 137 %2 = load i32, i32* %c, align 4 138 %inc2 = add nsw i32 %2, 1 139 store i32 %inc2, i32* %c, align 4 140 %3 = load i32, i32* %d, align 4 141 %inc3 = add nsw i32 %3, 1 142 store i32 %inc3, i32* %d, align 4 143 %4 = load i32, i32* %a, align 4 144 %5 = load i32, i32* %b, align 4 145 %add = add nsw i32 %4, %5 146 %6 = load i32, i32* %c, align 4 147 %add4 = add nsw i32 %add, %6 148 %7 = load i32, i32* %d, align 4 149 %add5 = add nsw i32 %add4, %7 150 %add6 = add nsw i32 %add5, %i 151 call void @llvm.va_start(i8* null) 152 ret i32 %add6 153 154; Epilogue 155; -------- 156; CHECK-V4T: add sp, 157; CHECK-V4T-NEXT: pop {[[SAVED]]} 158; Only r1 to r3 are available to pop LR. 159; r0 is used for the return value. 160; CHECK-V4T-NEXT: pop {[[POP_REG:r[1-3]]]} 161; CHECK-V4T-NEXT: add sp, 162; CHECK-V4T-NEXT: bx [[POP_REG]] 163; CHECK-V5T: add sp, 164; CHECK-V5T-NEXT: pop {[[SAVED]]} 165; Only r1 to r3 are available to pop LR. 166; r0 is used for the return value. 167; CHECK-V5T-NEXT: pop {[[POP_REG:r[1-3]]]} 168; CHECK-V5T-NEXT: add sp, 169; CHECK-V5T-NEXT: bx [[POP_REG]] 170} 171 172; CHECK-V4T-LABEL: noframe 173; CHECK-V5T-LABEL: noframe 174define i32 @noframe() #0 { 175entry: 176; Prologue 177; -------- 178; CHECK-V4T-NOT: push 179; CHECK-V5T-NOT: push 180 ret i32 0; 181; Epilogue 182; -------- 183; CHECK-V4T-NOT: pop 184; CHECK-V5T-NOT: pop 185; CHECK-V4T: bx lr 186; CHECK-V5T: bx lr 187} 188 189; CHECK-V4T-LABEL: novariadicframe 190; CHECK-V5T-LABEL: novariadicframe 191define i32 @novariadicframe(i32 %i, ...) #0 { 192entry: 193; Prologue 194; -------- 195; CHECK-V4T: sub sp, 196; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr} 197; CHECK-V5T: sub sp, 198; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr} 199 200 call void @llvm.va_start(i8* null) 201 ret i32 %i; 202; Epilogue 203; -------- 204; CHECK-V4T: pop {[[SAVED]]} 205; Only r1 to r3 are available to pop LR. 206; r0 is used for the return value. 207; CHECK-V4T-NEXT: pop {[[POP_REG:r[1-3]]]} 208; CHECK-V4T-NEXT: add sp, 209; CHECK-V4T-NEXT: bx [[POP_REG]] 210; CHECK-V5T: pop {[[SAVED]]} 211; Only r1 to r3 are available to pop LR. 212; r0 is used for the return value. 213; CHECK-V5T-NEXT: pop {[[POP_REG:r[1-3]]]} 214; CHECK-V5T-NEXT: add sp, 215; CHECK-V5T-NEXT: bx [[POP_REG]] 216} 217 218declare void @llvm.va_start(i8*) nounwind 219