blob: f72a33347b4cdf9533888f498f8f225e3308b013 [file] [log] [blame]
Robert Lougher2428a402016-12-14 17:49:19 +00001; RUN: opt -instcombine -S < %s | FileCheck %s
2
3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4target triple = "x86_64-unknown-linux-gnu"
5
6; If all the operands to a phi node are of the same operation, instcombine
7; will try to pull them through the phi node, combining them into a single
8; operation. Check that when it does this the combined operation does not
9; have a debug location set.
10
11; Test folding of a binary operation. Generated from source:
12
13; extern int foo(void);
14; extern int bar(void);
15;
16; int binop(int a, int b) {
17; if(a)
18; b -= foo();
19; else
20; b -= bar();
21; return b;
22; }
23
24; CHECK: define i32 @binop
25; CHECK-LABEL: if.end:
26; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ]
27; CHECK: sub nsw i32 %b, %[[PHI]]
28; CHECK-NOT: !dbg
29; CHECK: ret i32
30
31define i32 @binop(i32 %a, i32 %b) !dbg !6 {
32entry:
33 %tobool = icmp ne i32 %a, 0, !dbg !8
34 br i1 %tobool, label %if.then, label %if.else, !dbg !8
35
36if.then: ; preds = %entry
37 %call = call i32 @foo(), !dbg !9
38 %sub = sub nsw i32 %b, %call, !dbg !10
39 br label %if.end, !dbg !11
40
41if.else: ; preds = %entry
42 %call1 = call i32 @bar(), !dbg !12
43 %sub2 = sub nsw i32 %b, %call1, !dbg !13
44 br label %if.end
45
46if.end: ; preds = %if.else, %if.then
47 %b.addr.0 = phi i32 [ %sub, %if.then ], [ %sub2, %if.else ]
48 ret i32 %b.addr.0, !dbg !14
49}
50
Robert Lougher4b0790d2016-12-14 18:14:57 +000051; Test folding of a compare. Generated from source (with editing to
52; common the zext):
53
54; extern int foo(void);
55; extern int bar(void);
56;
57; int cmp(int a, int b) {
58; int r;
59; if(a)
60; r = foo() < b;
61; else
62; r = bar() < b;
63; return r;
64; }
65
66; CHECK: define i32 @cmp
67; CHECK-LABEL: if.end:
68; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ]
69; CHECK: icmp slt i32 %[[PHI]], %b
70; CHECK-NOT: !dbg
71; CHECK: ret i32
72
73define i32 @cmp(i32 %a, i32 %b) !dbg !15 {
74entry:
75 %tobool = icmp ne i32 %a, 0, !dbg !16
76 br i1 %tobool, label %if.then, label %if.else, !dbg !16
77
78if.then: ; preds = %entry
79 %call = call i32 @foo(), !dbg !17
80 %cmp = icmp slt i32 %call, %b, !dbg !18
81 br label %if.end, !dbg !19
82
83if.else: ; preds = %entry
84 %call1 = call i32 @bar(), !dbg !20
85 %cmp2 = icmp slt i32 %call1, %b, !dbg !21
86 br label %if.end
87
88if.end: ; preds = %if.else, %if.then
89 %r.0 = phi i1 [ %cmp, %if.then ], [ %cmp2, %if.else ]
90 %conv = zext i1 %r.0 to i32
91 ret i32 %conv, !dbg !22
92}
93
Robert Lougher8fc1e892016-12-14 18:37:50 +000094; Test folding of getelementptr. Generated from source:
95
96; extern long long foo2(void);
97; extern long long bar2(void);
98;
99; int *gep(int a, int *b) {
100; int *r;
101; if(a)
102; r = &b[foo2()];
103; else
104; r = &b[bar2()];
105; return p;
106; }
107
108; CHECK: define i32* @gep
109; CHECK-LABEL: if.end:
110; CHECK: %[[PHI:.*]] = phi i64 [ %call, %if.then ], [ %call1, %if.else ]
111; CHECK: getelementptr inbounds i32, i32* %b, i64 %[[PHI]]
112; CHECK-NOT: !dbg
113; CHECK: ret i32*
114
115define i32* @gep(i32 %a, i32* %b) !dbg !23 {
116entry:
117 %tobool = icmp ne i32 %a, 0, !dbg !24
118 br i1 %tobool, label %if.then, label %if.else, !dbg !24
119
120if.then: ; preds = %entry
121 %call = call i64 @foo2(), !dbg !25
122 %arrayidx = getelementptr inbounds i32, i32* %b, i64 %call, !dbg !26
123 br label %if.end, !dbg !27
124
125if.else: ; preds = %entry
126 %call1 = call i64 @bar2(), !dbg !28
127 %arrayidx2 = getelementptr inbounds i32, i32* %b, i64 %call1, !dbg !29
128 br label %if.end
129
130if.end: ; preds = %if.else, %if.then
131 %r.0 = phi i32* [ %arrayidx, %if.then ], [ %arrayidx2, %if.else ]
132 ret i32* %r.0, !dbg !30
133}
134
Robert Lougher373e36a2016-12-14 19:02:14 +0000135; Test folding of load. Generated from source:
136
137; extern int *foo3(void);
138; extern int *bar3(void);
139;
140; int load(int a) {
141; int r;
142; if(a)
143; r = *foo3();
144; else
145; r = *bar3();
146; return r;
147; }
148
149; CHECK: define i32 @load
150; CHECK-LABEL: if.end:
151; CHECK: %[[PHI:.*]] = phi i32* [ %call, %if.then ], [ %call1, %if.else ]
152; CHECK: load i32, i32* %[[PHI]]
153; CHECK-NOT: !dbg
154; CHECK: ret i32
155
156define i32 @load(i32 %a) !dbg !31 {
157entry:
158 %tobool = icmp ne i32 %a, 0, !dbg !32
159 br i1 %tobool, label %if.then, label %if.else, !dbg !32
160
161if.then: ; preds = %entry
162 %call = call i32* @foo3(), !dbg !33
163 %0 = load i32, i32* %call, align 4, !dbg !34
164 br label %if.end, !dbg !35
165
166if.else: ; preds = %entry
167 %call1 = call i32* @bar3(), !dbg !36
168 %1 = load i32, i32* %call1, align 4, !dbg !37
169 br label %if.end
170
171if.end: ; preds = %if.else, %if.then
172 %r.0 = phi i32 [ %0, %if.then ], [ %1, %if.else ]
173 ret i32 %r.0, !dbg !38
174}
175
Robert Lougher2428a402016-12-14 17:49:19 +0000176declare i32 @foo()
177declare i32 @bar()
Robert Lougher8fc1e892016-12-14 18:37:50 +0000178declare i64 @foo2()
179declare i64 @bar2()
Robert Lougher373e36a2016-12-14 19:02:14 +0000180declare i32* @foo3()
181declare i32* @bar3()
Robert Lougher2428a402016-12-14 17:49:19 +0000182
183!llvm.dbg.cu = !{!0}
184!llvm.module.flags = !{!3, !4}
185
186!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
187!1 = !DIFile(filename: "test.c", directory: "")
188!2 = !{}
189!3 = !{i32 2, !"Dwarf Version", i32 4}
190!4 = !{i32 2, !"Debug Info Version", i32 3}
191!6 = distinct !DISubprogram(name: "binop", scope: !1, file: !1, line: 8, type: !7, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
192!7 = !DISubroutineType(types: !2)
193!8 = !DILocation(line: 9, column: 6, scope: !6)
194!9 = !DILocation(line: 10, column: 10, scope: !6)
195!10 = !DILocation(line: 10, column: 7, scope: !6)
196!11 = !DILocation(line: 10, column: 5, scope: !6)
197!12 = !DILocation(line: 12, column: 10, scope: !6)
198!13 = !DILocation(line: 12, column: 7, scope: !6)
199!14 = !DILocation(line: 13, column: 3, scope: !6)
Robert Lougher4b0790d2016-12-14 18:14:57 +0000200!15 = distinct !DISubprogram(name: "cmp", scope: !1, file: !1, line: 16, type: !7, isLocal: false, isDefinition: true, scopeLine: 16, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
201!16 = !DILocation(line: 18, column: 6, scope: !15)
202!17 = !DILocation(line: 19, column: 9, scope: !15)
203!18 = !DILocation(line: 19, column: 15, scope: !15)
204!19 = !DILocation(line: 19, column: 5, scope: !15)
205!20 = !DILocation(line: 21, column: 9, scope: !15)
206!21 = !DILocation(line: 21, column: 15, scope: !15)
207!22 = !DILocation(line: 22, column: 3, scope: !15)
Robert Lougher8fc1e892016-12-14 18:37:50 +0000208!23 = distinct !DISubprogram(name: "gep", scope: !1, file: !1, line: 25, type: !7, isLocal: false, isDefinition: true, scopeLine: 25, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
209!24 = !DILocation(line: 27, column: 6, scope: !23)
210!25 = !DILocation(line: 28, column: 12, scope: !23)
211!26 = !DILocation(line: 28, column: 10, scope: !23)
212!27 = !DILocation(line: 28, column: 5, scope: !23)
213!28 = !DILocation(line: 30, column: 12, scope: !23)
214!29 = !DILocation(line: 30, column: 10, scope: !23)
215!30 = !DILocation(line: 31, column: 3, scope: !23)
Robert Lougher373e36a2016-12-14 19:02:14 +0000216!31 = distinct !DISubprogram(name: "load", scope: !1, file: !1, line: 34, type: !7, isLocal: false, isDefinition: true, scopeLine: 34, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
217!32 = !DILocation(line: 36, column: 6, scope: !31)
218!33 = !DILocation(line: 37, column: 10, scope: !31)
219!34 = !DILocation(line: 37, column: 9, scope: !31)
220!35 = !DILocation(line: 37, column: 5, scope: !31)
221!36 = !DILocation(line: 39, column: 10, scope: !31)
222!37 = !DILocation(line: 39, column: 9, scope: !31)
223!38 = !DILocation(line: 40, column: 3, scope: !31)