997 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			997 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			LLVM
		
	
	
	
| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 | |
| ; RUN: opt -passes=print-predicateinfo -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:         [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
 | |
| ; CHECK:         [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
 | |
| ; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
 | |
| ; CHECK:         [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
 | |
| ; CHECK:         [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
 | |
| ; 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:         [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
 | |
| ; CHECK:         [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
 | |
| ; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
 | |
| ; CHECK:         [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
 | |
| ; CHECK:         [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
 | |
| ; 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:         [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
 | |
| ; CHECK:         [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
 | |
| ; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
 | |
| ; CHECK:         [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
 | |
| ; CHECK:         [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
 | |
| ; 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:         [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
 | |
| ; CHECK:         [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
 | |
| ; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
 | |
| ; CHECK:         [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
 | |
| ; CHECK:         [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
 | |
| ; 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:         [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
 | |
| ; CHECK:         [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XGT]])
 | |
| ; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
 | |
| ; CHECK:         [[X_0_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X_0]])
 | |
| ; CHECK:         [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XLT]])
 | |
| ; 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:         [[TMP1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
 | |
| ; CHECK:         [[TMP2:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
 | |
| ; CHECK:         [[TMP3:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
 | |
| ; CHECK:         [[TMP4:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
 | |
| ; CHECK:         [[TMP5:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
 | |
| ; CHECK:         [[DOT0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP5]])
 | |
| ; CHECK:         [[DOT01:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP4]])
 | |
| ; CHECK:         [[DOT02:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP3]])
 | |
| ; CHECK:         [[DOT03:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP2]])
 | |
| ; CHECK:         [[DOT04:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP1]])
 | |
| ; 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:         [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
 | |
| ; CHECK:         [[DOT0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP1]])
 | |
| ; 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:         [[A_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
 | |
| ; CHECK:         [[A_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
 | |
| ; CHECK:         [[C1_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C1]])
 | |
| ; CHECK:         [[C2_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C2]])
 | |
| ; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
 | |
| ; 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:         [[A_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
 | |
| ; CHECK:         [[A_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
 | |
| ; CHECK:         [[C1_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C1]])
 | |
| ; CHECK:         [[C2_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C2]])
 | |
| ; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
 | |
| ; 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:         [[AND2_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND2]])
 | |
| ; CHECK:         [[AND2_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND2]])
 | |
| ; CHECK:         [[AND1_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND1]])
 | |
| ; CHECK:         [[A_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
 | |
| ; CHECK:         [[B_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[B]])
 | |
| ; CHECK:         [[C_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C]])
 | |
| ; 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:         [[OR2_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[OR2]])
 | |
| ; CHECK:         [[OR2_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[OR2]])
 | |
| ; CHECK:         [[OR1_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[OR1]])
 | |
| ; CHECK:         [[A_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
 | |
| ; CHECK:         [[B_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[B]])
 | |
| ; CHECK:         [[C_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C]])
 | |
| ; 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:         [[AND_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND]])
 | |
| ; CHECK:         [[AND_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND]])
 | |
| ; CHECK:         [[OR_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[OR]])
 | |
| ; CHECK:         [[C_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C]])
 | |
| ; 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:         [[A15_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
 | |
| ; CHECK:         [[A15_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
 | |
| ; CHECK:         [[A14_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A14]])
 | |
| ; CHECK:         [[A13_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A13]])
 | |
| ; CHECK:         [[A12_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A12]])
 | |
| ; CHECK:         [[A11_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A11]])
 | |
| ; CHECK:         [[A10_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A10]])
 | |
| ; CHECK:         [[A9_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A9]])
 | |
| ; CHECK:         [[A8_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A8]])
 | |
| ; 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:         [[A15_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
 | |
| ; CHECK:         [[A15_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
 | |
| ; CHECK:         [[A14_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A14]])
 | |
| ; CHECK:         [[A13_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A13]])
 | |
| ; CHECK:         [[A12_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A12]])
 | |
| ; CHECK:         [[A11_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A11]])
 | |
| ; CHECK:         [[A10_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A10]])
 | |
| ; CHECK:         [[A9_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A9]])
 | |
| ; CHECK:         [[A8_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A8]])
 | |
| ; 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:         [[A15_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
 | |
| ; CHECK:         [[A15_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
 | |
| ; CHECK:         [[A14_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A14]])
 | |
| ; CHECK:         [[A13_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A13]])
 | |
| ; CHECK:         [[A12_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A12]])
 | |
| ; CHECK:         [[A11_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A11]])
 | |
| ; CHECK:         [[A10_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A10]])
 | |
| ; CHECK:         [[A9_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A9]])
 | |
| ; CHECK:         [[A8_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A8]])
 | |
| ; 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:         [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C]])
 | |
| ; CHECK:         [[TMP2:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[B]])
 | |
| ; CHECK:         [[TMP3:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
 | |
| ; CHECK:         [[TMP4:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND1]])
 | |
| ; CHECK:         [[TMP5:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND2]])
 | |
| ; 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:         [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[OR2]])
 | |
| ; 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:         [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A8]])
 | |
| ; CHECK:         [[TMP2:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A9]])
 | |
| ; CHECK:         [[TMP3:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A10]])
 | |
| ; CHECK:         [[TMP4:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A11]])
 | |
| ; CHECK:         [[TMP5:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A12]])
 | |
| ; CHECK:         [[TMP6:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A13]])
 | |
| ; CHECK:         [[TMP7:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A14]])
 | |
| ; CHECK:         [[TMP8:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
 | |
| ; 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
 | |
| }
 |