Files
clang-p2996/llvm/test/Transforms/LoopStrengthReduce/X86/pr46943.ll
Nikita Popov 835104a114 [LSR] Drop potentially invalid nowrap flags when switching to post-inc IV (PR46943)
When LSR converts a branch on the pre-inc IV into a branch on the
post-inc IV, the nowrap flags on the addition may no longer be valid.
Previously, a poison result of the addition might have been ignored,
in which case the program was well defined. After branching on the
post-inc IV, we might be branching on poison, which is undefined behavior.

Fix this by discarding nowrap flags which are not present on the SCEV
expression. Nowrap flags on the SCEV expression are proven by SCEV
to always hold, independently of how the expression will be used.
This is essentially the same fix we applied to IndVars LFTR, which
also performs this kind of pre-inc to post-inc conversion.

I believe a similar problem can also exist for getelementptr inbounds,
but I was not able to come up with a problematic test case. The
inbounds case would have to be addressed in a differently anyway
(as SCEV does not track this property).

Fixes https://bugs.llvm.org/show_bug.cgi?id=46943.

Differential Revision: https://reviews.llvm.org/D95286
2021-01-25 23:13:48 +01:00

99 lines
2.8 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -loop-reduce < %s | FileCheck %s
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
declare void @use(i8 zeroext)
declare void @use_p(i8*)
; nuw needs to be dropped when switching to post-inc comparison.
define i8 @drop_nuw() {
; CHECK-LABEL: @drop_nuw(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: call void @use(i8 [[IV]])
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[IV_NEXT]], 0
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[IV_NEXT]], -1
; CHECK-NEXT: ret i8 [[TMP0]]
;
entry:
br label %loop
loop:
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
call void @use(i8 %iv)
%iv.next = add nuw i8 %iv, 1
%cmp = icmp eq i8 %iv, -1
br i1 %cmp, label %exit, label %loop
exit:
ret i8 %iv
}
; nsw needs to be dropped when switching to post-inc comparison.
define i8 @drop_nsw() {
; CHECK-LABEL: @drop_nsw(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 127, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: call void @use(i8 [[IV]])
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[IV_NEXT]], 127
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[IV_NEXT]], 1
; CHECK-NEXT: ret i8 [[TMP0]]
;
entry:
br label %loop
loop:
%iv = phi i8 [ 127, %entry ], [ %iv.next, %loop ]
call void @use(i8 %iv)
%iv.next = add nsw i8 %iv, -1
%cmp = icmp eq i8 %iv, -128
br i1 %cmp, label %exit, label %loop
exit:
ret i8 %iv
}
; Comparison already in post-inc form, no need to drop nuw.
define i8 @already_postinc() {
; CHECK-LABEL: @already_postinc(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: call void @use(i8 [[IV]])
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[IV_NEXT]], -1
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[IV_NEXT]], -1
; CHECK-NEXT: ret i8 [[TMP0]]
;
entry:
br label %loop
loop:
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
call void @use(i8 %iv)
%iv.next = add nuw i8 %iv, 1
%cmp = icmp eq i8 %iv.next, -1
br i1 %cmp, label %exit, label %loop
exit:
ret i8 %iv
}