| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -indvars -S | FileCheck %s |
| |
| ; This tests that the IV is recomputed outside of the loop even when it is known |
| ; to be computed by the loop and used in the loop any way, if it is cheap to do |
| ; so. In the example below the value can be computed outside of the loop, |
| ; and we should do so because after that IV is no longer used outside of |
| ; the loop, which is likely beneficial for vectorization. |
| ; |
| ; extern void func(unsigned val); |
| ; |
| ; void test(unsigned m) |
| ; { |
| ; unsigned a = 0; |
| ; |
| ; for (int i=0; i<186; i++) { |
| ; a += m; |
| ; func(a); |
| ; } |
| ; |
| ; func(a); |
| ; } |
| |
| declare void @func(i32) |
| |
| define void @test(i32 %m) nounwind uwtable { |
| ; CHECK-LABEL: @test( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]] |
| ; CHECK-NEXT: tail call void @func(i32 [[ADD]]) |
| ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] |
| ; CHECK: for.end: |
| ; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[M]], 186 |
| ; CHECK-NEXT: tail call void @func(i32 [[TMP0]]) |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ] |
| %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ] |
| %add = add i32 %a.05, %m |
| tail call void @func(i32 %add) |
| %inc = add nsw i32 %i.06, 1 |
| %exitcond = icmp eq i32 %inc, 186 |
| br i1 %exitcond, label %for.end, label %for.body |
| |
| for.end: ; preds = %for.body |
| tail call void @func(i32 %add) |
| ret void |
| } |
| |
| define i32 @test2(i32 %m) nounwind uwtable { |
| ; CHECK-LABEL: @test2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]] |
| ; CHECK-NEXT: tail call void @func(i32 [[ADD]]) |
| ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] |
| ; CHECK: for.end: |
| ; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[M]], 186 |
| ; CHECK-NEXT: ret i32 [[TMP0]] |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ] |
| %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ] |
| %add = add i32 %a.05, %m |
| tail call void @func(i32 %add) |
| %inc = add nsw i32 %i.06, 1 |
| %exitcond = icmp eq i32 %inc, 186 |
| br i1 %exitcond, label %for.end, label %for.body |
| |
| for.end: ; preds = %for.body |
| ret i32 %add |
| } |
| |
| define void @test3(i32 %m) nounwind uwtable { |
| ; CHECK-LABEL: @test3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]] |
| ; CHECK-NEXT: tail call void @func(i32 [[ADD]]) |
| ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] |
| ; CHECK: for.end: |
| ; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[M]], 186 |
| ; CHECK-NEXT: tail call void @func(i32 [[TMP0]]) |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ] |
| %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ] |
| %add = add i32 %a.05, %m |
| mul i32 %add, 1 |
| mul i32 %add, 1 |
| mul i32 %add, 1 |
| mul i32 %add, 1 |
| mul i32 %add, 1 |
| mul i32 %add, 1 |
| tail call void @func(i32 %add) |
| %inc = add nsw i32 %i.06, 1 |
| %exitcond = icmp eq i32 %inc, 186 |
| br i1 %exitcond, label %for.end, label %for.body |
| |
| for.end: ; preds = %for.body |
| tail call void @func(i32 %add) |
| ret void |
| } |
| |
| define void @test4(i32 %m) nounwind uwtable { |
| ; CHECK-LABEL: @test4( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]] |
| ; CHECK-NEXT: tail call void @func(i32 [[ADD]]) |
| ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] |
| ; CHECK: for.end: |
| ; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[M]], 186 |
| ; CHECK-NEXT: [[SOFT_USE:%.*]] = add i32 [[TMP0]], 123 |
| ; CHECK-NEXT: tail call void @func(i32 [[SOFT_USE]]) |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ] |
| %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ] |
| %add = add i32 %a.05, %m |
| tail call void @func(i32 %add) |
| %inc = add nsw i32 %i.06, 1 |
| %exitcond = icmp eq i32 %inc, 186 |
| br i1 %exitcond, label %for.end, label %for.body |
| |
| for.end: ; preds = %for.body |
| %soft_use = add i32 %add, 123 |
| tail call void @func(i32 %soft_use) |
| ret void |
| } |
| |
| define void @test5(i32 %m) nounwind uwtable { |
| ; CHECK-LABEL: @test5( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]] |
| ; CHECK-NEXT: [[SOFT_USE:%.*]] = add i32 [[ADD]], 123 |
| ; CHECK-NEXT: tail call void @func(i32 [[SOFT_USE]]) |
| ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] |
| ; CHECK: for.end: |
| ; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[M]], 186 |
| ; CHECK-NEXT: tail call void @func(i32 [[TMP0]]) |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ] |
| %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ] |
| %add = add i32 %a.05, %m |
| %soft_use = add i32 %add, 123 |
| tail call void @func(i32 %soft_use) |
| %inc = add nsw i32 %i.06, 1 |
| %exitcond = icmp eq i32 %inc, 186 |
| br i1 %exitcond, label %for.end, label %for.body |
| |
| for.end: ; preds = %for.body |
| tail call void @func(i32 %add) |
| ret void |
| } |
| |
| define void @test6(i32 %m, i32* %p) nounwind uwtable { |
| ; CHECK-LABEL: @test6( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]] |
| ; CHECK-NEXT: [[SOFT_USE:%.*]] = add i32 [[ADD]], 123 |
| ; CHECK-NEXT: [[PIDX:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 [[ADD]] |
| ; CHECK-NEXT: store i32 [[SOFT_USE]], i32* [[PIDX]] |
| ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] |
| ; CHECK: for.end: |
| ; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[M]], 186 |
| ; CHECK-NEXT: tail call void @func(i32 [[TMP0]]) |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ] |
| %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ] |
| %add = add i32 %a.05, %m |
| %soft_use = add i32 %add, 123 |
| %pidx = getelementptr i32, i32* %p, i32 %add |
| store i32 %soft_use, i32* %pidx |
| %inc = add nsw i32 %i.06, 1 |
| %exitcond = icmp eq i32 %inc, 186 |
| br i1 %exitcond, label %for.end, label %for.body |
| |
| for.end: ; preds = %for.body |
| tail call void @func(i32 %add) |
| ret void |
| } |