[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / GVN / PRE / pre-load-guards.ll
blobeeb3ef649d945aa4f55b282012ef24bbd42a3ab6
1 ; RUN: opt < %s -basicaa -gvn -enable-load-pre -S | FileCheck %s
2 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
4 declare void @llvm.experimental.guard(i1, ...)
6 ; This is a motivating example on why we prohibit hoisting through guards.
7 ; In the bottom block, we check that the index is within bounds and only access
8 ; the element in this case and deoptimize otherwise. If we hoist the load to a
9 ; place above the guard, it will may lead to out-of-bound array access.
10 define i32 @test_motivation(i32* %p, i32* %q, i1 %C, i32 %index, i32 %len) {
11 ; CHECK-LABEL: @test_motivation(
12 block1:
13   %el1 = getelementptr inbounds i32, i32* %q, i32 %index
14   %el2 = getelementptr inbounds i32, i32* %p, i32 %index
15         br i1 %C, label %block2, label %block3
17 block2:
19 ; CHECK:        block2:
20 ; CHECK-NEXT:     br
21 ; CHECK-NOT:      load
22 ; CHECK-NOT:      sge
23 ; CHECK-NOT:      slt
24 ; CHECK-NOT:      and
25   br label %block4
27 block3:
28   store i32 0, i32* %el1
29   br label %block4
31 block4:
33 ; CHECK:        block4:
34 ; CHECK:          %cond1 = icmp sge i32 %index, 0
35 ; CHECK-NEXT:     %cond2 = icmp slt i32 %index, %len
36 ; CHECK-NEXT:     %in.bounds = and i1 %cond1, %cond2
37 ; CHECK:          call void (i1, ...) @llvm.experimental.guard(i1 %in.bounds)
38 ; CHECK-NEXT:     %PRE = load i32, i32* %P2
39 ; CHECK:          ret i32 %PRE
41   %P2 = phi i32* [%el2, %block3], [%el1, %block2]
42   %cond1 = icmp sge i32 %index, 0
43   %cond2 = icmp slt i32 %index, %len
44   %in.bounds = and i1 %cond1, %cond2
45   call void (i1, ...) @llvm.experimental.guard(i1 %in.bounds) [ "deopt"() ]
46   %PRE = load i32, i32* %P2
47   ret i32 %PRE
50 ; Guard in load's block that is above the load should prohibit the PRE.
51 define i32 @test_guard_01(i32* %p, i32* %q, i1 %C, i1 %G) {
52 ; CHECK-LABEL: @test_guard_01(
53 block1:
54         br i1 %C, label %block2, label %block3
56 block2:
58 ; CHECK:        block2:
59 ; CHECK-NEXT:     br
60 ; CHECK-NOT:      load
62  br label %block4
64 block3:
65   store i32 0, i32* %p
66   br label %block4
68 block4:
70 ; CHECK:        block4:
71 ; CHECK:          call void (i1, ...) @llvm.experimental.guard(i1 %G)
72 ; CHECK-NEXT:     load
73 ; CHECK:          ret i32
75   %P2 = phi i32* [%p, %block3], [%q, %block2]
76   call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]
77   %PRE = load i32, i32* %P2
78   ret i32 %PRE
81 ; Guard in load's block that is below the load should not prohibit the PRE.
82 define i32 @test_guard_02(i32* %p, i32* %q, i1 %C, i1 %G) {
83 ; CHECK-LABEL: @test_guard_02(
84 block1:
85         br i1 %C, label %block2, label %block3
87 block2:
89 ; CHECK:        block2:
90 ; CHECK-NEXT:     load i32, i32* %q
92  br label %block4
94 block3:
95   store i32 0, i32* %p
96   br label %block4
98 block4:
100 ; CHECK:        block4:
101 ; CHECK-NEXT:     phi i32 [
102 ; CHECK-NEXT:     phi i32* [
103 ; CHECK-NEXT:     call void (i1, ...) @llvm.experimental.guard(i1 %G)
104 ; CHECK-NOT:      load
105 ; CHECK:          ret i32
107   %P2 = phi i32* [%p, %block3], [%q, %block2]
108   %PRE = load i32, i32* %P2
109   call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]
110   ret i32 %PRE
113 ; Guard above the load's block should prevent PRE from hoisting through it.
114 define i32 @test_guard_03(i32* %p, i32* %q, i1 %C, i1 %G) {
115 ; CHECK-LABEL: @test_guard_03(
116 block1:
117         br i1 %C, label %block2, label %block3
119 block2:
121 ; CHECK:        block2:
122 ; CHECK-NEXT:     br
123 ; CHECK-NOT:      load
125  br label %block4
127 block3:
128   store i32 0, i32* %p
129   br label %block4
131 block4:
133 ; CHECK:        block4:
134 ; CHECK-NEXT:     phi i32*
135 ; CHECK-NEXT:     call void (i1, ...) @llvm.experimental.guard(i1 %G)
136 ; CHECK-NEXT:     load
137 ; CHECK-NEXT:     ret i32
139   %P2 = phi i32* [%p, %block3], [%q, %block2]
140   call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]
141   br label %block5
143 block5:
144   %PRE = load i32, i32* %P2
145   ret i32 %PRE