[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / LICM / explicit_guards.ll
blobc9e091359b0a4ac608a7ad6f93ae02a0b23eae70
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -make-guards-explicit -basicaa -licm < %s        | FileCheck %s
3 ; RUN: opt -S -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,make-guards-explicit,loop(licm)' < %s | FileCheck %s
5 ; Test interaction between explicit guards and LICM: make sure that we do not
6 ; hoist explicit conditions while we can hoist invariant loads in presence of
7 ; explicit guards.
9 declare void @llvm.experimental.guard(i1,...)
11 ; Make sure that we do not hoist widenable_cond out of loop.
12 define void @do_not_hoist_widenable_cond(i1 %cond, i32 %N, i32 %M) {
13 ; CHECK-LABEL: @do_not_hoist_widenable_cond(
14 ; CHECK-NEXT:  entry:
15 ; CHECK-NEXT:    br label [[LOOP:%.*]]
16 ; CHECK:       loop:
17 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ]
18 ; CHECK-NEXT:    [[GUARD_COND:%.*]] = icmp slt i32 [[IV]], [[N:%.*]]
19 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
20 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[GUARD_COND]], [[WIDENABLE_COND]]
21 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
22 ; CHECK:       deopt:
23 ; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
24 ; CHECK-NEXT:    ret void
25 ; CHECK:       guarded:
26 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV]], [[M:%.*]]
27 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
28 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
29 ; CHECK:       exit:
30 ; CHECK-NEXT:    ret void
32 entry:
33   br label %loop
35 loop:
36   %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
37   %guard_cond = icmp slt i32 %iv, %N
38   call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ]
39   %loop_cond = icmp slt i32 %iv, %M
40   %iv.next = add i32 %iv, 1
41   br i1 %loop_cond, label %loop, label %exit
43 exit:
44   ret void
47 define void @hoist_invariant_load(i1 %cond, i32* %np, i32 %M) {
48 ; CHECK-LABEL: @hoist_invariant_load(
49 ; CHECK-NEXT:  entry:
50 ; CHECK-NEXT:    [[N:%.*]] = load i32, i32* [[NP:%.*]]
51 ; CHECK-NEXT:    br label [[LOOP:%.*]]
52 ; CHECK:       loop:
53 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ]
54 ; CHECK-NEXT:    [[GUARD_COND:%.*]] = icmp slt i32 [[IV]], [[N]]
55 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
56 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[GUARD_COND]], [[WIDENABLE_COND]]
57 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
58 ; CHECK:       deopt:
59 ; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
60 ; CHECK-NEXT:    ret void
61 ; CHECK:       guarded:
62 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV]], [[M:%.*]]
63 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
64 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
65 ; CHECK:       exit:
66 ; CHECK-NEXT:    ret void
68 entry:
69   br label %loop
71 loop:
72   %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
73   %N = load i32, i32* %np
74   %guard_cond = icmp slt i32 %iv, %N
75   call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ]
76   %loop_cond = icmp slt i32 %iv, %M
77   %iv.next = add i32 %iv, 1
78   br i1 %loop_cond, label %loop, label %exit
80 exit:
81   ret void