blob: 7715abc8ada5e42f252a7779ca5aa4ac5725cf45 [file] [log] [blame]
Sanjoy Dasae09b3c2016-05-29 00:36:25 +00001; RUN: opt -S -indvars < %s | FileCheck %s
2
3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4target triple = "x86_64-unknown-linux-gnu"
5
6define void @f_sadd(i8* %a) {
7; CHECK-LABEL: @f_sadd(
8entry:
9 br label %for.body
10
11for.cond.cleanup: ; preds = %cont
12 ret void
13
14for.body: ; preds = %entry, %cont
15 %i.04 = phi i32 [ 0, %entry ], [ %2, %cont ]
16 %idxprom = sext i32 %i.04 to i64
17 %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom
18 store i8 0, i8* %arrayidx, align 1
19 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1)
20 %1 = extractvalue { i32, i1 } %0, 1
21; CHECK: for.body:
22; CHECK-NOT: @llvm.sadd.with.overflow
23; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
24 br i1 %1, label %trap, label %cont, !nosanitize !{}
25
26trap: ; preds = %for.body
27 tail call void @llvm.trap() #2, !nosanitize !{}
28 unreachable, !nosanitize !{}
29
30cont: ; preds = %for.body
31 %2 = extractvalue { i32, i1 } %0, 0
32 %cmp = icmp slt i32 %2, 16
33 br i1 %cmp, label %for.body, label %for.cond.cleanup
34}
35
36define void @f_uadd(i8* %a) {
37; CHECK-LABEL: @f_uadd(
38entry:
39 br label %for.body
40
41for.cond.cleanup: ; preds = %cont
42 ret void
43
44for.body: ; preds = %entry, %cont
45 %i.04 = phi i32 [ 0, %entry ], [ %2, %cont ]
46 %idxprom = sext i32 %i.04 to i64
47 %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom
48 store i8 0, i8* %arrayidx, align 1
49 %0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %i.04, i32 1)
50 %1 = extractvalue { i32, i1 } %0, 1
51; CHECK: for.body:
52; CHECK-NOT: @llvm.uadd.with.overflow
53; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
54 br i1 %1, label %trap, label %cont, !nosanitize !{}
55
56trap: ; preds = %for.body
57 tail call void @llvm.trap(), !nosanitize !{}
58 unreachable, !nosanitize !{}
59
60cont: ; preds = %for.body
61 %2 = extractvalue { i32, i1 } %0, 0
62 %cmp = icmp slt i32 %2, 16
63 br i1 %cmp, label %for.body, label %for.cond.cleanup
64}
65
66define void @f_ssub(i8* nocapture %a) {
67; CHECK-LABEL: @f_ssub(
68entry:
69 br label %for.body
70
71for.cond.cleanup: ; preds = %cont
72 ret void
73
74for.body: ; preds = %entry, %cont
75 %i.04 = phi i32 [ 15, %entry ], [ %2, %cont ]
76 %idxprom = sext i32 %i.04 to i64
77 %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom
78 store i8 0, i8* %arrayidx, align 1
79 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %i.04, i32 1)
80 %1 = extractvalue { i32, i1 } %0, 1
81; CHECK: for.body:
82; CHECK-NOT: @llvm.ssub.with.overflow.i32
83; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
84 br i1 %1, label %trap, label %cont, !nosanitize !{}
85
86trap: ; preds = %for.body
87 tail call void @llvm.trap(), !nosanitize !{}
88 unreachable, !nosanitize !{}
89
90cont: ; preds = %for.body
91 %2 = extractvalue { i32, i1 } %0, 0
92 %cmp = icmp sgt i32 %2, -1
93 br i1 %cmp, label %for.body, label %for.cond.cleanup
94}
95
96define void @f_usub(i8* nocapture %a) {
97; CHECK-LABEL: @f_usub(
98entry:
99 br label %for.body
100
101for.cond.cleanup: ; preds = %cont
102 ret void
103
104for.body: ; preds = %entry, %cont
105 %i.04 = phi i32 [ 15, %entry ], [ %2, %cont ]
106 %idxprom = sext i32 %i.04 to i64
107 %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom
108 store i8 0, i8* %arrayidx, align 1
109 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %i.04, i32 1)
110 %1 = extractvalue { i32, i1 } %0, 1
111
112; It is theoretically possible to prove this, but SCEV cannot
113; represent non-unsigned-wrapping subtraction operations.
114
115; CHECK: for.body:
116; CHECK: [[COND:%[^ ]+]] = extractvalue { i32, i1 } %1, 1
117; CHECK-NEXT: br i1 [[COND]], label %trap, label %cont, !nosanitize !0
118 br i1 %1, label %trap, label %cont, !nosanitize !{}
119
120trap: ; preds = %for.body
121 tail call void @llvm.trap(), !nosanitize !{}
122 unreachable, !nosanitize !{}
123
124cont: ; preds = %for.body
125 %2 = extractvalue { i32, i1 } %0, 0
126 %cmp = icmp sgt i32 %2, -1
127 br i1 %cmp, label %for.body, label %for.cond.cleanup
128}
129
130declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
131declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
132declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone
133declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone
134declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
135declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
136
137declare void @llvm.trap() #2