1; RUN: opt < %s -passes=gvn -S | FileCheck %s 2 3%struct.A = type { ptr } 4@_ZTV1A = available_externally unnamed_addr constant [4 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1A3fooEv, ptr @_ZN1A3barEv], align 8 5@_ZTI1A = external constant ptr 6 7; Checks if indirect calls can be replaced with direct 8; assuming that %vtable == @_ZTV1A (with alignment). 9; Checking const propagation across other BBs 10; CHECK-LABEL: define void @_Z1gb( 11 12define void @_Z1gb(i1 zeroext %p) { 13entry: 14 %call = tail call noalias ptr @_Znwm(i64 8) #4 15 tail call void @_ZN1AC1Ev(ptr %call) #1 16 %vtable = load ptr, ptr %call, align 8 17 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2) 18 tail call void @llvm.assume(i1 %cmp.vtables) 19 br i1 %p, label %if.then, label %if.else 20 21if.then: ; preds = %entry 22 %0 = load ptr, ptr %vtable, align 8 23 24 ; CHECK: call i32 @_ZN1A3fooEv( 25 %call2 = tail call i32 %0(ptr %call) #1 26 27 br label %if.end 28 29if.else: ; preds = %entry 30 %vfn47 = getelementptr inbounds ptr, ptr %vtable, i64 1 31 32 ; CHECK: call i32 @_ZN1A3barEv( 33 %1 = load ptr, ptr %vfn47, align 8 34 35 %call5 = tail call i32 %1(ptr %call) #1 36 br label %if.end 37 38if.end: ; preds = %if.else, %if.then 39 ret void 40} 41 42; Check integration with invariant.group handling 43; CHECK-LABEL: define void @invariantGroupHandling(i1 zeroext %p) { 44define void @invariantGroupHandling(i1 zeroext %p) { 45entry: 46 %call = tail call noalias ptr @_Znwm(i64 8) #4 47 tail call void @_ZN1AC1Ev(ptr %call) #1 48 %vtable = load ptr, ptr %call, align 8, !invariant.group !0 49 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2) 50 tail call void @llvm.assume(i1 %cmp.vtables) 51 br i1 %p, label %if.then, label %if.else 52 53if.then: ; preds = %entry 54 %0 = load ptr, ptr %vtable, align 8 55 56; CHECK: call i32 @_ZN1A3fooEv( 57 %call2 = tail call i32 %0(ptr %call) #1 58 %vtable1 = load ptr, ptr %call, align 8, !invariant.group !0 59 %call1 = load ptr, ptr %vtable1, align 8 60; CHECK: call i32 @_ZN1A3fooEv( 61 %callx = tail call i32 %call1(ptr %call) #1 62 63 %vtable2 = load ptr, ptr %call, align 8, !invariant.group !0 64 %call4 = load ptr, ptr %vtable2, align 8 65; CHECK: call i32 @_ZN1A3fooEv( 66 %cally = tail call i32 %call4(ptr %call) #1 67 68 %vtable3 = load ptr, ptr %call, align 8, !invariant.group !0 69 %vfun = load ptr, ptr %vtable3, align 8 70; CHECK: call i32 @_ZN1A3fooEv( 71 %unknown = tail call i32 %vfun(ptr %call) #1 72 73 br label %if.end 74 75if.else: ; preds = %entry 76 %vfn47 = getelementptr inbounds ptr, ptr %vtable, i64 1 77 78 ; CHECK: call i32 @_ZN1A3barEv( 79 %1 = load ptr, ptr %vfn47, align 8 80 81 %call5 = tail call i32 %1(ptr %call) #1 82 br label %if.end 83 84if.end: ; preds = %if.else, %if.then 85 ret void 86} 87 88 89; Checking const propagation in the same BB 90; CHECK-LABEL: define i32 @main() 91 92define i32 @main() { 93entry: 94 %call = tail call noalias ptr @_Znwm(i64 8) 95 tail call void @_ZN1AC1Ev(ptr %call) 96 %vtable = load ptr, ptr %call, align 8 97 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2) 98 tail call void @llvm.assume(i1 %cmp.vtables) 99 100 ; CHECK: call i32 @_ZN1A3fooEv( 101 %0 = load ptr, ptr %vtable, align 8 102 103 %call2 = tail call i32 %0(ptr %call) 104 ret i32 0 105} 106 107; This tests checks const propatation with fcmp instruction. 108; CHECK-LABEL: define float @_Z1gf(float %p) 109 110define float @_Z1gf(float %p) { 111entry: 112 %p.addr = alloca float, align 4 113 %f = alloca float, align 4 114 store float %p, ptr %p.addr, align 4 115 116 store float 3.000000e+00, ptr %f, align 4 117 %0 = load float, ptr %p.addr, align 4 118 %1 = load float, ptr %f, align 4 119 %cmp = fcmp oeq float %1, %0 ; note const on lhs 120 call void @llvm.assume(i1 %cmp) 121 122 ; CHECK: ret float 3.000000e+00 123 ret float %0 124} 125 126; CHECK-LABEL: define float @_Z1hf(float %p) 127 128define float @_Z1hf(float %p) { 129entry: 130 %p.addr = alloca float, align 4 131 store float %p, ptr %p.addr, align 4 132 133 %0 = load float, ptr %p.addr, align 4 134 %cmp = fcmp nnan ueq float %0, 3.000000e+00 135 call void @llvm.assume(i1 %cmp) 136 137 ; CHECK: ret float 3.000000e+00 138 ret float %0 139} 140 141; CHECK-LABEL: define float @_Z1if(float %p) 142define float @_Z1if(float %p) { 143entry: 144 %p.addr = alloca float, align 4 145 store float %p, ptr %p.addr, align 4 146 147 %0 = load float, ptr %p.addr, align 4 148 %cmp = fcmp ueq float %0, 3.000000e+00 ; no nnan flag - can't propagate 149 call void @llvm.assume(i1 %cmp) 150 151 ; CHECK-NOT: ret float 3.000000e+00 152 ret float %0 153} 154 155; This test checks if constant propagation works for multiple node edges 156; CHECK-LABEL: define i32 @_Z1ii(i32 %p) 157define i32 @_Z1ii(i32 %p) { 158entry: 159 %cmp = icmp eq i32 %p, 42 160 call void @llvm.assume(i1 %cmp) 161 162 ; CHECK: br i1 true, label %bb2, label %bb2 163 br i1 %cmp, label %bb2, label %bb2 164bb2: 165 call void @llvm.assume(i1 true) 166 ; CHECK: br i1 true, label %bb2, label %bb2 167 br i1 %cmp, label %bb2, label %bb2 168 169 ; CHECK: ret i32 42 170 ret i32 %p 171} 172 173; CHECK-LABEL: define i32 @_Z1ij(i32 %p) 174define i32 @_Z1ij(i32 %p) { 175entry: 176 %cmp = icmp eq i32 %p, 42 177 call void @llvm.assume(i1 %cmp) 178 179 ; CHECK: br i1 true, label %bb2, label %bb2 180 br i1 %cmp, label %bb2, label %bb2 181bb2: 182 ; CHECK-NOT: %cmp2 = 183 %cmp2 = icmp eq i32 %p, 42 184 ; CHECK-NOT: call void @llvm.assume( 185 call void @llvm.assume(i1 %cmp2) 186 187 ; CHECK: br i1 true, label %bb2, label %bb2 188 br i1 %cmp, label %bb2, label %bb2 189 190 ; CHECK: ret i32 42 191 ret i32 %p 192} 193 194; CHECK-LABEL: define i32 @_Z1ik(i32 %p) 195define i32 @_Z1ik(i32 %p) { 196entry: 197 %cmp = icmp eq i32 %p, 42 198 call void @llvm.assume(i1 %cmp) 199 200 ; CHECK: br i1 true, label %bb2, label %bb3 201 br i1 %cmp, label %bb2, label %bb3 202bb2: 203 ; CHECK-NOT: %cmp3 = 204 %cmp3 = icmp eq i32 %p, 43 205 ; CHECK: store i8 poison, ptr null 206 call void @llvm.assume(i1 %cmp3) 207 ret i32 15 208bb3: 209 ret i32 17 210} 211 212; This test checks if GVN can do the constant propagation correctly 213; when there are multiple uses of the same assume value in the 214; basic block that has a loop back-edge pointing to itself. 215; 216; CHECK-LABEL: define i32 @_Z1il(i32 %val, i1 %k) 217define i32 @_Z1il(i32 %val, i1 %k) { 218 br label %next 219 220next: 221; CHECK: tail call void @llvm.assume(i1 %k) 222; CHECK-NEXT: %cmp = icmp eq i32 %val, 50 223 tail call void @llvm.assume(i1 %k) 224 tail call void @llvm.assume(i1 %k) 225 %cmp = icmp eq i32 %val, 50 226 br i1 %cmp, label %next, label %meh 227 228meh: 229 ret i32 0 230} 231 232; This test checks if GVN can prevent the constant propagation correctly 233; in the successor blocks that are not dominated by the basic block 234; with the assume instruction. 235; 236; CHECK-LABEL: define i1 @_z1im(i32 %val, i1 %k, i1 %j) 237define i1 @_z1im(i32 %val, i1 %k, i1 %j) { 238 br i1 %j, label %next, label %meh 239 240next: 241; CHECK: tail call void @llvm.assume(i1 %k) 242; CHECK-NEXT: br label %meh 243 tail call void @llvm.assume(i1 %k) 244 tail call void @llvm.assume(i1 %k) 245 br label %meh 246 247meh: 248; CHECK: ret i1 %k 249 ret i1 %k 250} 251 252declare noalias ptr @_Znwm(i64) 253declare void @_ZN1AC1Ev(ptr) 254declare void @llvm.assume(i1) 255declare i32 @_ZN1A3fooEv(ptr) 256declare i32 @_ZN1A3barEv(ptr) 257 258!0 = !{!"struct A"} 259