|
3 | 3 |
|
4 | 4 | %struct.interrupt_frame = type { i64, i64, i64, i64, i64 }
|
5 | 5 |
|
6 |
| -@llvm.used = appending global [4 x i8*] [i8* bitcast (void (%struct.interrupt_frame*)* @test_isr_no_ecode to i8*), i8* bitcast (void (%struct.interrupt_frame*, i64)* @test_isr_ecode to i8*), i8* bitcast (void (%struct.interrupt_frame*, i64)* @test_isr_clobbers to i8*), i8* bitcast (void (%struct.interrupt_frame*)* @test_isr_x87 to i8*)], section "llvm.metadata" |
| 6 | +@sink_address = global i64* null |
| 7 | +@sink_i32 = global i64 0 |
7 | 8 |
|
8 | 9 | ; Spills rax, putting original esp at +8.
|
9 | 10 | ; No stack adjustment if declared with no error code
|
@@ -105,3 +106,75 @@ entry:
|
105 | 106 | store x86_fp80 %add, x86_fp80* @f80, align 4
|
106 | 107 | ret void
|
107 | 108 | }
|
| 109 | + |
| 110 | +; Use a frame pointer to check the offsets. No return address, arguments start |
| 111 | +; at RBP+4. |
| 112 | +define dso_local x86_intrcc void @test_fp_1(%struct.interrupt_frame* %p) #0 { |
| 113 | + ; CHECK-LABEL: test_fp_1: |
| 114 | + ; CHECK: # %bb.0: # %entry |
| 115 | + ; CHECK-NEXT: pushq %rbp |
| 116 | + ; CHECK-NEXT: movq %rsp, %rbp |
| 117 | + ; CHECK: cld |
| 118 | + ; CHECK-DAG: leaq 8(%rbp), %[[R1:[^ ]*]] |
| 119 | + ; CHECK-DAG: leaq 40(%rbp), %[[R2:[^ ]*]] |
| 120 | + ; CHECK: movq %[[R1]], sink_address |
| 121 | + ; CHECK: movq %[[R2]], sink_address |
| 122 | + ; CHECK: popq %rbp |
| 123 | + ; CHECK: iretq |
| 124 | +entry: |
| 125 | + %arrayidx = getelementptr inbounds %struct.interrupt_frame, %struct.interrupt_frame* %p, i64 0, i32 0 |
| 126 | + %arrayidx2 = getelementptr inbounds %struct.interrupt_frame, %struct.interrupt_frame* %p, i64 0, i32 4 |
| 127 | + store volatile i64* %arrayidx, i64** @sink_address |
| 128 | + store volatile i64* %arrayidx2, i64** @sink_address |
| 129 | + ret void |
| 130 | +} |
| 131 | + |
| 132 | +; The error code is between RBP and the interrupt_frame. |
| 133 | +define dso_local x86_intrcc void @test_fp_2(%struct.interrupt_frame* %p, i64 %err) #0 { |
| 134 | + ; CHECK-LABEL: test_fp_2: |
| 135 | + ; CHECK: # %bb.0: # %entry |
| 136 | + ; This RAX push is just to align the stack. |
| 137 | + ; CHECK-NEXT: pushq %rax |
| 138 | + ; CHECK-NEXT: pushq %rbp |
| 139 | + ; CHECK-NEXT: movq %rsp, %rbp |
| 140 | + ; CHECK: cld |
| 141 | + ; CHECK-DAG: movq 16(%rbp), %[[R3:[^ ]*]] |
| 142 | + ; CHECK-DAG: leaq 24(%rbp), %[[R1:[^ ]*]] |
| 143 | + ; CHECK-DAG: leaq 56(%rbp), %[[R2:[^ ]*]] |
| 144 | + ; CHECK: movq %[[R1]], sink_address(%rip) |
| 145 | + ; CHECK: movq %[[R2]], sink_address(%rip) |
| 146 | + ; CHECK: movq %[[R3]], sink_i32(%rip) |
| 147 | + ; CHECK: popq %rbp |
| 148 | + ; Pop off both the error code and the 8 byte alignment adjustment from the |
| 149 | + ; prologue. |
| 150 | + ; CHECK: addq $16, %rsp |
| 151 | + ; CHECK: iretq |
| 152 | +entry: |
| 153 | + %arrayidx = getelementptr inbounds %struct.interrupt_frame, %struct.interrupt_frame* %p, i64 0, i32 0 |
| 154 | + %arrayidx2 = getelementptr inbounds %struct.interrupt_frame, %struct.interrupt_frame* %p, i64 0, i32 4 |
| 155 | + store volatile i64* %arrayidx, i64** @sink_address |
| 156 | + store volatile i64* %arrayidx2, i64** @sink_address |
| 157 | + store volatile i64 %err, i64* @sink_i32 |
| 158 | + ret void |
| 159 | +} |
| 160 | + |
| 161 | +; Test argument copy elision when copied to a local alloca. |
| 162 | +define x86_intrcc void @test_copy_elide(%struct.interrupt_frame* %frame, i64 %err) #0 { |
| 163 | + ; CHECK-LABEL: test_copy_elide: |
| 164 | + ; CHECK: # %bb.0: # %entry |
| 165 | + ; This RAX push is just to align the stack. |
| 166 | + ; CHECK-NEXT: pushq %rax |
| 167 | + ; CHECK-NEXT: pushq %rbp |
| 168 | + ; CHECK-NEXT: movq %rsp, %rbp |
| 169 | + ; CHECK: cld |
| 170 | + ; CHECK: leaq 16(%rbp), %[[R1:[^ ]*]] |
| 171 | + ; CHECK: movq %[[R1]], sink_address(%rip) |
| 172 | +entry: |
| 173 | + %err.addr = alloca i64, align 4 |
| 174 | + store i64 %err, i64* %err.addr, align 4 |
| 175 | + store volatile i64* %err.addr, i64** @sink_address |
| 176 | + ret void |
| 177 | +} |
| 178 | + |
| 179 | + |
| 180 | +attributes #0 = { nounwind "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" } |
0 commit comments