summaryrefslogtreecommitdiff
path: root/test/CodeGen/ARM
diff options
context:
space:
mode:
authorStephen Lin <stephenwlin@gmail.com>2013-04-30 22:49:28 +0000
committerStephen Lin <stephenwlin@gmail.com>2013-04-30 22:49:28 +0000
commit3484da9479a4daff3efc7febe004e1f4d69b3b4a (patch)
treeb635dd293a2073de9c87b543a3f35cc50ecd9fd8 /test/CodeGen/ARM
parent8e229c24ed8b8a9a3866947a709e616b33780f1f (diff)
downloadllvm-3484da9479a4daff3efc7febe004e1f4d69b3b4a.tar.gz
llvm-3484da9479a4daff3efc7febe004e1f4d69b3b4a.tar.bz2
llvm-3484da9479a4daff3efc7febe004e1f4d69b3b4a.tar.xz
Only pass 'returned' to target-specific lowering code when the value of entire register is guaranteed to be preserved.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180825 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGen/ARM')
-rw-r--r--test/CodeGen/ARM/returned-ext.ll178
-rw-r--r--test/CodeGen/ARM/this-return.ll64
2 files changed, 178 insertions, 64 deletions
diff --git a/test/CodeGen/ARM/returned-ext.ll b/test/CodeGen/ARM/returned-ext.ll
new file mode 100644
index 0000000000..670b12f249
--- /dev/null
+++ b/test/CodeGen/ARM/returned-ext.ll
@@ -0,0 +1,178 @@
+; RUN: llc < %s -mtriple=armv6-linux-gnueabi -arm-tail-calls | FileCheck %s -check-prefix=CHECKELF
+; RUN: llc < %s -mtriple=thumbv7-apple-ios -arm-tail-calls | FileCheck %s -check-prefix=CHECKT2D
+
+declare i16 @identity16(i16 returned %x)
+declare i32 @identity32(i32 returned %x)
+declare zeroext i16 @retzext16(i16 returned %x)
+declare i16 @paramzext16(i16 zeroext returned %x)
+declare zeroext i16 @bothzext16(i16 zeroext returned %x)
+
+; The zeroext param attribute below is meant to have no effect
+define i16 @test_identity(i16 zeroext %x) {
+entry:
+; CHECKELF: test_identity:
+; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
+; CHECKELF: bl identity16
+; CHECKELF: uxth r0, r0
+; CHECKELF: bl identity32
+; CHECKELF: mov r0, [[SAVEX]]
+; CHECKT2D: test_identity:
+; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
+; CHECKT2D: blx _identity16
+; CHECKT2D: uxth r0, r0
+; CHECKT2D: blx _identity32
+; CHECKT2D: mov r0, [[SAVEX]]
+ %call = tail call i16 @identity16(i16 %x)
+ %b = zext i16 %call to i32
+ %call2 = tail call i32 @identity32(i32 %b)
+ ret i16 %x
+}
+
+; FIXME: This ought not to require register saving but currently does because
+; x is not considered equal to %call (see SelectionDAGBuilder.cpp)
+define i16 @test_matched_ret(i16 %x) {
+entry:
+; CHECKELF: test_matched_ret:
+
+; This shouldn't be required
+; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
+
+; CHECKELF: bl retzext16
+; CHECKELF-NOT: uxth r0, {{r[0-9]+}}
+; CHECKELF: bl identity32
+
+; This shouldn't be required
+; CHECKELF: mov r0, [[SAVEX]]
+
+; CHECKT2D: test_matched_ret:
+
+; This shouldn't be required
+; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
+
+; CHECKT2D: blx _retzext16
+; CHECKT2D-NOT: uxth r0, {{r[0-9]+}}
+; CHECKT2D: blx _identity32
+
+; This shouldn't be required
+; CHECKT2D: mov r0, [[SAVEX]]
+
+ %call = tail call i16 @retzext16(i16 %x)
+ %b = zext i16 %call to i32
+ %call2 = tail call i32 @identity32(i32 %b)
+ ret i16 %x
+}
+
+define i16 @test_mismatched_ret(i16 %x) {
+entry:
+; CHECKELF: test_mismatched_ret:
+; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
+; CHECKELF: bl retzext16
+; CHECKELF: sxth r0, {{r[0-9]+}}
+; CHECKELF: bl identity32
+; CHECKELF: mov r0, [[SAVEX]]
+; CHECKT2D: test_mismatched_ret:
+; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
+; CHECKT2D: blx _retzext16
+; CHECKT2D: sxth r0, {{r[0-9]+}}
+; CHECKT2D: blx _identity32
+; CHECKT2D: mov r0, [[SAVEX]]
+ %call = tail call i16 @retzext16(i16 %x)
+ %b = sext i16 %call to i32
+ %call2 = tail call i32 @identity32(i32 %b)
+ ret i16 %x
+}
+
+define i16 @test_matched_paramext(i16 %x) {
+entry:
+; CHECKELF: test_matched_paramext:
+; CHECKELF: uxth r0, r0
+; CHECKELF: bl paramzext16
+; CHECKELF: uxth r0, r0
+; CHECKELF: bl identity32
+; CHECKELF: b paramzext16
+; CHECKT2D: test_matched_paramext:
+; CHECKT2D: uxth r0, r0
+; CHECKT2D: blx _paramzext16
+; CHECKT2D: uxth r0, r0
+; CHECKT2D: blx _identity32
+; CHECKT2D: b.w _paramzext16
+ %call = tail call i16 @paramzext16(i16 %x)
+ %b = zext i16 %call to i32
+ %call2 = tail call i32 @identity32(i32 %b)
+ %call3 = tail call i16 @paramzext16(i16 %call)
+ ret i16 %call3
+}
+
+; FIXME: This theoretically ought to optimize to exact same output as the
+; version above, but doesn't currently (see SelectionDAGBuilder.cpp)
+define i16 @test_matched_paramext2(i16 %x) {
+entry:
+
+; Since there doesn't seem to be an unambiguous optimal selection and
+; scheduling of uxth and mov instructions below in lieu of the 'returned'
+; optimization, don't bother checking: just verify that the calls are made
+; in the correct order as a basic sanity check
+
+; CHECKELF: test_matched_paramext2:
+; CHECKELF: bl paramzext16
+; CHECKELF: bl identity32
+; CHECKELF: b paramzext16
+; CHECKT2D: test_matched_paramext2:
+; CHECKT2D: blx _paramzext16
+; CHECKT2D: blx _identity32
+; CHECKT2D: b.w _paramzext16
+ %call = tail call i16 @paramzext16(i16 %x)
+
+; Should make no difference if %x is used below rather than %call, but it does
+ %b = zext i16 %x to i32
+
+ %call2 = tail call i32 @identity32(i32 %b)
+ %call3 = tail call i16 @paramzext16(i16 %call)
+ ret i16 %call3
+}
+
+define i16 @test_matched_bothext(i16 %x) {
+entry:
+; CHECKELF: test_matched_bothext:
+; CHECKELF: uxth r0, r0
+; CHECKELF: bl bothzext16
+; CHECKELF-NOT: uxth r0, r0
+
+; FIXME: Tail call should be OK here
+; CHECKELF: bl identity32
+
+; CHECKT2D: test_matched_bothext:
+; CHECKT2D: uxth r0, r0
+; CHECKT2D: blx _bothzext16
+; CHECKT2D-NOT: uxth r0, r0
+
+; FIXME: Tail call should be OK here
+; CHECKT2D: blx _identity32
+
+ %call = tail call i16 @bothzext16(i16 %x)
+ %b = zext i16 %x to i32
+ %call2 = tail call i32 @identity32(i32 %b)
+ ret i16 %call
+}
+
+define i16 @test_mismatched_bothext(i16 %x) {
+entry:
+; CHECKELF: test_mismatched_bothext:
+; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
+; CHECKELF: uxth r0, {{r[0-9]+}}
+; CHECKELF: bl bothzext16
+; CHECKELF: sxth r0, [[SAVEX]]
+; CHECKELF: bl identity32
+; CHECKELF: mov r0, [[SAVEX]]
+; CHECKT2D: test_mismatched_bothext:
+; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
+; CHECKT2D: uxth r0, {{r[0-9]+}}
+; CHECKT2D: blx _bothzext16
+; CHECKT2D: sxth r0, [[SAVEX]]
+; CHECKT2D: blx _identity32
+; CHECKT2D: mov r0, [[SAVEX]]
+ %call = tail call i16 @bothzext16(i16 %x)
+ %b = sext i16 %x to i32
+ %call2 = tail call i32 @identity32(i32 %b)
+ ret i16 %x
+}
diff --git a/test/CodeGen/ARM/this-return.ll b/test/CodeGen/ARM/this-return.ll
index 3047302ea7..f06e4a4f8d 100644
--- a/test/CodeGen/ARM/this-return.ll
+++ b/test/CodeGen/ARM/this-return.ll
@@ -103,67 +103,3 @@ entry:
%call2 = tail call %struct.B* @B_ctor_complete(%struct.B* %b2, i32 %x)
ret %struct.E* %this
}
-
-declare i16 @identity16(i16 returned %x)
-declare zeroext i16 @zeroext16(i16 returned %x)
-declare i32 @identity32(i32 returned %x)
-
-define i16 @test_identity(i16 %x) {
-entry:
-; CHECKELF: test_identity:
-; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
-; CHECKELF: bl identity16
-; CHECKELF: uxth r0, [[SAVEX]]
-; CHECKELF: bl identity32
-; CHECKELF: mov r0, [[SAVEX]]
-; CHECKT2D: test_identity:
-; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
-; CHECKT2D: blx _identity16
-; CHECKT2D: uxth r0, [[SAVEX]]
-; CHECKT2D: blx _identity32
-; CHECKT2D: mov r0, [[SAVEX]]
- %call = tail call i16 @identity16(i16 %x)
- %b = zext i16 %x to i32
- %call2 = tail call i32 @identity32(i32 %b)
- ret i16 %call
-}
-
-define i16 @test_matched_ext(i16 %x) {
-entry:
-; CHECKELF: test_matched_ext:
-; CHECKELF-NOT: mov {{r[0-9]+}}, r0
-; CHECKELF: bl zeroext16
-; CHECKELF-NOT: uxth r0, {{r[0-9]+}}
-; CHECKELF: bl identity32
-; CHECKELF-NOT: mov r0, {{r[0-9]+}}
-; CHECKT2D: test_matched_ext:
-; CHECKT2D-NOT: mov {{r[0-9]+}}, r0
-; CHECKT2D: blx _zeroext16
-; CHECKT2D-NOT: uxth r0, {{r[0-9]+}}
-; CHECKT2D: blx _identity32
-; CHECKT2D-NOT: mov r0, {{r[0-9]+}}
- %call = tail call i16 @zeroext16(i16 %x)
- %b = zext i16 %call to i32
- %call2 = tail call i32 @identity32(i32 %b)
- ret i16 %call
-}
-
-define i16 @test_mismatched_ext(i16 %x) {
-entry:
-; CHECKELF: test_mismatched_ext:
-; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
-; CHECKELF: bl zeroext16
-; CHECKELF: sxth r0, [[SAVEX]]
-; CHECKELF: bl identity32
-; CHECKELF: mov r0, [[SAVEX]]
-; CHECKT2D: test_mismatched_ext:
-; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
-; CHECKT2D: blx _zeroext16
-; CHECKT2D: sxth r0, [[SAVEX]]
-; CHECKT2D: blx _identity32
-; CHECKT2D: mov r0, [[SAVEX]]
- %call = tail call i16 @zeroext16(i16 %x)
- %b = sext i16 %call to i32
- %call2 = tail call i32 @identity32(i32 %b)
- ret i16 %call
-}