1; 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 51; 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 94; 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 135; 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 176; Test folding of a cast. Generated from source: 177 178; extern int foo(void); 179; extern int bar(void); 180; 181; long long cast(int a) { 182; long long r; 183; if(a) 184; r = foo(); 185; else 186; r = bar(); 187; return r; 188; } 189 190; CHECK: define i64 @cast 191; CHECK-LABEL: if.end: 192; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ] 193; CHECK: sext i32 %[[PHI]] to i64 194; CHECK-NOT: !dbg 195; CHECK: ret i64 196 197define i64 @cast(i32 %a) !dbg !39 { 198entry: 199 %tobool = icmp ne i32 %a, 0, !dbg !40 200 br i1 %tobool, label %if.then, label %if.else, !dbg !40 201 202if.then: ; preds = %entry 203 %call = call i32 @foo(), !dbg !41 204 %conv = sext i32 %call to i64, !dbg !41 205 br label %if.end, !dbg !42 206 207if.else: ; preds = %entry 208 %call1 = call i32 @bar(), !dbg !43 209 %conv2 = sext i32 %call1 to i64, !dbg !43 210 br label %if.end 211 212if.end: ; preds = %if.else, %if.then 213 %r.0 = phi i64 [ %conv, %if.then ], [ %conv2, %if.else ] 214 ret i64 %r.0, !dbg !44 215} 216 217; Test folding of a binary op with a RHS constant. Generated from source: 218 219; extern int foo(void); 220; extern int bar(void); 221; 222; int binop_const(int a) { 223; int r; 224; if(a) 225; r = foo() - 5; 226; else 227; r = bar() - 5; 228; return r; 229; } 230 231; CHECK: define i32 @binop_const 232; CHECK-LABEL: if.end: 233; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ] 234; CHECK: add nsw i32 %[[PHI]], -5 235; CHECK-NOT: !dbg 236; CHECK: ret i32 237 238define i32 @binop_const(i32 %a) !dbg !45 { 239entry: 240 %tobool = icmp ne i32 %a, 0, !dbg !46 241 br i1 %tobool, label %if.then, label %if.else, !dbg !46 242 243if.then: ; preds = %entry 244 %call = call i32 @foo(), !dbg !47 245 %sub = sub nsw i32 %call, 5, !dbg !48 246 br label %if.end, !dbg !49 247 248if.else: ; preds = %entry 249 %call1 = call i32 @bar(), !dbg !50 250 %sub2 = sub nsw i32 %call1, 5, !dbg !51 251 br label %if.end 252 253if.end: ; preds = %if.else, %if.then 254 %r.0 = phi i32 [ %sub, %if.then ], [ %sub2, %if.else ] 255 ret i32 %r.0, !dbg !52 256} 257 258; Test folding of a compare with RHS constant. Generated from source (with 259; editing to common the zext): 260 261; extern int foo(void); 262; extern int bar(void); 263; 264; int cmp_const(int a) { 265; int r; 266; if(a) 267; r = foo() < 10; 268; else 269; r = bar() < 10; 270; return r; 271; } 272 273; CHECK: define i32 @cmp_const 274; CHECK-LABEL: if.end: 275; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ] 276; CHECK: icmp slt i32 %[[PHI]], 10 277; CHECK-NOT: !dbg 278; CHECK: ret i32 279 280define i32 @cmp_const(i32 %a) !dbg !53 { 281entry: 282 %tobool = icmp ne i32 %a, 0, !dbg !54 283 br i1 %tobool, label %if.then, label %if.else, !dbg !54 284 285if.then: ; preds = %entry 286 %call = call i32 @foo(), !dbg !55 287 %cmp = icmp slt i32 %call, 10, !dbg !56 288 br label %if.end, !dbg !57 289 290if.else: ; preds = %entry 291 %call1 = call i32 @bar(), !dbg !58 292 %cmp2 = icmp slt i32 %call1, 10, !dbg !59 293 br label %if.end 294 295if.end: ; preds = %if.else, %if.then 296 %r.0 = phi i1 [ %cmp, %if.then ], [ %cmp2, %if.else ] 297 %conv = zext i1 %r.0 to i32 298 ret i32 %conv, !dbg !60 299} 300 301declare i32 @foo() 302declare i32 @bar() 303declare i64 @foo2() 304declare i64 @bar2() 305declare i32* @foo3() 306declare i32* @bar3() 307 308!llvm.dbg.cu = !{!0} 309!llvm.module.flags = !{!3, !4} 310 311!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2) 312!1 = !DIFile(filename: "test.c", directory: "") 313!2 = !{} 314!3 = !{i32 2, !"Dwarf Version", i32 4} 315!4 = !{i32 2, !"Debug Info Version", i32 3} 316!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) 317!7 = !DISubroutineType(types: !2) 318!8 = !DILocation(line: 9, column: 6, scope: !6) 319!9 = !DILocation(line: 10, column: 10, scope: !6) 320!10 = !DILocation(line: 10, column: 7, scope: !6) 321!11 = !DILocation(line: 10, column: 5, scope: !6) 322!12 = !DILocation(line: 12, column: 10, scope: !6) 323!13 = !DILocation(line: 12, column: 7, scope: !6) 324!14 = !DILocation(line: 13, column: 3, scope: !6) 325!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) 326!16 = !DILocation(line: 18, column: 6, scope: !15) 327!17 = !DILocation(line: 19, column: 9, scope: !15) 328!18 = !DILocation(line: 19, column: 15, scope: !15) 329!19 = !DILocation(line: 19, column: 5, scope: !15) 330!20 = !DILocation(line: 21, column: 9, scope: !15) 331!21 = !DILocation(line: 21, column: 15, scope: !15) 332!22 = !DILocation(line: 22, column: 3, scope: !15) 333!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) 334!24 = !DILocation(line: 27, column: 6, scope: !23) 335!25 = !DILocation(line: 28, column: 12, scope: !23) 336!26 = !DILocation(line: 28, column: 10, scope: !23) 337!27 = !DILocation(line: 28, column: 5, scope: !23) 338!28 = !DILocation(line: 30, column: 12, scope: !23) 339!29 = !DILocation(line: 30, column: 10, scope: !23) 340!30 = !DILocation(line: 31, column: 3, scope: !23) 341!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) 342!32 = !DILocation(line: 36, column: 6, scope: !31) 343!33 = !DILocation(line: 37, column: 10, scope: !31) 344!34 = !DILocation(line: 37, column: 9, scope: !31) 345!35 = !DILocation(line: 37, column: 5, scope: !31) 346!36 = !DILocation(line: 39, column: 10, scope: !31) 347!37 = !DILocation(line: 39, column: 9, scope: !31) 348!38 = !DILocation(line: 40, column: 3, scope: !31) 349!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, variables: !2) 350!40 = !DILocation(line: 45, column: 6, scope: !39) 351!41 = !DILocation(line: 46, column: 9, scope: !39) 352!42 = !DILocation(line: 46, column: 5, scope: !39) 353!43 = !DILocation(line: 48, column: 9, scope: !39) 354!44 = !DILocation(line: 49, column: 3, scope: !39) 355!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, variables: !2) 356!46 = !DILocation(line: 54, column: 6, scope: !45) 357!47 = !DILocation(line: 55, column: 9, scope: !45) 358!48 = !DILocation(line: 55, column: 15, scope: !45) 359!49 = !DILocation(line: 55, column: 5, scope: !45) 360!50 = !DILocation(line: 57, column: 9, scope: !45) 361!51 = !DILocation(line: 57, column: 15, scope: !45) 362!52 = !DILocation(line: 58, column: 3, scope: !45) 363!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, variables: !2) 364!54 = !DILocation(line: 63, column: 6, scope: !53) 365!55 = !DILocation(line: 64, column: 9, scope: !53) 366!56 = !DILocation(line: 64, column: 15, scope: !53) 367!57 = !DILocation(line: 64, column: 5, scope: !53) 368!58 = !DILocation(line: 66, column: 9, scope: !53) 369!59 = !DILocation(line: 66, column: 15, scope: !53) 370!60 = !DILocation(line: 67, column: 3, scope: !53) 371