Jan Voung | 28068ad | 2015-07-31 12:58:46 -0700 | [diff] [blame] | 1 | ; This tries to create variables with very large stack offsets. |
| 2 | ; This requires a lot of variables/register pressure. To simplify this |
| 3 | ; we assume poor register allocation from Om1, and a flag that forces |
| 4 | ; the frame to add K amount of unused stack for testing. |
| 5 | ; We only need to test ARM and other architectures which have limited space |
| 6 | ; for specifying an offset within an instruction. |
| 7 | |
Jim Stichnoth | 033dda7 | 2016-10-03 07:56:25 -0700 | [diff] [blame] | 8 | ; RUN: %if --need=target_ARM32 \ |
| 9 | ; RUN: --command %p2i --filetype=obj --disassemble --target arm32 \ |
| 10 | ; RUN: -i %s --args -Om1 --test-stack-extra 4096 \ |
Karl Schimpf | 57d31ac | 2015-10-07 09:53:12 -0700 | [diff] [blame] | 11 | ; RUN: -allow-externally-defined-symbols \ |
Jim Stichnoth | 033dda7 | 2016-10-03 07:56:25 -0700 | [diff] [blame] | 12 | ; RUN: | %if --need=target_ARM32 \ |
Jan Voung | 28068ad | 2015-07-31 12:58:46 -0700 | [diff] [blame] | 13 | ; RUN: --command FileCheck --check-prefix ARM32 %s |
| 14 | |
| 15 | declare i64 @dummy(i32 %t1, i32 %t2, i32 %t3, i64 %t4, i64 %t5) |
| 16 | |
| 17 | ; Test a function that requires lots of stack (due to test flag), and uses |
| 18 | ; SP as the base register (originally). |
| 19 | define internal i64 @lotsOfStack(i32 %a, i32 %b, i32 %c, i32 %d) { |
| 20 | entry: |
| 21 | %t1 = xor i32 %a, %b |
| 22 | %t2 = or i32 %c, %d |
| 23 | %cmp = icmp eq i32 %t1, %t2 |
| 24 | br i1 %cmp, label %br_1, label %br_2 |
| 25 | |
| 26 | br_1: |
| 27 | %x1 = zext i32 %t1 to i64 |
| 28 | %y1 = ashr i64 %x1, 17 |
| 29 | ; Use some stack during the call, so that references to %t1 and %t2's |
| 30 | ; stack slots require stack adjustment. |
| 31 | %r1 = call i64 @dummy(i32 123, i32 321, i32 %t2, i64 %x1, i64 %y1) |
| 32 | %z1 = sub i64 %r1, %y1 |
| 33 | br label %end |
| 34 | |
| 35 | br_2: |
| 36 | %x2 = zext i32 %t2 to i64 |
| 37 | %y2 = and i64 %x2, 123 |
| 38 | %r2 = call i64 @dummy(i32 123, i32 321, i32 %t2, i64 %x2, i64 %y2) |
| 39 | %z2 = and i64 %r2, %y2 |
| 40 | br label %end |
| 41 | |
| 42 | end: |
| 43 | %x3 = phi i64 [ %x1, %br_1 ], [ %x2, %br_2 ] |
| 44 | %z3 = phi i64 [ %z1, %br_1 ], [ %z2, %br_2 ] |
| 45 | %r3 = and i64 %x3, %z3 |
| 46 | ret i64 %r3 |
| 47 | } |
| 48 | ; ARM32-LABEL: lotsOfStack |
| 49 | ; ARM32-NOT: mov fp, sp |
| 50 | ; ARM32: movw ip, #4{{.*}} |
| 51 | ; ARM32-NEXT: sub sp, sp, ip |
John Porto | f419854 | 2015-11-20 14:17:23 -0800 | [diff] [blame] | 52 | ; ARM32: movw ip, #4248 |
Jan Voung | 28068ad | 2015-07-31 12:58:46 -0700 | [diff] [blame] | 53 | ; ARM32-NEXT: add ip, sp, ip |
| 54 | ; ARM32-NOT: movw ip |
| 55 | ; %t2 is the result of the "or", and %t2 will be passed via r1 to the call. |
| 56 | ; Use that to check the stack offset of %t2. The first offset and the |
| 57 | ; later offset right before the call should be 16 bytes apart, |
| 58 | ; because of the sub sp, sp, #16. |
| 59 | ; ARM32: orr [[REG:r.*]], {{.*}}, |
| 60 | ; I.e., the slot for t2 is (sp0 + 4232 - 20) == sp0 + 4212. |
| 61 | ; ARM32: str [[REG]], [ip, #-20] |
| 62 | ; ARM32: b {{[a-f0-9]+}} |
| 63 | ; Now skip ahead to where the call in br_1 begins, to check how %t2 is used. |
John Porto | f419854 | 2015-11-20 14:17:23 -0800 | [diff] [blame] | 64 | ; ARM32: movw ip, #4232 |
Jan Voung | 28068ad | 2015-07-31 12:58:46 -0700 | [diff] [blame] | 65 | ; ARM32-NEXT: add ip, sp, ip |
Jan Voung | 28068ad | 2015-07-31 12:58:46 -0700 | [diff] [blame] | 66 | ; ARM32: ldr r2, [ip, #-4] |
John Porto | b82d79a | 2016-03-01 06:11:05 -0800 | [diff] [blame] | 67 | ; ARM32: bl {{.*}} dummy |
Jan Voung | 28068ad | 2015-07-31 12:58:46 -0700 | [diff] [blame] | 68 | ; The call clobbers ip, so we need to re-create the base register. |
| 69 | ; ARM32: movw ip, #4{{.*}} |
| 70 | ; ARM32: b {{[a-f0-9]+}} |
John Porto | b82d79a | 2016-03-01 06:11:05 -0800 | [diff] [blame] | 71 | ; ARM32: bl {{.*}} dummy |
Jan Voung | 28068ad | 2015-07-31 12:58:46 -0700 | [diff] [blame] | 72 | |
| 73 | ; Similar, but test a function that uses FP as the base register (originally). |
| 74 | define internal i64 @usesFrameReg(i32 %a, i32 %b, i32 %c, i32 %d) { |
| 75 | entry: |
| 76 | %p = alloca i8, i32 %d, align 4 |
| 77 | %t1 = xor i32 %a, %b |
| 78 | %t2 = or i32 %c, %d |
| 79 | %cmp = icmp eq i32 %t1, %t2 |
| 80 | br i1 %cmp, label %br_1, label %br_2 |
| 81 | |
| 82 | br_1: |
| 83 | %x1 = zext i32 %t1 to i64 |
| 84 | %y1 = ashr i64 %x1, 17 |
| 85 | %p32 = ptrtoint i8* %p to i32 |
| 86 | %r1 = call i64 @dummy(i32 %p32, i32 321, i32 %t2, i64 %x1, i64 %y1) |
| 87 | %z1 = sub i64 %r1, %y1 |
| 88 | br label %end |
| 89 | |
| 90 | br_2: |
| 91 | %x2 = zext i32 %t2 to i64 |
| 92 | %y2 = and i64 %x2, 123 |
| 93 | %r2 = call i64 @dummy(i32 123, i32 321, i32 %d, i64 %x2, i64 %y2) |
| 94 | %z2 = and i64 %r2, %y2 |
| 95 | br label %end |
| 96 | |
| 97 | end: |
| 98 | %x3 = phi i64 [ %x1, %br_1 ], [ %x2, %br_2 ] |
| 99 | %z3 = phi i64 [ %z1, %br_1 ], [ %z2, %br_2 ] |
| 100 | %r3 = and i64 %x3, %z3 |
| 101 | ret i64 %r3 |
| 102 | } |
| 103 | ; ARM32-LABEL: usesFrameReg |
| 104 | ; ARM32: mov fp, sp |
| 105 | ; ARM32: movw ip, #4{{.*}} |
| 106 | ; ARM32-NEXT: sub sp, sp, ip |
| 107 | ; ARM32: movw ip, #4100 |
| 108 | ; ARM32-NEXT: sub ip, fp, ip |
| 109 | ; ARM32-NOT: movw ip |
| 110 | ; %t2 is the result of the "or", and %t2 will be passed via r1 to the call. |
| 111 | ; Use that to check the stack offset of %t2. It should be the same offset |
| 112 | ; even after sub sp, sp, #16, because the base register was originally |
| 113 | ; the FP and not the SP. |
| 114 | ; ARM32: orr [[REG:r.*]], {{.*}}, |
| 115 | ; I.e., the slot for t2 is (fp0 - 4100 -24) == fp0 - 4124 |
| 116 | ; ARM32: str [[REG]], [ip, #-24] |
| 117 | ; ARM32: b {{[a-f0-9]+}} |
| 118 | ; Now skip ahead to where the call in br_1 begins, to check how %t2 is used. |
| 119 | ; ARM32: movw ip, #4120 |
| 120 | ; ARM32-NEXT: sub ip, fp, ip |
Jan Voung | 28068ad | 2015-07-31 12:58:46 -0700 | [diff] [blame] | 121 | ; ARM32: ldr r2, [ip, #-4] |
John Porto | b82d79a | 2016-03-01 06:11:05 -0800 | [diff] [blame] | 122 | ; ARM32: bl {{.*}} dummy |
Jan Voung | 28068ad | 2015-07-31 12:58:46 -0700 | [diff] [blame] | 123 | ; The call clobbers ip, so we need to re-create the base register. |
| 124 | ; ARM32: movw ip, #4{{.*}} |
| 125 | ; ARM32: b {{[a-f0-9]+}} |
John Porto | b82d79a | 2016-03-01 06:11:05 -0800 | [diff] [blame] | 126 | ; ARM32: bl {{.*}} dummy |