161 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			LLVM
		
	
	
	
| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 | |
| ; RUN: opt -instcombine -S < %s | FileCheck %s
 | |
| ; RUN: opt -passes=instcombine -S < %s | FileCheck %s
 | |
| 
 | |
| declare void @use(i32 %x)
 | |
| declare i1 @cond()
 | |
| 
 | |
| define void @test_01(i32 %x, i32 %y) {
 | |
| ; CHECK-LABEL: @test_01(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
 | |
| ; CHECK-NEXT:    br i1 [[C2]], label [[EXIT:%.*]], label [[UNREACHED:%.*]]
 | |
| ; CHECK:       unreached:
 | |
| ; CHECK-NEXT:    [[C1:%.*]] = icmp ne i32 [[X]], [[Y]]
 | |
| ; CHECK-NEXT:    [[COMPARATOR:%.*]] = zext i1 [[C1]] to i32
 | |
| ; CHECK-NEXT:    call void @use(i32 [[COMPARATOR]])
 | |
| ; CHECK-NEXT:    unreachable
 | |
| ; CHECK:       exit:
 | |
| ; CHECK-NEXT:    ret void
 | |
| ;
 | |
| entry:
 | |
|   %c1 = icmp eq i32 %x, %y
 | |
|   %c2 = icmp slt i32 %x, %y
 | |
|   %signed = select i1 %c2, i32 -1, i32 1
 | |
|   %comparator = select i1 %c1, i32 0, i32 %signed
 | |
|   br i1 %c2, label %exit, label %unreached
 | |
| 
 | |
| unreached:
 | |
|   call void @use(i32 %comparator)
 | |
|   unreachable
 | |
| 
 | |
| exit:
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| 
 | |
| define void @test_02(i32 %x, i32 %y) {
 | |
| ; CHECK-LABEL: @test_02(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
 | |
| ; CHECK-NEXT:    br i1 [[C2]], label [[EXIT:%.*]], label [[MEDIUM:%.*]]
 | |
| ; CHECK:       medium:
 | |
| ; CHECK-NEXT:    [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]]
 | |
| ; CHECK-NEXT:    br i1 [[C3]], label [[EXIT]], label [[UNREACHED:%.*]]
 | |
| ; CHECK:       unreached:
 | |
| ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i32 [[X]], [[Y]]
 | |
| ; CHECK-NEXT:    [[SIGNED:%.*]] = select i1 [[C2]], i32 -1, i32 1
 | |
| ; CHECK-NEXT:    [[COMPARATOR:%.*]] = select i1 [[C1]], i32 0, i32 [[SIGNED]]
 | |
| ; CHECK-NEXT:    call void @use(i32 [[COMPARATOR]])
 | |
| ; CHECK-NEXT:    unreachable
 | |
| ; CHECK:       exit:
 | |
| ; CHECK-NEXT:    ret void
 | |
| ;
 | |
| entry:
 | |
|   %c1 = icmp eq i32 %x, %y
 | |
|   %c2 = icmp slt i32 %x, %y
 | |
|   %signed = select i1 %c2, i32 -1, i32 1
 | |
|   %comparator = select i1 %c1, i32 0, i32 %signed
 | |
|   br i1 %c2, label %exit, label %medium
 | |
| 
 | |
| medium:
 | |
|   %c3 = icmp sgt i32 %x, %y
 | |
|   br i1 %c3, label %exit, label %unreached
 | |
| 
 | |
| unreached:
 | |
|   call void @use(i32 %comparator)
 | |
|   unreachable
 | |
| 
 | |
| exit:
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define i32 @test_03(i32 %x, i32 %y) {
 | |
| ; CHECK-LABEL: @test_03(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
 | |
| ; CHECK-NEXT:    br i1 [[C2]], label [[EXIT:%.*]], label [[MEDIUM:%.*]]
 | |
| ; CHECK:       medium:
 | |
| ; CHECK-NEXT:    [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]]
 | |
| ; CHECK-NEXT:    br i1 [[C3]], label [[EXIT]], label [[UNREACHED:%.*]]
 | |
| ; CHECK:       unreached:
 | |
| ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i32 [[X]], [[Y]]
 | |
| ; CHECK-NEXT:    [[SIGNED:%.*]] = select i1 [[C2]], i32 -1, i32 1
 | |
| ; CHECK-NEXT:    [[COMPARATOR:%.*]] = select i1 [[C1]], i32 0, i32 [[SIGNED]]
 | |
| ; CHECK-NEXT:    ret i32 [[COMPARATOR]]
 | |
| ; CHECK:       exit:
 | |
| ; CHECK-NEXT:    ret i32 0
 | |
| ;
 | |
| entry:
 | |
|   %c1 = icmp eq i32 %x, %y
 | |
|   %c2 = icmp slt i32 %x, %y
 | |
|   %signed = select i1 %c2, i32 -1, i32 1
 | |
|   %comparator = select i1 %c1, i32 0, i32 %signed
 | |
|   br i1 %c2, label %exit, label %medium
 | |
| 
 | |
| medium:
 | |
|   %c3 = icmp sgt i32 %x, %y
 | |
|   br i1 %c3, label %exit, label %unreached
 | |
| 
 | |
| unreached:
 | |
|   ret i32 %comparator
 | |
| 
 | |
| exit:
 | |
|   ret i32 0
 | |
| }
 | |
| 
 | |
| define i32 @test_04(i32 %x, i1 %c) {
 | |
| ; CHECK-LABEL: @test_04(
 | |
| ; CHECK-NEXT:  bb0:
 | |
| ; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
 | |
| ; CHECK:       bb1:
 | |
| ; CHECK-NEXT:    br label [[BB3:%.*]]
 | |
| ; CHECK:       bb2:
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[BB1]] ], [ 1, [[BB2]] ]
 | |
| ; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], 1
 | |
| ; CHECK-NEXT:    [[R:%.*]] = add i32 [[P]], [[A]]
 | |
| ; CHECK-NEXT:    ret i32 [[R]]
 | |
| ;
 | |
| bb0:
 | |
|   %a = add i32 %x, 1
 | |
|   br i1 %c, label %bb1, label %bb2
 | |
| bb1:
 | |
|   br label %bb3
 | |
| bb2:
 | |
|   br label %bb3
 | |
| bb3:
 | |
|   %p = phi i32 [0, %bb1], [1, %bb2]
 | |
|   %r = add i32 %p, %a
 | |
|   ret i32 %r
 | |
| }
 | |
| 
 | |
| ; Do not sink into a potentially hotter block.
 | |
| define i32 @test_05_neg(i32 %x, i1 %cond) {
 | |
| ; CHECK-LABEL: @test_05_neg(
 | |
| ; CHECK-NEXT:  bb0:
 | |
| ; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], 1
 | |
| ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
 | |
| ; CHECK:       bb1:
 | |
| ; CHECK-NEXT:    br label [[BB3:%.*]]
 | |
| ; CHECK:       bb2:
 | |
| ; CHECK-NEXT:    [[CALL:%.*]] = call i1 @cond()
 | |
| ; CHECK-NEXT:    br i1 [[CALL]], label [[BB2]], label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[BB1]] ], [ [[A]], [[BB2]] ]
 | |
| ; CHECK-NEXT:    ret i32 [[P]]
 | |
| ;
 | |
| bb0:
 | |
|   %a = add i32 %x, 1
 | |
|   br i1 %cond, label %bb1, label %bb2
 | |
| bb1:
 | |
|   br label %bb3
 | |
| bb2:
 | |
|   %call = call i1 @cond()
 | |
|   br i1 %call, label %bb2, label %bb3
 | |
| bb3:
 | |
|   %p = phi i32 [0, %bb1], [%a, %bb2]
 | |
|   ret i32 %p
 | |
| }
 |