| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-inst-comments | |
| ; RUN: opt -passes='print<predicate-info>' -disable-output < %s 2>&1 | FileCheck %s | |
| declare void @foo(i1) | |
| declare void @bar(i32) | |
| declare void @llvm.assume(i1) | |
| define void @test_or(i32 %x, i32 %y) { | |
| ; CHECK-LABEL: @test_or( | |
| ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 | |
| ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 | |
| ; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = or i1 [[XZ]], [[YZ]] Edge: [label [[TMP0:%.*]],label [[NEITHER:%.*]]], RenamedOp: [[Z]] } | |
| ; CHECK-NEXT: [[Z_0:%.*]] = bitcast i1 [[Z]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[NEITHER]]], RenamedOp: [[XZ]] } | |
| ; CHECK-NEXT: [[XZ_0:%.*]] = bitcast i1 [[XZ]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[NEITHER]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[X_0:%.*]] = bitcast i32 [[X]] to i32 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label [[NEITHER]]], RenamedOp: [[YZ]] } | |
| ; CHECK-NEXT: [[YZ_0:%.*]] = bitcast i1 [[YZ]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label [[NEITHER]]], RenamedOp: [[Y]] } | |
| ; CHECK-NEXT: [[Y_0:%.*]] = bitcast i32 [[Y]] to i32 | |
| ; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER]] | |
| ; CHECK: oneof: | |
| ; CHECK-NEXT: call void @foo(i1 [[XZ]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[YZ]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[X]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[Y]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: neither: | |
| ; CHECK-NEXT: call void @foo(i1 [[XZ_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[YZ_0]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[X_0]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[Y_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[Z_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %xz = icmp eq i32 %x, 0 | |
| %yz = icmp eq i32 %y, 0 | |
| %z = or i1 %xz, %yz | |
| br i1 %z, label %oneof, label %neither | |
| oneof: | |
| ;; Should not insert on the true edge for or | |
| call void @foo(i1 %xz) | |
| call void @foo(i1 %yz) | |
| call void @bar(i32 %x) | |
| call void @bar(i32 %y) | |
| ret void | |
| neither: | |
| call void @foo(i1 %xz) | |
| call void @foo(i1 %yz) | |
| call void @bar(i32 %x) | |
| call void @bar(i32 %y) | |
| call void @foo(i1 %z) | |
| ret void | |
| } | |
| define void @test_or_logical(i32 %x, i32 %y) { | |
| ; CHECK-LABEL: @test_or_logical( | |
| ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 | |
| ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 | |
| ; CHECK-NEXT: [[Z:%.*]] = select i1 [[XZ]], i1 true, i1 [[YZ]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = select i1 [[XZ]], i1 true, i1 [[YZ]] Edge: [label [[TMP0:%.*]],label [[NEITHER:%.*]]], RenamedOp: [[Z]] } | |
| ; CHECK-NEXT: [[Z_0:%.*]] = bitcast i1 [[Z]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[NEITHER]]], RenamedOp: [[XZ]] } | |
| ; CHECK-NEXT: [[XZ_0:%.*]] = bitcast i1 [[XZ]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[NEITHER]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[X_0:%.*]] = bitcast i32 [[X]] to i32 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label [[NEITHER]]], RenamedOp: [[YZ]] } | |
| ; CHECK-NEXT: [[YZ_0:%.*]] = bitcast i1 [[YZ]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label [[NEITHER]]], RenamedOp: [[Y]] } | |
| ; CHECK-NEXT: [[Y_0:%.*]] = bitcast i32 [[Y]] to i32 | |
| ; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER]] | |
| ; CHECK: oneof: | |
| ; CHECK-NEXT: call void @foo(i1 [[XZ]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[YZ]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[X]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[Y]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: neither: | |
| ; CHECK-NEXT: call void @foo(i1 [[XZ_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[YZ_0]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[X_0]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[Y_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[Z_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %xz = icmp eq i32 %x, 0 | |
| %yz = icmp eq i32 %y, 0 | |
| %z = select i1 %xz, i1 true, i1 %yz | |
| br i1 %z, label %oneof, label %neither | |
| oneof: | |
| ;; Should not insert on the true edge for or | |
| call void @foo(i1 %xz) | |
| call void @foo(i1 %yz) | |
| call void @bar(i32 %x) | |
| call void @bar(i32 %y) | |
| ret void | |
| neither: | |
| call void @foo(i1 %xz) | |
| call void @foo(i1 %yz) | |
| call void @bar(i32 %x) | |
| call void @bar(i32 %y) | |
| call void @foo(i1 %z) | |
| ret void | |
| } | |
| define void @test_and(i32 %x, i32 %y) { | |
| ; CHECK-LABEL: @test_and( | |
| ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 | |
| ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 | |
| ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = and i1 [[XZ]], [[YZ]] Edge: [label [[TMP0:%.*]],label [[NOPE:%.*]]], RenamedOp: [[Z]] } | |
| ; CHECK-NEXT: [[Z_0:%.*]] = bitcast i1 [[Z]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH:%.*]]], RenamedOp: [[XZ]] } | |
| ; CHECK-NEXT: [[XZ_0:%.*]] = bitcast i1 [[XZ]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[X_0:%.*]] = bitcast i32 [[X]] to i32 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[YZ]] } | |
| ; CHECK-NEXT: [[YZ_0:%.*]] = bitcast i1 [[YZ]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[Y]] } | |
| ; CHECK-NEXT: [[Y_0:%.*]] = bitcast i32 [[Y]] to i32 | |
| ; CHECK-NEXT: br i1 [[Z]], label [[BOTH]], label [[NOPE]] | |
| ; CHECK: both: | |
| ; CHECK-NEXT: call void @foo(i1 [[XZ_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[YZ_0]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[X_0]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[Y_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: nope: | |
| ; CHECK-NEXT: call void @foo(i1 [[XZ]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[YZ]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[X]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[Y]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[Z_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %xz = icmp eq i32 %x, 0 | |
| %yz = icmp eq i32 %y, 0 | |
| %z = and i1 %xz, %yz | |
| br i1 %z, label %both, label %nope | |
| both: | |
| call void @foo(i1 %xz) | |
| call void @foo(i1 %yz) | |
| call void @bar(i32 %x) | |
| call void @bar(i32 %y) | |
| ret void | |
| nope: | |
| ;; Should not insert on the false edge for and | |
| call void @foo(i1 %xz) | |
| call void @foo(i1 %yz) | |
| call void @bar(i32 %x) | |
| call void @bar(i32 %y) | |
| call void @foo(i1 %z) | |
| ret void | |
| } | |
| define void @test_and_logical(i32 %x, i32 %y) { | |
| ; CHECK-LABEL: @test_and_logical( | |
| ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 | |
| ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 | |
| ; CHECK-NEXT: [[Z:%.*]] = select i1 [[XZ]], i1 [[YZ]], i1 false | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = select i1 [[XZ]], i1 [[YZ]], i1 false Edge: [label [[TMP0:%.*]],label [[NOPE:%.*]]], RenamedOp: [[Z]] } | |
| ; CHECK-NEXT: [[Z_0:%.*]] = bitcast i1 [[Z]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH:%.*]]], RenamedOp: [[XZ]] } | |
| ; CHECK-NEXT: [[XZ_0:%.*]] = bitcast i1 [[XZ]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[X_0:%.*]] = bitcast i32 [[X]] to i32 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[YZ]] } | |
| ; CHECK-NEXT: [[YZ_0:%.*]] = bitcast i1 [[YZ]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[Y]] } | |
| ; CHECK-NEXT: [[Y_0:%.*]] = bitcast i32 [[Y]] to i32 | |
| ; CHECK-NEXT: br i1 [[Z]], label [[BOTH]], label [[NOPE]] | |
| ; CHECK: both: | |
| ; CHECK-NEXT: call void @foo(i1 [[XZ_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[YZ_0]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[X_0]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[Y_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: nope: | |
| ; CHECK-NEXT: call void @foo(i1 [[XZ]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[YZ]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[X]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[Y]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[Z_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %xz = icmp eq i32 %x, 0 | |
| %yz = icmp eq i32 %y, 0 | |
| %z = select i1 %xz, i1 %yz, i1 false | |
| br i1 %z, label %both, label %nope | |
| both: | |
| call void @foo(i1 %xz) | |
| call void @foo(i1 %yz) | |
| call void @bar(i32 %x) | |
| call void @bar(i32 %y) | |
| ret void | |
| nope: | |
| ;; Should not insert on the false edge for and | |
| call void @foo(i1 %xz) | |
| call void @foo(i1 %yz) | |
| call void @bar(i32 %x) | |
| call void @bar(i32 %y) | |
| call void @foo(i1 %z) | |
| ret void | |
| } | |
| define void @testandsame(i32 %x, i32 %y) { | |
| ; CHECK-LABEL: @testandsame( | |
| ; CHECK-NEXT: [[XGT:%.*]] = icmp sgt i32 [[X:%.*]], 0 | |
| ; CHECK-NEXT: [[XLT:%.*]] = icmp slt i32 [[X]], 100 | |
| ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XGT]], [[XLT]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = and i1 [[XGT]], [[XLT]] Edge: [label [[TMP0:%.*]],label [[NOPE:%.*]]], RenamedOp: [[Z]] } | |
| ; CHECK-NEXT: [[Z_0:%.*]] = bitcast i1 [[Z]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XGT]] = icmp sgt i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH:%.*]]], RenamedOp: [[XGT]] } | |
| ; CHECK-NEXT: [[XGT_0:%.*]] = bitcast i1 [[XGT]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XGT]] = icmp sgt i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[X_0:%.*]] = bitcast i32 [[X]] to i32 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XLT]] = icmp slt i32 [[X]], 100 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[X_0_1:%.*]] = bitcast i32 [[X_0]] to i32 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XLT]] = icmp slt i32 [[X]], 100 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[XLT]] } | |
| ; CHECK-NEXT: [[XLT_0:%.*]] = bitcast i1 [[XLT]] to i1 | |
| ; CHECK-NEXT: br i1 [[Z]], label [[BOTH]], label [[NOPE]] | |
| ; CHECK: both: | |
| ; CHECK-NEXT: call void @foo(i1 [[XGT_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[XLT_0]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[X_0_1]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: nope: | |
| ; CHECK-NEXT: call void @foo(i1 [[XGT]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[XLT]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[Z_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %xgt = icmp sgt i32 %x, 0 | |
| %xlt = icmp slt i32 %x, 100 | |
| %z = and i1 %xgt, %xlt | |
| br i1 %z, label %both, label %nope | |
| both: | |
| call void @foo(i1 %xgt) | |
| call void @foo(i1 %xlt) | |
| call void @bar(i32 %x) | |
| ret void | |
| nope: | |
| call void @foo(i1 %xgt) | |
| call void @foo(i1 %xlt) | |
| call void @foo(i1 %z) | |
| ret void | |
| } | |
| define void @testandassume(i32 %x, i32 %y) { | |
| ; CHECK-LABEL: @testandassume( | |
| ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 | |
| ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 | |
| ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]] | |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[Z]]) | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[YZ]] = icmp eq i32 [[Y]], 0, RenamedOp: [[Y]] } | |
| ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 [[Y]] to i32 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[YZ]] = icmp eq i32 [[Y]], 0, RenamedOp: [[YZ]] } | |
| ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i1 [[YZ]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[XZ]] = icmp eq i32 [[X]], 0, RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[X]] to i32 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[XZ]] = icmp eq i32 [[X]], 0, RenamedOp: [[XZ]] } | |
| ; CHECK-NEXT: [[TMP4:%.*]] = bitcast i1 [[XZ]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[Z]] = and i1 [[XZ]], [[YZ]], RenamedOp: [[Z]] } | |
| ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i1 [[Z]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = and i1 [[XZ]], [[YZ]] Edge: [label [[TMP0:%.*]],label [[NOPE:%.*]]], RenamedOp: [[TMP5]] } | |
| ; CHECK-NEXT: [[DOT0:%.*]] = bitcast i1 [[TMP5]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH:%.*]]], RenamedOp: [[XZ]] } | |
| ; CHECK-NEXT: [[DOT01:%.*]] = bitcast i1 [[TMP4]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XZ]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[DOT02:%.*]] = bitcast i32 [[TMP3]] to i32 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[YZ]] } | |
| ; CHECK-NEXT: [[DOT03:%.*]] = bitcast i1 [[TMP2]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[YZ]] = icmp eq i32 [[Y]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[Y]] } | |
| ; CHECK-NEXT: [[DOT04:%.*]] = bitcast i32 [[TMP1]] to i32 | |
| ; CHECK-NEXT: br i1 [[TMP5]], label [[BOTH]], label [[NOPE]] | |
| ; CHECK: both: | |
| ; CHECK-NEXT: call void @foo(i1 [[DOT01]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[DOT03]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[DOT02]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[DOT04]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: nope: | |
| ; CHECK-NEXT: call void @foo(i1 [[DOT0]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %xz = icmp eq i32 %x, 0 | |
| %yz = icmp eq i32 %y, 0 | |
| %z = and i1 %xz, %yz | |
| call void @llvm.assume(i1 %z) | |
| br i1 %z, label %both, label %nope | |
| both: | |
| call void @foo(i1 %xz) | |
| call void @foo(i1 %yz) | |
| call void @bar(i32 %x) | |
| call void @bar(i32 %y) | |
| ret void | |
| nope: | |
| call void @foo(i1 %z) | |
| ret void | |
| } | |
| ;; Unlike and/or for branches, assume is *always* true, so we only match and for it | |
| define void @testorassume(i32 %x, i32 %y) { | |
| ; | |
| ; CHECK-LABEL: @testorassume( | |
| ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 | |
| ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 | |
| ; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]] | |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[Z]]) | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[Z]] = or i1 [[XZ]], [[YZ]], RenamedOp: [[Z]] } | |
| ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i1 [[Z]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[Z]] = or i1 [[XZ]], [[YZ]] Edge: [label [[TMP0:%.*]],label [[NOPE:%.*]]], RenamedOp: [[TMP1]] } | |
| ; CHECK-NEXT: [[DOT0:%.*]] = bitcast i1 [[TMP1]] to i1 | |
| ; CHECK-NEXT: br i1 [[TMP1]], label [[BOTH:%.*]], label [[NOPE]] | |
| ; CHECK: both: | |
| ; CHECK-NEXT: call void @foo(i1 [[XZ]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[YZ]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[X]]) | |
| ; CHECK-NEXT: call void @bar(i32 [[Y]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: nope: | |
| ; CHECK-NEXT: call void @foo(i1 [[DOT0]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %xz = icmp eq i32 %x, 0 | |
| %yz = icmp eq i32 %y, 0 | |
| %z = or i1 %xz, %yz | |
| call void @llvm.assume(i1 %z) | |
| br i1 %z, label %both, label %nope | |
| both: | |
| call void @foo(i1 %xz) | |
| call void @foo(i1 %yz) | |
| call void @bar(i32 %x) | |
| call void @bar(i32 %y) | |
| ret void | |
| nope: | |
| call void @foo(i1 %z) | |
| ret void | |
| } | |
| define void @test_and_one_unknown_cond(i32 %x, i1 %c1) { | |
| ; CHECK-LABEL: @test_and_one_unknown_cond( | |
| ; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[X:%.*]], 0 | |
| ; CHECK-NEXT: [[A:%.*]] = and i1 [[C1:%.*]], [[C2]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A]] = and i1 [[C1]], [[C2]] Edge: [label [[TMP0:%.*]],label [[BOTH:%.*]]], RenamedOp: [[A]] } | |
| ; CHECK-NEXT: [[A_0:%.*]] = bitcast i1 [[A]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A]] = and i1 [[C1]], [[C2]] Edge: [label [[TMP0]],label [[NOPE:%.*]]], RenamedOp: [[A]] } | |
| ; CHECK-NEXT: [[A_1:%.*]] = bitcast i1 [[A]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison:i1 [[C1]] Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[C1]] } | |
| ; CHECK-NEXT: [[C1_0:%.*]] = bitcast i1 [[C1]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[C2]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[C2]] } | |
| ; CHECK-NEXT: [[C2_0:%.*]] = bitcast i1 [[C2]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[C2]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[X_0:%.*]] = bitcast i32 [[X]] to i32 | |
| ; CHECK-NEXT: br i1 [[A]], label [[BOTH]], label [[NOPE]] | |
| ; CHECK: both: | |
| ; CHECK-NEXT: call void @bar(i32 [[X_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C1_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C2_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: nope: | |
| ; CHECK-NEXT: call void @bar(i32 [[X]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A_1]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %c2 = icmp eq i32 %x, 0 | |
| %a = and i1 %c1, %c2 | |
| br i1 %a, label %both, label %nope | |
| both: | |
| call void @bar(i32 %x) | |
| call void @foo(i1 %c1) | |
| call void @foo(i1 %c2) | |
| call void @foo(i1 %a) | |
| ret void | |
| nope: | |
| call void @bar(i32 %x) | |
| call void @foo(i1 %c1) | |
| call void @foo(i1 %c2) | |
| call void @foo(i1 %a) | |
| ret void | |
| } | |
| define void @test_or_one_unknown_cond(i32 %x, i1 %c1) { | |
| ; CHECK-LABEL: @test_or_one_unknown_cond( | |
| ; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[X:%.*]], 0 | |
| ; CHECK-NEXT: [[A:%.*]] = or i1 [[C1:%.*]], [[C2]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A]] = or i1 [[C1]], [[C2]] Edge: [label [[TMP0:%.*]],label [[NOPE:%.*]]], RenamedOp: [[A]] } | |
| ; CHECK-NEXT: [[A_0:%.*]] = bitcast i1 [[A]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A]] = or i1 [[C1]], [[C2]] Edge: [label [[TMP0]],label [[BOTH_INVERTED:%.*]]], RenamedOp: [[A]] } | |
| ; CHECK-NEXT: [[A_1:%.*]] = bitcast i1 [[A]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison:i1 [[C1]] Edge: [label [[TMP0]],label [[BOTH_INVERTED]]], RenamedOp: [[C1]] } | |
| ; CHECK-NEXT: [[C1_0:%.*]] = bitcast i1 [[C1]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[C2]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH_INVERTED]]], RenamedOp: [[C2]] } | |
| ; CHECK-NEXT: [[C2_0:%.*]] = bitcast i1 [[C2]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[C2]] = icmp eq i32 [[X]], 0 Edge: [label [[TMP0]],label [[BOTH_INVERTED]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[X_0:%.*]] = bitcast i32 [[X]] to i32 | |
| ; CHECK-NEXT: br i1 [[A]], label [[NOPE]], label [[BOTH_INVERTED]] | |
| ; CHECK: both_inverted: | |
| ; CHECK-NEXT: call void @bar(i32 [[X_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C1_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C2_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A_1]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: nope: | |
| ; CHECK-NEXT: call void @bar(i32 [[X]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %c2 = icmp eq i32 %x, 0 | |
| %a = or i1 %c1, %c2 | |
| br i1 %a, label %nope, label %both_inverted | |
| both_inverted: | |
| call void @bar(i32 %x) | |
| call void @foo(i1 %c1) | |
| call void @foo(i1 %c2) | |
| call void @foo(i1 %a) | |
| ret void | |
| nope: | |
| call void @bar(i32 %x) | |
| call void @foo(i1 %c1) | |
| call void @foo(i1 %c2) | |
| call void @foo(i1 %a) | |
| ret void | |
| } | |
| define void @test_and_chain(i1 %a, i1 %b, i1 %c) { | |
| ; CHECK-LABEL: @test_and_chain( | |
| ; CHECK-NEXT: [[AND1:%.*]] = and i1 [[A:%.*]], [[B:%.*]] | |
| ; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[C:%.*]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[AND2]] = and i1 [[AND1]], [[C]] Edge: [label [[TMP0:%.*]],label [[IF:%.*]]], RenamedOp: [[AND2]] } | |
| ; CHECK-NEXT: [[AND2_0:%.*]] = bitcast i1 [[AND2]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[AND2]] = and i1 [[AND1]], [[C]] Edge: [label [[TMP0]],label [[ELSE:%.*]]], RenamedOp: [[AND2]] } | |
| ; CHECK-NEXT: [[AND2_1:%.*]] = bitcast i1 [[AND2]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[AND1]] = and i1 [[A]], [[B]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[AND1]] } | |
| ; CHECK-NEXT: [[AND1_0:%.*]] = bitcast i1 [[AND1]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison:i1 [[A]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A]] } | |
| ; CHECK-NEXT: [[A_0:%.*]] = bitcast i1 [[A]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison:i1 [[B]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[B]] } | |
| ; CHECK-NEXT: [[B_0:%.*]] = bitcast i1 [[B]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison:i1 [[C]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[C]] } | |
| ; CHECK-NEXT: [[C_0:%.*]] = bitcast i1 [[C]] to i1 | |
| ; CHECK-NEXT: br i1 [[AND2]], label [[IF]], label [[ELSE]] | |
| ; CHECK: if: | |
| ; CHECK-NEXT: call void @foo(i1 [[A_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[B_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[AND1_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[AND2_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: else: | |
| ; CHECK-NEXT: call void @foo(i1 [[A]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[B]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[AND1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[AND2_1]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %and1 = and i1 %a, %b | |
| %and2 = and i1 %and1, %c | |
| br i1 %and2, label %if, label %else | |
| if: | |
| call void @foo(i1 %a) | |
| call void @foo(i1 %b) | |
| call void @foo(i1 %c) | |
| call void @foo(i1 %and1) | |
| call void @foo(i1 %and2) | |
| ret void | |
| else: | |
| call void @foo(i1 %a) | |
| call void @foo(i1 %b) | |
| call void @foo(i1 %c) | |
| call void @foo(i1 %and1) | |
| call void @foo(i1 %and2) | |
| ret void | |
| } | |
| define void @test_or_chain(i1 %a, i1 %b, i1 %c) { | |
| ; CHECK-LABEL: @test_or_chain( | |
| ; CHECK-NEXT: [[OR1:%.*]] = or i1 [[A:%.*]], [[B:%.*]] | |
| ; CHECK-NEXT: [[OR2:%.*]] = or i1 [[OR1]], [[C:%.*]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[OR2]] = or i1 [[OR1]], [[C]] Edge: [label [[TMP0:%.*]],label [[IF:%.*]]], RenamedOp: [[OR2]] } | |
| ; CHECK-NEXT: [[OR2_0:%.*]] = bitcast i1 [[OR2]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[OR2]] = or i1 [[OR1]], [[C]] Edge: [label [[TMP0]],label [[ELSE:%.*]]], RenamedOp: [[OR2]] } | |
| ; CHECK-NEXT: [[OR2_1:%.*]] = bitcast i1 [[OR2]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[OR1]] = or i1 [[A]], [[B]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[OR1]] } | |
| ; CHECK-NEXT: [[OR1_0:%.*]] = bitcast i1 [[OR1]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison:i1 [[A]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[A]] } | |
| ; CHECK-NEXT: [[A_0:%.*]] = bitcast i1 [[A]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison:i1 [[B]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[B]] } | |
| ; CHECK-NEXT: [[B_0:%.*]] = bitcast i1 [[B]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison:i1 [[C]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[C]] } | |
| ; CHECK-NEXT: [[C_0:%.*]] = bitcast i1 [[C]] to i1 | |
| ; CHECK-NEXT: br i1 [[OR2]], label [[IF]], label [[ELSE]] | |
| ; CHECK: if: | |
| ; CHECK-NEXT: call void @foo(i1 [[A]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[B]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[OR1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[OR2_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: else: | |
| ; CHECK-NEXT: call void @foo(i1 [[A_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[B_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[OR1_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[OR2_1]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %or1 = or i1 %a, %b | |
| %or2 = or i1 %or1, %c | |
| br i1 %or2, label %if, label %else | |
| if: | |
| call void @foo(i1 %a) | |
| call void @foo(i1 %b) | |
| call void @foo(i1 %c) | |
| call void @foo(i1 %or1) | |
| call void @foo(i1 %or2) | |
| ret void | |
| else: | |
| call void @foo(i1 %a) | |
| call void @foo(i1 %b) | |
| call void @foo(i1 %c) | |
| call void @foo(i1 %or1) | |
| call void @foo(i1 %or2) | |
| ret void | |
| } | |
| define void @test_and_or_mixed(i1 %a, i1 %b, i1 %c) { | |
| ; CHECK-LABEL: @test_and_or_mixed( | |
| ; CHECK-NEXT: [[OR:%.*]] = or i1 [[A:%.*]], [[B:%.*]] | |
| ; CHECK-NEXT: [[AND:%.*]] = and i1 [[OR]], [[C:%.*]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[AND]] = and i1 [[OR]], [[C]] Edge: [label [[TMP0:%.*]],label [[IF:%.*]]], RenamedOp: [[AND]] } | |
| ; CHECK-NEXT: [[AND_0:%.*]] = bitcast i1 [[AND]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[AND]] = and i1 [[OR]], [[C]] Edge: [label [[TMP0]],label [[ELSE:%.*]]], RenamedOp: [[AND]] } | |
| ; CHECK-NEXT: [[AND_1:%.*]] = bitcast i1 [[AND]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[OR]] = or i1 [[A]], [[B]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[OR]] } | |
| ; CHECK-NEXT: [[OR_0:%.*]] = bitcast i1 [[OR]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison:i1 [[C]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[C]] } | |
| ; CHECK-NEXT: [[C_0:%.*]] = bitcast i1 [[C]] to i1 | |
| ; CHECK-NEXT: br i1 [[AND]], label [[IF]], label [[ELSE]] | |
| ; CHECK: if: | |
| ; CHECK-NEXT: call void @foo(i1 [[A]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[B]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[OR_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[AND_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: else: | |
| ; CHECK-NEXT: call void @foo(i1 [[A]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[B]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[OR]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[AND_1]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %or = or i1 %a, %b | |
| %and = and i1 %or, %c | |
| br i1 %and, label %if, label %else | |
| if: | |
| call void @foo(i1 %a) | |
| call void @foo(i1 %b) | |
| call void @foo(i1 %c) | |
| call void @foo(i1 %or) | |
| call void @foo(i1 %and) | |
| ret void | |
| else: | |
| call void @foo(i1 %a) | |
| call void @foo(i1 %b) | |
| call void @foo(i1 %c) | |
| call void @foo(i1 %or) | |
| call void @foo(i1 %and) | |
| ret void | |
| } | |
| define void @test_deep_and_chain(i1 %a1) { | |
| ; CHECK-LABEL: @test_deep_and_chain( | |
| ; CHECK-NEXT: [[A2:%.*]] = and i1 [[A1:%.*]], true | |
| ; CHECK-NEXT: [[A3:%.*]] = and i1 [[A2]], true | |
| ; CHECK-NEXT: [[A4:%.*]] = and i1 [[A3]], true | |
| ; CHECK-NEXT: [[A5:%.*]] = and i1 [[A4]], true | |
| ; CHECK-NEXT: [[A6:%.*]] = and i1 [[A5]], true | |
| ; CHECK-NEXT: [[A7:%.*]] = and i1 [[A6]], true | |
| ; CHECK-NEXT: [[A8:%.*]] = and i1 [[A7]], true | |
| ; CHECK-NEXT: [[A9:%.*]] = and i1 [[A8]], true | |
| ; CHECK-NEXT: [[A10:%.*]] = and i1 [[A9]], true | |
| ; CHECK-NEXT: [[A11:%.*]] = and i1 [[A10]], true | |
| ; CHECK-NEXT: [[A12:%.*]] = and i1 [[A11]], true | |
| ; CHECK-NEXT: [[A13:%.*]] = and i1 [[A12]], true | |
| ; CHECK-NEXT: [[A14:%.*]] = and i1 [[A13]], true | |
| ; CHECK-NEXT: [[A15:%.*]] = and i1 [[A14]], true | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A15]] = and i1 [[A14]], true Edge: [label [[TMP0:%.*]],label [[IF:%.*]]], RenamedOp: [[A15]] } | |
| ; CHECK-NEXT: [[A15_0:%.*]] = bitcast i1 [[A15]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A15]] = and i1 [[A14]], true Edge: [label [[TMP0]],label [[ELSE:%.*]]], RenamedOp: [[A15]] } | |
| ; CHECK-NEXT: [[A15_1:%.*]] = bitcast i1 [[A15]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A14]] = and i1 [[A13]], true Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A14]] } | |
| ; CHECK-NEXT: [[A14_0:%.*]] = bitcast i1 [[A14]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A13]] = and i1 [[A12]], true Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A13]] } | |
| ; CHECK-NEXT: [[A13_0:%.*]] = bitcast i1 [[A13]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A12]] = and i1 [[A11]], true Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A12]] } | |
| ; CHECK-NEXT: [[A12_0:%.*]] = bitcast i1 [[A12]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A11]] = and i1 [[A10]], true Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A11]] } | |
| ; CHECK-NEXT: [[A11_0:%.*]] = bitcast i1 [[A11]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A10]] = and i1 [[A9]], true Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A10]] } | |
| ; CHECK-NEXT: [[A10_0:%.*]] = bitcast i1 [[A10]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A9]] = and i1 [[A8]], true Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A9]] } | |
| ; CHECK-NEXT: [[A9_0:%.*]] = bitcast i1 [[A9]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A8]] = and i1 [[A7]], true Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A8]] } | |
| ; CHECK-NEXT: [[A8_0:%.*]] = bitcast i1 [[A8]] to i1 | |
| ; CHECK-NEXT: br i1 [[A15]], label [[IF]], label [[ELSE]] | |
| ; CHECK: if: | |
| ; CHECK-NEXT: call void @foo(i1 [[A1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A3]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A4]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A5]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A6]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A7]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A8_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A9_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A10_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A11_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A12_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A13_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A14_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A15_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: else: | |
| ; CHECK-NEXT: call void @foo(i1 [[A1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A3]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A4]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A5]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A6]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A7]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A8]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A9]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A10]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A11]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A12]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A13]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A14]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A15_1]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %a2 = and i1 %a1, true | |
| %a3 = and i1 %a2, true | |
| %a4 = and i1 %a3, true | |
| %a5 = and i1 %a4, true | |
| %a6 = and i1 %a5, true | |
| %a7 = and i1 %a6, true | |
| %a8 = and i1 %a7, true | |
| %a9 = and i1 %a8, true | |
| %a10 = and i1 %a9, true | |
| %a11 = and i1 %a10, true | |
| %a12 = and i1 %a11, true | |
| %a13 = and i1 %a12, true | |
| %a14 = and i1 %a13, true | |
| %a15 = and i1 %a14, true | |
| br i1 %a15, label %if, label %else | |
| if: | |
| call void @foo(i1 %a1) | |
| call void @foo(i1 %a2) | |
| call void @foo(i1 %a3) | |
| call void @foo(i1 %a4) | |
| call void @foo(i1 %a5) | |
| call void @foo(i1 %a6) | |
| call void @foo(i1 %a7) | |
| call void @foo(i1 %a8) | |
| call void @foo(i1 %a9) | |
| call void @foo(i1 %a10) | |
| call void @foo(i1 %a11) | |
| call void @foo(i1 %a12) | |
| call void @foo(i1 %a13) | |
| call void @foo(i1 %a14) | |
| call void @foo(i1 %a15) | |
| ret void | |
| else: | |
| call void @foo(i1 %a1) | |
| call void @foo(i1 %a2) | |
| call void @foo(i1 %a3) | |
| call void @foo(i1 %a4) | |
| call void @foo(i1 %a5) | |
| call void @foo(i1 %a6) | |
| call void @foo(i1 %a7) | |
| call void @foo(i1 %a8) | |
| call void @foo(i1 %a9) | |
| call void @foo(i1 %a10) | |
| call void @foo(i1 %a11) | |
| call void @foo(i1 %a12) | |
| call void @foo(i1 %a13) | |
| call void @foo(i1 %a14) | |
| call void @foo(i1 %a15) | |
| ret void | |
| } | |
| define void @test_deep_and_tree(i1 %a1) { | |
| ; CHECK-LABEL: @test_deep_and_tree( | |
| ; CHECK-NEXT: [[A2:%.*]] = and i1 [[A1:%.*]], [[A1]] | |
| ; CHECK-NEXT: [[A3:%.*]] = and i1 [[A2]], [[A2]] | |
| ; CHECK-NEXT: [[A4:%.*]] = and i1 [[A3]], [[A3]] | |
| ; CHECK-NEXT: [[A5:%.*]] = and i1 [[A4]], [[A4]] | |
| ; CHECK-NEXT: [[A6:%.*]] = and i1 [[A5]], [[A5]] | |
| ; CHECK-NEXT: [[A7:%.*]] = and i1 [[A6]], [[A6]] | |
| ; CHECK-NEXT: [[A8:%.*]] = and i1 [[A7]], [[A7]] | |
| ; CHECK-NEXT: [[A9:%.*]] = and i1 [[A8]], [[A8]] | |
| ; CHECK-NEXT: [[A10:%.*]] = and i1 [[A9]], [[A9]] | |
| ; CHECK-NEXT: [[A11:%.*]] = and i1 [[A10]], [[A10]] | |
| ; CHECK-NEXT: [[A12:%.*]] = and i1 [[A11]], [[A11]] | |
| ; CHECK-NEXT: [[A13:%.*]] = and i1 [[A12]], [[A12]] | |
| ; CHECK-NEXT: [[A14:%.*]] = and i1 [[A13]], [[A13]] | |
| ; CHECK-NEXT: [[A15:%.*]] = and i1 [[A14]], [[A14]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A15]] = and i1 [[A14]], [[A14]] Edge: [label [[TMP0:%.*]],label [[IF:%.*]]], RenamedOp: [[A15]] } | |
| ; CHECK-NEXT: [[A15_0:%.*]] = bitcast i1 [[A15]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A15]] = and i1 [[A14]], [[A14]] Edge: [label [[TMP0]],label [[ELSE:%.*]]], RenamedOp: [[A15]] } | |
| ; CHECK-NEXT: [[A15_1:%.*]] = bitcast i1 [[A15]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A14]] = and i1 [[A13]], [[A13]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A14]] } | |
| ; CHECK-NEXT: [[A14_0:%.*]] = bitcast i1 [[A14]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A13]] = and i1 [[A12]], [[A12]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A13]] } | |
| ; CHECK-NEXT: [[A13_0:%.*]] = bitcast i1 [[A13]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A12]] = and i1 [[A11]], [[A11]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A12]] } | |
| ; CHECK-NEXT: [[A12_0:%.*]] = bitcast i1 [[A12]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A11]] = and i1 [[A10]], [[A10]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A11]] } | |
| ; CHECK-NEXT: [[A11_0:%.*]] = bitcast i1 [[A11]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A10]] = and i1 [[A9]], [[A9]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A10]] } | |
| ; CHECK-NEXT: [[A10_0:%.*]] = bitcast i1 [[A10]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A9]] = and i1 [[A8]], [[A8]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A9]] } | |
| ; CHECK-NEXT: [[A9_0:%.*]] = bitcast i1 [[A9]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A8]] = and i1 [[A7]], [[A7]] Edge: [label [[TMP0]],label [[IF]]], RenamedOp: [[A8]] } | |
| ; CHECK-NEXT: [[A8_0:%.*]] = bitcast i1 [[A8]] to i1 | |
| ; CHECK-NEXT: br i1 [[A15]], label [[IF]], label [[ELSE]] | |
| ; CHECK: if: | |
| ; CHECK-NEXT: call void @foo(i1 [[A1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A3]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A4]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A5]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A6]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A7]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A8_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A9_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A10_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A11_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A12_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A13_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A14_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A15_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: else: | |
| ; CHECK-NEXT: call void @foo(i1 [[A1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A3]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A4]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A5]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A6]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A7]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A8]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A9]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A10]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A11]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A12]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A13]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A14]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A15_1]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %a2 = and i1 %a1, %a1 | |
| %a3 = and i1 %a2, %a2 | |
| %a4 = and i1 %a3, %a3 | |
| %a5 = and i1 %a4, %a4 | |
| %a6 = and i1 %a5, %a5 | |
| %a7 = and i1 %a6, %a6 | |
| %a8 = and i1 %a7, %a7 | |
| %a9 = and i1 %a8, %a8 | |
| %a10 = and i1 %a9, %a9 | |
| %a11 = and i1 %a10, %a10 | |
| %a12 = and i1 %a11, %a11 | |
| %a13 = and i1 %a12, %a12 | |
| %a14 = and i1 %a13, %a13 | |
| %a15 = and i1 %a14, %a14 | |
| br i1 %a15, label %if, label %else | |
| if: | |
| call void @foo(i1 %a1) | |
| call void @foo(i1 %a2) | |
| call void @foo(i1 %a3) | |
| call void @foo(i1 %a4) | |
| call void @foo(i1 %a5) | |
| call void @foo(i1 %a6) | |
| call void @foo(i1 %a7) | |
| call void @foo(i1 %a8) | |
| call void @foo(i1 %a9) | |
| call void @foo(i1 %a10) | |
| call void @foo(i1 %a11) | |
| call void @foo(i1 %a12) | |
| call void @foo(i1 %a13) | |
| call void @foo(i1 %a14) | |
| call void @foo(i1 %a15) | |
| ret void | |
| else: | |
| call void @foo(i1 %a1) | |
| call void @foo(i1 %a2) | |
| call void @foo(i1 %a3) | |
| call void @foo(i1 %a4) | |
| call void @foo(i1 %a5) | |
| call void @foo(i1 %a6) | |
| call void @foo(i1 %a7) | |
| call void @foo(i1 %a8) | |
| call void @foo(i1 %a9) | |
| call void @foo(i1 %a10) | |
| call void @foo(i1 %a11) | |
| call void @foo(i1 %a12) | |
| call void @foo(i1 %a13) | |
| call void @foo(i1 %a14) | |
| call void @foo(i1 %a15) | |
| ret void | |
| } | |
| define void @test_deep_or_tree(i1 %a1) { | |
| ; CHECK-LABEL: @test_deep_or_tree( | |
| ; CHECK-NEXT: [[A2:%.*]] = or i1 [[A1:%.*]], [[A1]] | |
| ; CHECK-NEXT: [[A3:%.*]] = or i1 [[A2]], [[A2]] | |
| ; CHECK-NEXT: [[A4:%.*]] = or i1 [[A3]], [[A3]] | |
| ; CHECK-NEXT: [[A5:%.*]] = or i1 [[A4]], [[A4]] | |
| ; CHECK-NEXT: [[A6:%.*]] = or i1 [[A5]], [[A5]] | |
| ; CHECK-NEXT: [[A7:%.*]] = or i1 [[A6]], [[A6]] | |
| ; CHECK-NEXT: [[A8:%.*]] = or i1 [[A7]], [[A7]] | |
| ; CHECK-NEXT: [[A9:%.*]] = or i1 [[A8]], [[A8]] | |
| ; CHECK-NEXT: [[A10:%.*]] = or i1 [[A9]], [[A9]] | |
| ; CHECK-NEXT: [[A11:%.*]] = or i1 [[A10]], [[A10]] | |
| ; CHECK-NEXT: [[A12:%.*]] = or i1 [[A11]], [[A11]] | |
| ; CHECK-NEXT: [[A13:%.*]] = or i1 [[A12]], [[A12]] | |
| ; CHECK-NEXT: [[A14:%.*]] = or i1 [[A13]], [[A13]] | |
| ; CHECK-NEXT: [[A15:%.*]] = or i1 [[A14]], [[A14]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[A15]] = or i1 [[A14]], [[A14]] Edge: [label [[TMP0:%.*]],label [[IF:%.*]]], RenamedOp: [[A15]] } | |
| ; CHECK-NEXT: [[A15_0:%.*]] = bitcast i1 [[A15]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A15]] = or i1 [[A14]], [[A14]] Edge: [label [[TMP0]],label [[ELSE:%.*]]], RenamedOp: [[A15]] } | |
| ; CHECK-NEXT: [[A15_1:%.*]] = bitcast i1 [[A15]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A14]] = or i1 [[A13]], [[A13]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[A14]] } | |
| ; CHECK-NEXT: [[A14_0:%.*]] = bitcast i1 [[A14]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A13]] = or i1 [[A12]], [[A12]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[A13]] } | |
| ; CHECK-NEXT: [[A13_0:%.*]] = bitcast i1 [[A13]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A12]] = or i1 [[A11]], [[A11]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[A12]] } | |
| ; CHECK-NEXT: [[A12_0:%.*]] = bitcast i1 [[A12]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A11]] = or i1 [[A10]], [[A10]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[A11]] } | |
| ; CHECK-NEXT: [[A11_0:%.*]] = bitcast i1 [[A11]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A10]] = or i1 [[A9]], [[A9]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[A10]] } | |
| ; CHECK-NEXT: [[A10_0:%.*]] = bitcast i1 [[A10]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A9]] = or i1 [[A8]], [[A8]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[A9]] } | |
| ; CHECK-NEXT: [[A9_0:%.*]] = bitcast i1 [[A9]] to i1 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 0 Comparison: [[A8]] = or i1 [[A7]], [[A7]] Edge: [label [[TMP0]],label [[ELSE]]], RenamedOp: [[A8]] } | |
| ; CHECK-NEXT: [[A8_0:%.*]] = bitcast i1 [[A8]] to i1 | |
| ; CHECK-NEXT: br i1 [[A15]], label [[IF]], label [[ELSE]] | |
| ; CHECK: if: | |
| ; CHECK-NEXT: call void @foo(i1 [[A1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A3]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A4]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A5]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A6]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A7]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A8]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A9]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A10]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A11]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A12]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A13]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A14]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A15_0]]) | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: else: | |
| ; CHECK-NEXT: call void @foo(i1 [[A1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A3]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A4]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A5]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A6]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A7]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A8_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A9_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A10_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A11_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A12_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A13_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A14_0]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A15_1]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %a2 = or i1 %a1, %a1 | |
| %a3 = or i1 %a2, %a2 | |
| %a4 = or i1 %a3, %a3 | |
| %a5 = or i1 %a4, %a4 | |
| %a6 = or i1 %a5, %a5 | |
| %a7 = or i1 %a6, %a6 | |
| %a8 = or i1 %a7, %a7 | |
| %a9 = or i1 %a8, %a8 | |
| %a10 = or i1 %a9, %a9 | |
| %a11 = or i1 %a10, %a10 | |
| %a12 = or i1 %a11, %a11 | |
| %a13 = or i1 %a12, %a12 | |
| %a14 = or i1 %a13, %a13 | |
| %a15 = or i1 %a14, %a14 | |
| br i1 %a15, label %if, label %else | |
| if: | |
| call void @foo(i1 %a1) | |
| call void @foo(i1 %a2) | |
| call void @foo(i1 %a3) | |
| call void @foo(i1 %a4) | |
| call void @foo(i1 %a5) | |
| call void @foo(i1 %a6) | |
| call void @foo(i1 %a7) | |
| call void @foo(i1 %a8) | |
| call void @foo(i1 %a9) | |
| call void @foo(i1 %a10) | |
| call void @foo(i1 %a11) | |
| call void @foo(i1 %a12) | |
| call void @foo(i1 %a13) | |
| call void @foo(i1 %a14) | |
| call void @foo(i1 %a15) | |
| ret void | |
| else: | |
| call void @foo(i1 %a1) | |
| call void @foo(i1 %a2) | |
| call void @foo(i1 %a3) | |
| call void @foo(i1 %a4) | |
| call void @foo(i1 %a5) | |
| call void @foo(i1 %a6) | |
| call void @foo(i1 %a7) | |
| call void @foo(i1 %a8) | |
| call void @foo(i1 %a9) | |
| call void @foo(i1 %a10) | |
| call void @foo(i1 %a11) | |
| call void @foo(i1 %a12) | |
| call void @foo(i1 %a13) | |
| call void @foo(i1 %a14) | |
| call void @foo(i1 %a15) | |
| ret void | |
| } | |
| define void @test_assume_and_chain(i1 %a, i1 %b, i1 %c) { | |
| ; CHECK-LABEL: @test_assume_and_chain( | |
| ; CHECK-NEXT: [[AND1:%.*]] = and i1 [[A:%.*]], [[B:%.*]] | |
| ; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[C:%.*]] | |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[AND2]]) | |
| ; CHECK-NEXT: ; assume predicate info { Comparison:i1 [[C]], RenamedOp: [[C]] } | |
| ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i1 [[C]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison:i1 [[B]], RenamedOp: [[B]] } | |
| ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i1 [[B]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison:i1 [[A]], RenamedOp: [[A]] } | |
| ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i1 [[A]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[AND1]] = and i1 [[A]], [[B]], RenamedOp: [[AND1]] } | |
| ; CHECK-NEXT: [[TMP4:%.*]] = bitcast i1 [[AND1]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[AND2]] = and i1 [[AND1]], [[C]], RenamedOp: [[AND2]] } | |
| ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i1 [[AND2]] to i1 | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP3]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP4]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP5]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %and1 = and i1 %a, %b | |
| %and2 = and i1 %and1, %c | |
| call void @llvm.assume(i1 %and2) | |
| call void @foo(i1 %a) | |
| call void @foo(i1 %b) | |
| call void @foo(i1 %c) | |
| call void @foo(i1 %and1) | |
| call void @foo(i1 %and2) | |
| ret void | |
| } | |
| define void @test_assume_or_chain(i1 %a, i1 %b, i1 %c) { | |
| ; CHECK-LABEL: @test_assume_or_chain( | |
| ; CHECK-NEXT: [[OR1:%.*]] = or i1 [[A:%.*]], [[B:%.*]] | |
| ; CHECK-NEXT: [[OR2:%.*]] = or i1 [[OR1]], [[C:%.*]] | |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[OR2]]) | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[OR2]] = or i1 [[OR1]], [[C]], RenamedOp: [[OR2]] } | |
| ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i1 [[OR2]] to i1 | |
| ; CHECK-NEXT: call void @foo(i1 [[A]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[B]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[C]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[OR1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP1]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %or1 = or i1 %a, %b | |
| %or2 = or i1 %or1, %c | |
| call void @llvm.assume(i1 %or2) | |
| call void @foo(i1 %a) | |
| call void @foo(i1 %b) | |
| call void @foo(i1 %c) | |
| call void @foo(i1 %or1) | |
| call void @foo(i1 %or2) | |
| ret void | |
| } | |
| define void @test_assume_deep_and_tree(i1 %a1) { | |
| ; CHECK-LABEL: @test_assume_deep_and_tree( | |
| ; CHECK-NEXT: [[A2:%.*]] = and i1 [[A1:%.*]], [[A1]] | |
| ; CHECK-NEXT: [[A3:%.*]] = and i1 [[A2]], [[A2]] | |
| ; CHECK-NEXT: [[A4:%.*]] = and i1 [[A3]], [[A3]] | |
| ; CHECK-NEXT: [[A5:%.*]] = and i1 [[A4]], [[A4]] | |
| ; CHECK-NEXT: [[A6:%.*]] = and i1 [[A5]], [[A5]] | |
| ; CHECK-NEXT: [[A7:%.*]] = and i1 [[A6]], [[A6]] | |
| ; CHECK-NEXT: [[A8:%.*]] = and i1 [[A7]], [[A7]] | |
| ; CHECK-NEXT: [[A9:%.*]] = and i1 [[A8]], [[A8]] | |
| ; CHECK-NEXT: [[A10:%.*]] = and i1 [[A9]], [[A9]] | |
| ; CHECK-NEXT: [[A11:%.*]] = and i1 [[A10]], [[A10]] | |
| ; CHECK-NEXT: [[A12:%.*]] = and i1 [[A11]], [[A11]] | |
| ; CHECK-NEXT: [[A13:%.*]] = and i1 [[A12]], [[A12]] | |
| ; CHECK-NEXT: [[A14:%.*]] = and i1 [[A13]], [[A13]] | |
| ; CHECK-NEXT: [[A15:%.*]] = and i1 [[A14]], [[A14]] | |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[A15]]) | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[A8]] = and i1 [[A7]], [[A7]], RenamedOp: [[A8]] } | |
| ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i1 [[A8]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[A9]] = and i1 [[A8]], [[A8]], RenamedOp: [[A9]] } | |
| ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i1 [[A9]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[A10]] = and i1 [[A9]], [[A9]], RenamedOp: [[A10]] } | |
| ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i1 [[A10]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[A11]] = and i1 [[A10]], [[A10]], RenamedOp: [[A11]] } | |
| ; CHECK-NEXT: [[TMP4:%.*]] = bitcast i1 [[A11]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[A12]] = and i1 [[A11]], [[A11]], RenamedOp: [[A12]] } | |
| ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i1 [[A12]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[A13]] = and i1 [[A12]], [[A12]], RenamedOp: [[A13]] } | |
| ; CHECK-NEXT: [[TMP6:%.*]] = bitcast i1 [[A13]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[A14]] = and i1 [[A13]], [[A13]], RenamedOp: [[A14]] } | |
| ; CHECK-NEXT: [[TMP7:%.*]] = bitcast i1 [[A14]] to i1 | |
| ; CHECK-NEXT: ; assume predicate info { Comparison: [[A15]] = and i1 [[A14]], [[A14]], RenamedOp: [[A15]] } | |
| ; CHECK-NEXT: [[TMP8:%.*]] = bitcast i1 [[A15]] to i1 | |
| ; CHECK-NEXT: call void @foo(i1 [[A1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A3]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A4]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A5]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A6]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[A7]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP1]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP2]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP3]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP4]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP5]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP6]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP7]]) | |
| ; CHECK-NEXT: call void @foo(i1 [[TMP8]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %a2 = and i1 %a1, %a1 | |
| %a3 = and i1 %a2, %a2 | |
| %a4 = and i1 %a3, %a3 | |
| %a5 = and i1 %a4, %a4 | |
| %a6 = and i1 %a5, %a5 | |
| %a7 = and i1 %a6, %a6 | |
| %a8 = and i1 %a7, %a7 | |
| %a9 = and i1 %a8, %a8 | |
| %a10 = and i1 %a9, %a9 | |
| %a11 = and i1 %a10, %a10 | |
| %a12 = and i1 %a11, %a11 | |
| %a13 = and i1 %a12, %a12 | |
| %a14 = and i1 %a13, %a13 | |
| %a15 = and i1 %a14, %a14 | |
| call void @llvm.assume(i1 %a15) | |
| call void @foo(i1 %a1) | |
| call void @foo(i1 %a2) | |
| call void @foo(i1 %a3) | |
| call void @foo(i1 %a4) | |
| call void @foo(i1 %a5) | |
| call void @foo(i1 %a6) | |
| call void @foo(i1 %a7) | |
| call void @foo(i1 %a8) | |
| call void @foo(i1 %a9) | |
| call void @foo(i1 %a10) | |
| call void @foo(i1 %a11) | |
| call void @foo(i1 %a12) | |
| call void @foo(i1 %a13) | |
| call void @foo(i1 %a14) | |
| call void @foo(i1 %a15) | |
| ret void | |
| } | |
| define i32 @test_and_with_phinode(i32 %x) { | |
| ; CHECK-LABEL: @test_and_with_phinode( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: [[XGE1:%.*]] = icmp uge i32 [[X:%.*]], 1 | |
| ; CHECK-NEXT: [[XLT2:%.*]] = icmp ult i32 [[X]], 2 | |
| ; CHECK-NEXT: [[AND:%.*]] = and i1 [[XGE1]], [[XLT2]] | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XGE1]] = icmp uge i32 [[X]], 1 Edge: [label [[ENTRY:%.*]],label [[PHI:%.*]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[X_0_1:%.*]] = bitcast i32 [[X]] to i32 | |
| ; CHECK-NEXT: ; branch predicate info { TrueEdge: 1 Comparison: [[XLT2]] = icmp ult i32 [[X]], 2 Edge: [label [[ENTRY]],label [[PHI]]], RenamedOp: [[X]] } | |
| ; CHECK-NEXT: [[X_0_2:%.*]] = bitcast i32 [[X_0_1]] to i32 | |
| ; CHECK-NEXT: br i1 [[AND]], label [[PHI]], label [[NOPE:%.*]] | |
| ; CHECK: nope: | |
| ; CHECK-NEXT: br label [[PHI]] | |
| ; CHECK: phi: | |
| ; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[X_0_2]], [[ENTRY]] ], [ 1, [[NOPE]] ] | |
| ; CHECK-NEXT: ret i32 [[RES]] | |
| ; | |
| entry: | |
| %xge1 = icmp uge i32 %x, 1 | |
| %xlt2 = icmp ult i32 %x, 2 | |
| %and = and i1 %xge1, %xlt2 | |
| br i1 %and, label %phi, label %nope | |
| nope: | |
| br label %phi | |
| phi: | |
| %res = phi i32 [ %x, %entry ], [ 1, %nope ] | |
| ret i32 %res | |
| } |