add x86 codegen tests for 'add nsw' followed by 'sext'
[oota-llvm.git] / test / CodeGen / X86 / add-nsw-sext.ll
1 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
2
3 ; The fundamental problem: an add separated from other arithmetic by a sext can't
4 ; be combined with the later instructions. However, if the first add is 'nsw', 
5 ; then we can promote the sext ahead of that add to allow optimizations.
6
7 define i64 @add_nsw_consts(i32 %i) {
8 ; CHECK-LABEL: add_nsw_consts:
9 ; CHECK:       # BB#0:
10 ; CHECK-NEXT:    addl $5, %edi
11 ; CHECK-NEXT:    movslq %edi, %rax
12 ; CHECK-NEXT:    addq $7, %rax
13 ; CHECK-NEXT:    retq
14
15   %add = add nsw i32 %i, 5
16   %ext = sext i32 %add to i64
17   %idx = add i64 %ext, 7
18   ret i64 %idx
19 }
20
21 ; An x86 bonus: If we promote the sext ahead of the 'add nsw',
22 ; we allow LEA formation and eliminate an add instruction.
23
24 define i64 @add_nsw_sext_add(i32 %i, i64 %x) {
25 ; CHECK-LABEL: add_nsw_sext_add:
26 ; CHECK:       # BB#0:
27 ; CHECK-NEXT:    addl $5, %edi
28 ; CHECK-NEXT:    movslq %edi, %rax
29 ; CHECK-NEXT:    addq %rsi, %rax
30 ; CHECK-NEXT:    retq
31
32   %add = add nsw i32 %i, 5
33   %ext = sext i32 %add to i64
34   %idx = add i64 %x, %ext
35   ret i64 %idx
36 }
37
38 ; Throw in a scale (left shift) because an LEA can do that too.
39 ; Use a negative constant (LEA displacement) to verify that's handled correctly.
40
41 define i64 @add_nsw_sext_lsh_add(i32 %i, i64 %x) {
42 ; CHECK-LABEL: add_nsw_sext_lsh_add:
43 ; CHECK:       # BB#0:
44 ; CHECK-NEXT:    addl $-5, %edi
45 ; CHECK-NEXT:    movslq %edi, %rax
46 ; CHECK-NEXT:    leaq (%rsi,%rax,8), %rax
47 ; CHECK-NEXT:    retq
48
49   %add = add nsw i32 %i, -5
50   %ext = sext i32 %add to i64
51   %shl = shl i64 %ext, 3
52   %idx = add i64 %x, %shl
53   ret i64 %idx
54 }
55
56 ; Don't promote the sext if it has no users. The wider add instruction needs an
57 ; extra byte to encode.
58
59 define i64 @add_nsw_sext(i32 %i, i64 %x) {
60 ; CHECK-LABEL: add_nsw_sext:
61 ; CHECK:       # BB#0:
62 ; CHECK-NEXT:    addl $5, %edi
63 ; CHECK-NEXT:    movslq %edi, %rax
64 ; CHECK-NEXT:    retq
65
66   %add = add nsw i32 %i, 5
67   %ext = sext i32 %add to i64
68   ret i64 %ext
69 }
70
71 ; The typical use case: a 64-bit system where an 'int' is used as an index into an array.
72
73 define i8* @gep8(i32 %i, i8* %x) {
74 ; CHECK-LABEL: gep8:
75 ; CHECK:       # BB#0:
76 ; CHECK-NEXT:    addl $5, %edi
77 ; CHECK-NEXT:    movslq %edi, %rax
78 ; CHECK-NEXT:    addq %rsi, %rax
79 ; CHECK-NEXT:    retq
80
81   %add = add nsw i32 %i, 5
82   %ext = sext i32 %add to i64
83   %idx = getelementptr i8, i8* %x, i64 %ext
84   ret i8* %idx
85 }
86
87 define i16* @gep16(i32 %i, i16* %x) {
88 ; CHECK-LABEL: gep16:
89 ; CHECK:       # BB#0:
90 ; CHECK-NEXT:    addl $-5, %edi
91 ; CHECK-NEXT:    movslq %edi, %rax
92 ; CHECK-NEXT:    leaq (%rsi,%rax,2), %rax
93 ; CHECK-NEXT:    retq
94
95   %add = add nsw i32 %i, -5
96   %ext = sext i32 %add to i64
97   %idx = getelementptr i16, i16* %x, i64 %ext
98   ret i16* %idx
99 }
100
101 define i32* @gep32(i32 %i, i32* %x) {
102 ; CHECK-LABEL: gep32:
103 ; CHECK:       # BB#0:
104 ; CHECK-NEXT:    addl $5, %edi
105 ; CHECK-NEXT:    movslq %edi, %rax
106 ; CHECK-NEXT:    leaq (%rsi,%rax,4), %rax
107 ; CHECK-NEXT:    retq
108
109   %add = add nsw i32 %i, 5
110   %ext = sext i32 %add to i64
111   %idx = getelementptr i32, i32* %x, i64 %ext
112   ret i32* %idx
113 }
114
115 define i64* @gep64(i32 %i, i64* %x) {
116 ; CHECK-LABEL: gep64:
117 ; CHECK:       # BB#0:
118 ; CHECK-NEXT:    addl $-5, %edi
119 ; CHECK-NEXT:    movslq %edi, %rax
120 ; CHECK-NEXT:    leaq (%rsi,%rax,8), %rax
121 ; CHECK-NEXT:    retq
122
123   %add = add nsw i32 %i, -5
124   %ext = sext i32 %add to i64
125   %idx = getelementptr i64, i64* %x, i64 %ext
126   ret i64* %idx
127 }
128
129 ; LEA can't scale by 16, but the adds can still be combined into an LEA.
130
131 define i128* @gep128(i32 %i, i128* %x) {
132 ; CHECK-LABEL: gep128:
133 ; CHECK:       # BB#0:
134 ; CHECK-NEXT:    addl $5, %edi
135 ; CHECK-NEXT:    movslq %edi, %rax
136 ; CHECK-NEXT:    shlq $4, %rax
137 ; CHECK-NEXT:    addq %rsi, %rax
138 ; CHECK-NEXT:    retq
139
140   %add = add nsw i32 %i, 5
141   %ext = sext i32 %add to i64
142   %idx = getelementptr i128, i128* %x, i64 %ext
143   ret i128* %idx
144 }
145
146 ; A bigger win can be achieved when there is more than one use of the
147 ; sign extended value. In this case, we can eliminate sign extension
148 ; instructions plus use more efficient addressing modes for memory ops.
149
150 define void @PR20134(i32* %a, i32 %i) {
151 ; CHECK-LABEL: PR20134:
152 ; CHECK:       # BB#0:
153 ; CHECK-NEXT:    leal 1(%rsi), %eax
154 ; CHECK-NEXT:    cltq
155 ; CHECK-NEXT:    movl (%rdi,%rax,4), %eax
156 ; CHECK-NEXT:    leal 2(%rsi), %ecx
157 ; CHECK-NEXT:    movslq %ecx, %rcx
158 ; CHECK-NEXT:    addl (%rdi,%rcx,4), %eax
159 ; CHECK-NEXT:    movslq %esi, %rcx
160 ; CHECK-NEXT:    movl %eax, (%rdi,%rcx,4)
161 ; CHECK-NEXT:    retq
162
163   %add1 = add nsw i32 %i, 1
164   %idx1 = sext i32 %add1 to i64
165   %gep1 = getelementptr i32, i32* %a, i64 %idx1
166   %load1 = load i32, i32* %gep1, align 4
167
168   %add2 = add nsw i32 %i, 2
169   %idx2 = sext i32 %add2 to i64
170   %gep2 = getelementptr i32, i32* %a, i64 %idx2
171   %load2 = load i32, i32* %gep2, align 4
172
173   %add3 = add i32 %load1, %load2
174   %idx3 = sext i32 %i to i64
175   %gep3 = getelementptr i32, i32* %a, i64 %idx3
176   store i32 %add3, i32* %gep3, align 4
177   ret void
178 }
179