Tim Northover | 798697d | 2013-04-21 11:57:07 +0000 | [diff] [blame] | 1 | ; RUN: llc -mtriple=armv7-none-linux-gnueabi -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK-WITH-LDRD |
| 2 | ; RUN: llc -mtriple=armv4-none-linux-gnueabi -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK-WITHOUT-LDRD |
| 3 | ; RUN: llc -mtriple=thumbv7-none-linux-gnueabi -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK-WITH-LDRD |
Tim Northover | d9d4211 | 2013-04-20 19:31:00 +0000 | [diff] [blame] | 4 | |
| 5 | define void @foo(i64* %addr) { |
Tim Northover | 798697d | 2013-04-21 11:57:07 +0000 | [diff] [blame] | 6 | %val1 = tail call i64 asm sideeffect "ldrexd $0, ${0:H}, [r0]", "=&r,r"(i64* %addr) |
| 7 | %val2 = tail call i64 asm sideeffect "ldrexd $0, ${0:H}, [r0]", "=&r,r"(i64* %addr) |
| 8 | %val3 = tail call i64 asm sideeffect "ldrexd $0, ${0:H}, [r0]", "=&r,r"(i64* %addr) |
| 9 | %val4 = tail call i64 asm sideeffect "ldrexd $0, ${0:H}, [r0]", "=&r,r"(i64* %addr) |
| 10 | %val5 = tail call i64 asm sideeffect "ldrexd $0, ${0:H}, [r0]", "=&r,r"(i64* %addr) |
| 11 | %val6 = tail call i64 asm sideeffect "ldrexd $0, ${0:H}, [r0]", "=&r,r"(i64* %addr) |
| 12 | %val7 = tail call i64 asm sideeffect "ldrexd $0, ${0:H}, [r0]", "=&r,r"(i64* %addr) |
Tim Northover | d9d4211 | 2013-04-20 19:31:00 +0000 | [diff] [blame] | 13 | |
| 14 | ; Key point is that enough 64-bit paired GPR values are live that |
| 15 | ; one of them has to be spilled. This used to cause an abort because |
| 16 | ; an LDMIA was created with both a FrameIndex and an offset, which |
| 17 | ; is not allowed. |
| 18 | |
Tim Northover | 798697d | 2013-04-21 11:57:07 +0000 | [diff] [blame] | 19 | ; CHECK-WITH-LDRD: strd {{r[0-9]+}}, {{r[0-9]+}}, [sp, #8] |
| 20 | ; CHECK-WITH-LDRD: strd {{r[0-9]+}}, {{r[0-9]+}}, [sp] |
| 21 | |
| 22 | ; CHECK-WITH-LDRD: ldrd {{r[0-9]+}}, {{r[0-9]+}}, [sp, #8] |
| 23 | ; CHECK-WITH-LDRD: ldrd {{r[0-9]+}}, {{r[0-9]+}}, [sp] |
| 24 | |
Tim Northover | d9d4211 | 2013-04-20 19:31:00 +0000 | [diff] [blame] | 25 | ; We also want to ensure the register scavenger is working (i.e. an |
| 26 | ; offset from sp can be generated), so we need two spills. |
Tim Northover | 798697d | 2013-04-21 11:57:07 +0000 | [diff] [blame] | 27 | ; CHECK-WITHOUT-LDRD: add [[ADDRREG:[a-z0-9]+]], sp, #{{[0-9]+}} |
| 28 | ; CHECK-WITHOUT-LDRD: stm [[ADDRREG]], {r{{[0-9]+}}, r{{[0-9]+}}} |
| 29 | ; CHECK-WITHOUT-LDRD: stm sp, {r{{[0-9]+}}, r{{[0-9]+}}} |
Tim Northover | d9d4211 | 2013-04-20 19:31:00 +0000 | [diff] [blame] | 30 | |
| 31 | ; In principle LLVM may have to recalculate the offset. At the moment |
| 32 | ; it reuses the original though. |
Tim Northover | 798697d | 2013-04-21 11:57:07 +0000 | [diff] [blame] | 33 | ; CHECK-WITHOUT-LDRD: ldm [[ADDRREG]], {r{{[0-9]+}}, r{{[0-9]+}}} |
| 34 | ; CHECK-WITHOUT-LDRD: ldm sp, {r{{[0-9]+}}, r{{[0-9]+}}} |
| 35 | |
Tim Northover | d9d4211 | 2013-04-20 19:31:00 +0000 | [diff] [blame] | 36 | store volatile i64 %val1, i64* %addr |
| 37 | store volatile i64 %val2, i64* %addr |
| 38 | store volatile i64 %val3, i64* %addr |
| 39 | store volatile i64 %val4, i64* %addr |
| 40 | store volatile i64 %val5, i64* %addr |
| 41 | store volatile i64 %val6, i64* %addr |
| 42 | store volatile i64 %val7, i64* %addr |
| 43 | ret void |
| 44 | } |