aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Christopher <echristo@apple.com>2011-05-28 01:40:44 +0000
committerEric Christopher <echristo@apple.com>2011-05-28 01:40:44 +0000
commit3c14f24c9da3f811d3530e984e692acf1a471b91 (patch)
treed6cab1f83402546eddb6476f2d1fa318e1bfc802
parentb6019320bfc3d0d5f9ec596b4d786c9a9e079519 (diff)
Implement the 'M' output modifier for arm inline asm. This is fairly
register allocation dependent and will occasionally break. WIP in the register allocator to model paired/etc registers. rdar://9119939 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132242 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMAsmPrinter.cpp29
-rw-r--r--test/CodeGen/ARM/arm-modifier.ll37
2 files changed, 54 insertions, 12 deletions
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp
index 709d8c6e62..eb7390236d 100644
--- a/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -387,16 +387,41 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
return true;
O << (MI->getOperand(OpNum).getImm() & 0xffff);
return false;
+ case 'M': { // A register range suitable for LDM/STM.
+ if (!MI->getOperand(OpNum).isReg())
+ return true;
+ const MachineOperand &MO = MI->getOperand(OpNum);
+ unsigned RegBegin = MO.getReg();
+ // This takes advantage of the 2 operand-ness of ldm/stm and that we've
+ // already got the operands in registers that are operands to the
+ // inline asm statement.
+
+ O << "{" << ARMInstPrinter::getRegisterName(RegBegin);
+
+ // FIXME: The register allocator not only may not have given us the
+ // registers in sequence, but may not be in ascending registers. This
+ // will require changes in the register allocator that'll need to be
+ // propagated down here if the operands change.
+ unsigned RegOps = OpNum + 1;
+ while (MI->getOperand(RegOps).isReg()) {
+ O << ", "
+ << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg());
+ RegOps++;
+ }
+
+ O << "}";
+
+ return false;
+ }
+ // These modifiers are not yet supported.
case 'p': // The high single-precision register of a VFP double-precision
// register.
case 'e': // The low doubleword register of a NEON quad register.
case 'f': // The high doubleword register of a NEON quad register.
case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1.
- case 'M': // A register range suitable for LDM/STM.
case 'Q': // The least significant register of a pair.
case 'R': // The most significant register of a pair.
case 'H': // The highest-numbered register of a pair.
- // These modifiers are not yet supported.
return true;
}
}
diff --git a/test/CodeGen/ARM/arm-modifier.ll b/test/CodeGen/ARM/arm-modifier.ll
index 6dd3989728..0a7bb6cd21 100644
--- a/test/CodeGen/ARM/arm-modifier.ll
+++ b/test/CodeGen/ARM/arm-modifier.ll
@@ -1,6 +1,6 @@
; RUN: llc < %s -march=arm -mattr=+vfp2 | FileCheck %s
-define i32 @foo(float %scale, float %scale2) nounwind ssp {
+define i32 @foo(float %scale, float %scale2) nounwind {
entry:
%scale.addr = alloca float, align 4
%scale2.addr = alloca float, align 4
@@ -8,35 +8,52 @@ entry:
store float %scale2, float* %scale2.addr, align 4
%tmp = load float* %scale.addr, align 4
%tmp1 = load float* %scale2.addr, align 4
- call void asm sideeffect "vmul.f32 q0, q0, ${0:y} \0A\09vmul.f32 q1, q1, ${0:y} \0A\09vmul.f32 q1, q0, ${1:y} \0A\09", "w,w,~{q0},~{q1}"(float %tmp, float %tmp1) nounwind, !srcloc !0
+ call void asm sideeffect "vmul.f32 q0, q0, ${0:y} \0A\09vmul.f32 q1, q1, ${0:y} \0A\09vmul.f32 q1, q0, ${1:y} \0A\09", "w,w,~{q0},~{q1}"(float %tmp, float %tmp1) nounwind
ret i32 0
}
-!0 = metadata !{i32 56, i32 89, i32 128, i32 168}
-
-define void @f0() nounwind ssp {
+define void @f0() nounwind {
entry:
; CHECK: f0
; CHECK: .word -1
-call void asm sideeffect ".word ${0:B} \0A\09", "i"(i32 0) nounwind, !srcloc !0
+call void asm sideeffect ".word ${0:B} \0A\09", "i"(i32 0) nounwind
ret void
}
-define void @f1() nounwind ssp {
+define void @f1() nounwind {
entry:
; CHECK: f1
; CHECK: .word 65535
-call void asm sideeffect ".word ${0:L} \0A\09", "i"(i32 -1) nounwind, !srcloc !0
+call void asm sideeffect ".word ${0:L} \0A\09", "i"(i32 -1) nounwind
ret void
}
@f2_ptr = internal global i32* @f2_var, align 4
@f2_var = external global i32
-define void @f2() nounwind ssp {
+define void @f2() nounwind {
entry:
; CHECK: f2
; CHECK: ldr r0, [r{{[0-9]+}}]
-call void asm sideeffect "ldr r0, [${0:m}]\0A\09", "*m,~{r0}"(i32** @f2_ptr) nounwind, !srcloc !0
+call void asm sideeffect "ldr r0, [${0:m}]\0A\09", "*m,~{r0}"(i32** @f2_ptr) nounwind
+ret void
+}
+
+@f3_ptr = internal global i64* @f3_var, align 4
+@f3_var = external global i64
+@f3_var2 = external global i64
+
+define void @f3() nounwind {
+entry:
+; CHECK: f3
+; CHECK: stm r{{[0-9]+}}, {[[REG1:(r[0-9]+)]], r{{[0-9]+}}}
+; CHECK: adds lr, [[REG1]]
+; CHECK: ldm r{{[0-9]+}}, {r{{[0-9]+}}, r{{[0-9]+}}}
+%tmp = load i64* @f3_var, align 4
+%tmp1 = load i64* @f3_var2, align 4
+%0 = call i64 asm sideeffect "stm ${0:m}, ${1:M}\0A\09adds $3, $1\0A\09", "=*m,=r,1,r"(i64** @f3_ptr, i64 %tmp, i64 %tmp1) nounwind
+store i64 %0, i64* @f3_var, align 4
+%1 = call i64 asm sideeffect "ldm ${1:m}, ${0:M}\0A\09", "=r,*m"(i64** @f3_ptr) nounwind
+store i64 %1, i64* @f3_var, align 4
ret void
}