1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -print-predicateinfo -disable-output < %s 2>&1 | FileCheck %s 3 4declare void @foo(i1) 5declare void @bar(i32) 6declare void @llvm.assume(i1) 7 8define void @testor(i32 %x, i32 %y) { 9; CHECK-LABEL: @testor( 10; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 11; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 12; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]] 13; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]]) 14; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]]) 15; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]]) 16; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]]) 17; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]]) 18; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER:%.*]] 19; CHECK: oneof: 20; CHECK-NEXT: call void @foo(i1 [[XZ]]) 21; CHECK-NEXT: call void @foo(i1 [[YZ]]) 22; CHECK-NEXT: call void @bar(i32 [[X]]) 23; CHECK-NEXT: call void @bar(i32 [[Y]]) 24; CHECK-NEXT: ret void 25; CHECK: neither: 26; CHECK-NEXT: call void @foo(i1 [[XZ_0]]) 27; CHECK-NEXT: call void @foo(i1 [[YZ_0]]) 28; CHECK-NEXT: call void @bar(i32 [[X_0]]) 29; CHECK-NEXT: call void @bar(i32 [[Y_0]]) 30; CHECK-NEXT: call void @foo(i1 [[Z_0]]) 31; CHECK-NEXT: ret void 32; 33 %xz = icmp eq i32 %x, 0 34 %yz = icmp eq i32 %y, 0 35 %z = or i1 %xz, %yz 36 br i1 %z, label %oneof, label %neither 37oneof: 38;; Should not insert on the true edge for or 39 call void @foo(i1 %xz) 40 call void @foo(i1 %yz) 41 call void @bar(i32 %x) 42 call void @bar(i32 %y) 43 ret void 44neither: 45 call void @foo(i1 %xz) 46 call void @foo(i1 %yz) 47 call void @bar(i32 %x) 48 call void @bar(i32 %y) 49 call void @foo(i1 %z) 50 ret void 51} 52define void @testand(i32 %x, i32 %y) { 53; CHECK-LABEL: @testand( 54; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 55; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 56; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]] 57; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]]) 58; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]]) 59; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]]) 60; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]]) 61; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]]) 62; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]] 63; CHECK: both: 64; CHECK-NEXT: call void @foo(i1 [[XZ_0]]) 65; CHECK-NEXT: call void @foo(i1 [[YZ_0]]) 66; CHECK-NEXT: call void @bar(i32 [[X_0]]) 67; CHECK-NEXT: call void @bar(i32 [[Y_0]]) 68; CHECK-NEXT: ret void 69; CHECK: nope: 70; CHECK-NEXT: call void @foo(i1 [[XZ]]) 71; CHECK-NEXT: call void @foo(i1 [[YZ]]) 72; CHECK-NEXT: call void @bar(i32 [[X]]) 73; CHECK-NEXT: call void @bar(i32 [[Y]]) 74; CHECK-NEXT: call void @foo(i1 [[Z_0]]) 75; CHECK-NEXT: ret void 76; 77 %xz = icmp eq i32 %x, 0 78 %yz = icmp eq i32 %y, 0 79 %z = and i1 %xz, %yz 80 br i1 %z, label %both, label %nope 81both: 82 call void @foo(i1 %xz) 83 call void @foo(i1 %yz) 84 call void @bar(i32 %x) 85 call void @bar(i32 %y) 86 ret void 87nope: 88;; Should not insert on the false edge for and 89 call void @foo(i1 %xz) 90 call void @foo(i1 %yz) 91 call void @bar(i32 %x) 92 call void @bar(i32 %y) 93 call void @foo(i1 %z) 94 ret void 95} 96define void @testandsame(i32 %x, i32 %y) { 97; CHECK-LABEL: @testandsame( 98; CHECK-NEXT: [[XGT:%.*]] = icmp sgt i32 [[X:%.*]], 0 99; CHECK-NEXT: [[XLT:%.*]] = icmp slt i32 [[X]], 100 100; CHECK-NEXT: [[Z:%.*]] = and i1 [[XGT]], [[XLT]] 101; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XGT]]) 102; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]]) 103; CHECK: [[X_0_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X_0]]) 104; CHECK: [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XLT]]) 105; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]]) 106; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]] 107; CHECK: both: 108; CHECK-NEXT: call void @foo(i1 [[XGT_0]]) 109; CHECK-NEXT: call void @foo(i1 [[XLT_0]]) 110; CHECK-NEXT: call void @bar(i32 [[X_0_1]]) 111; CHECK-NEXT: ret void 112; CHECK: nope: 113; CHECK-NEXT: call void @foo(i1 [[XGT]]) 114; CHECK-NEXT: call void @foo(i1 [[XLT]]) 115; CHECK-NEXT: call void @foo(i1 [[Z_0]]) 116; CHECK-NEXT: ret void 117; 118 %xgt = icmp sgt i32 %x, 0 119 %xlt = icmp slt i32 %x, 100 120 %z = and i1 %xgt, %xlt 121 br i1 %z, label %both, label %nope 122both: 123 call void @foo(i1 %xgt) 124 call void @foo(i1 %xlt) 125 call void @bar(i32 %x) 126 ret void 127nope: 128 call void @foo(i1 %xgt) 129 call void @foo(i1 %xlt) 130 call void @foo(i1 %z) 131 ret void 132} 133 134define void @testandassume(i32 %x, i32 %y) { 135; CHECK-LABEL: @testandassume( 136; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 137; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 138; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]] 139; CHECK-NEXT: call void @llvm.assume(i1 [[Z]]) 140; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]]) 141; CHECK: [[TMP2:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]]) 142; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]]) 143; CHECK: [[TMP4:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]]) 144; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]]) 145; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP5]]) 146; CHECK: [[DOT01:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP4]]) 147; CHECK: [[DOT02:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP3]]) 148; CHECK: [[DOT03:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP2]]) 149; CHECK: [[DOT04:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP1]]) 150; CHECK-NEXT: br i1 [[TMP1]], label [[BOTH:%.*]], label [[NOPE:%.*]] 151; CHECK: both: 152; CHECK-NEXT: call void @foo(i1 [[DOT0]]) 153; CHECK-NEXT: call void @foo(i1 [[DOT02]]) 154; CHECK-NEXT: call void @bar(i32 [[DOT01]]) 155; CHECK-NEXT: call void @bar(i32 [[DOT03]]) 156; CHECK-NEXT: ret void 157; CHECK: nope: 158; CHECK-NEXT: call void @foo(i1 [[DOT04]]) 159; CHECK-NEXT: ret void 160; 161 %xz = icmp eq i32 %x, 0 162 %yz = icmp eq i32 %y, 0 163 %z = and i1 %xz, %yz 164 call void @llvm.assume(i1 %z) 165 br i1 %z, label %both, label %nope 166both: 167 call void @foo(i1 %xz) 168 call void @foo(i1 %yz) 169 call void @bar(i32 %x) 170 call void @bar(i32 %y) 171 ret void 172nope: 173 call void @foo(i1 %z) 174 ret void 175} 176 177;; Unlike and/or for branches, assume is *always* true, so we only match and for it 178define void @testorassume(i32 %x, i32 %y) { 179; 180; CHECK-LABEL: @testorassume( 181; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 182; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 183; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]] 184; CHECK-NEXT: call void @llvm.assume(i1 [[Z]]) 185; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]]) 186; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]] 187; CHECK: both: 188; CHECK-NEXT: call void @foo(i1 [[XZ]]) 189; CHECK-NEXT: call void @foo(i1 [[YZ]]) 190; CHECK-NEXT: call void @bar(i32 [[X]]) 191; CHECK-NEXT: call void @bar(i32 [[Y]]) 192; CHECK-NEXT: ret void 193; CHECK: nope: 194; CHECK-NEXT: call void @foo(i1 [[Z_0]]) 195; CHECK-NEXT: ret void 196; 197 %xz = icmp eq i32 %x, 0 198 %yz = icmp eq i32 %y, 0 199 %z = or i1 %xz, %yz 200 call void @llvm.assume(i1 %z) 201 br i1 %z, label %both, label %nope 202both: 203 call void @foo(i1 %xz) 204 call void @foo(i1 %yz) 205 call void @bar(i32 %x) 206 call void @bar(i32 %y) 207 ret void 208nope: 209 call void @foo(i1 %z) 210 ret void 211} 212