1 2 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 -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s
; RUN: opt < %s -instcombine -S -debugify-each | FileCheck %s
; RUN: opt < %s -passes=instcombine -S -debugify-each | FileCheck %s
declare void @llvm.experimental.guard(i1, ...)
define void @test_guard_adjacent_same_cond(i1 %A) {
; CHECK-LABEL: @test_guard_adjacent_same_cond(
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[A:%.*]]) [ "deopt"() ]
; CHECK-NEXT: ret void
;
call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
ret void
}
define void @test_guard_adjacent_diff_cond(i1 %A, i1 %B, i1 %C) {
; CHECK-LABEL: @test_guard_adjacent_diff_cond(
; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[C:%.*]]
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 123) [ "deopt"() ]
; CHECK-NEXT: ret void
;
call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ]
ret void
}
; This version tests for the common form where the conditions are
; between the guards
define void @test_guard_adjacent_diff_cond2(i32 %V1, i32 %V2) {
; CHECK-LABEL: @test_guard_adjacent_diff_cond2(
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[V1:%.*]], [[V2:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
; CHECK-NEXT: [[AND:%.*]] = and i32 [[V1]], 255
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[AND]], 129
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[C]]
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 123) [ "deopt"() ]
; CHECK-NEXT: ret void
;
%A = icmp slt i32 %V1, 0
call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
%B = icmp slt i32 %V2, 0
call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
%and = and i32 %V1, 255
%C = icmp sle i32 %and, 128
call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ]
ret void
}
; Might not be legal to hoist the load above the first guard since the
; guard might control dereferenceability
define void @negative_load(i32 %V1, i32* %P) {
; CHECK-LABEL: @negative_load(
; CHECK-NEXT: [[A:%.*]] = icmp slt i32 [[V1:%.*]], 0
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[A]], i32 123) [ "deopt"() ]
; CHECK-NEXT: [[V2:%.*]] = load i32, i32* [[P:%.*]], align 4
; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[V2]], 0
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[B]], i32 456) [ "deopt"() ]
; CHECK-NEXT: ret void
;
%A = icmp slt i32 %V1, 0
call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
%V2 = load i32, i32* %P
%B = icmp slt i32 %V2, 0
call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
ret void
}
define void @deref_load(i32 %V1, i32* dereferenceable(4) align 4 %P) nofree nosync {
; CHECK-LABEL: @deref_load(
; CHECK-NEXT: [[V2:%.*]] = load i32, i32* [[P:%.*]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[V2]], [[V1:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 123) [ "deopt"() ]
; CHECK-NEXT: ret void
;
%A = icmp slt i32 %V1, 0
call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
%V2 = load i32, i32* %P
%B = icmp slt i32 %V2, 0
call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
ret void
}
; The divide might fault above the guard
define void @negative_div(i32 %V1, i32 %D) {
; CHECK-LABEL: @negative_div(
; CHECK-NEXT: [[A:%.*]] = icmp slt i32 [[V1:%.*]], 0
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[A]], i32 123) [ "deopt"() ]
; CHECK-NEXT: [[V2:%.*]] = udiv i32 [[V1]], [[D:%.*]]
; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[V2]], 0
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[B]], i32 456) [ "deopt"() ]
; CHECK-NEXT: ret void
;
%A = icmp slt i32 %V1, 0
call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
%V2 = udiv i32 %V1, %D
%B = icmp slt i32 %V2, 0
call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
ret void
}
; Highlight the limit of the window in a case which would otherwise be mergable
define void @negative_window(i32 %V1, i32 %a, i32 %b, i32 %c, i32 %d) {
; CHECK-LABEL: @negative_window(
; CHECK-NEXT: [[A:%.*]] = icmp slt i32 [[V1:%.*]], 0
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[A]], i32 123) [ "deopt"() ]
; CHECK-NEXT: [[V2:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[V3:%.*]] = add i32 [[V2]], [[C:%.*]]
; CHECK-NEXT: [[V4:%.*]] = add i32 [[V3]], [[D:%.*]]
; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[V4]], 0
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[B]], i32 456) [ "deopt"() ]
; CHECK-NEXT: ret void
;
%A = icmp slt i32 %V1, 0
call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
%V2 = add i32 %a, %b
%V3 = add i32 %V2, %c
%V4 = add i32 %V3, %d
%B = icmp slt i32 %V4, 0
call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
ret void
}
|