blob: 86d1a0d247d84523f170f834351020ba8565583e [file] [log] [blame]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -print-predicateinfo < %s 2>&1 | FileCheck %s
declare void @foo(i1)
declare void @bar(i32)
declare void @llvm.assume(i1)
define void @testor(i32 %x, i32 %y) {
; CHECK-LABEL: @testor(
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; 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 @testand(i32 %x, i32 %y) {
; CHECK-LABEL: @testand(
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; 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 @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: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK: [[X_0_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X_0]])
; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XGT]])
; CHECK: [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XLT]])
; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; 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: [[TMP1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK: [[TMP2:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP5]])
; CHECK: [[DOT0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP1]])
; CHECK: [[DOT01:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP2]])
; CHECK: [[DOT02:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP3]])
; CHECK: [[DOT03:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP4]])
; CHECK: [[DOT04:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP5]])
; CHECK-NEXT: br i1 [[TMP5]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
; CHECK-NEXT: call void @foo(i1 [[DOT02]])
; CHECK-NEXT: call void @foo(i1 [[DOT03]])
; CHECK-NEXT: call void @bar(i32 [[DOT0]])
; CHECK-NEXT: call void @bar(i32 [[DOT01]])
; CHECK-NEXT: ret void
; CHECK: nope:
; CHECK-NEXT: call void @foo(i1 [[DOT04]])
; 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: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK-NEXT: br i1 [[Z]], 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 [[Z_0]])
; 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
}