1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=i386-unknown-linux-gnu | FileCheck %s --check-prefix=X86
3; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=X64
4
5@a = common dso_local global i32 0, align 4
6@b = common dso_local global i32 0, align 4
7@c = common dso_local global i32 0, align 4
8@e = common dso_local global i32 0, align 4
9@x = common dso_local global i32 0, align 4
10@f = common dso_local global i32 0, align 4
11@h = common dso_local global i32 0, align 4
12@i = common dso_local global i32 0, align 4
13
14; Test -Os to make sure immediates with multiple users don't get pulled in to
15; instructions (8-bit immediates are exceptions).
16
17define dso_local i32 @foo() optsize {
18; X86-LABEL: foo:
19; X86:       # %bb.0: # %entry
20; X86-NEXT:    movl $1234, %eax # imm = 0x4D2
21; X86-NEXT:    movl %eax, a
22; X86-NEXT:    movl %eax, b
23; X86-NEXT:    movl $12, c
24; X86-NEXT:    cmpl $12, e
25; X86-NEXT:    jne .LBB0_2
26; X86-NEXT:  # %bb.1: # %if.then
27; X86-NEXT:    movl $1, x
28; X86-NEXT:  .LBB0_2: # %if.end
29; X86-NEXT:    movl $1234, f # imm = 0x4D2
30; X86-NEXT:    movl $555, %eax # imm = 0x22B
31; X86-NEXT:    movl %eax, h
32; X86-NEXT:    addl %eax, i
33; X86-NEXT:    xorl %eax, %eax
34; X86-NEXT:    retl
35;
36; X64-LABEL: foo:
37; X64:       # %bb.0: # %entry
38; X64-NEXT:    movl $1234, %eax # imm = 0x4D2
39; X64-NEXT:    movl %eax, a(%rip)
40; X64-NEXT:    movl %eax, b(%rip)
41; X64-NEXT:    movl $12, c(%rip)
42; X64-NEXT:    cmpl $12, e(%rip)
43; X64-NEXT:    jne .LBB0_2
44; X64-NEXT:  # %bb.1: # %if.then
45; X64-NEXT:    movl $1, x(%rip)
46; X64-NEXT:  .LBB0_2: # %if.end
47; X64-NEXT:    movl $1234, f(%rip) # imm = 0x4D2
48; X64-NEXT:    movl $555, %eax # imm = 0x22B
49; X64-NEXT:    movl %eax, h(%rip)
50; X64-NEXT:    addl %eax, i(%rip)
51; X64-NEXT:    xorl %eax, %eax
52; X64-NEXT:    retq
53entry:
54  store i32 1234, i32* @a
55  store i32 1234, i32* @b
56  store i32 12, i32* @c
57  %0 = load i32, i32* @e
58  %cmp = icmp eq i32 %0, 12
59  br i1 %cmp, label %if.then, label %if.end
60
61if.then:                                          ; preds = %entry
62  store i32 1, i32* @x
63  br label %if.end
64
65; New block.. Make sure 1234 isn't live across basic blocks from before.
66if.end:                                           ; preds = %if.then, %entry
67  store i32 1234, i32* @f
68  store i32 555, i32* @h
69  %1 = load i32, i32* @i
70  %add1 = add nsw i32 %1, 555
71  store i32 %add1, i32* @i
72  ret i32 0
73}
74
75; Test PGSO to make sure immediates with multiple users don't get pulled in to
76; instructions (8-bit immediates are exceptions).
77
78define dso_local i32 @foo_pgso() !prof !14 {
79; X86-LABEL: foo_pgso:
80; X86:       # %bb.0: # %entry
81; X86-NEXT:    movl $1234, %eax # imm = 0x4D2
82; X86-NEXT:    movl %eax, a
83; X86-NEXT:    movl %eax, b
84; X86-NEXT:    movl $12, c
85; X86-NEXT:    cmpl $12, e
86; X86-NEXT:    jne .LBB1_2
87; X86-NEXT:  # %bb.1: # %if.then
88; X86-NEXT:    movl $1, x
89; X86-NEXT:  .LBB1_2: # %if.end
90; X86-NEXT:    movl $1234, f # imm = 0x4D2
91; X86-NEXT:    movl $555, %eax # imm = 0x22B
92; X86-NEXT:    movl %eax, h
93; X86-NEXT:    addl %eax, i
94; X86-NEXT:    xorl %eax, %eax
95; X86-NEXT:    retl
96;
97; X64-LABEL: foo_pgso:
98; X64:       # %bb.0: # %entry
99; X64-NEXT:    movl $1234, %eax # imm = 0x4D2
100; X64-NEXT:    movl %eax, a(%rip)
101; X64-NEXT:    movl %eax, b(%rip)
102; X64-NEXT:    movl $12, c(%rip)
103; X64-NEXT:    cmpl $12, e(%rip)
104; X64-NEXT:    jne .LBB1_2
105; X64-NEXT:  # %bb.1: # %if.then
106; X64-NEXT:    movl $1, x(%rip)
107; X64-NEXT:  .LBB1_2: # %if.end
108; X64-NEXT:    movl $1234, f(%rip) # imm = 0x4D2
109; X64-NEXT:    movl $555, %eax # imm = 0x22B
110; X64-NEXT:    movl %eax, h(%rip)
111; X64-NEXT:    addl %eax, i(%rip)
112; X64-NEXT:    xorl %eax, %eax
113; X64-NEXT:    retq
114entry:
115  store i32 1234, i32* @a
116  store i32 1234, i32* @b
117  store i32 12, i32* @c
118  %0 = load i32, i32* @e
119  %cmp = icmp eq i32 %0, 12
120  br i1 %cmp, label %if.then, label %if.end
121
122if.then:                                          ; preds = %entry
123  store i32 1, i32* @x
124  br label %if.end
125
126; New block.. Make sure 1234 isn't live across basic blocks from before.
127if.end:                                           ; preds = %if.then, %entry
128  store i32 1234, i32* @f
129  store i32 555, i32* @h
130  %1 = load i32, i32* @i
131  %add1 = add nsw i32 %1, 555
132  store i32 %add1, i32* @i
133  ret i32 0
134}
135
136; Test -O2 to make sure that all immediates get pulled in to their users.
137define dso_local i32 @foo2() {
138; X86-LABEL: foo2:
139; X86:       # %bb.0: # %entry
140; X86-NEXT:    movl $1234, a # imm = 0x4D2
141; X86-NEXT:    movl $1234, b # imm = 0x4D2
142; X86-NEXT:    xorl %eax, %eax
143; X86-NEXT:    retl
144;
145; X64-LABEL: foo2:
146; X64:       # %bb.0: # %entry
147; X64-NEXT:    movl $1234, a(%rip) # imm = 0x4D2
148; X64-NEXT:    movl $1234, b(%rip) # imm = 0x4D2
149; X64-NEXT:    xorl %eax, %eax
150; X64-NEXT:    retq
151entry:
152  store i32 1234, i32* @a
153  store i32 1234, i32* @b
154  ret i32 0
155}
156
157declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) #1
158
159@AA = common dso_local global [100 x i8] zeroinitializer, align 1
160
161; memset gets lowered in DAG. Constant merging should hoist all the
162; immediates used to store to the individual memory locations. Make
163; sure we don't directly store the immediates.
164define dso_local void @foomemset() optsize {
165; X86-LABEL: foomemset:
166; X86:       # %bb.0: # %entry
167; X86-NEXT:    movl $555819297, %eax # imm = 0x21212121
168; X86-NEXT:    movl %eax, AA+20
169; X86-NEXT:    movl %eax, AA+16
170; X86-NEXT:    movl %eax, AA+12
171; X86-NEXT:    movl %eax, AA+8
172; X86-NEXT:    movl %eax, AA+4
173; X86-NEXT:    movl %eax, AA
174; X86-NEXT:    retl
175;
176; X64-LABEL: foomemset:
177; X64:       # %bb.0: # %entry
178; X64-NEXT:    movabsq $2387225703656530209, %rax # imm = 0x2121212121212121
179; X64-NEXT:    movq %rax, AA+16(%rip)
180; X64-NEXT:    movq %rax, AA+8(%rip)
181; X64-NEXT:    movq %rax, AA(%rip)
182; X64-NEXT:    retq
183entry:
184  call void @llvm.memset.p0i8.i32(i8* getelementptr inbounds ([100 x i8], [100 x i8]* @AA, i32 0, i32 0), i8 33, i32 24, i1 false)
185  ret void
186}
187
188; memset gets lowered in DAG. Constant merging should hoist all the
189; immediates used to store to the individual memory locations. Make
190; sure we don't directly store the immediates.
191define dso_local void @foomemset_pgso() !prof !14 {
192; X86-LABEL: foomemset_pgso:
193; X86:       # %bb.0: # %entry
194; X86-NEXT:    movl $555819297, %eax # imm = 0x21212121
195; X86-NEXT:    movl %eax, AA+20
196; X86-NEXT:    movl %eax, AA+16
197; X86-NEXT:    movl %eax, AA+12
198; X86-NEXT:    movl %eax, AA+8
199; X86-NEXT:    movl %eax, AA+4
200; X86-NEXT:    movl %eax, AA
201; X86-NEXT:    retl
202;
203; X64-LABEL: foomemset_pgso:
204; X64:       # %bb.0: # %entry
205; X64-NEXT:    movabsq $2387225703656530209, %rax # imm = 0x2121212121212121
206; X64-NEXT:    movq %rax, AA+16(%rip)
207; X64-NEXT:    movq %rax, AA+8(%rip)
208; X64-NEXT:    movq %rax, AA(%rip)
209; X64-NEXT:    retq
210entry:
211  call void @llvm.memset.p0i8.i32(i8* getelementptr inbounds ([100 x i8], [100 x i8]* @AA, i32 0, i32 0), i8 33, i32 24, i1 false)
212  ret void
213}
214
215!llvm.module.flags = !{!0}
216!0 = !{i32 1, !"ProfileSummary", !1}
217!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
218!2 = !{!"ProfileFormat", !"InstrProf"}
219!3 = !{!"TotalCount", i64 10000}
220!4 = !{!"MaxCount", i64 10}
221!5 = !{!"MaxInternalCount", i64 1}
222!6 = !{!"MaxFunctionCount", i64 1000}
223!7 = !{!"NumCounts", i64 3}
224!8 = !{!"NumFunctions", i64 3}
225!9 = !{!"DetailedSummary", !10}
226!10 = !{!11, !12, !13}
227!11 = !{i32 10000, i64 100, i32 1}
228!12 = !{i32 999000, i64 100, i32 1}
229!13 = !{i32 999999, i64 1, i32 2}
230!14 = !{!"function_entry_count", i64 0}
231