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