; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt < %s -mtriple=x86_64-unknown-unknown --loop-simplify -codegenprepare -S | FileCheck %s declare void @use.i32(i32) declare void @use.2xi64(<2 x i64>) declare void @do_stuff0() declare void @do_stuff1() declare i1 @get.i1() declare i32 @get.i32() define void @simple_urem_to_sel(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[REM:%.*]] = phi i32 [ 0, %[[FOR_BODY_PREHEADER]] ], [ [[TMP3:%.*]], %[[FOR_BODY]] ] ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[REM]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], [[REM_AMT]] ; CHECK-NEXT: [[TMP3]] = select i1 [[TMP2]], i32 0, i32 [[TMP1]] ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 0, %entry ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_fail_not_in_loop(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_fail_not_in_loop( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[INC:%.*]], %[[FOR_BODY]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_05]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC]], %[[FOR_BODY]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: tail call void @use.i32(i32 [[I_04]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: %i.05 = phi i32 [ %inc, %for.body ], [ 0, %entry ] %rem = urem i32 %i.05, %rem_amt tail call void @use.i32(i32 %rem) ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 0, %entry ] tail call void @use.i32(i32 %i.04) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_inner_loop(i32 %N, i32 %M) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_inner_loop( ; CHECK-SAME: i32 [[N:%.*]], i32 [[M:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[REM_AMT:%.*]] = call i32 @get.i32() ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[REM:%.*]] = phi i32 [ 0, %[[FOR_BODY_PREHEADER]] ], [ [[TMP3:%.*]], %[[FOR_INNER_COND_CLEANUP:.*]] ] ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_INNER_COND_CLEANUP]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[CMP_INNER:%.*]] = icmp eq i32 [[M]], 0 ; CHECK-NEXT: br i1 [[CMP_INNER]], label %[[FOR_INNER_COND_CLEANUP]], label %[[FOR_INNER_BODY_PREHEADER:.*]] ; CHECK: [[FOR_INNER_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_INNER_BODY:.*]] ; CHECK: [[FOR_INNER_BODY]]: ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[INC_INNER:%.*]], %[[FOR_INNER_BODY]] ], [ 0, %[[FOR_INNER_BODY_PREHEADER]] ] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC_INNER]] = add nuw i32 [[J]], 1 ; CHECK-NEXT: [[EXITCOND_INNER:%.*]] = icmp eq i32 [[INC_INNER]], [[M]] ; CHECK-NEXT: br i1 [[EXITCOND_INNER]], label %[[FOR_INNER_COND_CLEANUP]], label %[[FOR_INNER_BODY]] ; CHECK: [[FOR_INNER_COND_CLEANUP]]: ; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[REM]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], [[REM_AMT]] ; CHECK-NEXT: [[TMP3]] = select i1 [[TMP2]], i32 0, i32 [[TMP1]] ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %rem_amt = call i32 @get.i32() %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.inner.cond.cleanup ], [ 0, %entry ] %cmp_inner = icmp eq i32 %M, 0 br i1 %cmp_inner, label %for.inner.cond.cleanup, label %for.inner.body for.inner.body: %j = phi i32 [ %inc_inner, %for.inner.body ], [ 0, %for.body ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc_inner = add nuw i32 %j, 1 %exitcond_inner = icmp eq i32 %inc_inner, %M br i1 %exitcond_inner, label %for.inner.cond.cleanup, label %for.inner.body for.inner.cond.cleanup: %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_inner_loop_fail_not_invariant(i32 %N, i32 %M) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_inner_loop_fail_not_invariant( ; CHECK-SAME: i32 [[N:%.*]], i32 [[M:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_INNER_COND_CLEANUP:.*]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[REM_AMT:%.*]] = call i32 @get.i32() ; CHECK-NEXT: [[CMP_INNER:%.*]] = icmp eq i32 [[M]], 0 ; CHECK-NEXT: br i1 [[CMP_INNER]], label %[[FOR_INNER_COND_CLEANUP]], label %[[FOR_INNER_BODY_PREHEADER:.*]] ; CHECK: [[FOR_INNER_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_INNER_BODY:.*]] ; CHECK: [[FOR_INNER_BODY]]: ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[INC_INNER:%.*]], %[[FOR_INNER_BODY]] ], [ 0, %[[FOR_INNER_BODY_PREHEADER]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_04]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC_INNER]] = add nuw i32 [[J]], 1 ; CHECK-NEXT: [[EXITCOND_INNER:%.*]] = icmp eq i32 [[INC_INNER]], [[M]] ; CHECK-NEXT: br i1 [[EXITCOND_INNER]], label %[[FOR_INNER_COND_CLEANUP]], label %[[FOR_INNER_BODY]] ; CHECK: [[FOR_INNER_COND_CLEANUP]]: ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.inner.cond.cleanup ], [ 0, %entry ] %rem_amt = call i32 @get.i32() %cmp_inner = icmp eq i32 %M, 0 br i1 %cmp_inner, label %for.inner.cond.cleanup, label %for.inner.body for.inner.body: %j = phi i32 [ %inc_inner, %for.inner.body ], [ 0, %for.body ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc_inner = add nuw i32 %j, 1 %exitcond_inner = icmp eq i32 %inc_inner, %M br i1 %exitcond_inner, label %for.inner.cond.cleanup, label %for.inner.body for.inner.cond.cleanup: %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_nested2(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_nested2( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[REM:%.*]] = phi i32 [ 0, %[[FOR_BODY_PREHEADER]] ], [ [[TMP3:%.*]], %[[FOR_BODY_TAIL:.*]] ] ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY_TAIL]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[COND0:%.*]] = call i1 @get.i1() ; CHECK-NEXT: br i1 [[COND0]], label %[[FOR_BODY0:.*]], label %[[FOR_BODY_TAIL]] ; CHECK: [[FOR_BODY0]]: ; CHECK-NEXT: [[COND1:%.*]] = call i1 @get.i1() ; CHECK-NEXT: br i1 [[COND1]], label %[[FOR_BODY1:.*]], label %[[FOR_BODY2:.*]] ; CHECK: [[FOR_BODY2]]: ; CHECK-NEXT: [[COND2:%.*]] = call i1 @get.i1() ; CHECK-NEXT: br i1 [[COND2]], label %[[FOR_BODY1]], label %[[FOR_BODY_TAIL]] ; CHECK: [[FOR_BODY1]]: ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: br label %[[FOR_BODY_TAIL]] ; CHECK: [[FOR_BODY_TAIL]]: ; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[REM]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], [[REM_AMT]] ; CHECK-NEXT: [[TMP3]] = select i1 [[TMP2]], i32 0, i32 [[TMP1]] ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body.tail ], [ 0, %entry ] %cond0 = call i1 @get.i1() br i1 %cond0, label %for.body0, label %for.body.tail for.body0: %cond1 = call i1 @get.i1() br i1 %cond1, label %for.body1, label %for.body2 for.body2: %cond2 = call i1 @get.i1() br i1 %cond2, label %for.body1, label %for.body.tail for.body1: %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) br label %for.body.tail for.body.tail: %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_fail_bad_incr3(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_fail_bad_incr3( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[COND0:%.*]] = call i1 @get.i1() ; CHECK-NEXT: br i1 [[COND0]], label %[[FOR_BODY0:.*]], label %[[FOR_BODY2:.*]] ; CHECK: [[FOR_BODY0]]: ; CHECK-NEXT: [[COND1:%.*]] = call i1 @get.i1() ; CHECK-NEXT: [[VAL:%.*]] = call i32 @get.i32() ; CHECK-NEXT: [[INC:%.*]] = add nuw i32 [[VAL]], 1 ; CHECK-NEXT: br i1 [[COND1]], label %[[FOR_BODY1:.*]], label %[[FOR_BODY_TAIL:.*]] ; CHECK: [[FOR_BODY2]]: ; CHECK-NEXT: [[COND2:%.*]] = call i1 @get.i1() ; CHECK-NEXT: br i1 [[COND2]], label %[[FOR_BODY1]], label %[[FOR_BODY_TAIL]] ; CHECK: [[FOR_BODY1]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC]], %[[FOR_BODY0]] ], [ 0, %[[FOR_BODY2]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_04]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: br label %[[FOR_BODY_TAIL]] ; CHECK: [[FOR_BODY_TAIL]]: ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = call i1 @get.i1() ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %cond0 = call i1 @get.i1() br i1 %cond0, label %for.body0, label %for.body2 for.body0: %cond1 = call i1 @get.i1() %val = call i32 @get.i32() %inc = add nuw i32 %val, 1 br i1 %cond1, label %for.body1, label %for.body.tail for.body2: %cond2 = call i1 @get.i1() br i1 %cond2, label %for.body1, label %for.body.tail for.body1: %i.04 = phi i32 [ %inc, %for.body0], [ 0, %for.body2 ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) br label %for.body.tail for.body.tail: %exitcond.not = call i1 @get.i1() br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_vec(<2 x i64> %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_vec( ; CHECK-SAME: <2 x i64> [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP:.*]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[REM:%.*]] = phi <2 x i64> [ zeroinitializer, %[[ENTRY]] ], [ [[TMP3:%.*]], %[[FOR_BODY]] ] ; CHECK-NEXT: [[I_04:%.*]] = phi <2 x i64> [ [[INC:%.*]], %[[FOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: tail call void @use.2xi64(<2 x i64> [[REM]]) ; CHECK-NEXT: [[TMP1:%.*]] = add nuw <2 x i64> [[REM]], splat (i64 1) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], [[REM_AMT]] ; CHECK-NEXT: [[TMP3]] = select <2 x i1> [[TMP2]], <2 x i64> zeroinitializer, <2 x i64> [[TMP1]] ; CHECK-NEXT: [[INC]] = add nuw <2 x i64> [[I_04]], splat (i64 1) ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = call i1 @get.i1() ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: br label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi <2 x i64> [ %inc, %for.body ], [ zeroinitializer, %entry ] %rem = urem <2 x i64> %i.04, %rem_amt tail call void @use.2xi64(<2 x i64> %rem) %inc = add nuw <2 x i64> %i.04, %exitcond.not = call i1 @get.i1() br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_fail_bad_incr(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_fail_bad_incr( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_03:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY_TAIL:.*]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[COND0:%.*]] = call i1 @get.i1() ; CHECK-NEXT: br i1 [[COND0]], label %[[FOR_BODY0:.*]], label %[[FOR_BODY_TAIL]] ; CHECK: [[FOR_BODY0]]: ; CHECK-NEXT: [[SOME_VAL:%.*]] = call i32 @get.i32() ; CHECK-NEXT: br label %[[FOR_BODY_TAIL]] ; CHECK: [[FOR_BODY_TAIL]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[I_03]], %[[FOR_BODY]] ], [ [[SOME_VAL]], %[[FOR_BODY0]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_04]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.03 = phi i32 [ %inc, %for.body.tail ], [ 0, %entry ] %cond0 = call i1 @get.i1() br i1 %cond0, label %for.body0, label %for.body.tail for.body0: %some_val = call i32 @get.i32() br label %for.body.tail for.body.tail: %i.04 = phi i32 [ %i.03, %for.body ], [ %some_val, %for.body0 ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_second_acc(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_second_acc( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp ult i32 [[N]], 2 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[REM:%.*]] = phi i32 [ 0, %[[FOR_BODY_PREHEADER]] ], [ [[TMP3:%.*]], %[[FOR_BODY]] ] ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ [[INC2:%.*]], %[[FOR_BODY]] ], [ 1, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[REM]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], [[REM_AMT]] ; CHECK-NEXT: [[TMP3]] = select i1 [[TMP2]], i32 0, i32 [[TMP1]] ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[INC2]] = add nuw i32 [[I_05]], 2 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp ugt i32 [[INC2]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp ult i32 %N, 2 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 0, %entry ] %i.05 = phi i32 [ %inc2, %for.body ], [ 1, %entry ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %inc2 = add nuw i32 %i.05, 2 %exitcond.not = icmp ugt i32 %inc2, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_fail_srem(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_fail_srem( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[I_04]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 0, %entry ] %rem = srem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_fail_missing_nuw(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_fail_missing_nuw( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_04]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nsw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 0, %entry ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nsw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_fail_bad_incr2(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_fail_bad_incr2( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_04]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 2 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 0, %entry ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 2 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_non_zero_entry4(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_non_zero_entry4( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 4, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_04]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 4, %entry ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_skip_const_rem_amt(i32 %N) nounwind { ; CHECK-LABEL: define void @simple_urem_skip_const_rem_amt( ; CHECK-SAME: i32 [[N:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 4, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_04]], 19 ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 4, %entry ] %rem = urem i32 %i.04, 19 tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_fail_no_preheader_non_canonical(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_fail_no_preheader_non_canonical( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_BODY_PREHEADER:.*]], label %[[FOR_BODY1:.*]] ; CHECK: [[FOR_COND_CLEANUP:.*]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY1]]: ; CHECK-NEXT: br label %[[FOR_BODY_PREHEADER]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: [[I_04_PH:%.*]] = phi i32 [ 1, %[[FOR_BODY1]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ [[I_04_PH]], %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_04]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.body0, label %for.body1 for.cond.cleanup: ret void for.body0: br label %for.body for.body1: br label %for.body for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 0, %for.body0 ], [ 1, %for.body1 ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_multi_latch_non_canonical(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_multi_latch_non_canonical( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ 0, %[[FOR_BODY_PREHEADER]] ], [ [[INC:%.*]], %[[FOR_BODY]] ], [ [[INC]], %[[FOR_BODY0:.*]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_04]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[COND:%.*]] = call i1 @get.i1() ; CHECK-NEXT: call void @do_stuff0() ; CHECK-NEXT: br i1 [[COND]], label %[[FOR_BODY0]], label %[[FOR_BODY]] ; CHECK: [[FOR_BODY0]]: ; CHECK-NEXT: call void @do_stuff1() ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ %inc, %for.body0 ], [ 0, %entry ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %cond = call i1 @get.i1() call void @do_stuff0() br i1 %cond, label %for.body0, label %for.body for.body0: call void @do_stuff1() %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_fail_bad_loop(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_fail_bad_loop( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[CALL:%.*]] = call i32 @get.i32() ; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CALL]], 0 ; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label %[[FOR_COND:.*]], label %[[HALFWAY:.*]] ; CHECK: [[FOR_COND]]: ; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ [[INC:%.*]], %[[HALFWAY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[I_0]], [[N]] ; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]] ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[I_0]], 1 ; CHECK-NEXT: call void @use.i32(i32 [[XOR]]) ; CHECK-NEXT: br label %[[HALFWAY]] ; CHECK: [[HALFWAY]]: ; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ poison, %[[ENTRY]] ], [ [[I_0]], %[[FOR_BODY]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_1]], [[REM_AMT]] ; CHECK-NEXT: call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_1]], 1 ; CHECK-NEXT: br label %[[FOR_COND]] ; CHECK: [[FOR_END]]: ; CHECK-NEXT: ret void ; entry: %call = call i32 @get.i32() %tobool.not = icmp eq i32 %call, 0 br i1 %tobool.not, label %for.cond, label %halfway for.cond: %i.0 = phi i32 [ %inc, %halfway ], [ 0, %entry ] %cmp = icmp ult i32 %i.0, %N br i1 %cmp, label %for.body, label %for.end for.body: %xor = xor i32 %i.0, 1 call void @use.i32(i32 %xor) br label %halfway halfway: %i.1 = phi i32 [ poison, %entry ], [ %i.0, %for.body ] %rem = urem i32 %i.1, %rem_amt call void @use.i32(i32 %rem) %inc = add nuw i32 %i.1, 1 br label %for.cond for.end: ret void } define void @simple_urem_fail_intermediate_inc(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_fail_intermediate_inc( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp eq i32 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 0, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[INC2:%.*]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[INC2]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp eq i32 %N, 0 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 0, %entry ] %inc2 = add nuw i32 %i.04, 1 %rem = urem i32 %inc2, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @weird_loop(i64 %sub.ptr.div.i56) personality ptr null { ; CHECK-LABEL: define void @weird_loop( ; CHECK-SAME: i64 [[SUB_PTR_DIV_I56:%.*]]) personality ptr null { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[ADD74_US:%.*]] = add nuw i64 0, 1 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[ADD74_US]], [[SUB_PTR_DIV_I56]] ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i64 0, i64 [[ADD74_US]] ; CHECK-NEXT: [[ADD74_US1:%.*]] = add nuw i64 0, 1 ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: br label %[[FOR_BODY]] ; entry: br label %for.preheader for.preheader: %i57.0540.us = phi i64 [ 0, %entry ], [ %add74.us, %for.body ] %add74.us = add nuw i64 %i57.0540.us, 1 br label %for.body for.body: %rem.us = urem i64 %i57.0540.us, %sub.ptr.div.i56 br i1 false, label %for.preheader, label %for.body } define void @simple_urem_to_sel_non_zero_start_fail(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_non_zero_start_fail( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp ult i32 [[N]], 3 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 2, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_04]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp ult i32 %N, 3 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 2, %entry ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_non_zero_start_okay(i32 %N, i32 %rem_amt_in) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_non_zero_start_okay( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT_IN:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[REM_AMT:%.*]] = or i32 [[REM_AMT_IN]], 16 ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp ult i32 [[N]], 3 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[REM:%.*]] = phi i32 [ 2, %[[FOR_BODY_PREHEADER]] ], [ [[TMP3:%.*]], %[[FOR_BODY]] ] ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 2, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[REM]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], [[REM_AMT]] ; CHECK-NEXT: [[TMP3]] = select i1 [[TMP2]], i32 0, i32 [[TMP1]] ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %rem_amt = or i32 %rem_amt_in, 16 %cmp3.not = icmp ult i32 %N, 3 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 2, %entry ] %rem = urem i32 %i.04, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_non_zero_start_through_add(i32 %N, i32 %rem_amt_in) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_non_zero_start_through_add( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT_IN:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[REM_AMT:%.*]] = or i32 [[REM_AMT_IN]], 16 ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp ult i32 [[N]], 3 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[REM:%.*]] = phi i32 [ 7, %[[FOR_BODY_PREHEADER]] ], [ [[TMP3:%.*]], %[[FOR_BODY]] ] ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 2, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[REM]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], [[REM_AMT]] ; CHECK-NEXT: [[TMP3]] = select i1 [[TMP2]], i32 0, i32 [[TMP1]] ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %rem_amt = or i32 %rem_amt_in, 16 %cmp3.not = icmp ult i32 %N, 3 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 2, %entry ] %i_with_off = add nuw i32 %i.04, 5 %rem = urem i32 %i_with_off, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_non_zero_start_through_add_fail_missing_nuw(i32 %N, i32 %rem_amt_in) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_non_zero_start_through_add_fail_missing_nuw( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT_IN:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[REM_AMT:%.*]] = or i32 [[REM_AMT_IN]], 16 ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp ult i32 [[N]], 3 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 2, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[I_WITH_OFF:%.*]] = add i32 [[I_04]], 5 ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_WITH_OFF]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %rem_amt = or i32 %rem_amt_in, 16 %cmp3.not = icmp ult i32 %N, 3 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 2, %entry ] %i_with_off = add i32 %i.04, 5 %rem = urem i32 %i_with_off, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_non_zero_start_through_add_fail_no_simplify_rem(i32 %N, i32 %rem_amt) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_non_zero_start_through_add_fail_no_simplify_rem( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp ult i32 [[N]], 3 ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 2, %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[I_WITH_OFF:%.*]] = add nuw i32 [[I_04]], 5 ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_WITH_OFF]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp ult i32 %N, 3 br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ 2, %entry ] %i_with_off = add nuw i32 %i.04, 5 %rem = urem i32 %i_with_off, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_non_zero_start_through_sub(i32 %N, i32 %rem_amt, i32 %start) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_non_zero_start_through_sub( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]], i32 [[START:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp ule i32 [[N]], [[START]] ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ [[START]], %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[I_WITH_OFF:%.*]] = sub nuw i32 [[I_04]], [[START]] ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_WITH_OFF]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp ule i32 %N, %start br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ %start, %entry ] %i_with_off = sub nuw i32 %i.04, %start %rem = urem i32 %i_with_off, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } define void @simple_urem_to_sel_non_zero_start_through_sub_no_simplfy(i32 %N, i32 %rem_amt, i32 %start) nounwind { ; CHECK-LABEL: define void @simple_urem_to_sel_non_zero_start_through_sub_no_simplfy( ; CHECK-SAME: i32 [[N:%.*]], i32 [[REM_AMT:%.*]], i32 [[START:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[CMP3_NOT:%.*]] = icmp ule i32 [[N]], [[START]] ; CHECK-NEXT: br i1 [[CMP3_NOT]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] ; CHECK: [[FOR_BODY_PREHEADER]]: ; CHECK-NEXT: br label %[[FOR_BODY:.*]] ; CHECK: [[FOR_COND_CLEANUP]]: ; CHECK-NEXT: ret void ; CHECK: [[FOR_BODY]]: ; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ [[START]], %[[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[I_WITH_OFF:%.*]] = sub nuw i32 [[I_04]], 2 ; CHECK-NEXT: [[REM:%.*]] = urem i32 [[I_WITH_OFF]], [[REM_AMT]] ; CHECK-NEXT: tail call void @use.i32(i32 [[REM]]) ; CHECK-NEXT: [[INC]] = add nuw i32 [[I_04]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]] ; entry: %cmp3.not = icmp ule i32 %N, %start br i1 %cmp3.not, label %for.cond.cleanup, label %for.body for.cond.cleanup: ret void for.body: %i.04 = phi i32 [ %inc, %for.body ], [ %start, %entry ] %i_with_off = sub nuw i32 %i.04, 2 %rem = urem i32 %i_with_off, %rem_amt tail call void @use.i32(i32 %rem) %inc = add nuw i32 %i.04, 1 %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body }