1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-24 21:42:54 +02:00
llvm-mirror/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll
Sanjoy Das 9baaae9344 [SCEV] Don't always add no-wrap flags to post-inc add recs
Fixes PR27315.

The post-inc version of an add recurrence needs to "follow the same
rules" as a normal add or subtract expression.  Otherwise we miscompile
programs like

```
int main() {
  int a = 0;
  unsigned a_u = 0;
  volatile long last_value;
  do {
    a_u += 3;
    last_value = (long) ((int) a_u);
    if (will_add_overflow(a, 3)) {
      // Leave, and don't actually do the increment, so no UB.
      printf("last_value = %ld\n", last_value);
      exit(0);
    }
    a += 3;
  } while (a != 46);
  return 0;
}
```

This patch changes SCEV to put no-wrap flags on post-inc add recurrences
only when the poison from a potential overflow will go ahead to cause
undefined behavior.

To avoid regressing performance too much, I've assumed infinite loops
without side effects is undefined behavior to prove poison<->UB
equivalence in more cases.  This isn't ideal, but is not new to LLVM as
a whole, and far better than the situation I'm trying to fix.

llvm-svn: 271151
2016-05-29 00:32:17 +00:00

110 lines
3.2 KiB
LLVM

; ; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s
define void @infer.sext.0(i1* %c, i32 %start, i32* %buf) {
; CHECK-LABEL: Classifying expressions for: @infer.sext.0
entry:
br label %loop
loop:
%counter = phi i32 [ 0, %entry ], [ %counter.inc, %loop ]
%idx = phi i32 [ %start, %entry ], [ %idx.inc, %loop ]
%idx.inc = add nsw i32 %idx, 1
%idx.inc.sext = sext i32 %idx.inc to i64
; CHECK: %idx.inc.sext = sext i32 %idx.inc to i64
; CHECK-NEXT: --> {(1 + (sext i32 %start to i64))<nsw>,+,1}<nsw><%loop>
%buf.gep = getelementptr inbounds i32, i32* %buf, i32 %idx.inc
%val = load i32, i32* %buf.gep
%condition = icmp eq i32 %counter, 1
%counter.inc = add i32 %counter, 1
br i1 %condition, label %exit, label %loop
exit:
ret void
}
define void @infer.zext.0(i1* %c, i32 %start, i32* %buf) {
; CHECK-LABEL: Classifying expressions for: @infer.zext.0
entry:
br label %loop
loop:
%counter = phi i32 [ 0, %entry ], [ %counter.inc, %loop ]
%idx = phi i32 [ %start, %entry ], [ %idx.inc, %loop ]
%idx.inc = add nuw i32 %idx, 1
%idx.inc.sext = zext i32 %idx.inc to i64
; CHECK: %idx.inc.sext = zext i32 %idx.inc to i64
; CHECK-NEXT: --> {(1 + (zext i32 %start to i64))<nuw><nsw>,+,1}<nuw><%loop>
%buf.gep = getelementptr inbounds i32, i32* %buf, i32 %idx.inc
%val = load i32, i32* %buf.gep
%condition = icmp eq i32 %counter, 1
%counter.inc = add i32 %counter, 1
br i1 %condition, label %exit, label %loop
exit:
ret void
}
define void @infer.sext.1(i32 %start, i1* %c) {
; CHECK-LABEL: Classifying expressions for: @infer.sext.1
entry:
%start.mul = mul i32 %start, 4
%start.real = add i32 %start.mul, 2
br label %loop
loop:
%idx = phi i32 [ %start.real, %entry ], [ %idx.inc, %loop ]
%idx.sext = sext i32 %idx to i64
; CHECK: %idx.sext = sext i32 %idx to i64
; CHECK-NEXT: --> {(2 + (sext i32 (4 * %start) to i64))<nsw>,+,2}<nsw><%loop>
%idx.inc = add nsw i32 %idx, 2
%condition = load i1, i1* %c
br i1 %condition, label %exit, label %loop
exit:
ret void
}
define void @infer.sext.2(i1* %c, i8 %start) {
; CHECK-LABEL: Classifying expressions for: @infer.sext.2
entry:
%start.inc = add i8 %start, 1
%entry.condition = icmp slt i8 %start, 127
br i1 %entry.condition, label %loop, label %exit
loop:
%idx = phi i8 [ %start.inc, %entry ], [ %idx.inc, %loop ]
%idx.sext = sext i8 %idx to i16
; CHECK: %idx.sext = sext i8 %idx to i16
; CHECK-NEXT: --> {(1 + (sext i8 %start to i16))<nsw>,+,1}<nsw><%loop>
%idx.inc = add nsw i8 %idx, 1
%condition = load volatile i1, i1* %c
br i1 %condition, label %exit, label %loop
exit:
ret void
}
define void @infer.zext.1(i1* %c, i8 %start) {
; CHECK-LABEL: Classifying expressions for: @infer.zext.1
entry:
%start.inc = add i8 %start, 1
%entry.condition = icmp ult i8 %start, 255
br i1 %entry.condition, label %loop, label %exit
loop:
%idx = phi i8 [ %start.inc, %entry ], [ %idx.inc, %loop ]
%idx.zext = zext i8 %idx to i16
; CHECK: %idx.zext = zext i8 %idx to i16
; CHECK-NEXT: --> {(1 + (zext i8 %start to i16))<nuw><nsw>,+,1}<nuw><%loop>
%idx.inc = add nuw i8 %idx, 1
%condition = load volatile i1, i1* %c
br i1 %condition, label %exit, label %loop
exit:
ret void
}