1f24175fcSPhilip Reames; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2cee313d2SEric Christopher; RUN: opt < %s -jump-threading -dce -S | FileCheck %s 3cee313d2SEric Christopher 4cee313d2SEric Christopherdeclare void @llvm.experimental.guard(i1, ...) 5cee313d2SEric Christopher 6cee313d2SEric Christopherdeclare i32 @f1() 7cee313d2SEric Christopherdeclare i32 @f2() 8cee313d2SEric Christopher 9cee313d2SEric Christopherdefine i32 @branch_implies_guard(i32 %a) { 10cee313d2SEric Christopher; CHECK-LABEL: @branch_implies_guard( 11f24175fcSPhilip Reames; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[A:%.*]], 10 12f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[COND]], label [[T1_SPLIT:%.*]], label [[F1_SPLIT:%.*]] 13f24175fcSPhilip Reames; CHECK: T1.split: 14f24175fcSPhilip Reames; CHECK-NEXT: [[V1:%.*]] = call i32 @f1() 15f24175fcSPhilip Reames; CHECK-NEXT: [[RETVAL3:%.*]] = add i32 [[V1]], 10 16f24175fcSPhilip Reames; CHECK-NEXT: br label [[MERGE:%.*]] 17f24175fcSPhilip Reames; CHECK: F1.split: 18f24175fcSPhilip Reames; CHECK-NEXT: [[V2:%.*]] = call i32 @f2() 19f24175fcSPhilip Reames; CHECK-NEXT: [[RETVAL1:%.*]] = add i32 [[V2]], 10 20f24175fcSPhilip Reames; CHECK-NEXT: [[CONDGUARD2:%.*]] = icmp slt i32 [[A]], 20 21f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[CONDGUARD2]]) [ "deopt"() ] 22f24175fcSPhilip Reames; CHECK-NEXT: br label [[MERGE]] 23f24175fcSPhilip Reames; CHECK: Merge: 24f24175fcSPhilip Reames; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[RETVAL3]], [[T1_SPLIT]] ], [ [[RETVAL1]], [[F1_SPLIT]] ] 25f24175fcSPhilip Reames; CHECK-NEXT: ret i32 [[TMP1]] 26f24175fcSPhilip Reames; 27cee313d2SEric Christopher %cond = icmp slt i32 %a, 10 28cee313d2SEric Christopher br i1 %cond, label %T1, label %F1 29cee313d2SEric Christopher 30cee313d2SEric ChristopherT1: 31cee313d2SEric Christopher %v1 = call i32 @f1() 32cee313d2SEric Christopher br label %Merge 33cee313d2SEric Christopher 34cee313d2SEric ChristopherF1: 35cee313d2SEric Christopher %v2 = call i32 @f2() 36cee313d2SEric Christopher br label %Merge 37cee313d2SEric Christopher 38cee313d2SEric ChristopherMerge: 39cee313d2SEric Christopher %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ] 40cee313d2SEric Christopher %retVal = add i32 %retPhi, 10 41cee313d2SEric Christopher %condGuard = icmp slt i32 %a, 20 42cee313d2SEric Christopher call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ] 43cee313d2SEric Christopher ret i32 %retVal 44cee313d2SEric Christopher} 45cee313d2SEric Christopher 46cee313d2SEric Christopherdefine i32 @not_branch_implies_guard(i32 %a) { 47cee313d2SEric Christopher; CHECK-LABEL: @not_branch_implies_guard( 48f24175fcSPhilip Reames; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[A:%.*]], 20 49f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[COND]], label [[T1_SPLIT:%.*]], label [[F1_SPLIT:%.*]] 50f24175fcSPhilip Reames; CHECK: T1.split: 51f24175fcSPhilip Reames; CHECK-NEXT: [[V1:%.*]] = call i32 @f1() 52f24175fcSPhilip Reames; CHECK-NEXT: [[RETVAL1:%.*]] = add i32 [[V1]], 10 53f24175fcSPhilip Reames; CHECK-NEXT: [[CONDGUARD2:%.*]] = icmp sgt i32 [[A]], 10 54f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[CONDGUARD2]]) [ "deopt"() ] 55f24175fcSPhilip Reames; CHECK-NEXT: br label [[MERGE:%.*]] 56f24175fcSPhilip Reames; CHECK: F1.split: 57f24175fcSPhilip Reames; CHECK-NEXT: [[V2:%.*]] = call i32 @f2() 58f24175fcSPhilip Reames; CHECK-NEXT: [[RETVAL3:%.*]] = add i32 [[V2]], 10 59f24175fcSPhilip Reames; CHECK-NEXT: br label [[MERGE]] 60f24175fcSPhilip Reames; CHECK: Merge: 61f24175fcSPhilip Reames; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[RETVAL3]], [[F1_SPLIT]] ], [ [[RETVAL1]], [[T1_SPLIT]] ] 62f24175fcSPhilip Reames; CHECK-NEXT: ret i32 [[TMP1]] 63f24175fcSPhilip Reames; 64cee313d2SEric Christopher %cond = icmp slt i32 %a, 20 65cee313d2SEric Christopher br i1 %cond, label %T1, label %F1 66cee313d2SEric Christopher 67cee313d2SEric ChristopherT1: 68cee313d2SEric Christopher %v1 = call i32 @f1() 69cee313d2SEric Christopher br label %Merge 70cee313d2SEric Christopher 71cee313d2SEric ChristopherF1: 72cee313d2SEric Christopher %v2 = call i32 @f2() 73cee313d2SEric Christopher br label %Merge 74cee313d2SEric Christopher 75cee313d2SEric ChristopherMerge: 76cee313d2SEric Christopher %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ] 77cee313d2SEric Christopher %retVal = add i32 %retPhi, 10 78cee313d2SEric Christopher %condGuard = icmp sgt i32 %a, 10 79cee313d2SEric Christopher call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ] 80cee313d2SEric Christopher ret i32 %retVal 81cee313d2SEric Christopher} 82cee313d2SEric Christopher 83cee313d2SEric Christopherdefine i32 @branch_overlaps_guard(i32 %a) { 84cee313d2SEric Christopher; CHECK-LABEL: @branch_overlaps_guard( 85f24175fcSPhilip Reames; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[A:%.*]], 20 86f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[COND]], label [[T1:%.*]], label [[F1:%.*]] 87f24175fcSPhilip Reames; CHECK: T1: 88f24175fcSPhilip Reames; CHECK-NEXT: [[V1:%.*]] = call i32 @f1() 89f24175fcSPhilip Reames; CHECK-NEXT: br label [[MERGE:%.*]] 90f24175fcSPhilip Reames; CHECK: F1: 91f24175fcSPhilip Reames; CHECK-NEXT: [[V2:%.*]] = call i32 @f2() 92f24175fcSPhilip Reames; CHECK-NEXT: br label [[MERGE]] 93f24175fcSPhilip Reames; CHECK: Merge: 94f24175fcSPhilip Reames; CHECK-NEXT: [[RETPHI:%.*]] = phi i32 [ [[V1]], [[T1]] ], [ [[V2]], [[F1]] ] 95f24175fcSPhilip Reames; CHECK-NEXT: [[RETVAL:%.*]] = add i32 [[RETPHI]], 10 96f24175fcSPhilip Reames; CHECK-NEXT: [[CONDGUARD:%.*]] = icmp slt i32 [[A]], 10 97f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[CONDGUARD]]) [ "deopt"() ] 98f24175fcSPhilip Reames; CHECK-NEXT: ret i32 [[RETVAL]] 99f24175fcSPhilip Reames; 100cee313d2SEric Christopher %cond = icmp slt i32 %a, 20 101cee313d2SEric Christopher br i1 %cond, label %T1, label %F1 102cee313d2SEric Christopher 103cee313d2SEric ChristopherT1: 104cee313d2SEric Christopher %v1 = call i32 @f1() 105cee313d2SEric Christopher br label %Merge 106cee313d2SEric Christopher 107cee313d2SEric ChristopherF1: 108cee313d2SEric Christopher %v2 = call i32 @f2() 109cee313d2SEric Christopher br label %Merge 110cee313d2SEric Christopher 111cee313d2SEric ChristopherMerge: 112cee313d2SEric Christopher %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ] 113cee313d2SEric Christopher %retVal = add i32 %retPhi, 10 114cee313d2SEric Christopher %condGuard = icmp slt i32 %a, 10 115cee313d2SEric Christopher call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ] 116cee313d2SEric Christopher ret i32 %retVal 117cee313d2SEric Christopher} 118cee313d2SEric Christopher 119cee313d2SEric Christopherdefine i32 @branch_doesnt_overlap_guard(i32 %a) { 120cee313d2SEric Christopher; CHECK-LABEL: @branch_doesnt_overlap_guard( 121f24175fcSPhilip Reames; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[A:%.*]], 10 122f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[COND]], label [[T1:%.*]], label [[F1:%.*]] 123f24175fcSPhilip Reames; CHECK: T1: 124f24175fcSPhilip Reames; CHECK-NEXT: [[V1:%.*]] = call i32 @f1() 125f24175fcSPhilip Reames; CHECK-NEXT: br label [[MERGE:%.*]] 126f24175fcSPhilip Reames; CHECK: F1: 127f24175fcSPhilip Reames; CHECK-NEXT: [[V2:%.*]] = call i32 @f2() 128f24175fcSPhilip Reames; CHECK-NEXT: br label [[MERGE]] 129f24175fcSPhilip Reames; CHECK: Merge: 130f24175fcSPhilip Reames; CHECK-NEXT: [[RETPHI:%.*]] = phi i32 [ [[V1]], [[T1]] ], [ [[V2]], [[F1]] ] 131f24175fcSPhilip Reames; CHECK-NEXT: [[RETVAL:%.*]] = add i32 [[RETPHI]], 10 132f24175fcSPhilip Reames; CHECK-NEXT: [[CONDGUARD:%.*]] = icmp sgt i32 [[A]], 20 133f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[CONDGUARD]]) [ "deopt"() ] 134f24175fcSPhilip Reames; CHECK-NEXT: ret i32 [[RETVAL]] 135f24175fcSPhilip Reames; 136cee313d2SEric Christopher %cond = icmp slt i32 %a, 10 137cee313d2SEric Christopher br i1 %cond, label %T1, label %F1 138cee313d2SEric Christopher 139cee313d2SEric ChristopherT1: 140cee313d2SEric Christopher %v1 = call i32 @f1() 141cee313d2SEric Christopher br label %Merge 142cee313d2SEric Christopher 143cee313d2SEric ChristopherF1: 144cee313d2SEric Christopher %v2 = call i32 @f2() 145cee313d2SEric Christopher br label %Merge 146cee313d2SEric Christopher 147cee313d2SEric ChristopherMerge: 148cee313d2SEric Christopher %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ] 149cee313d2SEric Christopher %retVal = add i32 %retPhi, 10 150cee313d2SEric Christopher %condGuard = icmp sgt i32 %a, 20 151cee313d2SEric Christopher call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ] 152cee313d2SEric Christopher ret i32 %retVal 153cee313d2SEric Christopher} 154cee313d2SEric Christopher 155cee313d2SEric Christopherdefine i32 @not_a_diamond1(i32 %a, i1 %cond1) { 156cee313d2SEric Christopher; CHECK-LABEL: @not_a_diamond1( 157f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[COND1:%.*]], label [[PRED:%.*]], label [[EXIT:%.*]] 158f24175fcSPhilip Reames; CHECK: Pred: 159f24175fcSPhilip Reames; CHECK-NEXT: switch i32 [[A:%.*]], label [[EXIT]] [ 160f24175fcSPhilip Reames; CHECK-NEXT: i32 10, label [[MERGE:%.*]] 161f24175fcSPhilip Reames; CHECK-NEXT: i32 20, label [[MERGE]] 162f24175fcSPhilip Reames; CHECK-NEXT: ] 163f24175fcSPhilip Reames; CHECK: Merge: 164f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND1]]) [ "deopt"() ] 165f24175fcSPhilip Reames; CHECK-NEXT: br label [[EXIT]] 166f24175fcSPhilip Reames; CHECK: Exit: 167f24175fcSPhilip Reames; CHECK-NEXT: ret i32 [[A]] 168f24175fcSPhilip Reames; 169cee313d2SEric Christopher br i1 %cond1, label %Pred, label %Exit 170cee313d2SEric Christopher 171cee313d2SEric ChristopherPred: 172cee313d2SEric Christopher switch i32 %a, label %Exit [ 173cee313d2SEric Christopher i32 10, label %Merge 174cee313d2SEric Christopher i32 20, label %Merge 175cee313d2SEric Christopher ] 176cee313d2SEric Christopher 177cee313d2SEric ChristopherMerge: 178cee313d2SEric Christopher call void(i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ] 179cee313d2SEric Christopher br label %Exit 180cee313d2SEric Christopher 181cee313d2SEric ChristopherExit: 182cee313d2SEric Christopher ret i32 %a 183cee313d2SEric Christopher} 184cee313d2SEric Christopher 185cee313d2SEric Christopherdefine void @not_a_diamond2(i32 %a, i1 %cond1) { 186cee313d2SEric Christopher; CHECK-LABEL: @not_a_diamond2( 187f24175fcSPhilip Reames; CHECK-NEXT: Pred: 188f24175fcSPhilip Reames; CHECK-NEXT: switch i32 [[A:%.*]], label [[EXIT:%.*]] [ 189f24175fcSPhilip Reames; CHECK-NEXT: i32 10, label [[MERGE:%.*]] 190f24175fcSPhilip Reames; CHECK-NEXT: i32 20, label [[MERGE]] 191f24175fcSPhilip Reames; CHECK-NEXT: ] 192f24175fcSPhilip Reames; CHECK: Merge: 193f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND1:%.*]]) [ "deopt"() ] 194f24175fcSPhilip Reames; CHECK-NEXT: ret void 195f24175fcSPhilip Reames; CHECK: Exit: 196f24175fcSPhilip Reames; CHECK-NEXT: ret void 197f24175fcSPhilip Reames; 198cee313d2SEric Christopher br label %Parent 199cee313d2SEric Christopher 200cee313d2SEric ChristopherMerge: 201cee313d2SEric Christopher call void(i1, ...) @llvm.experimental.guard(i1 %cond1)[ "deopt"() ] 202cee313d2SEric Christopher ret void 203cee313d2SEric Christopher 204cee313d2SEric ChristopherPred: 205cee313d2SEric Christopher switch i32 %a, label %Exit [ 206cee313d2SEric Christopher i32 10, label %Merge 207cee313d2SEric Christopher i32 20, label %Merge 208cee313d2SEric Christopher ] 209cee313d2SEric Christopher 210cee313d2SEric ChristopherParent: 211cee313d2SEric Christopher br label %Pred 212cee313d2SEric Christopher 213cee313d2SEric ChristopherExit: 214cee313d2SEric Christopher ret void 215cee313d2SEric Christopher} 216cee313d2SEric Christopher 217cee313d2SEric Christopherdeclare void @never_called(i1) 218cee313d2SEric Christopher 219cee313d2SEric Christopher; LVI uses guard to identify value of %c2 in branch as true, we cannot replace that 220cee313d2SEric Christopher; guard with guard(true & c1). 221cee313d2SEric Christopherdefine void @dont_fold_guard(i8* %addr, i32 %i, i32 %length) { 222f24175fcSPhilip Reames; CHECK-LABEL: @dont_fold_guard( 223f24175fcSPhilip Reames; CHECK-NEXT: BB1: 224f24175fcSPhilip Reames; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[I:%.*]], [[LENGTH:%.*]] 225f24175fcSPhilip Reames; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[I]], 0 226f24175fcSPhilip Reames; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]] 227f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] 228cee313d2SEric Christopher; CHECK-NEXT: call void @never_called(i1 true) 229cee313d2SEric Christopher; CHECK-NEXT: ret void 230f24175fcSPhilip Reames; 231cee313d2SEric Christopher %c1 = icmp ult i32 %i, %length 232cee313d2SEric Christopher %c2 = icmp eq i32 %i, 0 233cee313d2SEric Christopher %wide.chk = and i1 %c1, %c2 234cee313d2SEric Christopher call void(i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 235cee313d2SEric Christopher br i1 %c2, label %BB1, label %BB2 236cee313d2SEric Christopher 237cee313d2SEric ChristopherBB1: 238cee313d2SEric Christopher call void @never_called(i1 %c2) 239cee313d2SEric Christopher ret void 240cee313d2SEric Christopher 241cee313d2SEric ChristopherBB2: 242cee313d2SEric Christopher ret void 243cee313d2SEric Christopher} 244cee313d2SEric Christopher 2455d12b976SNikita Popovdeclare void @dummy(i1) nounwind willreturn 246cee313d2SEric Christopher; same as dont_fold_guard1 but there's a use immediately after guard and before 247cee313d2SEric Christopher; branch. We can fold that use. 248cee313d2SEric Christopherdefine void @dont_fold_guard2(i8* %addr, i32 %i, i32 %length) { 249f24175fcSPhilip Reames; CHECK-LABEL: @dont_fold_guard2( 250f24175fcSPhilip Reames; CHECK-NEXT: BB1: 251f24175fcSPhilip Reames; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[I:%.*]], [[LENGTH:%.*]] 252f24175fcSPhilip Reames; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[I]], 0 253f24175fcSPhilip Reames; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]] 254f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] 255f24175fcSPhilip Reames; CHECK-NEXT: call void @dummy(i1 true) 256cee313d2SEric Christopher; CHECK-NEXT: call void @never_called(i1 true) 257cee313d2SEric Christopher; CHECK-NEXT: ret void 258f24175fcSPhilip Reames; 259cee313d2SEric Christopher %c1 = icmp ult i32 %i, %length 260cee313d2SEric Christopher %c2 = icmp eq i32 %i, 0 261cee313d2SEric Christopher %wide.chk = and i1 %c1, %c2 262cee313d2SEric Christopher call void(i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 263cee313d2SEric Christopher call void @dummy(i1 %c2) 264cee313d2SEric Christopher br i1 %c2, label %BB1, label %BB2 265cee313d2SEric Christopher 266cee313d2SEric ChristopherBB1: 267cee313d2SEric Christopher call void @never_called(i1 %c2) 268cee313d2SEric Christopher ret void 269cee313d2SEric Christopher 270cee313d2SEric ChristopherBB2: 271cee313d2SEric Christopher ret void 272cee313d2SEric Christopher} 273cee313d2SEric Christopher 274cee313d2SEric Christopher; same as dont_fold_guard1 but condition %cmp is not an instruction. 275cee313d2SEric Christopher; We cannot fold the guard under any circumstance. 276cee313d2SEric Christopher; FIXME: We can merge unreachableBB2 into not_zero. 277cee313d2SEric Christopherdefine void @dont_fold_guard3(i8* %addr, i1 %cmp, i32 %i, i32 %length) { 278f24175fcSPhilip Reames; CHECK-LABEL: @dont_fold_guard3( 279f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[CMP:%.*]]) [ "deopt"() ] 280f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[CMP]], label [[BB1:%.*]], label [[BB2:%.*]] 281f24175fcSPhilip Reames; CHECK: BB1: 282f24175fcSPhilip Reames; CHECK-NEXT: call void @never_called(i1 [[CMP]]) 283f24175fcSPhilip Reames; CHECK-NEXT: ret void 284f24175fcSPhilip Reames; CHECK: BB2: 285f24175fcSPhilip Reames; CHECK-NEXT: ret void 286f24175fcSPhilip Reames; 287cee313d2SEric Christopher call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ] 288cee313d2SEric Christopher br i1 %cmp, label %BB1, label %BB2 289cee313d2SEric Christopher 290cee313d2SEric ChristopherBB1: 291cee313d2SEric Christopher call void @never_called(i1 %cmp) 292cee313d2SEric Christopher ret void 293cee313d2SEric Christopher 294cee313d2SEric ChristopherBB2: 295cee313d2SEric Christopher ret void 296cee313d2SEric Christopher} 297cee313d2SEric Christopher 298cee313d2SEric Christopherdeclare void @f(i1) 299cee313d2SEric Christopher; Same as dont_fold_guard1 but use switch instead of branch. 300cee313d2SEric Christopher; triggers source code `ProcessThreadableEdges`. 301cee313d2SEric Christopherdefine void @dont_fold_guard4(i1 %cmp1, i32 %i) nounwind { 302f24175fcSPhilip Reames; CHECK-LABEL: @dont_fold_guard4( 303f24175fcSPhilip Reames; CHECK-NEXT: entry: 304f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[CMP1:%.*]], label [[L2:%.*]], label [[L3:%.*]] 305f24175fcSPhilip Reames; CHECK: L2: 306f24175fcSPhilip Reames; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 0 307f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[CMP]]) [ "deopt"() ] 308f24175fcSPhilip Reames; CHECK-NEXT: call void @dummy(i1 true) 309f24175fcSPhilip Reames; CHECK-NEXT: call void @f(i1 true) 310cee313d2SEric Christopher; CHECK-NEXT: ret void 311f24175fcSPhilip Reames; CHECK: L3: 312f24175fcSPhilip Reames; CHECK-NEXT: ret void 313f24175fcSPhilip Reames; 314cee313d2SEric Christopherentry: 315cee313d2SEric Christopher br i1 %cmp1, label %L0, label %L3 316cee313d2SEric ChristopherL0: 317cee313d2SEric Christopher %cmp = icmp eq i32 %i, 0 318cee313d2SEric Christopher call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ] 319cee313d2SEric Christopher call void @dummy(i1 %cmp) 320cee313d2SEric Christopher switch i1 %cmp, label %L3 [ 321cee313d2SEric Christopher i1 false, label %L1 322cee313d2SEric Christopher i1 true, label %L2 323cee313d2SEric Christopher ] 324cee313d2SEric Christopher 325cee313d2SEric ChristopherL1: 326cee313d2SEric Christopher ret void 327cee313d2SEric ChristopherL2: 328cee313d2SEric Christopher call void @f(i1 %cmp) 329cee313d2SEric Christopher ret void 330cee313d2SEric ChristopherL3: 331cee313d2SEric Christopher ret void 332cee313d2SEric Christopher} 333cee313d2SEric Christopher 334cee313d2SEric Christopher; Make sure that we don't PRE a non-speculable load across a guard. 335cee313d2SEric Christopherdefine void @unsafe_pre_across_guard(i8* %p, i1 %load.is.valid) { 336cee313d2SEric Christopher; CHECK-LABEL: @unsafe_pre_across_guard( 337f24175fcSPhilip Reames; CHECK-NEXT: entry: 338f24175fcSPhilip Reames; CHECK-NEXT: br label [[LOOP:%.*]] 339cee313d2SEric Christopher; CHECK: loop: 340f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[LOAD_IS_VALID:%.*]]) [ "deopt"() ] 341f24175fcSPhilip Reames; CHECK-NEXT: [[LOADED:%.*]] = load i8, i8* [[P:%.*]], align 1 342f24175fcSPhilip Reames; CHECK-NEXT: [[CONTINUE:%.*]] = icmp eq i8 [[LOADED]], 0 343f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[CONTINUE]], label [[EXIT:%.*]], label [[LOOP]] 344f24175fcSPhilip Reames; CHECK: exit: 345f24175fcSPhilip Reames; CHECK-NEXT: ret void 346f24175fcSPhilip Reames; 347cee313d2SEric Christopherentry: 348cee313d2SEric Christopher br label %loop 349cee313d2SEric Christopher 350cee313d2SEric Christopherloop: ; preds = %loop, %entry 351cee313d2SEric Christopher call void (i1, ...) @llvm.experimental.guard(i1 %load.is.valid) [ "deopt"() ] 352cee313d2SEric Christopher %loaded = load i8, i8* %p 353cee313d2SEric Christopher %continue = icmp eq i8 %loaded, 0 354cee313d2SEric Christopher br i1 %continue, label %exit, label %loop 355cee313d2SEric Christopher 356cee313d2SEric Christopherexit: ; preds = %loop 357cee313d2SEric Christopher ret void 358cee313d2SEric Christopher} 359cee313d2SEric Christopher 360cee313d2SEric Christopher; Make sure that we can safely PRE a speculable load across a guard. 361*e75a2dfeSPhilip Reamesdefine void @safe_pre_across_guard(i8* noalias nocapture readonly dereferenceable(8) %p, i1 %load.is.valid) nofree nosync { 362cee313d2SEric Christopher; CHECK-LABEL: @safe_pre_across_guard( 363f24175fcSPhilip Reames; CHECK-NEXT: entry: 364f24175fcSPhilip Reames; CHECK-NEXT: [[LOADED_PR:%.*]] = load i8, i8* [[P:%.*]], align 1 365f24175fcSPhilip Reames; CHECK-NEXT: br label [[LOOP:%.*]] 366cee313d2SEric Christopher; CHECK: loop: 367f24175fcSPhilip Reames; CHECK-NEXT: [[LOADED:%.*]] = phi i8 [ [[LOADED]], [[LOOP]] ], [ [[LOADED_PR]], [[ENTRY:%.*]] ] 368f24175fcSPhilip Reames; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[LOAD_IS_VALID:%.*]]) [ "deopt"() ] 369f24175fcSPhilip Reames; CHECK-NEXT: [[CONTINUE:%.*]] = icmp eq i8 [[LOADED]], 0 370f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[CONTINUE]], label [[EXIT:%.*]], label [[LOOP]] 371f24175fcSPhilip Reames; CHECK: exit: 372f24175fcSPhilip Reames; CHECK-NEXT: ret void 373f24175fcSPhilip Reames; 374cee313d2SEric Christopher 375cee313d2SEric Christopherentry: 376cee313d2SEric Christopher br label %loop 377cee313d2SEric Christopher 378cee313d2SEric Christopherloop: ; preds = %loop, %entry 379cee313d2SEric Christopher call void (i1, ...) @llvm.experimental.guard(i1 %load.is.valid) [ "deopt"() ] 380cee313d2SEric Christopher %loaded = load i8, i8* %p 381cee313d2SEric Christopher %continue = icmp eq i8 %loaded, 0 382cee313d2SEric Christopher br i1 %continue, label %exit, label %loop 383cee313d2SEric Christopher 384cee313d2SEric Christopherexit: ; preds = %loop 385cee313d2SEric Christopher ret void 386cee313d2SEric Christopher} 387cee313d2SEric Christopher 388cee313d2SEric Christopher; Make sure that we don't PRE a non-speculable load across a call which may 389cee313d2SEric Christopher; alias with the load. 390cee313d2SEric Christopherdefine void @unsafe_pre_across_call(i8* %p) { 391cee313d2SEric Christopher; CHECK-LABEL: @unsafe_pre_across_call( 392f24175fcSPhilip Reames; CHECK-NEXT: entry: 393f24175fcSPhilip Reames; CHECK-NEXT: br label [[LOOP:%.*]] 394cee313d2SEric Christopher; CHECK: loop: 395f24175fcSPhilip Reames; CHECK-NEXT: [[TMP0:%.*]] = call i32 @f1() 396f24175fcSPhilip Reames; CHECK-NEXT: [[LOADED:%.*]] = load i8, i8* [[P:%.*]], align 1 397f24175fcSPhilip Reames; CHECK-NEXT: [[CONTINUE:%.*]] = icmp eq i8 [[LOADED]], 0 398f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[CONTINUE]], label [[EXIT:%.*]], label [[LOOP]] 399f24175fcSPhilip Reames; CHECK: exit: 400f24175fcSPhilip Reames; CHECK-NEXT: ret void 401f24175fcSPhilip Reames; 402cee313d2SEric Christopherentry: 403cee313d2SEric Christopher br label %loop 404cee313d2SEric Christopher 405cee313d2SEric Christopherloop: ; preds = %loop, %entry 406cee313d2SEric Christopher call i32 @f1() 407cee313d2SEric Christopher %loaded = load i8, i8* %p 408cee313d2SEric Christopher %continue = icmp eq i8 %loaded, 0 409cee313d2SEric Christopher br i1 %continue, label %exit, label %loop 410cee313d2SEric Christopher 411cee313d2SEric Christopherexit: ; preds = %loop 412cee313d2SEric Christopher ret void 413cee313d2SEric Christopher} 414cee313d2SEric Christopher 415cee313d2SEric Christopher; Make sure that we can safely PRE a speculable load across a call. 416*e75a2dfeSPhilip Reamesdefine void @safe_pre_across_call(i8* noalias nocapture readonly dereferenceable(8) %p) nofree nosync { 417cee313d2SEric Christopher; CHECK-LABEL: @safe_pre_across_call( 418f24175fcSPhilip Reames; CHECK-NEXT: entry: 419f24175fcSPhilip Reames; CHECK-NEXT: [[LOADED_PR:%.*]] = load i8, i8* [[P:%.*]], align 1 420f24175fcSPhilip Reames; CHECK-NEXT: br label [[LOOP:%.*]] 421cee313d2SEric Christopher; CHECK: loop: 422f24175fcSPhilip Reames; CHECK-NEXT: [[LOADED:%.*]] = phi i8 [ [[LOADED]], [[LOOP]] ], [ [[LOADED_PR]], [[ENTRY:%.*]] ] 423f24175fcSPhilip Reames; CHECK-NEXT: [[TMP0:%.*]] = call i32 @f1() 424f24175fcSPhilip Reames; CHECK-NEXT: [[CONTINUE:%.*]] = icmp eq i8 [[LOADED]], 0 425f24175fcSPhilip Reames; CHECK-NEXT: br i1 [[CONTINUE]], label [[EXIT:%.*]], label [[LOOP]] 426f24175fcSPhilip Reames; CHECK: exit: 427f24175fcSPhilip Reames; CHECK-NEXT: ret void 428f24175fcSPhilip Reames; 429cee313d2SEric Christopher 430cee313d2SEric Christopherentry: 431cee313d2SEric Christopher br label %loop 432cee313d2SEric Christopher 433cee313d2SEric Christopherloop: ; preds = %loop, %entry 434cee313d2SEric Christopher call i32 @f1() 435cee313d2SEric Christopher %loaded = load i8, i8* %p 436cee313d2SEric Christopher %continue = icmp eq i8 %loaded, 0 437cee313d2SEric Christopher br i1 %continue, label %exit, label %loop 438cee313d2SEric Christopher 439cee313d2SEric Christopherexit: ; preds = %loop 440cee313d2SEric Christopher ret void 441cee313d2SEric Christopher} 442