Home | History | Annotate | Download | only in InstCombine
      1 ; RUN: opt -instcombine -S < %s | FileCheck %s
      2 
      3 @gp = global i32* null, align 8
      4 
      5 declare i8* @malloc(i64) #1
      6 
      7 define i1 @compare_global_trivialeq() {
      8   %m = call i8* @malloc(i64 4)
      9   %bc = bitcast i8* %m to i32*
     10   %lgp = load i32*, i32** @gp, align 8
     11   %cmp = icmp eq i32* %bc, %lgp
     12   ret i1 %cmp
     13 ; CHECK-LABEL: compare_global_trivialeq
     14 ; CHECK: ret i1 false
     15 }
     16 
     17 define i1 @compare_global_trivialne() {
     18   %m = call i8* @malloc(i64 4)
     19   %bc = bitcast i8* %m to i32*
     20   %lgp = load i32*, i32** @gp, align 8
     21   %cmp = icmp ne i32* %bc, %lgp
     22   ret i1 %cmp
     23 ; CHECK-LABEL: compare_global_trivialne
     24 ; CHECK: ret i1 true
     25 }
     26 
     27 
     28 ; Although the %m is marked nocapture in the deopt operand in call to function f,
     29 ; we cannot remove the alloc site: call to malloc
     30 ; The comparison should fold to false irrespective of whether the call to malloc can be elided or not
     31 declare void @f()
     32 define i1 @compare_and_call_with_deopt() {
     33 ; CHECK-LABEL: compare_and_call_with_deopt
     34   %m = call i8* @malloc(i64 24)
     35   %bc = bitcast i8* %m to i32*
     36   %lgp = load i32*, i32** @gp, align 8, !nonnull !0
     37   %cmp = icmp eq i32* %lgp, %bc
     38   tail call void @f() [ "deopt"(i8* %m) ]
     39   ret i1 %cmp
     40 ; CHECK: ret i1 false
     41 }
     42 
     43 ; Same functon as above with deopt operand in function f, but comparison is NE
     44 define i1 @compare_ne_and_call_with_deopt() {
     45 ; CHECK-LABEL: compare_ne_and_call_with_deopt
     46   %m = call i8* @malloc(i64 24)
     47   %bc = bitcast i8* %m to i32*
     48   %lgp = load i32*, i32** @gp, align 8, !nonnull !0
     49   %cmp = icmp ne i32* %lgp, %bc
     50   tail call void @f() [ "deopt"(i8* %m) ]
     51   ret i1 %cmp
     52 ; CHECK: ret i1 true
     53 }
     54 
     55 ; Same function as above, but global not marked nonnull, and we cannot fold the comparison
     56 define i1 @compare_ne_global_maybe_null() {
     57 ; CHECK-LABEL: compare_ne_global_maybe_null
     58   %m = call i8* @malloc(i64 24)
     59   %bc = bitcast i8* %m to i32*
     60   %lgp = load i32*, i32** @gp
     61   %cmp = icmp ne i32* %lgp, %bc
     62   tail call void @f() [ "deopt"(i8* %m) ]
     63   ret i1 %cmp
     64 ; CHECK: ret i1 %cmp
     65 }
     66 
     67 ; FIXME: The comparison should fold to false since %m escapes (call to function escape)
     68 ; after the comparison.
     69 declare void @escape(i8*)
     70 define i1 @compare_and_call_after() {
     71 ; CHECK-LABEL: compare_and_call_after
     72   %m = call i8* @malloc(i64 24)
     73   %bc = bitcast i8* %m to i32*
     74   %lgp = load i32*, i32** @gp, align 8, !nonnull !0
     75   %cmp = icmp eq i32* %bc, %lgp
     76   br i1 %cmp, label %escape_call, label %just_return
     77 
     78 escape_call:
     79  call void @escape(i8* %m)
     80  ret i1 true
     81 
     82 just_return:
     83  ret i1 %cmp
     84 }
     85 
     86 define i1 @compare_distinct_mallocs() {
     87   %m = call i8* @malloc(i64 4)
     88   %n = call i8* @malloc(i64 4)
     89   %cmp = icmp eq i8* %m, %n
     90   ret i1 %cmp
     91   ; CHECK-LABEL: compare_distinct_mallocs
     92   ; CHECK: ret i1 false
     93 }
     94 
     95 ; the compare is folded to true since the folding compare looks through bitcasts. 
     96 ; call to malloc and the bitcast instructions are elided after that since there are no uses of the malloc 
     97 define i1 @compare_samepointer_under_bitcast() {
     98   %m = call i8* @malloc(i64 4)
     99   %bc = bitcast i8* %m to i32*
    100   %bcback = bitcast i32* %bc to i8*
    101   %cmp = icmp eq i8* %m, %bcback
    102   ret i1 %cmp
    103 ; CHECK-LABEL: compare_samepointer_under_bitcast
    104 ; CHECK: ret i1 true 
    105 }
    106 
    107 ; the compare is folded to true since the folding compare looks through bitcasts. 
    108 ; The malloc call for %m cannot be elided since it is used in the call to function f.
    109 define i1 @compare_samepointer_escaped() {
    110   %m = call i8* @malloc(i64 4)
    111   %bc = bitcast i8* %m to i32*
    112   %bcback = bitcast i32* %bc to i8*
    113   %cmp = icmp eq i8* %m, %bcback
    114   call void @f() [ "deopt"(i8* %m) ]
    115   ret i1 %cmp
    116 ; CHECK-LABEL: compare_samepointer_escaped
    117 ; CHECK-NEXT: %m = call i8* @malloc(i64 4)
    118 ; CHECK-NEXT: call void @f() [ "deopt"(i8* %m) ]
    119 ; CHECK: ret i1 true 
    120 }
    121 
    122 ; Technically, we can fold the %cmp2 comparison, even though %m escapes through
    123 ; the ret statement since `ret` terminates the function and we cannot reach from
    124 ; the ret to cmp. 
    125 ; FIXME: Folding this %cmp2 when %m escapes through ret could be an issue with
    126 ; cross-threading data dependencies since we do not make the distinction between
    127 ; atomic and non-atomic loads in capture tracking.
    128 define i8* @compare_ret_escape(i8* %c) {
    129   %m = call i8* @malloc(i64 4)
    130   %n = call i8* @malloc(i64 4)
    131   %cmp = icmp eq i8* %n, %c
    132   br i1 %cmp, label %retst, label %chk
    133 
    134 retst:
    135   ret i8* %m
    136 
    137 chk:
    138   %bc = bitcast i8* %m to i32*
    139   %lgp = load i32*, i32** @gp, align 8, !nonnull !0
    140   %cmp2 = icmp eq i32* %bc, %lgp
    141   br i1 %cmp2, label %retst,  label %chk2
    142 
    143 chk2:
    144   ret i8* %n
    145 ; CHECK-LABEL: compare_ret_escape
    146 ; CHECK: %cmp = icmp eq i8* %n, %c
    147 ; CHECK: %cmp2 = icmp eq i32* %bc, %lgp
    148 }
    149 
    150 ; The malloc call for %m cannot be elided since it is used in the call to function f.
    151 ; However, the cmp can be folded to true as %n doesnt escape and %m, %n are distinct allocations
    152 define i1 @compare_distinct_pointer_escape() {
    153   %m = call i8* @malloc(i64 4)
    154   %n = call i8* @malloc(i64 4)
    155   tail call void @f() [ "deopt"(i8* %m) ]
    156   %cmp = icmp ne i8* %m, %n
    157   ret i1 %cmp
    158 ; CHECK-LABEL: compare_distinct_pointer_escape
    159 ; CHECK-NEXT: %m = call i8* @malloc(i64 4)
    160 ; CHECK-NEXT: tail call void @f() [ "deopt"(i8* %m) ]
    161 ; CHECK-NEXT: ret i1 true
    162 }
    163 
    164 !0 = !{}
    165