1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00
llvm-mirror/test/Transforms/IndVarSimplify/lftr-pr31181.ll
Nikita Popov ec3b3dd170 [IndVarSimplify] Fixup nowrap flags during LFTR (PR31181)
Fix for https://bugs.llvm.org/show_bug.cgi?id=31181 and partial fix
for LFTR poison handling issues in general.

When LFTR moves a condition from pre-inc to post-inc, it may now
depend on value that is poison due to nowrap flags. To avoid this,
we clear any nowrap flag that SCEV cannot prove for the post-inc
addrec.

Additionally, LFTR may switch to a different IV that is dynamically
dead and as such may be arbitrarily poison. This patch will correct
nowrap flags in some but not all cases where this happens. This is
related to the adoption of IR nowrap flags for the pre-inc addrec.
(See some of the switch_to_different_iv tests, where flags are not
dropped or insufficiently dropped.)

Finally, there are likely similar issues with the handling of GEP
inbounds, but we don't have a test case for this yet.

Differential Revision: https://reviews.llvm.org/D60935

llvm-svn: 362292
2019-06-01 09:40:18 +00:00

361 lines
12 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -indvars -S | FileCheck %s
; PR31181: It may be necessary to drop nuw/nsw flags when moving from a
; pre-increment comparison to a post-increment comparison.
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
@a = global i32 0
define i32 @test_drop_nuw() {
; CHECK-LABEL: @test_drop_nuw(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ -2, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: store i32 [[STOREMERGE]], i32* @a
; CHECK-NEXT: [[INC]] = add nsw i32 [[STOREMERGE]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC]], 0
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret i32 0
;
entry:
br label %loop
loop:
%storemerge = phi i32 [ -2, %entry ], [ %inc, %loop ]
store i32 %storemerge, i32* @a
%cmp = icmp slt i32 %storemerge, -1
%inc = add nuw nsw i32 %storemerge, 1
br i1 %cmp, label %loop, label %exit
exit:
ret i32 0
}
define i32 @test_drop_nsw() {
; CHECK-LABEL: @test_drop_nsw(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: store i32 [[STOREMERGE]], i32* @a
; CHECK-NEXT: [[INC]] = add nuw i32 [[STOREMERGE]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC]], -2147483648
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret i32 0
;
entry:
br label %loop
loop:
%storemerge = phi i32 [ 0, %entry ], [ %inc, %loop ]
store i32 %storemerge, i32* @a
%cmp = icmp ult i32 %storemerge, 2147483647
%inc = add nuw nsw i32 %storemerge, 1
br i1 %cmp, label %loop, label %exit
exit:
ret i32 0
}
define i32 @test_no_drop_nuw() {
; CHECK-LABEL: @test_no_drop_nuw(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ -3, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: store i32 [[STOREMERGE]], i32* @a
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[STOREMERGE]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC]], -1
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret i32 0
;
entry:
br label %loop
loop:
%storemerge = phi i32 [ -3, %entry ], [ %inc, %loop ]
store i32 %storemerge, i32* @a
%cmp = icmp slt i32 %storemerge, -2
%inc = add nuw nsw i32 %storemerge, 1
br i1 %cmp, label %loop, label %exit
exit:
ret i32 0
}
define i32 @test_no_drop_nsw() {
; CHECK-LABEL: @test_no_drop_nsw(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: store i32 [[STOREMERGE]], i32* @a
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[STOREMERGE]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC]], 2147483647
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret i32 0
;
entry:
br label %loop
loop:
%storemerge = phi i32 [ 0, %entry ], [ %inc, %loop ]
store i32 %storemerge, i32* @a
%cmp = icmp ult i32 %storemerge, 2147483646
%inc = add nuw nsw i32 %storemerge, 1
br i1 %cmp, label %loop, label %exit
exit:
ret i32 0
}
define i32 @test_no_add_nuw() {
; CHECK-LABEL: @test_no_add_nuw(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: store i32 [[STOREMERGE]], i32* @a
; CHECK-NEXT: [[INC]] = add nsw i32 [[STOREMERGE]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC]], 10
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret i32 0
;
entry:
br label %loop
loop:
%storemerge = phi i32 [ -1, %entry ], [ %inc, %loop ]
store i32 %storemerge, i32* @a
%cmp = icmp slt i32 %storemerge, 9
%inc = add i32 %storemerge, 1
br i1 %cmp, label %loop, label %exit
exit:
ret i32 0
}
define i32 @test_drop_nsw_var_lim(i32 %lim) {
; CHECK-LABEL: @test_drop_nsw_var_lim(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[LIM:%.*]], -1
; CHECK-NEXT: br i1 [[C]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
; CHECK: loop.preheader:
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LIM]], 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ [[INC:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
; CHECK-NEXT: store i32 [[STOREMERGE]], i32* @a
; CHECK-NEXT: [[INC]] = add nuw i32 [[STOREMERGE]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC]], [[TMP0]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: exit.loopexit:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret i32 0
;
entry:
%c = icmp ult i32 %lim, -1
br i1 %c, label %loop, label %exit
loop:
%storemerge = phi i32 [ 0, %entry ], [ %inc, %loop ]
store i32 %storemerge, i32* @a
%cmp = icmp ult i32 %storemerge, %lim
%inc = add nuw nsw i32 %storemerge, 1
br i1 %cmp, label %loop, label %exit
exit:
ret i32 0
}
; Adopted from D30446.
; We switch from %iv to %iv2 and need to change nsw to nuw in the process.
define i32 @switch_to_different_iv_post_inc(i32* %ptr, i1 %always_false) {
; CHECK-LABEL: @switch_to_different_iv_post_inc(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[ALWAYS_TAKEN:%.*]] ]
; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV2_INC:%.*]], [[ALWAYS_TAKEN]] ]
; CHECK-NEXT: store i32 [[IV]], i32* [[PTR:%.*]]
; CHECK-NEXT: br i1 [[ALWAYS_FALSE:%.*]], label [[NEVER_TAKEN:%.*]], label [[ALWAYS_TAKEN]]
; CHECK: never_taken:
; CHECK-NEXT: store volatile i32 [[IV2]], i32* [[PTR]]
; CHECK-NEXT: br label [[ALWAYS_TAKEN]]
; CHECK: always_taken:
; CHECK-NEXT: [[IV_INC]] = add nsw i32 [[IV]], 1
; CHECK-NEXT: [[IV2_INC]] = add nuw i32 [[IV2]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV2_INC]], -2147483627
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret i32 0
;
entry:
br label %for.cond
for.cond:
%iv = phi i32 [ -2147483648, %entry ], [ %iv.inc, %always_taken ]
%iv2 = phi i32 [ 0, %entry ], [ %iv2.inc, %always_taken ]
store i32 %iv, i32* %ptr
br i1 %always_false, label %never_taken, label %always_taken
never_taken:
store volatile i32 %iv2, i32* %ptr
br label %always_taken
always_taken:
%iv.inc = add nsw i32 %iv, 1
%iv2.inc = add nuw nsw i32 %iv2, 1
%cmp = icmp slt i32 %iv, 20
br i1 %cmp, label %for.cond, label %for.end
for.end:
ret i32 0
}
; Same as previous test case, but with exit block and loop latch being distinct
; blocks requiring the use of pre-increment.
define i32 @switch_to_different_iv_pre_inc(i32* %ptr, i1 %always_false) {
; CHECK-LABEL: @switch_to_different_iv_pre_inc(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[ALWAYS_TAKEN:%.*]] ]
; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV2_INC:%.*]], [[ALWAYS_TAKEN]] ]
; CHECK-NEXT: store i32 [[IV]], i32* [[PTR:%.*]]
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV2]], -2147483628
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
; CHECK: for.body:
; CHECK-NEXT: br i1 [[ALWAYS_FALSE:%.*]], label [[NEVER_TAKEN:%.*]], label [[ALWAYS_TAKEN]]
; CHECK: never_taken:
; CHECK-NEXT: store volatile i32 [[IV2]], i32* [[PTR]]
; CHECK-NEXT: br label [[ALWAYS_TAKEN]]
; CHECK: always_taken:
; CHECK-NEXT: [[IV_INC]] = add nsw i32 [[IV]], 1
; CHECK-NEXT: [[IV2_INC]] = add nuw i32 [[IV2]], 1
; CHECK-NEXT: br label [[FOR_COND]]
; CHECK: for.end:
; CHECK-NEXT: ret i32 0
;
entry:
br label %for.cond
for.cond:
%iv = phi i32 [ -2147483648, %entry ], [ %iv.inc, %always_taken ]
%iv2 = phi i32 [ 0, %entry ], [ %iv2.inc, %always_taken ]
store i32 %iv, i32* %ptr
%cmp = icmp slt i32 %iv, 20
br i1 %cmp, label %for.body, label %for.end
for.body:
br i1 %always_false, label %never_taken, label %always_taken
never_taken:
store volatile i32 %iv2, i32* %ptr
br label %always_taken
always_taken:
%iv.inc = add nsw i32 %iv, 1
%iv2.inc = add nuw nsw i32 %iv2, 1
br label %for.cond
for.end:
ret i32 0
}
define i32 @switch_to_different_iv_first_poison(i32* %ptr, i1 %always_false) {
; CHECK-LABEL: @switch_to_different_iv_first_poison(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[IV2_INC:%.*]], [[ALWAYS_TAKEN:%.*]] ]
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ -2147483648, [[ENTRY]] ], [ [[IV_INC:%.*]], [[ALWAYS_TAKEN]] ]
; CHECK-NEXT: store i32 [[IV]], i32* [[PTR:%.*]]
; CHECK-NEXT: br i1 [[ALWAYS_FALSE:%.*]], label [[NEVER_TAKEN:%.*]], label [[ALWAYS_TAKEN]]
; CHECK: never_taken:
; CHECK-NEXT: store volatile i32 [[IV2]], i32* [[PTR]]
; CHECK-NEXT: br label [[ALWAYS_TAKEN]]
; CHECK: always_taken:
; CHECK-NEXT: [[IV2_INC]] = add nuw nsw i32 [[IV2]], 1
; CHECK-NEXT: [[IV_INC]] = add nsw i32 [[IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV2_INC]], -2147483628
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret i32 0
;
entry:
br label %for.cond
for.cond:
%iv2 = phi i32 [ -1, %entry ], [ %iv2.inc, %always_taken ]
%iv = phi i32 [ -2147483648, %entry ], [ %iv.inc, %always_taken ]
store i32 %iv, i32* %ptr
br i1 %always_false, label %never_taken, label %always_taken
never_taken:
store volatile i32 %iv2, i32* %ptr
br label %always_taken
always_taken:
%iv2.inc = add nuw nsw i32 %iv2, 1
%iv.inc = add nsw i32 %iv, 1
%cmp = icmp slt i32 %iv, 20
br i1 %cmp, label %for.cond, label %for.end
for.end:
ret i32 0
}
define i32 @switch_to_different_iv_second_poison(i32* %ptr, i1 %always_false) {
; CHECK-LABEL: @switch_to_different_iv_second_poison(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ -2, [[ENTRY:%.*]] ], [ [[IV2_INC:%.*]], [[ALWAYS_TAKEN:%.*]] ]
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ -2147483648, [[ENTRY]] ], [ [[IV_INC:%.*]], [[ALWAYS_TAKEN]] ]
; CHECK-NEXT: store i32 [[IV]], i32* [[PTR:%.*]]
; CHECK-NEXT: br i1 [[ALWAYS_FALSE:%.*]], label [[NEVER_TAKEN:%.*]], label [[ALWAYS_TAKEN]]
; CHECK: never_taken:
; CHECK-NEXT: store volatile i32 [[IV2]], i32* [[PTR]]
; CHECK-NEXT: br label [[ALWAYS_TAKEN]]
; CHECK: always_taken:
; CHECK-NEXT: [[IV2_INC]] = add nsw i32 [[IV2]], 1
; CHECK-NEXT: [[IV_INC]] = add nsw i32 [[IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV2_INC]], -2147483629
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret i32 0
;
entry:
br label %for.cond
for.cond:
%iv2 = phi i32 [ -2, %entry ], [ %iv2.inc, %always_taken ]
%iv = phi i32 [ -2147483648, %entry ], [ %iv.inc, %always_taken ]
store i32 %iv, i32* %ptr
br i1 %always_false, label %never_taken, label %always_taken
never_taken:
store volatile i32 %iv2, i32* %ptr
br label %always_taken
always_taken:
%iv2.inc = add nuw nsw i32 %iv2, 1
%iv.inc = add nsw i32 %iv, 1
%cmp = icmp slt i32 %iv, 20
br i1 %cmp, label %for.cond, label %for.end
for.end:
ret i32 0
}