1 ; RUN: opt -instcombine -S < %s | FileCheck %s 2 3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 4 target 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 has a merged 9 ; debug location. 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]], !dbg [[binopMergedLoc:![0-9]+]] 28 ; CHECK: ret i32 29 30 define i32 @binop(i32 %a, i32 %b) !dbg !6 { 31 entry: 32 %tobool = icmp ne i32 %a, 0, !dbg !8 33 br i1 %tobool, label %if.then, label %if.else, !dbg !8 34 35 if.then: ; preds = %entry 36 %call = call i32 @foo(), !dbg !9 37 %sub = sub nsw i32 %b, %call, !dbg !10 38 br label %if.end, !dbg !11 39 40 if.else: ; preds = %entry 41 %call1 = call i32 @bar(), !dbg !12 42 %sub2 = sub nsw i32 %b, %call1, !dbg !13 43 br label %if.end 44 45 if.end: ; preds = %if.else, %if.then 46 %b.addr.0 = phi i32 [ %sub, %if.then ], [ %sub2, %if.else ] 47 ret i32 %b.addr.0, !dbg !14 48 } 49 50 ; Test folding of a compare. Generated from source (with editing to 51 ; common the zext): 52 53 ; extern int foo(void); 54 ; extern int bar(void); 55 ; 56 ; int cmp(int a, int b) { 57 ; int r; 58 ; if(a) 59 ; r = foo() < b; 60 ; else 61 ; r = bar() < b; 62 ; return r; 63 ; } 64 65 ; CHECK: define i32 @cmp 66 ; CHECK-LABEL: if.end: 67 ; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ] 68 ; CHECK: icmp slt i32 %[[PHI]], %b, !dbg [[cmpMergedLoc:![0-9]+]] 69 ; CHECK: ret i32 70 71 define i32 @cmp(i32 %a, i32 %b) !dbg !15 { 72 entry: 73 %tobool = icmp ne i32 %a, 0, !dbg !16 74 br i1 %tobool, label %if.then, label %if.else, !dbg !16 75 76 if.then: ; preds = %entry 77 %call = call i32 @foo(), !dbg !17 78 %cmp = icmp slt i32 %call, %b, !dbg !18 79 br label %if.end, !dbg !19 80 81 if.else: ; preds = %entry 82 %call1 = call i32 @bar(), !dbg !20 83 %cmp2 = icmp slt i32 %call1, %b, !dbg !21 84 br label %if.end 85 86 if.end: ; preds = %if.else, %if.then 87 %r.0 = phi i1 [ %cmp, %if.then ], [ %cmp2, %if.else ] 88 %conv = zext i1 %r.0 to i32 89 ret i32 %conv, !dbg !22 90 } 91 92 ; Test folding of getelementptr. Generated from source: 93 94 ; extern long long foo2(void); 95 ; extern long long bar2(void); 96 ; 97 ; int *gep(int a, int *b) { 98 ; int *r; 99 ; if(a) 100 ; r = &b[foo2()]; 101 ; else 102 ; r = &b[bar2()]; 103 ; return p; 104 ; } 105 106 ; CHECK: define i32* @gep 107 ; CHECK-LABEL: if.end: 108 ; CHECK: %[[PHI:.*]] = phi i64 [ %call, %if.then ], [ %call1, %if.else ] 109 ; CHECK: getelementptr inbounds i32, i32* %b, i64 %[[PHI]], !dbg [[gepMergedLoc:![0-9]+]] 110 ; CHECK: ret i32* 111 112 define i32* @gep(i32 %a, i32* %b) !dbg !23 { 113 entry: 114 %tobool = icmp ne i32 %a, 0, !dbg !24 115 br i1 %tobool, label %if.then, label %if.else, !dbg !24 116 117 if.then: ; preds = %entry 118 %call = call i64 @foo2(), !dbg !25 119 %arrayidx = getelementptr inbounds i32, i32* %b, i64 %call, !dbg !26 120 br label %if.end, !dbg !27 121 122 if.else: ; preds = %entry 123 %call1 = call i64 @bar2(), !dbg !28 124 %arrayidx2 = getelementptr inbounds i32, i32* %b, i64 %call1, !dbg !29 125 br label %if.end 126 127 if.end: ; preds = %if.else, %if.then 128 %r.0 = phi i32* [ %arrayidx, %if.then ], [ %arrayidx2, %if.else ] 129 ret i32* %r.0, !dbg !30 130 } 131 132 ; Test folding of load. Generated from source: 133 134 ; extern int *foo3(void); 135 ; extern int *bar3(void); 136 ; 137 ; int load(int a) { 138 ; int r; 139 ; if(a) 140 ; r = *foo3(); 141 ; else 142 ; r = *bar3(); 143 ; return r; 144 ; } 145 146 ; CHECK: define i32 @load 147 ; CHECK-LABEL: if.end: 148 ; CHECK: %[[PHI:.*]] = phi i32* [ %call, %if.then ], [ %call1, %if.else ] 149 ; CHECK: load i32, i32* %[[PHI]],{{.*}} !dbg [[loadMergedLoc:![0-9]+]] 150 ; CHECK: ret i32 151 152 define i32 @load(i32 %a) !dbg !31 { 153 entry: 154 %tobool = icmp ne i32 %a, 0, !dbg !32 155 br i1 %tobool, label %if.then, label %if.else, !dbg !32 156 157 if.then: ; preds = %entry 158 %call = call i32* @foo3(), !dbg !33 159 %0 = load i32, i32* %call, align 4, !dbg !34 160 br label %if.end, !dbg !35 161 162 if.else: ; preds = %entry 163 %call1 = call i32* @bar3(), !dbg !36 164 %1 = load i32, i32* %call1, align 4, !dbg !37 165 br label %if.end 166 167 if.end: ; preds = %if.else, %if.then 168 %r.0 = phi i32 [ %0, %if.then ], [ %1, %if.else ] 169 ret i32 %r.0, !dbg !38 170 } 171 172 ; Test folding of a cast. Generated from source: 173 174 ; extern int foo(void); 175 ; extern int bar(void); 176 ; 177 ; long long cast(int a) { 178 ; long long r; 179 ; if(a) 180 ; r = foo(); 181 ; else 182 ; r = bar(); 183 ; return r; 184 ; } 185 186 ; CHECK: define i64 @cast 187 ; CHECK-LABEL: if.end: 188 ; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ] 189 ; CHECK: sext i32 %[[PHI]] to i64, !dbg [[castMergedLoc:![0-9]+]] 190 ; CHECK: ret i64 191 192 define i64 @cast(i32 %a) !dbg !39 { 193 entry: 194 %tobool = icmp ne i32 %a, 0, !dbg !40 195 br i1 %tobool, label %if.then, label %if.else, !dbg !40 196 197 if.then: ; preds = %entry 198 %call = call i32 @foo(), !dbg !41 199 %conv = sext i32 %call to i64, !dbg !41 200 br label %if.end, !dbg !42 201 202 if.else: ; preds = %entry 203 %call1 = call i32 @bar(), !dbg !43 204 %conv2 = sext i32 %call1 to i64, !dbg !43 205 br label %if.end 206 207 if.end: ; preds = %if.else, %if.then 208 %r.0 = phi i64 [ %conv, %if.then ], [ %conv2, %if.else ] 209 ret i64 %r.0, !dbg !44 210 } 211 212 ; Test folding of a binary op with a RHS constant. Generated from source: 213 214 ; extern int foo(void); 215 ; extern int bar(void); 216 ; 217 ; int binop_const(int a) { 218 ; int r; 219 ; if(a) 220 ; r = foo() - 5; 221 ; else 222 ; r = bar() - 5; 223 ; return r; 224 ; } 225 226 ; CHECK: define i32 @binop_const 227 ; CHECK-LABEL: if.end: 228 ; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ] 229 ; CHECK: add nsw i32 %[[PHI]], -5, !dbg [[binopConstMergedLoc:![0-9]+]] 230 ; CHECK: ret i32 231 232 define i32 @binop_const(i32 %a) !dbg !45 { 233 entry: 234 %tobool = icmp ne i32 %a, 0, !dbg !46 235 br i1 %tobool, label %if.then, label %if.else, !dbg !46 236 237 if.then: ; preds = %entry 238 %call = call i32 @foo(), !dbg !47 239 %sub = sub nsw i32 %call, 5, !dbg !48 240 br label %if.end, !dbg !49 241 242 if.else: ; preds = %entry 243 %call1 = call i32 @bar(), !dbg !50 244 %sub2 = sub nsw i32 %call1, 5, !dbg !51 245 br label %if.end 246 247 if.end: ; preds = %if.else, %if.then 248 %r.0 = phi i32 [ %sub, %if.then ], [ %sub2, %if.else ] 249 ret i32 %r.0, !dbg !52 250 } 251 252 ; Test folding of a compare with RHS constant. Generated from source (with 253 ; editing to common the zext): 254 255 ; extern int foo(void); 256 ; extern int bar(void); 257 ; 258 ; int cmp_const(int a) { 259 ; int r; 260 ; if(a) 261 ; r = foo() < 10; 262 ; else 263 ; r = bar() < 10; 264 ; return r; 265 ; } 266 267 ; CHECK: define i32 @cmp_const 268 ; CHECK-LABEL: if.end: 269 ; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ] 270 ; CHECK: icmp slt i32 %[[PHI]], 10, !dbg [[cmpConstMergedLoc:![0-9]+]] 271 ; CHECK: ret i32 272 273 define i32 @cmp_const(i32 %a) !dbg !53 { 274 entry: 275 %tobool = icmp ne i32 %a, 0, !dbg !54 276 br i1 %tobool, label %if.then, label %if.else, !dbg !54 277 278 if.then: ; preds = %entry 279 %call = call i32 @foo(), !dbg !55 280 %cmp = icmp slt i32 %call, 10, !dbg !56 281 br label %if.end, !dbg !57 282 283 if.else: ; preds = %entry 284 %call1 = call i32 @bar(), !dbg !58 285 %cmp2 = icmp slt i32 %call1, 10, !dbg !59 286 br label %if.end 287 288 if.end: ; preds = %if.else, %if.then 289 %r.0 = phi i1 [ %cmp, %if.then ], [ %cmp2, %if.else ] 290 %conv = zext i1 %r.0 to i32 291 ret i32 %conv, !dbg !60 292 } 293 294 declare i32 @foo() 295 declare i32 @bar() 296 declare i64 @foo2() 297 declare i64 @bar2() 298 declare i32* @foo3() 299 declare i32* @bar3() 300 301 ; CHECK: [[binopMergedLoc]] = !DILocation(line: 0 302 ; CHECK: [[cmpMergedLoc]] = !DILocation(line: 0 303 ; CHECK: [[gepMergedLoc]] = !DILocation(line: 0 304 ; CHECK: [[loadMergedLoc]] = !DILocation(line: 0 305 ; CHECK: [[castMergedLoc]] = !DILocation(line: 0 306 ; CHECK: [[binopConstMergedLoc]] = !DILocation(line: 0 307 ; CHECK: [[cmpConstMergedLoc]] = !DILocation(line: 0 308 309 !llvm.dbg.cu = !{!0} 310 !llvm.module.flags = !{!3, !4} 311 312 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2) 313 !1 = !DIFile(filename: "test.c", directory: "") 314 !2 = !{} 315 !3 = !{i32 2, !"Dwarf Version", i32 4} 316 !4 = !{i32 2, !"Debug Info Version", i32 3} 317 !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, retainedNodes: !2) 318 !7 = !DISubroutineType(types: !2) 319 !8 = !DILocation(line: 9, column: 6, scope: !6) 320 !9 = !DILocation(line: 10, column: 10, scope: !6) 321 !10 = !DILocation(line: 10, column: 7, scope: !6) 322 !11 = !DILocation(line: 10, column: 5, scope: !6) 323 !12 = !DILocation(line: 12, column: 10, scope: !6) 324 !13 = !DILocation(line: 12, column: 7, scope: !6) 325 !14 = !DILocation(line: 13, column: 3, scope: !6) 326 !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, retainedNodes: !2) 327 !16 = !DILocation(line: 18, column: 6, scope: !15) 328 !17 = !DILocation(line: 19, column: 9, scope: !15) 329 !18 = !DILocation(line: 19, column: 15, scope: !15) 330 !19 = !DILocation(line: 19, column: 5, scope: !15) 331 !20 = !DILocation(line: 21, column: 9, scope: !15) 332 !21 = !DILocation(line: 21, column: 15, scope: !15) 333 !22 = !DILocation(line: 22, column: 3, scope: !15) 334 !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, retainedNodes: !2) 335 !24 = !DILocation(line: 27, column: 6, scope: !23) 336 !25 = !DILocation(line: 28, column: 12, scope: !23) 337 !26 = !DILocation(line: 28, column: 10, scope: !23) 338 !27 = !DILocation(line: 28, column: 5, scope: !23) 339 !28 = !DILocation(line: 30, column: 12, scope: !23) 340 !29 = !DILocation(line: 30, column: 10, scope: !23) 341 !30 = !DILocation(line: 31, column: 3, scope: !23) 342 !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, retainedNodes: !2) 343 !32 = !DILocation(line: 36, column: 6, scope: !31) 344 !33 = !DILocation(line: 37, column: 10, scope: !31) 345 !34 = !DILocation(line: 37, column: 9, scope: !31) 346 !35 = !DILocation(line: 37, column: 5, scope: !31) 347 !36 = !DILocation(line: 39, column: 10, scope: !31) 348 !37 = !DILocation(line: 39, column: 9, scope: !31) 349 !38 = !DILocation(line: 40, column: 3, scope: !31) 350 !39 = distinct !DISubprogram(name: "cast", scope: !1, file: !1, line: 43, type: !7, isLocal: false, isDefinition: true, scopeLine: 43, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) 351 !40 = !DILocation(line: 45, column: 6, scope: !39) 352 !41 = !DILocation(line: 46, column: 9, scope: !39) 353 !42 = !DILocation(line: 46, column: 5, scope: !39) 354 !43 = !DILocation(line: 48, column: 9, scope: !39) 355 !44 = !DILocation(line: 49, column: 3, scope: !39) 356 !45 = distinct !DISubprogram(name: "binop_const", scope: !1, file: !1, line: 52, type: !7, isLocal: false, isDefinition: true, scopeLine: 52, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) 357 !46 = !DILocation(line: 54, column: 6, scope: !45) 358 !47 = !DILocation(line: 55, column: 9, scope: !45) 359 !48 = !DILocation(line: 55, column: 15, scope: !45) 360 !49 = !DILocation(line: 55, column: 5, scope: !45) 361 !50 = !DILocation(line: 57, column: 9, scope: !45) 362 !51 = !DILocation(line: 57, column: 15, scope: !45) 363 !52 = !DILocation(line: 58, column: 3, scope: !45) 364 !53 = distinct !DISubprogram(name: "cmp_const", scope: !1, file: !1, line: 61, type: !7, isLocal: false, isDefinition: true, scopeLine: 61, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) 365 !54 = !DILocation(line: 63, column: 6, scope: !53) 366 !55 = !DILocation(line: 64, column: 9, scope: !53) 367 !56 = !DILocation(line: 64, column: 15, scope: !53) 368 !57 = !DILocation(line: 64, column: 5, scope: !53) 369 !58 = !DILocation(line: 66, column: 9, scope: !53) 370 !59 = !DILocation(line: 66, column: 15, scope: !53) 371 !60 = !DILocation(line: 67, column: 3, scope: !53) 372