
If a select's condition is a AND/OR, we can unswitch invariant operands. This patch uses existing logic from unswitching AND/OR's for branch conditions. This patch fixes the Cost computation for unswitching selects to have the cost of the entire loop, since unswitching selects do not remove branches. This is required for this patch because otherwise, there are cases where unswitching selects of AND/OR is beating out unswitching of branches. This patch also prevents unswitching of logical AND/OR selects. This should instead be done by unswitching of AND/OR branch conditions. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D151677
1085 lines
53 KiB
LLVM
1085 lines
53 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
|
|
; RUN: opt -passes='simple-loop-unswitch<nontrivial>' -S < %s | FileCheck %s
|
|
|
|
; Non-trivial loop unswitching of select instruction.
|
|
|
|
declare i1 @foo()
|
|
declare i1 @bar(i32)
|
|
declare i32 @llvm.vector.reduce.add.v2i32(<2 x i32>)
|
|
|
|
define i32 @basic(i32 %N, i1 %cond, i32 %select_input) {
|
|
; CHECK-LABEL: define i32 @basic
|
|
; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND:%.*]], i32 [[SELECT_INPUT:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
|
|
; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
|
; CHECK: entry.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_US:%.*]]
|
|
; CHECK: for.cond.us:
|
|
; CHECK-NEXT: [[RES_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[ADD_US:%.*]], [[TMP1:%.*]] ]
|
|
; CHECK-NEXT: [[I_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[INC_US:%.*]], [[TMP1]] ]
|
|
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i32 [[I_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_BODY_US:%.*]], label [[FOR_COND_CLEANUP_SPLIT_US:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ [[SELECT_INPUT]], [[TMP0]] ]
|
|
; CHECK-NEXT: [[ADD_US]] = add nuw nsw i32 [[UNSWITCHED_SELECT_US]], [[RES_US]]
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_US]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND_US]]
|
|
; CHECK: for.cond.cleanup.split.us:
|
|
; CHECK-NEXT: [[RES_LCSSA_US:%.*]] = phi i32 [ [[RES_US]], [[FOR_COND_US]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: entry.split:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[ADD:%.*]], [[TMP2:%.*]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[INC:%.*]], [[TMP2]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP_SPLIT:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: br label [[TMP2]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: [[ADD]] = add nuw nsw i32 42, [[RES]]
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
; CHECK: for.cond.cleanup.split:
|
|
; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i32 [ [[RES]], [[FOR_COND]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[RES_LCSSA]], [[FOR_COND_CLEANUP_SPLIT]] ], [ [[RES_LCSSA_US]], [[FOR_COND_CLEANUP_SPLIT_US]] ]
|
|
; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.body, %entry
|
|
%res = phi i32 [ 0, %entry ], [ %add, %for.body ]
|
|
%i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
|
|
%cmp = icmp slt i32 %i, %N
|
|
br i1 %cmp, label %for.body, label %for.cond.cleanup
|
|
|
|
for.body: ; preds = %for.cond
|
|
%cond1 = select i1 %cond, i32 %select_input, i32 42
|
|
%add = add nuw nsw i32 %cond1, %res
|
|
%inc = add nuw nsw i32 %i, 1
|
|
br label %for.cond
|
|
|
|
for.cond.cleanup: ; preds = %for.cond
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @basic_veccond(i32 %N, <2 x i1> %cond, <2 x i32> %select_input) {
|
|
; CHECK-LABEL: define i32 @basic_veccond
|
|
; CHECK-SAME: (i32 [[N:%.*]], <2 x i1> [[COND:%.*]], <2 x i32> [[SELECT_INPUT:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_BODY:%.*]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[COND1:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[SELECT_INPUT]], <2 x i32> <i32 42, i32 42>
|
|
; CHECK-NEXT: [[VREDUCE:%.*]] = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> [[COND1]])
|
|
; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[VREDUCE]], [[RES]]
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i32 [ [[RES]], [[FOR_COND]] ]
|
|
; CHECK-NEXT: ret i32 [[RES_LCSSA]]
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.body, %entry
|
|
%res = phi i32 [ 0, %entry ], [ %add, %for.body ]
|
|
%i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
|
|
%cmp = icmp slt i32 %i, %N
|
|
br i1 %cmp, label %for.body, label %for.cond.cleanup
|
|
|
|
for.body: ; preds = %for.cond
|
|
%cond1 = select <2 x i1> %cond, <2 x i32> %select_input, <2 x i32> <i32 42, i32 42>
|
|
%vreduce = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %cond1)
|
|
%add = add nuw nsw i32 %vreduce, %res
|
|
%inc = add nuw nsw i32 %i, 1
|
|
br label %for.cond
|
|
|
|
for.cond.cleanup: ; preds = %for.cond
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @select_phi_input(i32 %N, i1 %cond) {
|
|
; CHECK-LABEL: define i32 @select_phi_input
|
|
; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
|
|
; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
|
; CHECK: entry.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_US:%.*]]
|
|
; CHECK: for.cond.us:
|
|
; CHECK-NEXT: [[RES_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[ADD_US:%.*]], [[TMP1:%.*]] ]
|
|
; CHECK-NEXT: [[I_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[INC_US:%.*]], [[TMP1]] ]
|
|
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i32 [[I_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_BODY_US:%.*]], label [[FOR_COND_CLEANUP_SPLIT_US:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ [[I_US]], [[TMP0]] ]
|
|
; CHECK-NEXT: [[ADD_US]] = add nuw nsw i32 [[UNSWITCHED_SELECT_US]], [[RES_US]]
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_US]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND_US]]
|
|
; CHECK: for.cond.cleanup.split.us:
|
|
; CHECK-NEXT: [[RES_LCSSA_US:%.*]] = phi i32 [ [[RES_US]], [[FOR_COND_US]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: entry.split:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[ADD:%.*]], [[TMP2:%.*]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[INC:%.*]], [[TMP2]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP_SPLIT:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: br label [[TMP2]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: [[ADD]] = add nuw nsw i32 42, [[RES]]
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
; CHECK: for.cond.cleanup.split:
|
|
; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i32 [ [[RES]], [[FOR_COND]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[RES_LCSSA]], [[FOR_COND_CLEANUP_SPLIT]] ], [ [[RES_LCSSA_US]], [[FOR_COND_CLEANUP_SPLIT_US]] ]
|
|
; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.body, %entry
|
|
%res = phi i32 [ 0, %entry ], [ %add, %for.body ]
|
|
%i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
|
|
%cmp = icmp slt i32 %i, %N
|
|
br i1 %cmp, label %for.body, label %for.cond.cleanup
|
|
|
|
for.body: ; preds = %for.cond
|
|
%cond1 = select i1 %cond, i32 %i, i32 42
|
|
%add = add nuw nsw i32 %cond1, %res
|
|
%inc = add nuw nsw i32 %i, 1
|
|
br label %for.cond
|
|
|
|
for.cond.cleanup: ; preds = %for.cond
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @basic_cond_noundef(i32 %N, i1 noundef %cond) {
|
|
; CHECK-LABEL: define i32 @basic_cond_noundef
|
|
; CHECK-SAME: (i32 [[N:%.*]], i1 noundef [[COND:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[COND]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
|
; CHECK: entry.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_US:%.*]]
|
|
; CHECK: for.cond.us:
|
|
; CHECK-NEXT: [[RES_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[ADD_US:%.*]], [[TMP1:%.*]] ]
|
|
; CHECK-NEXT: [[I_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[INC_US:%.*]], [[TMP1]] ]
|
|
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i32 [[I_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_BODY_US:%.*]], label [[FOR_COND_CLEANUP_SPLIT_US:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ [[I_US]], [[TMP0]] ]
|
|
; CHECK-NEXT: [[ADD_US]] = add nuw nsw i32 [[UNSWITCHED_SELECT_US]], [[RES_US]]
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_US]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND_US]]
|
|
; CHECK: for.cond.cleanup.split.us:
|
|
; CHECK-NEXT: [[RES_LCSSA_US:%.*]] = phi i32 [ [[RES_US]], [[FOR_COND_US]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: entry.split:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[ADD:%.*]], [[TMP2:%.*]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[INC:%.*]], [[TMP2]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP_SPLIT:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: br label [[TMP2]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: [[ADD]] = add nuw nsw i32 42, [[RES]]
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
; CHECK: for.cond.cleanup.split:
|
|
; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i32 [ [[RES]], [[FOR_COND]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[RES_LCSSA]], [[FOR_COND_CLEANUP_SPLIT]] ], [ [[RES_LCSSA_US]], [[FOR_COND_CLEANUP_SPLIT_US]] ]
|
|
; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.body, %entry
|
|
%res = phi i32 [ 0, %entry ], [ %add, %for.body ]
|
|
%i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
|
|
%cmp = icmp slt i32 %i, %N
|
|
br i1 %cmp, label %for.body, label %for.cond.cleanup
|
|
|
|
for.body: ; preds = %for.cond
|
|
%cond1 = select i1 %cond, i32 %i, i32 42
|
|
%add = add nuw nsw i32 %cond1, %res
|
|
%inc = add nuw nsw i32 %i, 1
|
|
br label %for.cond
|
|
|
|
for.cond.cleanup: ; preds = %for.cond
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @cond_invariant(i32 %N) {
|
|
; CHECK-LABEL: define i32 @cond_invariant
|
|
; CHECK-SAME: (i32 [[N:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_BODY:%.*]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[COND:%.*]] = call i1 @foo()
|
|
; CHECK-NEXT: [[COND1:%.*]] = select i1 [[COND]], i32 [[I]], i32 42
|
|
; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[COND1]], [[RES]]
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i32 [ [[RES]], [[FOR_COND]] ]
|
|
; CHECK-NEXT: ret i32 [[RES_LCSSA]]
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.body, %entry
|
|
%res = phi i32 [ 0, %entry ], [ %add, %for.body ]
|
|
%i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
|
|
%cmp = icmp slt i32 %i, %N
|
|
br i1 %cmp, label %for.body, label %for.cond.cleanup
|
|
|
|
for.body: ; preds = %for.cond
|
|
%cond = call i1 @foo()
|
|
%cond1 = select i1 %cond, i32 %i, i32 42
|
|
%add = add nuw nsw i32 %cond1, %res
|
|
%inc = add nuw nsw i32 %i, 1
|
|
br label %for.cond
|
|
|
|
for.cond.cleanup: ; preds = %for.cond
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @chained_select(i32 %N, i1 %cond, i1 %cond2) {
|
|
; CHECK-LABEL: define i32 @chained_select
|
|
; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND:%.*]], i1 [[COND2:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
|
|
; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
|
; CHECK: entry.split.us:
|
|
; CHECK-NEXT: [[COND2_FR13:%.*]] = freeze i1 [[COND2]]
|
|
; CHECK-NEXT: br i1 [[COND2_FR13]], label [[ENTRY_SPLIT_US_SPLIT_US:%.*]], label [[ENTRY_SPLIT_US_SPLIT:%.*]]
|
|
; CHECK: entry.split.us.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_US_US:%.*]]
|
|
; CHECK: for.cond.us.us:
|
|
; CHECK-NEXT: [[RES_US_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US_SPLIT_US]] ], [ [[ADD_US_US:%.*]], [[TMP3:%.*]] ]
|
|
; CHECK-NEXT: [[I_US_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US_SPLIT_US]] ], [ [[INC_US_US:%.*]], [[TMP3]] ]
|
|
; CHECK-NEXT: [[CMP_US_US:%.*]] = icmp slt i32 [[I_US_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP_US_US]], label [[FOR_BODY_US_US:%.*]], label [[FOR_COND_CLEANUP_SPLIT_US_SPLIT_US:%.*]]
|
|
; CHECK: for.body.us.us:
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1:%.*]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US_US:%.*]] = phi i32 [ [[I_US_US]], [[TMP0]] ]
|
|
; CHECK-NEXT: br label [[TMP2:%.*]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: br label [[TMP3]]
|
|
; CHECK: 3:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US11:%.*]] = phi i32 [ [[UNSWITCHED_SELECT_US_US]], [[TMP2]] ]
|
|
; CHECK-NEXT: [[ADD_US_US]] = add nuw nsw i32 [[UNSWITCHED_SELECT_US11]], [[RES_US_US]]
|
|
; CHECK-NEXT: [[INC_US_US]] = add nuw nsw i32 [[I_US_US]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND_US_US]]
|
|
; CHECK: for.cond.cleanup.split.us.split.us:
|
|
; CHECK-NEXT: [[RES_LCSSA_US_US:%.*]] = phi i32 [ [[RES_US_US]], [[FOR_COND_US_US]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_SPLIT_US:%.*]]
|
|
; CHECK: entry.split.us.split:
|
|
; CHECK-NEXT: br label [[FOR_COND_US:%.*]]
|
|
; CHECK: for.cond.us:
|
|
; CHECK-NEXT: [[RES_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US_SPLIT]] ], [ [[ADD_US:%.*]], [[TMP6:%.*]] ]
|
|
; CHECK-NEXT: [[I_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US_SPLIT]] ], [ [[INC_US:%.*]], [[TMP6]] ]
|
|
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i32 [[I_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_BODY_US:%.*]], label [[FOR_COND_CLEANUP_SPLIT_US_SPLIT:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: br label [[TMP4:%.*]]
|
|
; CHECK: 4:
|
|
; CHECK-NEXT: br label [[TMP5:%.*]]
|
|
; CHECK: 5:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ [[I_US]], [[TMP4]] ]
|
|
; CHECK-NEXT: br label [[TMP6]]
|
|
; CHECK: 6:
|
|
; CHECK-NEXT: [[ADD_US]] = add nuw nsw i32 24, [[RES_US]]
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_US]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND_US]]
|
|
; CHECK: for.cond.cleanup.split.us.split:
|
|
; CHECK-NEXT: [[RES_LCSSA_US:%.*]] = phi i32 [ [[RES_US]], [[FOR_COND_US]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_SPLIT_US]]
|
|
; CHECK: for.cond.cleanup.split.us:
|
|
; CHECK-NEXT: [[DOTUS_PHI12:%.*]] = phi i32 [ [[RES_LCSSA_US]], [[FOR_COND_CLEANUP_SPLIT_US_SPLIT]] ], [ [[RES_LCSSA_US_US]], [[FOR_COND_CLEANUP_SPLIT_US_SPLIT_US]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: entry.split:
|
|
; CHECK-NEXT: [[COND2_FR:%.*]] = freeze i1 [[COND2]]
|
|
; CHECK-NEXT: br i1 [[COND2_FR]], label [[ENTRY_SPLIT_SPLIT_US:%.*]], label [[ENTRY_SPLIT_SPLIT:%.*]]
|
|
; CHECK: entry.split.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_US1:%.*]]
|
|
; CHECK: for.cond.us1:
|
|
; CHECK-NEXT: [[RES_US2:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_SPLIT_US]] ], [ [[ADD_US7:%.*]], [[TMP9:%.*]] ]
|
|
; CHECK-NEXT: [[I_US3:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_SPLIT_US]] ], [ [[INC_US8:%.*]], [[TMP9]] ]
|
|
; CHECK-NEXT: [[CMP_US4:%.*]] = icmp slt i32 [[I_US3]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP_US4]], label [[FOR_BODY_US5:%.*]], label [[FOR_COND_CLEANUP_SPLIT_SPLIT_US:%.*]]
|
|
; CHECK: for.body.us5:
|
|
; CHECK-NEXT: br label [[TMP7:%.*]]
|
|
; CHECK: 7:
|
|
; CHECK-NEXT: br label [[TMP8:%.*]]
|
|
; CHECK: 8:
|
|
; CHECK-NEXT: br label [[TMP9]]
|
|
; CHECK: 9:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US6:%.*]] = phi i32 [ 42, [[TMP8]] ]
|
|
; CHECK-NEXT: [[ADD_US7]] = add nuw nsw i32 [[UNSWITCHED_SELECT_US6]], [[RES_US2]]
|
|
; CHECK-NEXT: [[INC_US8]] = add nuw nsw i32 [[I_US3]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND_US1]]
|
|
; CHECK: for.cond.cleanup.split.split.us:
|
|
; CHECK-NEXT: [[RES_LCSSA_US9:%.*]] = phi i32 [ [[RES_US2]], [[FOR_COND_US1]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_SPLIT:%.*]]
|
|
; CHECK: entry.split.split:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_SPLIT]] ], [ [[ADD:%.*]], [[TMP11:%.*]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_SPLIT]] ], [ [[INC:%.*]], [[TMP11]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP_SPLIT_SPLIT:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: br label [[TMP10:%.*]]
|
|
; CHECK: 10:
|
|
; CHECK-NEXT: br label [[TMP11]]
|
|
; CHECK: 11:
|
|
; CHECK-NEXT: [[ADD]] = add nuw nsw i32 24, [[RES]]
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
; CHECK: for.cond.cleanup.split.split:
|
|
; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i32 [ [[RES]], [[FOR_COND]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_SPLIT]]
|
|
; CHECK: for.cond.cleanup.split:
|
|
; CHECK-NEXT: [[DOTUS_PHI10:%.*]] = phi i32 [ [[RES_LCSSA]], [[FOR_COND_CLEANUP_SPLIT_SPLIT]] ], [ [[RES_LCSSA_US9]], [[FOR_COND_CLEANUP_SPLIT_SPLIT_US]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[DOTUS_PHI10]], [[FOR_COND_CLEANUP_SPLIT]] ], [ [[DOTUS_PHI12]], [[FOR_COND_CLEANUP_SPLIT_US]] ]
|
|
; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.body, %entry
|
|
%res = phi i32 [ 0, %entry ], [ %add, %for.body ]
|
|
%i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
|
|
%cmp = icmp slt i32 %i, %N
|
|
br i1 %cmp, label %for.body, label %for.cond.cleanup
|
|
|
|
for.body: ; preds = %for.cond
|
|
%select1 = select i1 %cond, i32 %i, i32 42
|
|
%select2 = select i1 %cond2, i32 %select1, i32 24
|
|
%add = add nuw nsw i32 %select2, %res
|
|
%inc = add nuw nsw i32 %i, 1
|
|
br label %for.cond
|
|
|
|
for.cond.cleanup: ; preds = %for.cond
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @select_in_if(i32 %N, i1 %cond) {
|
|
; CHECK-LABEL: define i32 @select_in_if
|
|
; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
|
|
; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
|
; CHECK: entry.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_US:%.*]]
|
|
; CHECK: for.cond.us:
|
|
; CHECK-NEXT: [[RES_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[ADD_US:%.*]], [[FOR_BODY_END_US:%.*]] ]
|
|
; CHECK-NEXT: [[I_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[INC_US:%.*]], [[FOR_BODY_END_US]] ]
|
|
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i32 [[I_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_BODY_US:%.*]], label [[FOR_COND_CLEANUP_SPLIT_US:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: [[UREM_US:%.*]] = urem i32 [[I_US]], 2
|
|
; CHECK-NEXT: [[IF_COND_US:%.*]] = icmp eq i32 [[UREM_US]], 0
|
|
; CHECK-NEXT: br i1 [[IF_COND_US]], label [[FOR_BODY_IF_US:%.*]], label [[FOR_BODY_END_US]]
|
|
; CHECK: for.body.if.us:
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: for.body.end.us:
|
|
; CHECK-NEXT: [[P_US:%.*]] = phi i32 [ [[UNSWITCHED_SELECT_US:%.*]], [[TMP1:%.*]] ], [ 24, [[FOR_BODY_US]] ]
|
|
; CHECK-NEXT: [[ADD_US]] = add nuw nsw i32 [[P_US]], [[RES_US]]
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_US]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND_US]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US]] = phi i32 [ [[I_US]], [[TMP0]] ]
|
|
; CHECK-NEXT: br label [[FOR_BODY_END_US]]
|
|
; CHECK: for.cond.cleanup.split.us:
|
|
; CHECK-NEXT: [[RES_LCSSA_US:%.*]] = phi i32 [ [[RES_US]], [[FOR_COND_US]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: entry.split:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[ADD:%.*]], [[FOR_BODY_END:%.*]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[INC:%.*]], [[FOR_BODY_END]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP_SPLIT:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[UREM:%.*]] = urem i32 [[I]], 2
|
|
; CHECK-NEXT: [[IF_COND:%.*]] = icmp eq i32 [[UREM]], 0
|
|
; CHECK-NEXT: br i1 [[IF_COND]], label [[FOR_BODY_IF:%.*]], label [[FOR_BODY_END]]
|
|
; CHECK: for.body.if:
|
|
; CHECK-NEXT: br label [[TMP2:%.*]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: br label [[FOR_BODY_END]]
|
|
; CHECK: for.body.end:
|
|
; CHECK-NEXT: [[P:%.*]] = phi i32 [ 42, [[TMP2]] ], [ 24, [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[P]], [[RES]]
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
; CHECK: for.cond.cleanup.split:
|
|
; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i32 [ [[RES]], [[FOR_COND]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[RES_LCSSA]], [[FOR_COND_CLEANUP_SPLIT]] ], [ [[RES_LCSSA_US]], [[FOR_COND_CLEANUP_SPLIT_US]] ]
|
|
; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.body.end, %entry
|
|
%res = phi i32 [ 0, %entry ], [ %add, %for.body.end ]
|
|
%i = phi i32 [ 0, %entry ], [ %inc, %for.body.end ]
|
|
%cmp = icmp slt i32 %i, %N
|
|
br i1 %cmp, label %for.body, label %for.cond.cleanup
|
|
|
|
for.body: ; preds = %for.cond
|
|
%urem = urem i32 %i, 2
|
|
%if.cond = icmp eq i32 %urem, 0
|
|
br i1 %if.cond, label %for.body.if, label %for.body.end
|
|
|
|
for.body.if: ; preds = %for.body
|
|
%cond1 = select i1 %cond, i32 %i, i32 42
|
|
br label %for.body.end
|
|
|
|
for.body.end: ; preds = %for.body, %for.body.if
|
|
%p = phi i32 [ %cond1, %for.body.if ], [ 24, %for.body ]
|
|
%add = add nuw nsw i32 %p, %res
|
|
%inc = add nuw nsw i32 %i, 1
|
|
br label %for.cond
|
|
|
|
for.cond.cleanup: ; preds = %for.cond
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @select_in_if_else(i32 %N, i1 %cond) {
|
|
; CHECK-LABEL: define i32 @select_in_if_else
|
|
; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
|
|
; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
|
; CHECK: entry.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_US:%.*]]
|
|
; CHECK: for.cond.us:
|
|
; CHECK-NEXT: [[RES_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[ADD_US:%.*]], [[FOR_BODY_END_US:%.*]] ]
|
|
; CHECK-NEXT: [[I_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[INC_US:%.*]], [[FOR_BODY_END_US]] ]
|
|
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i32 [[I_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_BODY_US:%.*]], label [[FOR_COND_CLEANUP_SPLIT_US:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: [[UREM_US:%.*]] = urem i32 [[I_US]], 2
|
|
; CHECK-NEXT: [[IF_COND_US:%.*]] = icmp eq i32 [[UREM_US]], 0
|
|
; CHECK-NEXT: br i1 [[IF_COND_US]], label [[FOR_BODY_IF_US:%.*]], label [[FOR_BODY_ELSE_US:%.*]]
|
|
; CHECK: for.body.else.us:
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: for.body.if.us:
|
|
; CHECK-NEXT: [[COND1A_US:%.*]] = select i1 true, i32 [[I_US]], i32 42
|
|
; CHECK-NEXT: br label [[FOR_BODY_END_US]]
|
|
; CHECK: for.body.end.us:
|
|
; CHECK-NEXT: [[P_US:%.*]] = phi i32 [ [[COND1A_US]], [[FOR_BODY_IF_US]] ], [ [[UNSWITCHED_SELECT_US:%.*]], [[TMP1:%.*]] ]
|
|
; CHECK-NEXT: [[ADD_US]] = add nuw nsw i32 [[P_US]], [[RES_US]]
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_US]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND_US]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US]] = phi i32 [ 24, [[TMP0]] ]
|
|
; CHECK-NEXT: br label [[FOR_BODY_END_US]]
|
|
; CHECK: for.cond.cleanup.split.us:
|
|
; CHECK-NEXT: [[RES_LCSSA_US:%.*]] = phi i32 [ [[RES_US]], [[FOR_COND_US]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: entry.split:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[ADD:%.*]], [[FOR_BODY_END:%.*]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[INC:%.*]], [[FOR_BODY_END]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP_SPLIT:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[UREM:%.*]] = urem i32 [[I]], 2
|
|
; CHECK-NEXT: [[IF_COND:%.*]] = icmp eq i32 [[UREM]], 0
|
|
; CHECK-NEXT: br i1 [[IF_COND]], label [[FOR_BODY_IF:%.*]], label [[FOR_BODY_ELSE:%.*]]
|
|
; CHECK: for.body.if:
|
|
; CHECK-NEXT: [[COND1A:%.*]] = select i1 false, i32 [[I]], i32 42
|
|
; CHECK-NEXT: br label [[FOR_BODY_END]]
|
|
; CHECK: for.body.else:
|
|
; CHECK-NEXT: br label [[TMP2:%.*]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: br label [[FOR_BODY_END]]
|
|
; CHECK: for.body.end:
|
|
; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[COND1A]], [[FOR_BODY_IF]] ], [ [[I]], [[TMP2]] ]
|
|
; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[P]], [[RES]]
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
; CHECK: for.cond.cleanup.split:
|
|
; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i32 [ [[RES]], [[FOR_COND]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[RES_LCSSA]], [[FOR_COND_CLEANUP_SPLIT]] ], [ [[RES_LCSSA_US]], [[FOR_COND_CLEANUP_SPLIT_US]] ]
|
|
; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.body.end, %entry
|
|
%res = phi i32 [ 0, %entry ], [ %add, %for.body.end ]
|
|
%i = phi i32 [ 0, %entry ], [ %inc, %for.body.end ]
|
|
%cmp = icmp slt i32 %i, %N
|
|
br i1 %cmp, label %for.body, label %for.cond.cleanup
|
|
|
|
for.body: ; preds = %for.cond
|
|
%urem = urem i32 %i, 2
|
|
%if.cond = icmp eq i32 %urem, 0
|
|
br i1 %if.cond, label %for.body.if, label %for.body.else
|
|
|
|
for.body.if: ; preds = %for.body
|
|
%cond1a = select i1 %cond, i32 %i, i32 42
|
|
br label %for.body.end
|
|
|
|
for.body.else: ; preds = %for.body
|
|
%cond1b = select i1 %cond, i32 24, i32 %i
|
|
br label %for.body.end
|
|
|
|
for.body.end: ; preds = %for.body.if, %for.body.else
|
|
%p = phi i32 [ %cond1a, %for.body.if ], [ %cond1b, %for.body.else ]
|
|
%add = add nuw nsw i32 %p, %res
|
|
%inc = add nuw nsw i32 %i, 1
|
|
br label %for.cond
|
|
|
|
for.cond.cleanup: ; preds = %for.cond
|
|
ret i32 %res
|
|
}
|
|
|
|
define dso_local void @select_nested_loop(i1 noundef zeroext %cond, i32 noundef %n, i32 noundef %m) {
|
|
; CHECK-LABEL: define dso_local void @select_nested_loop
|
|
; CHECK-SAME: (i1 noundef zeroext [[COND:%.*]], i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP17_NOT:%.*]] = icmp eq i32 [[N]], 0
|
|
; CHECK-NEXT: [[CMP215_NOT:%.*]] = icmp eq i32 [[M]], 0
|
|
; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP17_NOT]], [[CMP215_NOT]]
|
|
; CHECK-NEXT: br i1 [[OR_COND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]]
|
|
; CHECK: for.cond1.preheader.us.preheader:
|
|
; CHECK-NEXT: br i1 [[COND]], label [[FOR_COND1_PREHEADER_US_PREHEADER_SPLIT_US:%.*]], label [[FOR_COND1_PREHEADER_US_PREHEADER_SPLIT:%.*]]
|
|
; CHECK: for.cond1.preheader.us.preheader.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US_US:%.*]]
|
|
; CHECK: for.cond1.preheader.us.us:
|
|
; CHECK-NEXT: [[I_018_US_US:%.*]] = phi i32 [ [[INC7_US_US:%.*]], [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_US:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER_SPLIT_US]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US_SPLIT_US_US:%.*]]
|
|
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us.us:
|
|
; CHECK-NEXT: [[INC7_US_US]] = add nuw i32 [[I_018_US_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND21_NOT_US:%.*]] = icmp eq i32 [[INC7_US_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND21_NOT_US]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT_US:%.*]], label [[FOR_COND1_PREHEADER_US_US]]
|
|
; CHECK: for.cond1.preheader.us.split.us.us:
|
|
; CHECK-NEXT: br label [[FOR_BODY4_US_US_US:%.*]]
|
|
; CHECK: for.body4.us.us.us:
|
|
; CHECK-NEXT: [[J_016_US_US_US:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_US_SPLIT_US_US]] ], [ [[INC_US_US_US:%.*]], [[TMP1:%.*]] ]
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US_US:%.*]] = phi i32 [ [[I_018_US_US]], [[TMP0]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US_US]])
|
|
; CHECK-NEXT: [[INC_US_US_US]] = add nuw i32 [[J_016_US_US_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT_US_US:%.*]] = icmp eq i32 [[INC_US_US_US]], [[M]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT_US_US]], label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_SPLIT_US_US:%.*]], label [[FOR_BODY4_US_US_US]]
|
|
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us.split.us.us:
|
|
; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_US]]
|
|
; CHECK: for.cond.cleanup.loopexit.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
|
|
; CHECK: for.cond1.preheader.us.preheader.split:
|
|
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US:%.*]]
|
|
; CHECK: for.cond1.preheader.us:
|
|
; CHECK-NEXT: [[I_018_US:%.*]] = phi i32 [ [[INC7_US:%.*]], [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER_SPLIT]] ]
|
|
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US_SPLIT:%.*]]
|
|
; CHECK: for.cond1.preheader.us.split:
|
|
; CHECK-NEXT: br label [[FOR_BODY4_US:%.*]]
|
|
; CHECK: for.body4.us:
|
|
; CHECK-NEXT: [[J_016_US:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_US_SPLIT]] ], [ [[INC_US:%.*]], [[TMP2:%.*]] ]
|
|
; CHECK-NEXT: br label [[TMP2]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[J_016_US]])
|
|
; CHECK-NEXT: [[INC_US]] = add nuw i32 [[J_016_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC_US]], [[M]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_SPLIT:%.*]], label [[FOR_BODY4_US]]
|
|
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us.split:
|
|
; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]]
|
|
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us:
|
|
; CHECK-NEXT: [[INC7_US]] = add nuw i32 [[I_018_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND21_NOT:%.*]] = icmp eq i32 [[INC7_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND21_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT:%.*]], label [[FOR_COND1_PREHEADER_US]]
|
|
; CHECK: for.cond.cleanup.loopexit.split:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]]
|
|
; CHECK: for.cond.cleanup.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cmp17.not = icmp eq i32 %n, 0
|
|
%cmp215.not = icmp eq i32 %m, 0
|
|
%or.cond = or i1 %cmp17.not, %cmp215.not
|
|
br i1 %or.cond, label %for.cond.cleanup, label %for.cond1.preheader.us
|
|
|
|
for.cond1.preheader.us: ; preds = %entry, %for.cond1.for.cond.cleanup3_crit_edge.us
|
|
%i.018.us = phi i32 [ %inc7.us, %for.cond1.for.cond.cleanup3_crit_edge.us ], [ 0, %entry ]
|
|
br label %for.body4.us
|
|
|
|
for.body4.us: ; preds = %for.cond1.preheader.us, %for.body4.us
|
|
%j.016.us = phi i32 [ 0, %for.cond1.preheader.us ], [ %inc.us, %for.body4.us ]
|
|
%cond5.us = select i1 %cond, i32 %i.018.us, i32 %j.016.us
|
|
tail call void @bar(i32 noundef %cond5.us) #2
|
|
%inc.us = add nuw i32 %j.016.us, 1
|
|
%exitcond.not = icmp eq i32 %inc.us, %m
|
|
br i1 %exitcond.not, label %for.cond1.for.cond.cleanup3_crit_edge.us, label %for.body4.us
|
|
|
|
for.cond1.for.cond.cleanup3_crit_edge.us: ; preds = %for.body4.us
|
|
%inc7.us = add nuw i32 %i.018.us, 1
|
|
%exitcond21.not = icmp eq i32 %inc7.us, %n
|
|
br i1 %exitcond21.not, label %for.cond.cleanup, label %for.cond1.preheader.us
|
|
|
|
for.cond.cleanup: ; preds = %for.cond1.for.cond.cleanup3_crit_edge.us, %entry
|
|
ret void
|
|
}
|
|
|
|
define dso_local void @select_invariant_outer_loop(i1 noundef zeroext %cond, i32 noundef %n, i32 noundef %m) {
|
|
; CHECK-LABEL: define dso_local void @select_invariant_outer_loop
|
|
; CHECK-SAME: (i1 noundef zeroext [[COND:%.*]], i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP20_NOT:%.*]] = icmp eq i32 [[N]], 0
|
|
; CHECK-NEXT: [[CMP218_NOT:%.*]] = icmp eq i32 [[M]], 0
|
|
; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP20_NOT]], [[CMP218_NOT]]
|
|
; CHECK-NEXT: br i1 [[OR_COND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]]
|
|
; CHECK: for.cond1.preheader.us.preheader:
|
|
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US:%.*]]
|
|
; CHECK: for.cond1.preheader.us:
|
|
; CHECK-NEXT: [[I_021_US:%.*]] = phi i32 [ [[INC9_US:%.*]], [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER]] ]
|
|
; CHECK-NEXT: [[REM_US:%.*]] = and i32 [[I_021_US]], 1
|
|
; CHECK-NEXT: [[CMP5_US:%.*]] = icmp eq i32 [[REM_US]], 0
|
|
; CHECK-NEXT: [[CMP5_US_FR:%.*]] = freeze i1 [[CMP5_US]]
|
|
; CHECK-NEXT: br i1 [[CMP5_US_FR]], label [[FOR_COND1_PREHEADER_US_SPLIT_US:%.*]], label [[FOR_COND1_PREHEADER_US_SPLIT:%.*]]
|
|
; CHECK: for.cond1.preheader.us.split.us:
|
|
; CHECK-NEXT: br label [[FOR_BODY4_US_US:%.*]]
|
|
; CHECK: for.body4.us.us:
|
|
; CHECK-NEXT: [[J_019_US_US:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_US_SPLIT_US]] ], [ [[INC_US_US:%.*]], [[TMP1:%.*]] ]
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ [[I_021_US]], [[TMP0]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US]])
|
|
; CHECK-NEXT: [[INC_US_US]] = add nuw i32 [[J_019_US_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT_US:%.*]] = icmp eq i32 [[INC_US_US]], [[M]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT_US]], label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_SPLIT_US:%.*]], label [[FOR_BODY4_US_US]]
|
|
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]]
|
|
; CHECK: for.cond1.preheader.us.split:
|
|
; CHECK-NEXT: br label [[FOR_BODY4_US:%.*]]
|
|
; CHECK: for.body4.us:
|
|
; CHECK-NEXT: [[J_019_US:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_US_SPLIT]] ], [ [[INC_US:%.*]], [[TMP2:%.*]] ]
|
|
; CHECK-NEXT: br label [[TMP2]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[J_019_US]])
|
|
; CHECK-NEXT: [[INC_US]] = add nuw i32 [[J_019_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC_US]], [[M]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_SPLIT:%.*]], label [[FOR_BODY4_US]]
|
|
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us.split:
|
|
; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]]
|
|
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us:
|
|
; CHECK-NEXT: [[INC9_US]] = add nuw i32 [[I_021_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND24_NOT:%.*]] = icmp eq i32 [[INC9_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND24_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_COND1_PREHEADER_US]]
|
|
; CHECK: for.cond.cleanup.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cmp20.not = icmp eq i32 %n, 0
|
|
%cmp218.not = icmp eq i32 %m, 0
|
|
%or.cond = or i1 %cmp20.not, %cmp218.not
|
|
br i1 %or.cond, label %for.cond.cleanup, label %for.cond1.preheader.us
|
|
|
|
for.cond1.preheader.us: ; preds = %entry, %for.cond1.for.cond.cleanup3_crit_edge.us
|
|
%i.021.us = phi i32 [ %inc9.us, %for.cond1.for.cond.cleanup3_crit_edge.us ], [ 0, %entry ]
|
|
%rem.us = and i32 %i.021.us, 1
|
|
%cmp5.us = icmp eq i32 %rem.us, 0
|
|
br label %for.body4.us
|
|
|
|
for.body4.us: ; preds = %for.cond1.preheader.us, %for.body4.us
|
|
%j.019.us = phi i32 [ 0, %for.cond1.preheader.us ], [ %inc.us, %for.body4.us ]
|
|
%cond7.us = select i1 %cmp5.us, i32 %i.021.us, i32 %j.019.us
|
|
tail call void @bar(i32 noundef %cond7.us) #2
|
|
%inc.us = add nuw i32 %j.019.us, 1
|
|
%exitcond.not = icmp eq i32 %inc.us, %m
|
|
br i1 %exitcond.not, label %for.cond1.for.cond.cleanup3_crit_edge.us, label %for.body4.us
|
|
|
|
for.cond1.for.cond.cleanup3_crit_edge.us: ; preds = %for.body4.us
|
|
%inc9.us = add nuw i32 %i.021.us, 1
|
|
%exitcond24.not = icmp eq i32 %inc9.us, %n
|
|
br i1 %exitcond24.not, label %for.cond.cleanup, label %for.cond1.preheader.us
|
|
|
|
for.cond.cleanup: ; preds = %for.cond1.for.cond.cleanup3_crit_edge.us, %entry
|
|
ret void
|
|
}
|
|
|
|
; Unswitch %val should look through the trivial select and unswitch on %cond
|
|
define dso_local i32 @trivial_select_cond(i32 noundef %n, i32 noundef %a, i32 noundef %b, i1 noundef %cond) {
|
|
; CHECK-LABEL: define dso_local i32 @trivial_select_cond
|
|
; CHECK-SAME: (i32 noundef [[N:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i1 noundef [[COND:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[N]], 0
|
|
; CHECK-NEXT: [[TRIVIAL_COND:%.*]] = select i1 [[COND]], i1 true, i1 false
|
|
; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: br i1 [[COND]], label [[FOR_BODY_PREHEADER_SPLIT_US:%.*]], label [[FOR_BODY_PREHEADER_SPLIT:%.*]]
|
|
; CHECK: for.body.preheader.split.us:
|
|
; CHECK-NEXT: br label [[FOR_BODY_US:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: [[I_03_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[TMP1:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT_US]] ]
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ [[A]], [[TMP0]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US]])
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_03_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT_US:%.*]] = icmp eq i32 [[INC_US]], [[N]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT_US]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT_US:%.*]], label [[FOR_BODY_US]]
|
|
; CHECK: for.cond.cleanup.loopexit.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
|
|
; CHECK: for.body.preheader.split:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.cond.cleanup.loopexit.split:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]]
|
|
; CHECK: for.cond.cleanup.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: ret i32 undef
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[I_03:%.*]] = phi i32 [ [[INC:%.*]], [[TMP2:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT]] ]
|
|
; CHECK-NEXT: br label [[TMP2]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[B]])
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_03]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT:%.*]], label [[FOR_BODY]]
|
|
;
|
|
entry:
|
|
%cmp2 = icmp sgt i32 %n, 0
|
|
%trivial_cond = select i1 %cond, i1 true, i1 false
|
|
br i1 %cmp2, label %for.body, label %for.cond.cleanup
|
|
|
|
for.cond.cleanup: ; preds = %for.body, %entry
|
|
ret i32 undef
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%i.03 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
|
|
%val = select i1 %trivial_cond, i32 %a, i32 %b
|
|
tail call void @bar(i32 noundef %val)
|
|
%inc = add nuw nsw i32 %i.03, 1
|
|
%exitcond.not = icmp eq i32 %inc, %n
|
|
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
|
|
}
|
|
|
|
; Test unswitch select when the condition is an AND whose LHS is invariant
|
|
define i32 @and_lhs_invariant(i32 %num, i1 %cond) {
|
|
; CHECK-LABEL: define i32 @and_lhs_invariant
|
|
; CHECK-SAME: (i32 [[NUM:%.*]], i1 [[COND:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[NUM]], 0
|
|
; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
|
|
; CHECK-NEXT: br i1 [[COND_FR]], label [[FOR_BODY_PREHEADER_SPLIT:%.*]], label [[FOR_BODY_PREHEADER_SPLIT_US:%.*]]
|
|
; CHECK: for.body.preheader.split.us:
|
|
; CHECK-NEXT: br label [[FOR_BODY_US:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: [[I_07_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[TMP0:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT_US]] ]
|
|
; CHECK-NEXT: br label [[TMP0]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ 0, [[FOR_BODY_US]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US]])
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_07_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT_US:%.*]] = icmp eq i32 [[INC_US]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT_US]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT_US:%.*]], label [[FOR_BODY_US]]
|
|
; CHECK: for.cond.cleanup.loopexit.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
|
|
; CHECK: for.body.preheader.split:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.cond.cleanup.loopexit.split:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]]
|
|
; CHECK: for.cond.cleanup.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: ret i32 undef
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[TMP3:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT]] ]
|
|
; CHECK-NEXT: [[REM:%.*]] = and i32 [[I_07]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[REM]], 0
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i1 true, [[CMP1]]
|
|
; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: br label [[TMP3]]
|
|
; CHECK: 3:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT:%.*]] = phi i32 [ [[I_07]], [[TMP2]] ], [ 0, [[FOR_BODY]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT]])
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_07]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT:%.*]], label [[FOR_BODY]]
|
|
;
|
|
entry:
|
|
%cmp6 = icmp sgt i32 %num, 0
|
|
br i1 %cmp6, label %for.body, label %for.cond.cleanup
|
|
|
|
for.cond.cleanup: ; preds = %for.body, %entry
|
|
ret i32 undef
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%i.07 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
|
|
%rem = and i32 %i.07, 1
|
|
%cmp1 = icmp eq i32 %rem, 0
|
|
%0 = and i1 %cond, %cmp1
|
|
%cond2 = select i1 %0, i32 %i.07, i32 0
|
|
tail call void @bar(i32 noundef %cond2)
|
|
%inc = add nuw nsw i32 %i.07, 1
|
|
%exitcond.not = icmp eq i32 %inc, %num
|
|
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
|
|
}
|
|
|
|
; Test unswitch select when the condition is an AND whose RHS is invariant
|
|
define i32 @and_rhs_invariant(i32 %num, i1 %cond) {
|
|
; CHECK-LABEL: define i32 @and_rhs_invariant
|
|
; CHECK-SAME: (i32 [[NUM:%.*]], i1 [[COND:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[NUM]], 0
|
|
; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
|
|
; CHECK-NEXT: br i1 [[COND_FR]], label [[FOR_BODY_PREHEADER_SPLIT:%.*]], label [[FOR_BODY_PREHEADER_SPLIT_US:%.*]]
|
|
; CHECK: for.body.preheader.split.us:
|
|
; CHECK-NEXT: br label [[FOR_BODY_US:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: [[I_07_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[TMP0:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT_US]] ]
|
|
; CHECK-NEXT: br label [[TMP0]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ 0, [[FOR_BODY_US]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US]])
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_07_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT_US:%.*]] = icmp eq i32 [[INC_US]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT_US]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT_US:%.*]], label [[FOR_BODY_US]]
|
|
; CHECK: for.cond.cleanup.loopexit.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
|
|
; CHECK: for.body.preheader.split:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.cond.cleanup.loopexit.split:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]]
|
|
; CHECK: for.cond.cleanup.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: ret i32 undef
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[TMP3:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT]] ]
|
|
; CHECK-NEXT: [[REM:%.*]] = and i32 [[I_07]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[REM]], 0
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[CMP1]], true
|
|
; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3]]
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: br label [[TMP3]]
|
|
; CHECK: 3:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT:%.*]] = phi i32 [ [[I_07]], [[TMP2]] ], [ 0, [[FOR_BODY]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT]])
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_07]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT:%.*]], label [[FOR_BODY]]
|
|
;
|
|
entry:
|
|
%cmp6 = icmp sgt i32 %num, 0
|
|
br i1 %cmp6, label %for.body, label %for.cond.cleanup
|
|
|
|
for.cond.cleanup: ; preds = %for.body, %entry
|
|
ret i32 undef
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%i.07 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
|
|
%rem = and i32 %i.07, 1
|
|
%cmp1 = icmp eq i32 %rem, 0
|
|
%0 = and i1 %cmp1, %cond
|
|
%cond2 = select i1 %0, i32 %i.07, i32 0
|
|
tail call void @bar(i32 noundef %cond2)
|
|
%inc = add nuw nsw i32 %i.07, 1
|
|
%exitcond.not = icmp eq i32 %inc, %num
|
|
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
|
|
}
|
|
|
|
; Test unswitch select when the condition is an OR whose LHS is invariant
|
|
define i32 @or_lhs_invariant(i32 %num, i1 %cond) {
|
|
; CHECK-LABEL: define i32 @or_lhs_invariant
|
|
; CHECK-SAME: (i32 [[NUM:%.*]], i1 [[COND:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[NUM]], 0
|
|
; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
|
|
; CHECK-NEXT: br i1 [[COND_FR]], label [[FOR_BODY_PREHEADER_SPLIT_US:%.*]], label [[FOR_BODY_PREHEADER_SPLIT:%.*]]
|
|
; CHECK: for.body.preheader.split.us:
|
|
; CHECK-NEXT: br label [[FOR_BODY_US:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: [[I_07_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[TMP1:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT_US]] ]
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ [[I_07_US]], [[TMP0]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US]])
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_07_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT_US:%.*]] = icmp eq i32 [[INC_US]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT_US]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT_US:%.*]], label [[FOR_BODY_US]]
|
|
; CHECK: for.cond.cleanup.loopexit.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
|
|
; CHECK: for.body.preheader.split:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.cond.cleanup.loopexit.split:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]]
|
|
; CHECK: for.cond.cleanup.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: ret i32 undef
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[TMP4:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT]] ]
|
|
; CHECK-NEXT: [[REM:%.*]] = and i32 [[I_07]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[REM]], 0
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or i1 false, [[CMP1]]
|
|
; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4]]
|
|
; CHECK: 3:
|
|
; CHECK-NEXT: br label [[TMP4]]
|
|
; CHECK: 4:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT:%.*]] = phi i32 [ [[I_07]], [[TMP3]] ], [ 0, [[FOR_BODY]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT]])
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_07]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT:%.*]], label [[FOR_BODY]]
|
|
;
|
|
entry:
|
|
%cmp6 = icmp sgt i32 %num, 0
|
|
br i1 %cmp6, label %for.body, label %for.cond.cleanup
|
|
|
|
for.cond.cleanup: ; preds = %for.body, %entry
|
|
ret i32 undef
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%i.07 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
|
|
%rem = and i32 %i.07, 1
|
|
%cmp1 = icmp eq i32 %rem, 0
|
|
%0 = or i1 %cond, %cmp1
|
|
%cond2 = select i1 %0, i32 %i.07, i32 0
|
|
tail call void @bar(i32 noundef %cond2)
|
|
%inc = add nuw nsw i32 %i.07, 1
|
|
%exitcond.not = icmp eq i32 %inc, %num
|
|
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
|
|
}
|
|
|
|
; Test unswitch select when the condition is an OR whose RHS is invariant
|
|
define i32 @or_rhs_invariant(i32 %num, i1 %cond) {
|
|
; CHECK-LABEL: define i32 @or_rhs_invariant
|
|
; CHECK-SAME: (i32 [[NUM:%.*]], i1 [[COND:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[NUM]], 0
|
|
; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
|
|
; CHECK-NEXT: br i1 [[COND_FR]], label [[FOR_BODY_PREHEADER_SPLIT_US:%.*]], label [[FOR_BODY_PREHEADER_SPLIT:%.*]]
|
|
; CHECK: for.body.preheader.split.us:
|
|
; CHECK-NEXT: br label [[FOR_BODY_US:%.*]]
|
|
; CHECK: for.body.us:
|
|
; CHECK-NEXT: [[I_07_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[TMP1:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT_US]] ]
|
|
; CHECK-NEXT: br label [[TMP0:%.*]]
|
|
; CHECK: 0:
|
|
; CHECK-NEXT: br label [[TMP1]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ [[I_07_US]], [[TMP0]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US]])
|
|
; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_07_US]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT_US:%.*]] = icmp eq i32 [[INC_US]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT_US]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT_US:%.*]], label [[FOR_BODY_US]]
|
|
; CHECK: for.cond.cleanup.loopexit.split.us:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
|
|
; CHECK: for.body.preheader.split:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.cond.cleanup.loopexit.split:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]]
|
|
; CHECK: for.cond.cleanup.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
|
|
; CHECK: for.cond.cleanup:
|
|
; CHECK-NEXT: ret i32 undef
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[TMP4:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT]] ]
|
|
; CHECK-NEXT: [[REM:%.*]] = and i32 [[I_07]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[REM]], 0
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[CMP1]], false
|
|
; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4]]
|
|
; CHECK: 3:
|
|
; CHECK-NEXT: br label [[TMP4]]
|
|
; CHECK: 4:
|
|
; CHECK-NEXT: [[UNSWITCHED_SELECT:%.*]] = phi i32 [ [[I_07]], [[TMP3]] ], [ 0, [[FOR_BODY]] ]
|
|
; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT]])
|
|
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_07]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT:%.*]], label [[FOR_BODY]]
|
|
;
|
|
entry:
|
|
%cmp6 = icmp sgt i32 %num, 0
|
|
br i1 %cmp6, label %for.body, label %for.cond.cleanup
|
|
|
|
for.cond.cleanup: ; preds = %for.body, %entry
|
|
ret i32 undef
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%i.07 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
|
|
%rem = and i32 %i.07, 1
|
|
%cmp1 = icmp eq i32 %rem, 0
|
|
%0 = or i1 %cmp1, %cond
|
|
%cond2 = select i1 %0, i32 %i.07, i32 0
|
|
tail call void @bar(i32 noundef %cond2)
|
|
%inc = add nuw nsw i32 %i.07, 1
|
|
%exitcond.not = icmp eq i32 %inc, %num
|
|
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
|
|
}
|