| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 
 | ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=make-guards-explicit < %s        | FileCheck %s
; RUN: opt -S -passes=make-guards-explicit < %s | FileCheck %s
declare void @llvm.experimental.guard(i1,...)
; Check that a sole guard can be turned into explicit guards form.
define void @trivial_guard(i1 %cond) {
; CHECK-LABEL: @trivial_guard(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND:%.*]], [[WIDENABLE_COND]]
; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
; CHECK:       deopt:
; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 123, i64 456) ]
; CHECK-NEXT:    ret void
; CHECK:       guarded:
; CHECK-NEXT:    ret void
;
entry:
  call void(i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"(i32 123, i64 456) ]
  ret void
}
; Check that a sequence of guards can be turned into explicit guards form.
define void @trivial_guard_sequence(i1 %cond1, i1 %cond2, i1 %cond3) {
; CHECK-LABEL: @trivial_guard_sequence(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND1:%.*]], [[WIDENABLE_COND]]
; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
; CHECK:       deopt:
; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 123, i64 456) ]
; CHECK-NEXT:    ret void
; CHECK:       guarded:
; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND2:%.*]], [[WIDENABLE_COND3]]
; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
; CHECK:       deopt2:
; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 789, i64 123) ]
; CHECK-NEXT:    ret void
; CHECK:       guarded1:
; CHECK-NEXT:    [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND3:%.*]], [[WIDENABLE_COND7]]
; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND8]], label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof !0
; CHECK:       deopt6:
; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 456, i64 789) ]
; CHECK-NEXT:    ret void
; CHECK:       guarded5:
; CHECK-NEXT:    ret void
;
entry:
  call void(i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"(i32 123, i64 456) ]
  call void(i1, ...) @llvm.experimental.guard(i1 %cond2) [ "deopt"(i32 789, i64 123) ]
  call void(i1, ...) @llvm.experimental.guard(i1 %cond3) [ "deopt"(i32 456, i64 789) ]
  ret void
}
; Check that all instructions between the guards preserve.
define void @split_block_contents(i1 %cond1, i1 %cond2, i1 %cond3, ptr %p) {
; CHECK-LABEL: @split_block_contents(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    store i32 0, ptr [[P:%.*]]
; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND1:%.*]], [[WIDENABLE_COND]]
; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
; CHECK:       deopt:
; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 123, i64 456) ]
; CHECK-NEXT:    ret void
; CHECK:       guarded:
; CHECK-NEXT:    store i32 1, ptr [[P]]
; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND2:%.*]], [[WIDENABLE_COND3]]
; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
; CHECK:       deopt2:
; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 789, i64 123) ]
; CHECK-NEXT:    ret void
; CHECK:       guarded1:
; CHECK-NEXT:    store i32 2, ptr [[P]]
; CHECK-NEXT:    [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND3:%.*]], [[WIDENABLE_COND7]]
; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND8]], label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof !0
; CHECK:       deopt6:
; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 456, i64 789) ]
; CHECK-NEXT:    ret void
; CHECK:       guarded5:
; CHECK-NEXT:    store i32 3, ptr [[P]]
; CHECK-NEXT:    ret void
;
entry:
  store i32 0, ptr %p
  call void(i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"(i32 123, i64 456) ]
  store i32 1, ptr %p
  call void(i1, ...) @llvm.experimental.guard(i1 %cond2) [ "deopt"(i32 789, i64 123) ]
  store i32 2, ptr %p
  call void(i1, ...) @llvm.experimental.guard(i1 %cond3) [ "deopt"(i32 456, i64 789) ]
  store i32 3, ptr %p
  ret void
}
; Check that the guard can split a loop properly.
define void @split_loop(i1 %cond, i32 %N, i32 %M) {
; CHECK-LABEL: @split_loop(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ]
; CHECK-NEXT:    [[GUARD_COND:%.*]] = icmp slt i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[GUARD_COND]], [[WIDENABLE_COND]]
; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
; CHECK:       deopt:
; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 123, i64 456) ]
; CHECK-NEXT:    ret void
; CHECK:       guarded:
; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV]], [[M:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    ret void
;
entry:
  br label %loop
loop:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
  %guard_cond = icmp slt i32 %iv, %N
  call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"(i32 123, i64 456) ]
  %loop_cond = icmp slt i32 %iv, %M
  %iv.next = add i32 %iv, 1
  br i1 %loop_cond, label %loop, label %exit
exit:
  ret void
}
 |