897 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			897 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			LLVM
		
	
	
	
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 | 
						|
; RUN: opt < %s -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -bonus-inst-threshold=10 | FileCheck %s
 | 
						|
 | 
						|
declare void @sideeffect0()
 | 
						|
declare void @sideeffect1()
 | 
						|
declare void @sideeffect2()
 | 
						|
declare void @use8(i8)
 | 
						|
declare i1 @gen1()
 | 
						|
 | 
						|
; Basic cases, blocks have nothing other than the comparison itself.
 | 
						|
 | 
						|
define void @one_pred(i8 %v0, i8 %v1) {
 | 
						|
; CHECK-LABEL: @one_pred(
 | 
						|
; CHECK-NEXT:  pred:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
pred:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
define void @two_preds(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
 | 
						|
; CHECK-LABEL: @two_preds(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
 | 
						|
; CHECK:       pred0:
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[C3_OLD:%.*]] = icmp eq i8 [[V3:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND1:%.*]] = or i1 [[C1]], [[C3_OLD]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       pred1:
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[C3:%.*]] = icmp eq i8 [[V3]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C2]], [[C3]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %pred0, label %pred1
 | 
						|
pred0:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %dispatch
 | 
						|
pred1:
 | 
						|
  %c2 = icmp eq i8 %v2, 0
 | 
						|
  br i1 %c2, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %c3 = icmp eq i8 %v3, 0
 | 
						|
  br i1 %c3, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
; More complex case, there's an extra op that is safe to execute unconditionally.
 | 
						|
 | 
						|
define void @one_pred_with_extra_op(i8 %v0, i8 %v1) {
 | 
						|
; CHECK-LABEL: @one_pred_with_extra_op(
 | 
						|
; CHECK-NEXT:  pred:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1_ADJ]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
pred:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v1_adj = add i8 %v0, %v1
 | 
						|
  %c1 = icmp eq i8 %v1_adj, 0
 | 
						|
  br i1 %c1, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
define void @two_preds_with_extra_op(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
 | 
						|
; CHECK-LABEL: @two_preds_with_extra_op(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
 | 
						|
; CHECK:       pred0:
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2:%.*]]
 | 
						|
; CHECK-NEXT:    [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_OLD]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND1:%.*]] = or i1 [[C1]], [[C3_OLD]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       pred1:
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = icmp eq i8 [[V2]], 0
 | 
						|
; CHECK-NEXT:    [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
 | 
						|
; CHECK-NEXT:    [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C2]], [[C3]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %pred0, label %pred1
 | 
						|
pred0:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %dispatch
 | 
						|
pred1:
 | 
						|
  %c2 = icmp eq i8 %v2, 0
 | 
						|
  br i1 %c2, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v3_adj = add i8 %v1, %v2
 | 
						|
  %c3 = icmp eq i8 %v3_adj, 0
 | 
						|
  br i1 %c3, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
; More complex case, there's an extra op that is safe to execute unconditionally, and it has multiple uses.
 | 
						|
 | 
						|
define void @one_pred_with_extra_op_multiuse(i8 %v0, i8 %v1) {
 | 
						|
; CHECK-LABEL: @one_pred_with_extra_op_multiuse(
 | 
						|
; CHECK-NEXT:  pred:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
 | 
						|
; CHECK-NEXT:    [[V1_ADJ_ADJ:%.*]] = add i8 [[V1_ADJ]], [[V1_ADJ]]
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1_ADJ_ADJ]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
pred:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v1_adj = add i8 %v0, %v1
 | 
						|
  %v1_adj_adj = add i8 %v1_adj, %v1_adj
 | 
						|
  %c1 = icmp eq i8 %v1_adj_adj, 0
 | 
						|
  br i1 %c1, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
define void @two_preds_with_extra_op_multiuse(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
 | 
						|
; CHECK-LABEL: @two_preds_with_extra_op_multiuse(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
 | 
						|
; CHECK:       pred0:
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2:%.*]]
 | 
						|
; CHECK-NEXT:    [[V3_ADJ_ADJ_OLD:%.*]] = add i8 [[V3_ADJ_OLD]], [[V3_ADJ_OLD]]
 | 
						|
; CHECK-NEXT:    [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_ADJ_OLD]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND1:%.*]] = or i1 [[C1]], [[C3_OLD]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       pred1:
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = icmp eq i8 [[V2]], 0
 | 
						|
; CHECK-NEXT:    [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
 | 
						|
; CHECK-NEXT:    [[V3_ADJ_ADJ:%.*]] = add i8 [[V3_ADJ]], [[V3_ADJ]]
 | 
						|
; CHECK-NEXT:    [[C3:%.*]] = icmp eq i8 [[V3_ADJ_ADJ]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C2]], [[C3]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %pred0, label %pred1
 | 
						|
pred0:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %dispatch
 | 
						|
pred1:
 | 
						|
  %c2 = icmp eq i8 %v2, 0
 | 
						|
  br i1 %c2, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v3_adj = add i8 %v1, %v2
 | 
						|
  %v3_adj_adj = add i8 %v3_adj, %v3_adj
 | 
						|
  %c3 = icmp eq i8 %v3_adj_adj, 0
 | 
						|
  br i1 %c3, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
; More complex case, there's an op that is safe to execute unconditionally,
 | 
						|
; and said op is live-out.
 | 
						|
 | 
						|
define void @one_pred_with_extra_op_liveout(i8 %v0, i8 %v1) {
 | 
						|
; CHECK-LABEL: @one_pred_with_extra_op_liveout(
 | 
						|
; CHECK-NEXT:  pred:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1_ADJ]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[V1_ADJ]])
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
pred:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v1_adj = add i8 %v0, %v1
 | 
						|
  %c1 = icmp eq i8 %v1_adj, 0
 | 
						|
  br i1 %c1, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  call void @use8(i8 %v1_adj)
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
define void @one_pred_with_extra_op_liveout_multiuse(i8 %v0, i8 %v1) {
 | 
						|
; CHECK-LABEL: @one_pred_with_extra_op_liveout_multiuse(
 | 
						|
; CHECK-NEXT:  pred:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1_ADJ]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[V1_ADJ]])
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[V1_ADJ]])
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
pred:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v1_adj = add i8 %v0, %v1
 | 
						|
  %c1 = icmp eq i8 %v1_adj, 0
 | 
						|
  br i1 %c1, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  call void @use8(i8 %v1_adj)
 | 
						|
  call void @use8(i8 %v1_adj)
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
define void @one_pred_with_extra_op_liveout_distant_phi(i8 %v0, i8 %v1) {
 | 
						|
; CHECK-LABEL: @one_pred_with_extra_op_liveout_distant_phi(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C0]], label [[PRED:%.*]], label [[LEFT_END:%.*]]
 | 
						|
; CHECK:       pred:
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V2_ADJ:%.*]] = add i8 [[V0]], [[V1]]
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = icmp eq i8 [[V2_ADJ]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C1]], [[C2]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[V2_ADJ]])
 | 
						|
; CHECK-NEXT:    br label [[LEFT_END]]
 | 
						|
; CHECK:       left_end:
 | 
						|
; CHECK-NEXT:    [[MERGE_LEFT:%.*]] = phi i8 [ [[V2_ADJ]], [[FINAL_LEFT]] ], [ 0, [[ENTRY:%.*]] ]
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[MERGE_LEFT]])
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect2()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %pred, label %left_end
 | 
						|
pred:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v2_adj = add i8 %v0, %v1
 | 
						|
  %c2 = icmp eq i8 %v2_adj, 0
 | 
						|
  br i1 %c2, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  call void @use8(i8 %v2_adj)
 | 
						|
  br label %left_end
 | 
						|
left_end:
 | 
						|
  %merge_left = phi i8 [ %v2_adj, %final_left ], [ 0, %entry ]
 | 
						|
  call void @sideeffect1()
 | 
						|
  call void @use8(i8 %merge_left)
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect2()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
define void @two_preds_with_extra_op_liveout(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
 | 
						|
; CHECK-LABEL: @two_preds_with_extra_op_liveout(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
 | 
						|
; CHECK:       pred0:
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
 | 
						|
; CHECK:       pred1:
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
 | 
						|
; CHECK-NEXT:    [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C2]], [[C3]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       dispatch:
 | 
						|
; CHECK-NEXT:    [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
 | 
						|
; CHECK-NEXT:    [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_OLD]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[MERGE_LEFT]])
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %pred0, label %pred1
 | 
						|
pred0:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %dispatch
 | 
						|
pred1:
 | 
						|
  %c2 = icmp eq i8 %v2, 0
 | 
						|
  br i1 %c2, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v3_adj = add i8 %v1, %v2
 | 
						|
  %c3 = icmp eq i8 %v3_adj, 0
 | 
						|
  br i1 %c3, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
 | 
						|
  call void @use8(i8 %merge_left)
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
define void @two_preds_with_extra_op_liveout_multiuse(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
 | 
						|
; CHECK-LABEL: @two_preds_with_extra_op_liveout_multiuse(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
 | 
						|
; CHECK:       pred0:
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
 | 
						|
; CHECK:       pred1:
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
 | 
						|
; CHECK-NEXT:    [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C2]], [[C3]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       dispatch:
 | 
						|
; CHECK-NEXT:    [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
 | 
						|
; CHECK-NEXT:    [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_OLD]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
 | 
						|
; CHECK-NEXT:    [[MERGE_LEFT_2:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 42, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[MERGE_LEFT]])
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[MERGE_LEFT_2]])
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %pred0, label %pred1
 | 
						|
pred0:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %dispatch
 | 
						|
pred1:
 | 
						|
  %c2 = icmp eq i8 %v2, 0
 | 
						|
  br i1 %c2, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v3_adj = add i8 %v1, %v2
 | 
						|
  %c3 = icmp eq i8 %v3_adj, 0
 | 
						|
  br i1 %c3, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
 | 
						|
  %merge_left_2 = phi i8 [ %v3_adj, %dispatch ], [ 42, %pred0 ]
 | 
						|
  call void @use8(i8 %merge_left)
 | 
						|
  call void @use8(i8 %merge_left_2)
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
; More complex case, there's an op that is safe to execute unconditionally,
 | 
						|
; and said op is live-out, and it is only used externally.
 | 
						|
 | 
						|
define void @one_pred_with_extra_op_eexternally_used_only(i8 %v0, i8 %v1) {
 | 
						|
; CHECK-LABEL: @one_pred_with_extra_op_eexternally_used_only(
 | 
						|
; CHECK-NEXT:  pred:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[V1_ADJ]])
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
pred:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v1_adj = add i8 %v0, %v1
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  call void @use8(i8 %v1_adj)
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
define void @one_pred_with_extra_op_externally_used_only_multiuse(i8 %v0, i8 %v1) {
 | 
						|
; CHECK-LABEL: @one_pred_with_extra_op_externally_used_only_multiuse(
 | 
						|
; CHECK-NEXT:  pred:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[V1_ADJ]])
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[V1_ADJ]])
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
pred:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v1_adj = add i8 %v0, %v1
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  call void @use8(i8 %v1_adj)
 | 
						|
  call void @use8(i8 %v1_adj)
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
define void @two_preds_with_extra_op_externally_used_only(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
 | 
						|
; CHECK-LABEL: @two_preds_with_extra_op_externally_used_only(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
 | 
						|
; CHECK:       pred0:
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
 | 
						|
; CHECK:       pred1:
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
 | 
						|
; CHECK-NEXT:    [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C2]], [[C3]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       dispatch:
 | 
						|
; CHECK-NEXT:    [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
 | 
						|
; CHECK-NEXT:    [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[MERGE_LEFT]])
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %pred0, label %pred1
 | 
						|
pred0:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %dispatch
 | 
						|
pred1:
 | 
						|
  %c2 = icmp eq i8 %v2, 0
 | 
						|
  br i1 %c2, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v3_adj = add i8 %v1, %v2
 | 
						|
  %c3 = icmp eq i8 %v3, 0
 | 
						|
  br i1 %c3, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
 | 
						|
  call void @use8(i8 %merge_left)
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
define void @two_preds_with_extra_op_externally_used_only_multiuse(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
 | 
						|
; CHECK-LABEL: @two_preds_with_extra_op_externally_used_only_multiuse(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
 | 
						|
; CHECK:       pred0:
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
 | 
						|
; CHECK:       pred1:
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
 | 
						|
; CHECK-NEXT:    [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C2]], [[C3]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       dispatch:
 | 
						|
; CHECK-NEXT:    [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
 | 
						|
; CHECK-NEXT:    [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
 | 
						|
; CHECK-NEXT:    [[MERGE_LEFT_2:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 42, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[MERGE_LEFT]])
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[MERGE_LEFT_2]])
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %pred0, label %pred1
 | 
						|
pred0:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %dispatch
 | 
						|
pred1:
 | 
						|
  %c2 = icmp eq i8 %v2, 0
 | 
						|
  br i1 %c2, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %v3_adj = add i8 %v1, %v2
 | 
						|
  %c3 = icmp eq i8 %v3, 0
 | 
						|
  br i1 %c3, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
 | 
						|
  %merge_left_2 = phi i8 [ %v3_adj, %dispatch ], [ 42, %pred0 ]
 | 
						|
  call void @use8(i8 %merge_left)
 | 
						|
  call void @use8(i8 %merge_left_2)
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
; The liveout instruction can be located after the branch condition.
 | 
						|
define void @one_pred_with_extra_op_externally_used_only_after_cond_distant_phi(i8 %v0, i8 %v1, i8 %v3, i8 %v4, i8 %v5) {
 | 
						|
; CHECK-LABEL: @one_pred_with_extra_op_externally_used_only_after_cond_distant_phi(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C0]], label [[PRED:%.*]], label [[LEFT_END:%.*]]
 | 
						|
; CHECK:       pred:
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V2_ADJ:%.*]] = add i8 [[V4:%.*]], [[V5:%.*]]
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C1]], [[C3]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[V2_ADJ]])
 | 
						|
; CHECK-NEXT:    br label [[LEFT_END]]
 | 
						|
; CHECK:       left_end:
 | 
						|
; CHECK-NEXT:    [[MERGE_LEFT:%.*]] = phi i8 [ [[V2_ADJ]], [[FINAL_LEFT]] ], [ 0, [[ENTRY:%.*]] ]
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[MERGE_LEFT]])
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect2()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %pred, label %left_end
 | 
						|
pred:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %c3 = icmp eq i8 %v3, 0
 | 
						|
  %v2_adj = add i8 %v4, %v5
 | 
						|
  br i1 %c3, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  call void @sideeffect0()
 | 
						|
  call void @use8(i8 %v2_adj)
 | 
						|
  br label %left_end
 | 
						|
left_end:
 | 
						|
  %merge_left = phi i8 [ %v2_adj, %final_left ], [ 0, %entry ]
 | 
						|
  call void @sideeffect1()
 | 
						|
  call void @use8(i8 %merge_left)
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect2()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
define void @two_preds_with_extra_op_externally_used_only_after_cond(i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
 | 
						|
; CHECK-LABEL: @two_preds_with_extra_op_externally_used_only_after_cond(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
 | 
						|
; CHECK:       pred0:
 | 
						|
; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
 | 
						|
; CHECK:       pred1:
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
 | 
						|
; CHECK-NEXT:    [[V3_ADJ:%.*]] = add i8 [[V4:%.*]], [[V5:%.*]]
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[C2]], [[C3]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
 | 
						|
; CHECK:       dispatch:
 | 
						|
; CHECK-NEXT:    [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
 | 
						|
; CHECK-NEXT:    [[V3_ADJ_OLD:%.*]] = add i8 [[V4]], [[V5]]
 | 
						|
; CHECK-NEXT:    br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
 | 
						|
; CHECK:       final_left:
 | 
						|
; CHECK-NEXT:    [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
 | 
						|
; CHECK-NEXT:    call void @use8(i8 [[MERGE_LEFT]])
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
; CHECK:       final_right:
 | 
						|
; CHECK-NEXT:    call void @sideeffect1()
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  %c0 = icmp eq i8 %v0, 0
 | 
						|
  br i1 %c0, label %pred0, label %pred1
 | 
						|
pred0:
 | 
						|
  %c1 = icmp eq i8 %v1, 0
 | 
						|
  br i1 %c1, label %final_left, label %dispatch
 | 
						|
pred1:
 | 
						|
  %c2 = icmp eq i8 %v2, 0
 | 
						|
  br i1 %c2, label %dispatch, label %final_right
 | 
						|
dispatch:
 | 
						|
  %c3 = icmp eq i8 %v3, 0
 | 
						|
  %v3_adj = add i8 %v4, %v5
 | 
						|
  br i1 %c3, label %final_left, label %final_right
 | 
						|
final_left:
 | 
						|
  %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
 | 
						|
  call void @use8(i8 %merge_left)
 | 
						|
  call void @sideeffect0()
 | 
						|
  ret void
 | 
						|
final_right:
 | 
						|
  call void @sideeffect1()
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
define void @pr48450() {
 | 
						|
; CHECK-LABEL: @pr48450(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 | 
						|
; CHECK:       for.body:
 | 
						|
; CHECK-NEXT:    [[COUNTDOWN:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[DEC_MERGE:%.*]], [[FOR_BODYTHREAD_PRE_SPLIT:%.*]] ]
 | 
						|
; CHECK-NEXT:    [[C:%.*]] = call i1 @gen1()
 | 
						|
; CHECK-NEXT:    br i1 [[C]], label [[FOR_INC:%.*]], label [[IF_THEN:%.*]]
 | 
						|
; CHECK:       for.inc:
 | 
						|
; CHECK-NEXT:    [[DEC_OLD:%.*]] = add i8 [[COUNTDOWN]], -1
 | 
						|
; CHECK-NEXT:    [[CMP_NOT_OLD:%.*]] = icmp eq i8 [[COUNTDOWN]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[CMP_NOT_OLD]], label [[IF_END_LOOPEXIT:%.*]], label [[FOR_BODYTHREAD_PRE_SPLIT]]
 | 
						|
; CHECK:       if.then:
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = call i1 @gen1()
 | 
						|
; CHECK-NEXT:    [[C2_NOT:%.*]] = xor i1 [[C2]], true
 | 
						|
; CHECK-NEXT:    [[DEC:%.*]] = add i8 [[COUNTDOWN]], -1
 | 
						|
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[COUNTDOWN]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[C2_NOT]], [[CMP_NOT]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[IF_END_LOOPEXIT]], label [[FOR_BODYTHREAD_PRE_SPLIT]]
 | 
						|
; CHECK:       for.bodythread-pre-split:
 | 
						|
; CHECK-NEXT:    [[DEC_MERGE]] = phi i8 [ [[DEC]], [[IF_THEN]] ], [ [[DEC_OLD]], [[FOR_INC]] ]
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    br label [[FOR_BODY]]
 | 
						|
; CHECK:       if.end.loopexit:
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  br label %for.body
 | 
						|
 | 
						|
for.body:
 | 
						|
  %countdown = phi i8 [ 8, %entry ], [ %dec, %for.bodythread-pre-split ]
 | 
						|
  %c = call i1 @gen1()
 | 
						|
  br i1 %c, label %for.inc, label %if.then
 | 
						|
 | 
						|
for.inc:
 | 
						|
  %dec = add i8 %countdown, -1
 | 
						|
  %cmp.not = icmp eq i8 %countdown, 0
 | 
						|
  br i1 %cmp.not, label %if.end.loopexit, label %for.bodythread-pre-split
 | 
						|
 | 
						|
if.then:
 | 
						|
  %c2 = call i1 @gen1()
 | 
						|
  br i1 %c2, label %for.inc, label %if.end.loopexit
 | 
						|
 | 
						|
for.bodythread-pre-split:
 | 
						|
  call void @sideeffect0()
 | 
						|
  br label %for.body
 | 
						|
 | 
						|
if.end.loopexit:
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
define void @pr48450_2(i1 %enable_loopback) {
 | 
						|
; CHECK-LABEL: @pr48450_2(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 | 
						|
; CHECK:       for.body:
 | 
						|
; CHECK-NEXT:    [[COUNTDOWN:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[DEC_MERGE:%.*]], [[FOR_BODYTHREAD_PRE_SPLIT:%.*]] ]
 | 
						|
; CHECK-NEXT:    [[C:%.*]] = call i1 @gen1()
 | 
						|
; CHECK-NEXT:    br i1 [[C]], label [[FOR_INC:%.*]], label [[IF_THEN:%.*]]
 | 
						|
; CHECK:       for.inc:
 | 
						|
; CHECK-NEXT:    [[DEC_OLD:%.*]] = add i8 [[COUNTDOWN]], -1
 | 
						|
; CHECK-NEXT:    [[CMP_NOT_OLD:%.*]] = icmp eq i8 [[COUNTDOWN]], 0
 | 
						|
; CHECK-NEXT:    br i1 [[CMP_NOT_OLD]], label [[IF_END_LOOPEXIT:%.*]], label [[FOR_BODYTHREAD_PRE_SPLIT]]
 | 
						|
; CHECK:       if.then:
 | 
						|
; CHECK-NEXT:    [[C2:%.*]] = call i1 @gen1()
 | 
						|
; CHECK-NEXT:    [[C2_NOT:%.*]] = xor i1 [[C2]], true
 | 
						|
; CHECK-NEXT:    [[DEC:%.*]] = add i8 [[COUNTDOWN]], -1
 | 
						|
; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[COUNTDOWN]], 0
 | 
						|
; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[C2_NOT]], [[CMP_NOT]]
 | 
						|
; CHECK-NEXT:    br i1 [[OR_COND]], label [[IF_END_LOOPEXIT]], label [[FOR_BODYTHREAD_PRE_SPLIT]]
 | 
						|
; CHECK:       for.bodythread-pre-split:
 | 
						|
; CHECK-NEXT:    [[DEC_MERGE]] = phi i8 [ [[DEC_OLD]], [[FOR_INC]] ], [ [[DEC_MERGE]], [[FOR_BODYTHREAD_PRE_SPLIT_LOOPBACK:%.*]] ], [ [[DEC]], [[IF_THEN]] ]
 | 
						|
; CHECK-NEXT:    [[SHOULD_LOOPBACK:%.*]] = phi i1 [ true, [[FOR_INC]] ], [ false, [[FOR_BODYTHREAD_PRE_SPLIT_LOOPBACK]] ], [ true, [[IF_THEN]] ]
 | 
						|
; CHECK-NEXT:    [[DO_LOOPBACK:%.*]] = and i1 [[SHOULD_LOOPBACK]], [[ENABLE_LOOPBACK:%.*]]
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    br i1 [[DO_LOOPBACK]], label [[FOR_BODYTHREAD_PRE_SPLIT_LOOPBACK]], label [[FOR_BODY]]
 | 
						|
; CHECK:       for.bodythread-pre-split.loopback:
 | 
						|
; CHECK-NEXT:    call void @sideeffect0()
 | 
						|
; CHECK-NEXT:    br label [[FOR_BODYTHREAD_PRE_SPLIT]]
 | 
						|
; CHECK:       if.end.loopexit:
 | 
						|
; CHECK-NEXT:    ret void
 | 
						|
;
 | 
						|
entry:
 | 
						|
  br label %for.body
 | 
						|
 | 
						|
for.body:
 | 
						|
  %countdown = phi i8 [ 8, %entry ], [ %dec, %for.bodythread-pre-split ]
 | 
						|
  %c = call i1 @gen1()
 | 
						|
  br i1 %c, label %for.inc, label %if.then
 | 
						|
 | 
						|
for.inc:
 | 
						|
  %dec = add i8 %countdown, -1
 | 
						|
  %cmp.not = icmp eq i8 %countdown, 0
 | 
						|
  br i1 %cmp.not, label %if.end.loopexit, label %for.bodythread-pre-split
 | 
						|
 | 
						|
if.then:
 | 
						|
  %c2 = call i1 @gen1()
 | 
						|
  br i1 %c2, label %for.inc, label %if.end.loopexit
 | 
						|
 | 
						|
for.bodythread-pre-split:
 | 
						|
  %should_loopback = phi i1 [ 1, %for.inc ], [ 0, %for.bodythread-pre-split.loopback ]
 | 
						|
  %do_loopback = and i1 %should_loopback, %enable_loopback
 | 
						|
  call void @sideeffect0()
 | 
						|
  br i1 %do_loopback, label %for.bodythread-pre-split.loopback, label %for.body
 | 
						|
 | 
						|
for.bodythread-pre-split.loopback:
 | 
						|
  call void @sideeffect0()
 | 
						|
  br label %for.bodythread-pre-split
 | 
						|
 | 
						|
if.end.loopexit:
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
@f.b = external global i8, align 1
 | 
						|
define void @pr48450_3() {
 | 
						|
; CHECK-LABEL: @pr48450_3(
 | 
						|
; CHECK-NEXT:  entry:
 | 
						|
; CHECK-NEXT:    br label [[FOR_COND1:%.*]]
 | 
						|
; CHECK:       for.cond1:
 | 
						|
; CHECK-NEXT:    [[V:%.*]] = load i8, i8* @f.b, align 1
 | 
						|
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[V]], 1
 | 
						|
; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
 | 
						|
; CHECK-NEXT:    br label [[FOR_COND1]]
 | 
						|
;
 | 
						|
entry:
 | 
						|
  br label %for.cond1
 | 
						|
 | 
						|
for.cond1:
 | 
						|
  %v = load i8, i8* @f.b, align 1
 | 
						|
  %cmp = icmp slt i8 %v, 1
 | 
						|
  br i1 %cmp, label %for.body, label %for.end
 | 
						|
 | 
						|
for.body:
 | 
						|
  br label %for.cond1
 | 
						|
 | 
						|
for.end:
 | 
						|
  %tobool = icmp ne i8 %v, 0
 | 
						|
  br i1 %tobool, label %if.then, label %if.end
 | 
						|
 | 
						|
if.then:
 | 
						|
  unreachable
 | 
						|
 | 
						|
if.end:
 | 
						|
  br label %for.cond2
 | 
						|
 | 
						|
for.cond2:
 | 
						|
  %c.0 = phi i8 [ undef, %if.end ], [ %inc, %if.end7 ]
 | 
						|
  %cmp3 = icmp slt i8 %c.0, 1
 | 
						|
  br i1 %cmp3, label %for.body4, label %for.cond.cleanup
 | 
						|
 | 
						|
for.cond.cleanup:
 | 
						|
  br label %cleanup
 | 
						|
 | 
						|
for.body4:
 | 
						|
  br i1 undef, label %if.then6, label %if.end7
 | 
						|
 | 
						|
if.then6:
 | 
						|
  br label %cleanup
 | 
						|
 | 
						|
if.end7:
 | 
						|
  %inc = add nsw i8 %c.0, 1
 | 
						|
  br label %for.cond2
 | 
						|
 | 
						|
cleanup:
 | 
						|
  unreachable
 | 
						|
}
 |