Home | History | Annotate | Download | only in Generic
      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