[ARM] MVE compare vector splat combine
[llvm-complete.git] / test / Transforms / InstCombine / compare-unescaped.ll
blobd15fc2fd4495c706a4511e556852a22616b0e666
1 ; RUN: opt -instcombine -S < %s | FileCheck %s
3 @gp = global i32* null, align 8
5 declare i8* @malloc(i64) #1
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
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
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
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
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
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
78 escape_call:
79  call void @escape(i8* %m)
80  ret i1 true
82 just_return:
83  ret i1 %cmp
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
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 
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 
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
134 retst:
135   ret i8* %m
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
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* %lgp, %bc
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
164 !0 = !{}