475 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt < %s -passes=gvn -S | FileCheck %s3 4target datalayout = "p1:64:64:64:32"5 6%struct.A = type { ptr }7@_ZTV1A = available_externally unnamed_addr constant [4 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1A3fooEv, ptr @_ZN1A3barEv], align 88@_ZTI1A = external constant ptr9 10; Checks if indirect calls can be replaced with direct11; assuming that %vtable == @_ZTV1A (with alignment).12; Checking const propagation across other BBs13 14define void @_Z1gb(i1 zeroext %p) {15; CHECK-LABEL: define void @_Z1gb(16; CHECK-SAME: i1 zeroext [[P:%.*]]) {17; CHECK-NEXT: [[ENTRY:.*:]]18; CHECK-NEXT: [[CALL:%.*]] = tail call noalias ptr @_Znwm(i64 8)19; CHECK-NEXT: tail call void @_ZN1AC1Ev(ptr [[CALL]])20; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 821; CHECK-NEXT: [[CMP_VTABLES:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2)22; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP_VTABLES]])23; CHECK-NEXT: br i1 [[P]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]24; CHECK: [[IF_THEN]]:25; CHECK-NEXT: [[CALL2:%.*]] = tail call i32 @_ZN1A3fooEv(ptr [[CALL]])26; CHECK-NEXT: br label %[[IF_END:.*]]27; CHECK: [[IF_ELSE]]:28; CHECK-NEXT: [[CALL5:%.*]] = tail call i32 @_ZN1A3barEv(ptr [[CALL]])29; CHECK-NEXT: br label %[[IF_END]]30; CHECK: [[IF_END]]:31; CHECK-NEXT: ret void32;33entry:34 %call = tail call noalias ptr @_Znwm(i64 8) #435 tail call void @_ZN1AC1Ev(ptr %call) #136 %vtable = load ptr, ptr %call, align 837 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2)38 tail call void @llvm.assume(i1 %cmp.vtables)39 br i1 %p, label %if.then, label %if.else40 41if.then: ; preds = %entry42 %0 = load ptr, ptr %vtable, align 843 44 %call2 = tail call i32 %0(ptr %call) #145 46 br label %if.end47 48if.else: ; preds = %entry49 %vfn47 = getelementptr inbounds ptr, ptr %vtable, i64 150 51 %1 = load ptr, ptr %vfn47, align 852 53 %call5 = tail call i32 %1(ptr %call) #154 br label %if.end55 56if.end: ; preds = %if.else, %if.then57 ret void58}59 60; Check integration with invariant.group handling61define void @invariantGroupHandling(i1 zeroext %p) {62; CHECK-LABEL: define void @invariantGroupHandling(63; CHECK-SAME: i1 zeroext [[P:%.*]]) {64; CHECK-NEXT: [[ENTRY:.*:]]65; CHECK-NEXT: [[CALL:%.*]] = tail call noalias ptr @_Znwm(i64 8)66; CHECK-NEXT: tail call void @_ZN1AC1Ev(ptr [[CALL]])67; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0:![0-9]+]]68; CHECK-NEXT: [[CMP_VTABLES:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2)69; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP_VTABLES]])70; CHECK-NEXT: br i1 [[P]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]71; CHECK: [[IF_THEN]]:72; CHECK-NEXT: [[CALL2:%.*]] = tail call i32 @_ZN1A3fooEv(ptr [[CALL]])73; CHECK-NEXT: [[CALLX:%.*]] = tail call i32 @_ZN1A3fooEv(ptr [[CALL]])74; CHECK-NEXT: [[CALLY:%.*]] = tail call i32 @_ZN1A3fooEv(ptr [[CALL]])75; CHECK-NEXT: [[UNKNOWN:%.*]] = tail call i32 @_ZN1A3fooEv(ptr [[CALL]])76; CHECK-NEXT: br label %[[IF_END:.*]]77; CHECK: [[IF_ELSE]]:78; CHECK-NEXT: [[CALL5:%.*]] = tail call i32 @_ZN1A3barEv(ptr [[CALL]])79; CHECK-NEXT: br label %[[IF_END]]80; CHECK: [[IF_END]]:81; CHECK-NEXT: ret void82;83entry:84 %call = tail call noalias ptr @_Znwm(i64 8) #485 tail call void @_ZN1AC1Ev(ptr %call) #186 %vtable = load ptr, ptr %call, align 8, !invariant.group !087 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2)88 tail call void @llvm.assume(i1 %cmp.vtables)89 br i1 %p, label %if.then, label %if.else90 91if.then: ; preds = %entry92 %0 = load ptr, ptr %vtable, align 893 94 %call2 = tail call i32 %0(ptr %call) #195 %vtable1 = load ptr, ptr %call, align 8, !invariant.group !096 %call1 = load ptr, ptr %vtable1, align 897 %callx = tail call i32 %call1(ptr %call) #198 99 %vtable2 = load ptr, ptr %call, align 8, !invariant.group !0100 %call4 = load ptr, ptr %vtable2, align 8101 %cally = tail call i32 %call4(ptr %call) #1102 103 %vtable3 = load ptr, ptr %call, align 8, !invariant.group !0104 %vfun = load ptr, ptr %vtable3, align 8105 %unknown = tail call i32 %vfun(ptr %call) #1106 107 br label %if.end108 109if.else: ; preds = %entry110 %vfn47 = getelementptr inbounds ptr, ptr %vtable, i64 1111 112 %1 = load ptr, ptr %vfn47, align 8113 114 %call5 = tail call i32 %1(ptr %call) #1115 br label %if.end116 117if.end: ; preds = %if.else, %if.then118 ret void119}120 121 122; Checking const propagation in the same BB123 124define i32 @main() {125; CHECK-LABEL: define i32 @main() {126; CHECK-NEXT: [[ENTRY:.*:]]127; CHECK-NEXT: [[CALL:%.*]] = tail call noalias ptr @_Znwm(i64 8)128; CHECK-NEXT: tail call void @_ZN1AC1Ev(ptr [[CALL]])129; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8130; CHECK-NEXT: [[CMP_VTABLES:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2)131; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP_VTABLES]])132; CHECK-NEXT: [[CALL2:%.*]] = tail call i32 @_ZN1A3fooEv(ptr [[CALL]])133; CHECK-NEXT: ret i32 0134;135entry:136 %call = tail call noalias ptr @_Znwm(i64 8)137 tail call void @_ZN1AC1Ev(ptr %call)138 %vtable = load ptr, ptr %call, align 8139 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2)140 tail call void @llvm.assume(i1 %cmp.vtables)141 142 %0 = load ptr, ptr %vtable, align 8143 144 %call2 = tail call i32 %0(ptr %call)145 ret i32 0146}147 148; This tests checks const propatation with fcmp instruction.149 150define float @_Z1gf(float %p) {151; CHECK-LABEL: define float @_Z1gf(152; CHECK-SAME: float [[P:%.*]]) {153; CHECK-NEXT: [[ENTRY:.*:]]154; CHECK-NEXT: [[P_ADDR:%.*]] = alloca float, align 4155; CHECK-NEXT: [[F:%.*]] = alloca float, align 4156; CHECK-NEXT: store float [[P]], ptr [[P_ADDR]], align 4157; CHECK-NEXT: store float 3.000000e+00, ptr [[F]], align 4158; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float 3.000000e+00, [[P]]159; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])160; CHECK-NEXT: ret float 3.000000e+00161;162entry:163 %p.addr = alloca float, align 4164 %f = alloca float, align 4165 store float %p, ptr %p.addr, align 4166 167 store float 3.000000e+00, ptr %f, align 4168 %0 = load float, ptr %p.addr, align 4169 %1 = load float, ptr %f, align 4170 %cmp = fcmp oeq float %1, %0 ; note const on lhs171 call void @llvm.assume(i1 %cmp)172 173 ret float %0174}175 176 177define float @_Z1hf(float %p) {178; CHECK-LABEL: define float @_Z1hf(179; CHECK-SAME: float [[P:%.*]]) {180; CHECK-NEXT: [[ENTRY:.*:]]181; CHECK-NEXT: [[P_ADDR:%.*]] = alloca float, align 4182; CHECK-NEXT: store float [[P]], ptr [[P_ADDR]], align 4183; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ueq float [[P]], 3.000000e+00184; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])185; CHECK-NEXT: ret float 3.000000e+00186;187entry:188 %p.addr = alloca float, align 4189 store float %p, ptr %p.addr, align 4190 191 %0 = load float, ptr %p.addr, align 4192 %cmp = fcmp nnan ueq float %0, 3.000000e+00193 call void @llvm.assume(i1 %cmp)194 195 ret float %0196}197 198define float @_Z1if(float %p) {199; CHECK-LABEL: define float @_Z1if(200; CHECK-SAME: float [[P:%.*]]) {201; CHECK-NEXT: [[ENTRY:.*:]]202; CHECK-NEXT: [[P_ADDR:%.*]] = alloca float, align 4203; CHECK-NEXT: store float [[P]], ptr [[P_ADDR]], align 4204; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq float [[P]], 3.000000e+00205; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])206; CHECK-NEXT: ret float [[P]]207;208entry:209 %p.addr = alloca float, align 4210 store float %p, ptr %p.addr, align 4211 212 %0 = load float, ptr %p.addr, align 4213 %cmp = fcmp ueq float %0, 3.000000e+00 ; no nnan flag - can't propagate214 call void @llvm.assume(i1 %cmp)215 216 ret float %0217}218 219; This test checks if constant propagation works for multiple node edges220define i32 @_Z1ii(i32 %p) {221; CHECK-LABEL: define i32 @_Z1ii(222; CHECK-SAME: i32 [[P:%.*]]) {223; CHECK-NEXT: [[ENTRY:.*:]]224; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[P]], 42225; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])226; CHECK-NEXT: br i1 true, label %[[COMMON:.*]], label %[[COMMON]]227; CHECK: [[COMMON]]:228; CHECK-NEXT: br i1 true, label %[[COMMON]], label %[[COMMON]]229; CHECK: [[EXIT:.*:]]230; CHECK-NEXT: ret i32 42231;232entry:233 %cmp = icmp eq i32 %p, 42234 call void @llvm.assume(i1 %cmp)235 236 br i1 %cmp, label %common, label %common237common:238 call void @llvm.assume(i1 true)239 br i1 %cmp, label %common, label %common240 241exit:242 ret i32 %p243}244 245define i32 @_Z1ij(i32 %p) {246; CHECK-LABEL: define i32 @_Z1ij(247; CHECK-SAME: i32 [[P:%.*]]) {248; CHECK-NEXT: [[ENTRY:.*:]]249; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[P]], 42250; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])251; CHECK-NEXT: br i1 true, label %[[BB2:.*]], label %[[BB2]]252; CHECK: [[BB2]]:253; CHECK-NEXT: br i1 true, label %[[BB2]], label %[[BB2]]254; CHECK: [[BB0:.*:]]255; CHECK-NEXT: ret i32 42256;257entry:258 %cmp = icmp eq i32 %p, 42259 call void @llvm.assume(i1 %cmp)260 261 br i1 %cmp, label %bb2, label %bb2262bb2:263 %cmp2 = icmp eq i32 %p, 42264 call void @llvm.assume(i1 %cmp2)265 266 br i1 %cmp, label %bb2, label %bb2267 268 ret i32 %p269}270 271define i32 @_Z1ik(i32 %p) {272; CHECK-LABEL: define i32 @_Z1ik(273; CHECK-SAME: i32 [[P:%.*]]) {274; CHECK-NEXT: [[ENTRY:.*:]]275; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[P]], 42276; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])277; CHECK-NEXT: br i1 true, label %[[BB2:.*]], label %[[BB3:.*]]278; CHECK: [[BB2]]:279; CHECK-NEXT: store i8 poison, ptr null, align 1280; CHECK-NEXT: ret i32 15281; CHECK: [[BB3]]:282; CHECK-NEXT: ret i32 17283;284entry:285 %cmp = icmp eq i32 %p, 42286 call void @llvm.assume(i1 %cmp)287 288 br i1 %cmp, label %bb2, label %bb3289bb2:290 %cmp3 = icmp eq i32 %p, 43291 call void @llvm.assume(i1 %cmp3)292 ret i32 15293bb3:294 ret i32 17295}296 297; This test checks if GVN can do the constant propagation correctly298; when there are multiple uses of the same assume value in the299; basic block that has a loop back-edge pointing to itself.300;301define i32 @_Z1il(i32 %val, i1 %k) {302; CHECK-LABEL: define i32 @_Z1il(303; CHECK-SAME: i32 [[VAL:%.*]], i1 [[K:%.*]]) {304; CHECK-NEXT: br label %[[NEXT:.*]]305; CHECK: [[NEXT]]:306; CHECK-NEXT: tail call void @llvm.assume(i1 [[K]])307; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL]], 50308; CHECK-NEXT: br i1 [[CMP]], label %[[NEXT]], label %[[MEH:.*]]309; CHECK: [[MEH]]:310; CHECK-NEXT: ret i32 0311;312 br label %next313 314next:315 tail call void @llvm.assume(i1 %k)316 tail call void @llvm.assume(i1 %k)317 %cmp = icmp eq i32 %val, 50318 br i1 %cmp, label %next, label %meh319 320meh:321 ret i32 0322}323 324; This test checks if GVN can prevent the constant propagation correctly325; in the successor blocks that are not dominated by the basic block326; with the assume instruction.327;328define i1 @_z1im(i32 %val, i1 %k, i1 %j) {329; CHECK-LABEL: define i1 @_z1im(330; CHECK-SAME: i32 [[VAL:%.*]], i1 [[K:%.*]], i1 [[J:%.*]]) {331; CHECK-NEXT: br i1 [[J]], label %[[NEXT:.*]], label %[[MEH:.*]]332; CHECK: [[NEXT]]:333; CHECK-NEXT: tail call void @llvm.assume(i1 [[K]])334; CHECK-NEXT: br label %[[MEH]]335; CHECK: [[MEH]]:336; CHECK-NEXT: ret i1 [[K]]337;338 br i1 %j, label %next, label %meh339 340next:341 tail call void @llvm.assume(i1 %k)342 tail call void @llvm.assume(i1 %k)343 br label %meh344 345meh:346 ret i1 %k347}348 349define i8 @assume_ptr_eq_different_prov_matters(ptr %p, ptr %p2) {350; CHECK-LABEL: define i8 @assume_ptr_eq_different_prov_matters(351; CHECK-SAME: ptr [[P:%.*]], ptr [[P2:%.*]]) {352; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]353; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])354; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P2]], align 1355; CHECK-NEXT: ret i8 [[V]]356;357 %cmp = icmp eq ptr %p, %p2358 call void @llvm.assume(i1 %cmp)359 %v = load i8, ptr %p2360 ret i8 %v361}362 363define i1 @assume_ptr_eq_different_prov_does_not_matter_icmp(ptr %p, ptr %p2) {364; CHECK-LABEL: define i1 @assume_ptr_eq_different_prov_does_not_matter_icmp(365; CHECK-SAME: ptr [[P:%.*]], ptr [[P2:%.*]]) {366; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]367; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])368; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P]], null369; CHECK-NEXT: ret i1 [[C]]370;371 %cmp = icmp eq ptr %p, %p2372 call void @llvm.assume(i1 %cmp)373 %c = icmp eq ptr %p2, null374 ret i1 %c375}376 377define i1 @assume_ptr_eq_different_prov_does_not_matter_icmp_addrsize(ptr addrspace(1) %p, ptr addrspace(1) %p2) {378; CHECK-LABEL: define i1 @assume_ptr_eq_different_prov_does_not_matter_icmp_addrsize(379; CHECK-SAME: ptr addrspace(1) [[P:%.*]], ptr addrspace(1) [[P2:%.*]]) {380; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr addrspace(1) [[P]], [[P2]]381; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])382; CHECK-NEXT: [[C:%.*]] = icmp eq ptr addrspace(1) [[P]], null383; CHECK-NEXT: ret i1 [[C]]384;385 %cmp = icmp eq ptr addrspace(1) %p, %p2386 call void @llvm.assume(i1 %cmp)387 %c = icmp eq ptr addrspace(1) %p2, null388 ret i1 %c389}390 391; This is not correct, as it may change the provenance exposed by ptrtoint.392; We still allow it for now.393define i64 @assume_ptr_eq_different_prov_does_not_matter_ptrtoint(ptr %p, ptr %p2) {394; CHECK-LABEL: define i64 @assume_ptr_eq_different_prov_does_not_matter_ptrtoint(395; CHECK-SAME: ptr [[P:%.*]], ptr [[P2:%.*]]) {396; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]397; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])398; CHECK-NEXT: [[INT:%.*]] = ptrtoint ptr [[P]] to i64399; CHECK-NEXT: ret i64 [[INT]]400;401 %cmp = icmp eq ptr %p, %p2402 call void @llvm.assume(i1 %cmp)403 %int = ptrtoint ptr %p2 to i64404 ret i64 %int405}406 407define i64 @assume_ptr_eq_different_prov_does_not_matter_ptrtoint_addrsize(ptr addrspace(1) %p, ptr addrspace(1) %p2) {408; CHECK-LABEL: define i64 @assume_ptr_eq_different_prov_does_not_matter_ptrtoint_addrsize(409; CHECK-SAME: ptr addrspace(1) [[P:%.*]], ptr addrspace(1) [[P2:%.*]]) {410; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr addrspace(1) [[P]], [[P2]]411; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])412; CHECK-NEXT: [[INT:%.*]] = ptrtoint ptr addrspace(1) [[P]] to i64413; CHECK-NEXT: ret i64 [[INT]]414;415 %cmp = icmp eq ptr addrspace(1) %p, %p2416 call void @llvm.assume(i1 %cmp)417 %int = ptrtoint ptr addrspace(1) %p2 to i64418 ret i64 %int419}420 421define i64 @assume_ptr_eq_different_prov_does_not_matter_ptrtoaddr(ptr %p, ptr %p2) {422; CHECK-LABEL: define i64 @assume_ptr_eq_different_prov_does_not_matter_ptrtoaddr(423; CHECK-SAME: ptr [[P:%.*]], ptr [[P2:%.*]]) {424; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]425; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])426; CHECK-NEXT: [[INT:%.*]] = ptrtoaddr ptr [[P]] to i64427; CHECK-NEXT: ret i64 [[INT]]428;429 %cmp = icmp eq ptr %p, %p2430 call void @llvm.assume(i1 %cmp)431 %int = ptrtoaddr ptr %p2 to i64432 ret i64 %int433}434 435define i32 @assume_ptr_eq_different_prov_does_not_matter_ptrtoaddr_addrsize(ptr addrspace(1) %p, ptr addrspace(1) %p2) {436; CHECK-LABEL: define i32 @assume_ptr_eq_different_prov_does_not_matter_ptrtoaddr_addrsize(437; CHECK-SAME: ptr addrspace(1) [[P:%.*]], ptr addrspace(1) [[P2:%.*]]) {438; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr addrspace(1) [[P]], [[P2]]439; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])440; CHECK-NEXT: [[INT:%.*]] = ptrtoaddr ptr addrspace(1) [[P]] to i32441; CHECK-NEXT: ret i32 [[INT]]442;443 %cmp = icmp eq ptr addrspace(1) %p, %p2444 call void @llvm.assume(i1 %cmp)445 %int = ptrtoaddr ptr addrspace(1) %p2 to i32446 ret i32 %int447}448 449define i8 @assume_ptr_eq_same_prov(ptr %p, i64 %x) {450; CHECK-LABEL: define i8 @assume_ptr_eq_same_prov(451; CHECK-SAME: ptr [[P:%.*]], i64 [[X:%.*]]) {452; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 [[X]]453; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]454; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])455; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P]], align 1456; CHECK-NEXT: ret i8 [[V]]457;458 %p2 = getelementptr i8, ptr %p, i64 %x459 %cmp = icmp eq ptr %p, %p2460 call void @llvm.assume(i1 %cmp)461 %v = load i8, ptr %p2462 ret i8 %v463}464 465declare noalias ptr @_Znwm(i64)466declare void @_ZN1AC1Ev(ptr)467declare void @llvm.assume(i1)468declare i32 @_ZN1A3fooEv(ptr)469declare i32 @_ZN1A3barEv(ptr)470 471!0 = !{!"struct A"}472;.473; CHECK: [[META0]] = !{!"struct A"}474;.475