summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/docs/LangRef.rst1
-rw-r--r--llvm/lib/Target/ARM/ARMFastISel.cpp2
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp1
-rw-r--r--llvm/test/CodeGen/ARM/swift-ios.ll68
-rw-r--r--llvm/test/CodeGen/ARM/swift-return.ll133
5 files changed, 205 insertions, 0 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index bc7cf9c8a08..6c09a24252c 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -430,6 +430,7 @@ added in the future:
"``swiftcc``" - This calling convention is used for Swift language.
- On X86-64 RCX and R8 are available for additional integer returns, and
XMM2 and XMM3 are available for additional FP/vector returns.
+ - On iOS platforms, we use AAPCS-VFP calling convention.
"``cc <n>``" - Numbered convention
Any calling convention may be specified by number, allowing
target-specific calling conventions to be used. Target specific
diff --git a/llvm/lib/Target/ARM/ARMFastISel.cpp b/llvm/lib/Target/ARM/ARMFastISel.cpp
index 6e41053ec5a..d4988b1b6e0 100644
--- a/llvm/lib/Target/ARM/ARMFastISel.cpp
+++ b/llvm/lib/Target/ARM/ARMFastISel.cpp
@@ -1859,6 +1859,7 @@ CCAssignFn *ARMFastISel::CCAssignFnForCall(CallingConv::ID CC,
return (Return ? RetCC_ARM_APCS: CC_ARM_APCS);
}
case CallingConv::ARM_AAPCS_VFP:
+ case CallingConv::Swift:
if (!isVarArg)
return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
// Fall through to soft float variant, variadic functions don't
@@ -3007,6 +3008,7 @@ bool ARMFastISel::fastLowerArguments() {
case CallingConv::ARM_AAPCS_VFP:
case CallingConv::ARM_AAPCS:
case CallingConv::ARM_APCS:
+ case CallingConv::Swift:
break;
}
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index f950adb9159..00446b61ed7 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1388,6 +1388,7 @@ ARMTargetLowering::getEffectiveCallingConv(CallingConv::ID CC,
case CallingConv::PreserveMost:
return CallingConv::PreserveMost;
case CallingConv::ARM_AAPCS_VFP:
+ case CallingConv::Swift:
return isVarArg ? CallingConv::ARM_AAPCS : CallingConv::ARM_AAPCS_VFP;
case CallingConv::C:
if (!Subtarget->isAAPCS_ABI())
diff --git a/llvm/test/CodeGen/ARM/swift-ios.ll b/llvm/test/CodeGen/ARM/swift-ios.ll
new file mode 100644
index 00000000000..a5d09524e11
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/swift-ios.ll
@@ -0,0 +1,68 @@
+; RUN: llc -mtriple=armv7-apple-ios < %s | FileCheck %s
+
+define swiftcc float @t1(float %a, float %b) {
+entry:
+; CHECK: t1
+; CHECK-NOT: vmov
+; CHECK: vadd.f32
+ %add = fadd float %a, %b
+ ret float %add
+}
+
+define swiftcc double @t2(double %a, double %b) {
+entry:
+; CHECK: t2
+; CHECK-NOT: vmov
+; CHECK: vadd.f64
+ %add = fadd double %a, %b
+ ret double %add
+}
+
+define swiftcc double @t9(double %d0, double %d1, double %d2, double %d3,
+ double %d4, double %d5, double %d6, double %d7, float %a, float %b) {
+entry:
+; CHECK-LABEL: t9:
+; CHECK-NOT: vmov
+; CHECK: vldr
+ %add = fadd float %a, %b
+ %conv = fpext float %add to double
+ ret double %conv
+}
+
+define swiftcc double @t10(double %d0, double %d1, double %d2, double %d3,
+ double %d4, double %d5, double %a, float %b, double %c) {
+entry:
+; CHECK-LABEL: t10:
+; CHECK-NOT: vmov
+; CHECK: vldr
+ %add = fadd double %a, %c
+ ret double %add
+}
+
+define swiftcc float @t11(double %d0, double %d1, double %d2, double %d3,
+ double %d4, double %d5, double %d6, float %a, double %b, float %c) {
+entry:
+; CHECK-LABEL: t11:
+; CHECK: vldr
+ %add = fadd float %a, %c
+ ret float %add
+}
+
+define swiftcc double @t12(double %a, double %b) {
+entry:
+; CHECK-LABEL: t12:
+; CHECK: vstr
+ %add = fadd double %a, %b
+ %sub = fsub double %a, %b
+ %call = tail call swiftcc double @x(double 0.000000e+00, double 0.000000e+00,
+ double 0.000000e+00, double 0.000000e+00, double 0.000000e+00,
+ double 0.000000e+00, double %add, float 0.000000e+00,
+ double %sub)
+ ret double %call
+}
+
+declare swiftcc double @x(double, double, double, double, double, double,
+ double, float, double)
+
+attributes #0 = { readnone }
+attributes #1 = { readonly }
diff --git a/llvm/test/CodeGen/ARM/swift-return.ll b/llvm/test/CodeGen/ARM/swift-return.ll
new file mode 100644
index 00000000000..4a5ef5e382c
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/swift-return.ll
@@ -0,0 +1,133 @@
+; RUN: llc -mtriple=armv7k-apple-ios8.0 -mcpu=cortex-a7 -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=armv7k-apple-ios8.0 -mcpu=cortex-a7 -verify-machineinstrs < %s -O0 | FileCheck --check-prefix=CHECK-O0 %s
+
+; RUN: llc -mtriple=armv7-apple-ios -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=armv7-apple-ios -verify-machineinstrs < %s -O0 | FileCheck --check-prefix=CHECK-O0 %s
+
+; Test how llvm handles return type of {i16, i8}. The return value will be
+; passed in %r0 and %r1.
+; CHECK-LABEL: test:
+; CHECK: bl {{.*}}gen
+; CHECK: sxth {{.*}}, r0
+; CHECK: sxtab r0, {{.*}}, r1
+; CHECK-O0-LABEL: test:
+; CHECK-O0: bl {{.*}}gen
+; CHECK-O0: sxth r0, r0
+; CHECK-O0: sxtb r1, r1
+; CHECK-O0: add r0, r0, r1
+define i16 @test(i32 %key) {
+entry:
+ %key.addr = alloca i32, align 4
+ store i32 %key, i32* %key.addr, align 4
+ %0 = load i32, i32* %key.addr, align 4
+ %call = call swiftcc { i16, i8 } @gen(i32 %0)
+ %v3 = extractvalue { i16, i8 } %call, 0
+ %v1 = sext i16 %v3 to i32
+ %v5 = extractvalue { i16, i8 } %call, 1
+ %v2 = sext i8 %v5 to i32
+ %add = add nsw i32 %v1, %v2
+ %conv = trunc i32 %add to i16
+ ret i16 %conv
+}
+
+declare swiftcc { i16, i8 } @gen(i32)
+
+; We can't pass every return value in register, instead, pass everything in
+; memroy.
+; The caller provides space for the return value and passes the address in %r0.
+; The first input argument will be in %r1.
+; CHECK-LABEL: test2:
+; CHECK: mov r1, r0
+; CHECK: mov r0, sp
+; CHECK: bl {{.*}}gen2
+; CHECK-DAG: add
+; CHECK-DAG: ldr {{.*}}, [sp, #16]
+; CHECK-DAG: add
+; CHECK-DAG: add
+; CHECK-DAG: add
+; CHECK-O0-LABEL: test2:
+; CHECK-O0: str r0
+; CHECK-O0: mov r0, sp
+; CHECK-O0: bl {{.*}}gen2
+; CHECK-O0-DAG: ldr {{.*}}, [sp]
+; CHECK-O0-DAG: ldr {{.*}}, [sp, #4]
+; CHECK-O0-DAG: ldr {{.*}}, [sp, #8]
+; CHECK-O0-DAG: ldr {{.*}}, [sp, #12]
+; CHECK-O0-DAG: ldr {{.*}}, [sp, #16]
+; CHECK-O0-DAG: add
+; CHECK-O0-DAG: add
+; CHECK-O0-DAG: add
+; CHECK-O0-DAG: add
+define i32 @test2(i32 %key) #0 {
+entry:
+ %key.addr = alloca i32, align 4
+ store i32 %key, i32* %key.addr, align 4
+ %0 = load i32, i32* %key.addr, align 4
+ %call = call swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %0)
+
+ %v3 = extractvalue { i32, i32, i32, i32, i32 } %call, 0
+ %v5 = extractvalue { i32, i32, i32, i32, i32 } %call, 1
+ %v6 = extractvalue { i32, i32, i32, i32, i32 } %call, 2
+ %v7 = extractvalue { i32, i32, i32, i32, i32 } %call, 3
+ %v8 = extractvalue { i32, i32, i32, i32, i32 } %call, 4
+
+ %add = add nsw i32 %v3, %v5
+ %add1 = add nsw i32 %add, %v6
+ %add2 = add nsw i32 %add1, %v7
+ %add3 = add nsw i32 %add2, %v8
+ ret i32 %add3
+}
+
+; The address of the return value is passed in %r0.
+; CHECK-LABEL: gen2:
+; CHECK-DAG: str r1, [r0]
+; CHECK-DAG: str r1, [r0, #4]
+; CHECK-DAG: str r1, [r0, #8]
+; CHECK-DAG: str r1, [r0, #12]
+; CHECK-DAG: str r1, [r0, #16]
+; CHECK-O0-LABEL: gen2:
+; CHECK-O0-DAG: str r1, [r0]
+; CHECK-O0-DAG: str r1, [r0, #4]
+; CHECK-O0-DAG: str r1, [r0, #8]
+; CHECK-O0-DAG: str r1, [r0, #12]
+; CHECK-O0-DAG: str r1, [r0, #16]
+define swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %key) {
+ %Y = insertvalue { i32, i32, i32, i32, i32 } undef, i32 %key, 0
+ %Z = insertvalue { i32, i32, i32, i32, i32 } %Y, i32 %key, 1
+ %Z2 = insertvalue { i32, i32, i32, i32, i32 } %Z, i32 %key, 2
+ %Z3 = insertvalue { i32, i32, i32, i32, i32 } %Z2, i32 %key, 3
+ %Z4 = insertvalue { i32, i32, i32, i32, i32 } %Z3, i32 %key, 4
+ ret { i32, i32, i32, i32, i32 } %Z4
+}
+
+; The return value {i32, i32, i32, i32} will be returned via registers %r0, %r1,
+; %r2, %r3.
+; CHECK-LABEL: test3:
+; CHECK: bl {{.*}}gen3
+; CHECK: add r0, r0, r1
+; CHECK: add r0, r0, r2
+; CHECK: add r0, r0, r3
+; CHECK-O0-LABEL: test3:
+; CHECK-O0: bl {{.*}}gen3
+; CHECK-O0: add r0, r0, r1
+; CHECK-O0: add r0, r0, r2
+; CHECK-O0: add r0, r0, r3
+define i32 @test3(i32 %key) #0 {
+entry:
+ %key.addr = alloca i32, align 4
+ store i32 %key, i32* %key.addr, align 4
+ %0 = load i32, i32* %key.addr, align 4
+ %call = call swiftcc { i32, i32, i32, i32 } @gen3(i32 %0)
+
+ %v3 = extractvalue { i32, i32, i32, i32 } %call, 0
+ %v5 = extractvalue { i32, i32, i32, i32 } %call, 1
+ %v6 = extractvalue { i32, i32, i32, i32 } %call, 2
+ %v7 = extractvalue { i32, i32, i32, i32 } %call, 3
+
+ %add = add nsw i32 %v3, %v5
+ %add1 = add nsw i32 %add, %v6
+ %add2 = add nsw i32 %add1, %v7
+ ret i32 %add2
+}
+
+declare swiftcc { i32, i32, i32, i32 } @gen3(i32 %key)
OpenPOWER on IntegriCloud