summaryrefslogtreecommitdiff
path: root/test/CodeGen/ARM/constantpool-promote.ll
diff options
context:
space:
mode:
authorJames Molloy <james.molloy@arm.com>2016-09-15 12:30:27 +0000
committerJames Molloy <james.molloy@arm.com>2016-09-15 12:30:27 +0000
commit095eb00556352aa1d8a6df112859e07aa3974ed1 (patch)
tree6cf10393d61778ac27af30862e1f640ed088e5b6 /test/CodeGen/ARM/constantpool-promote.ll
parent8c9a9af652d8b3aa22a8c3ae99793432f13d615e (diff)
[ARM] Promote small global constants to constant pools
If a constant is unamed_addr and is only used within one function, we can save on the code size and runtime cost of an indirection by changing the global's storage to inside the constant pool. For example, instead of: ldr r0, .CPI0 bl printf bx lr .CPI0: &format_string format_string: .asciz "hello, world!\n" We can emit: adr r0, .CPI0 bl printf bx lr .CPI0: .asciz "hello, world!\n" This can cause significant code size savings when many small strings are used in one function (4 bytes per string). This recommit contains fixes for a nasty bug related to fast-isel fallback - because fast-isel doesn't know about this optimization, if it runs and emits references to a string that we inline (because fast-isel fell back to SDAG) we will end up with an inlined string and also an out-of-line string, and we won't emit the out-of-line string, causing backend failures. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281604 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGen/ARM/constantpool-promote.ll')
-rw-r--r--test/CodeGen/ARM/constantpool-promote.ll109
1 files changed, 109 insertions, 0 deletions
diff --git a/test/CodeGen/ARM/constantpool-promote.ll b/test/CodeGen/ARM/constantpool-promote.ll
new file mode 100644
index 00000000000..7c81ce854f2
--- /dev/null
+++ b/test/CodeGen/ARM/constantpool-promote.ll
@@ -0,0 +1,109 @@
+; RUN: llc -relocation-model=static < %s | FileCheck %s
+; RUN: llc -relocation-model=pic < %s | FileCheck %s
+; RUN: llc -relocation-model=ropi < %s | FileCheck %s
+; RUN: llc -relocation-model=rwpi < %s | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7--linux-gnueabihf"
+
+@.str = private unnamed_addr constant [2 x i8] c"s\00", align 1
+@.str1 = private unnamed_addr constant [69 x i8] c"this string is far too long to fit in a literal pool by far and away\00", align 1
+@.str2 = private unnamed_addr constant [27 x i8] c"this string is just right!\00", align 1
+@.str3 = private unnamed_addr constant [26 x i8] c"this string is used twice\00", align 1
+@.str4 = private unnamed_addr constant [29 x i8] c"same string in two functions\00", align 1
+@.arr1 = private unnamed_addr constant [2 x i16] [i16 3, i16 4], align 2
+@.arr2 = private unnamed_addr constant [2 x i16] [i16 7, i16 8], align 2
+@.ptr = private unnamed_addr constant [2 x i16*] [i16* getelementptr inbounds ([2 x i16], [2 x i16]* @.arr2, i32 0, i32 0), i16* null], align 2
+
+; CHECK-LABEL: @test1
+; CHECK: adr r0, [[x:.*]]
+; CHECK: [[x]]:
+; CHECK: .asciz "s\000\000"
+define void @test1() #0 {
+ tail call void @a(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0)) #2
+ ret void
+}
+
+declare void @a(i8*) #1
+
+; CHECK-LABEL: @test2
+; CHECK-NOT: .asci
+; CHECK: .fnend
+define void @test2() #0 {
+ tail call void @a(i8* getelementptr inbounds ([69 x i8], [69 x i8]* @.str1, i32 0, i32 0)) #2
+ ret void
+}
+
+; CHECK-LABEL: @test3
+; CHECK: adr r0, [[x:.*]]
+; CHECK: [[x]]:
+; CHECK: .asciz "this string is just right!\000"
+define void @test3() #0 {
+ tail call void @a(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str2, i32 0, i32 0)) #2
+ ret void
+}
+
+
+; CHECK-LABEL: @test4
+; CHECK: adr r{{.*}}, [[x:.*]]
+; CHECK: [[x]]:
+; CHECK: .asciz "this string is used twice\000\000"
+define void @test4() #0 {
+ tail call void @a(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str3, i32 0, i32 0)) #2
+ tail call void @a(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str3, i32 0, i32 0)) #2
+ ret void
+}
+
+; CHECK-LABEL: @test5a
+; CHECK-NOT: adr
+define void @test5a() #0 {
+ tail call void @a(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str4, i32 0, i32 0)) #2
+ ret void
+}
+
+define void @test5b() #0 {
+ tail call void @b(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str4, i32 0, i32 0)) #2
+ ret void
+}
+
+; CHECK-LABEL: @test6a
+; CHECK: adr r0, [[x:.*]]
+; CHECK: [[x]]:
+; CHECK: .short 3
+; CHECK: .short 4
+define void @test6a() #0 {
+ tail call void @c(i16* getelementptr inbounds ([2 x i16], [2 x i16]* @.arr1, i32 0, i32 0)) #2
+ ret void
+}
+
+; CHECK-LABEL: @test6b
+; CHECK: adr r0, [[x:.*]]
+; CHECK: [[x]]:
+; CHECK: .short 3
+; CHECK: .short 4
+define void @test6b() #0 {
+ tail call void @c(i16* getelementptr inbounds ([2 x i16], [2 x i16]* @.arr1, i32 0, i32 0)) #2
+ ret void
+}
+
+; This shouldn't be promoted, as the string is used by another global.
+; CHECK-LABEL: @test7
+; CHECK-NOT: adr
+define void @test7() #0 {
+ tail call void @c(i16* getelementptr inbounds ([2 x i16], [2 x i16]* @.arr2, i32 0, i32 0)) #2
+ ret void
+}
+
+declare void @b(i8*) #1
+declare void @c(i16*) #1
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)"}