|
|
@@ -0,0 +1,879 @@ |
|
|
; 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_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]], <i64 1, 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]], <i64 1, 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, <i64 1, i64 1> |
|
|
%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: [[REM:%.*]] = phi i32 [ 4, %[[FOR_BODY_PREHEADER]] ], [ [[TMP3:%.*]], %[[FOR_BODY]] ] |
|
|
; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 4, %[[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 ], [ 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: [[REM:%.*]] = phi i32 [ [[I_04_PH]], %[[FOR_BODY_PREHEADER]] ], [ [[TMP3:%.*]], %[[FOR_BODY]] ] |
|
|
; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_BODY]] ], [ [[I_04_PH]], %[[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.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: br label %[[FOR_BODY:.*]] |
|
|
; CHECK: [[FOR_BODY]]: |
|
|
; CHECK-NEXT: [[REM_US:%.*]] = urem i64 0, [[SUB_PTR_DIV_I56]] |
|
|
; 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(i32 %N, i32 %rem_amt) nounwind { |
|
|
; CHECK-LABEL: define void @simple_urem_to_sel_non_zero_start( |
|
|
; 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: [[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: |
|
|
%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: [[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: |
|
|
%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 |
|
|
} |