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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes='gvn' -basic-aa-separate-storage -S | FileCheck %s
declare void @llvm.assume(i1)
; Test basic queries.
define i8 @simple_no(ptr %p1, ptr %p2) {
; CHECK-LABEL: @simple_no(
; CHECK-NEXT: entry:
; CHECK-NEXT: store i8 0, ptr [[P1:%.*]], align 1
; CHECK-NEXT: store i8 1, ptr [[P2:%.*]], align 1
; CHECK-NEXT: [[LOADOFSTORE:%.*]] = load i8, ptr [[P1]], align 1
; CHECK-NEXT: ret i8 [[LOADOFSTORE]]
;
entry:
store i8 0, ptr %p1
store i8 1, ptr %p2
%loadofstore = load i8, ptr %p1
ret i8 %loadofstore
}
define i8 @simple_yes(ptr %p1, ptr %p2) {
; CHECK-LABEL: @simple_yes(
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[P1:%.*]], ptr [[P2:%.*]]) ]
; CHECK-NEXT: store i8 0, ptr [[P1]], align 1
; CHECK-NEXT: store i8 1, ptr [[P2]], align 1
; CHECK-NEXT: ret i8 0
;
entry:
call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %p2)]
store i8 0, ptr %p1
store i8 1, ptr %p2
%loadofstore = load i8, ptr %p1
ret i8 %loadofstore
}
define i8 @ptr_to_ptr_no(ptr %pp) {
; CHECK-LABEL: @ptr_to_ptr_no(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[P_BASE:%.*]] = load ptr, ptr [[PP:%.*]], align 8
; CHECK-NEXT: store i8 0, ptr [[P_BASE]], align 1
; CHECK-NEXT: [[P_BASE2:%.*]] = load ptr, ptr [[PP]], align 8
; CHECK-NEXT: [[LOADOFSTORE:%.*]] = load i8, ptr [[P_BASE2]], align 1
; CHECK-NEXT: ret i8 [[LOADOFSTORE]]
;
entry:
%p_base = load ptr, ptr %pp
store i8 0, ptr %p_base
%p_base2 = load ptr, ptr %pp
%loadofstore = load i8, ptr %p_base2
ret i8 %loadofstore
}
define i8 @ptr_to_ptr_yes(ptr %pp) {
; CHECK-LABEL: @ptr_to_ptr_yes(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[P_BASE:%.*]] = load ptr, ptr [[PP:%.*]], align 8
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[P_BASE]], ptr [[PP]]) ]
; CHECK-NEXT: store i8 0, ptr [[P_BASE]], align 1
; CHECK-NEXT: ret i8 0
;
entry:
%p_base = load ptr, ptr %pp
call void @llvm.assume(i1 1) ["separate_storage"(ptr %p_base, ptr %pp)]
store i8 0, ptr %p_base
%p_base2 = load ptr, ptr %pp
%loadofstore = load i8, ptr %p_base2
ret i8 %loadofstore
}
; The analysis should only kick in if executed (or will be executed) at the
; given program point.
define i8 @flow_sensitive(ptr %p1, ptr %p2, i1 %cond) {
; CHECK-LABEL: @flow_sensitive(
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[COND:%.*]], label [[TRUE_BRANCH:%.*]], label [[FALSE_BRANCH:%.*]]
; CHECK: true_branch:
; CHECK-NEXT: store i8 11, ptr [[P1:%.*]], align 1
; CHECK-NEXT: store i8 22, ptr [[P2:%.*]], align 1
; CHECK-NEXT: [[LOADOFSTORE_TRUE:%.*]] = load i8, ptr [[P1]], align 1
; CHECK-NEXT: br label [[ENDIF:%.*]]
; CHECK: false_branch:
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[P1]], ptr [[P2]]) ]
; CHECK-NEXT: store i8 33, ptr [[P1]], align 1
; CHECK-NEXT: store i8 44, ptr [[P2]], align 1
; CHECK-NEXT: br label [[ENDIF]]
; CHECK: endif:
; CHECK-NEXT: [[LOADOFSTORE:%.*]] = phi i8 [ [[LOADOFSTORE_TRUE]], [[TRUE_BRANCH]] ], [ 33, [[FALSE_BRANCH]] ]
; CHECK-NEXT: ret i8 [[LOADOFSTORE]]
;
entry:
br i1 %cond, label %true_branch, label %false_branch
true_branch:
store i8 11, ptr %p1
store i8 22, ptr %p2
%loadofstore_true = load i8, ptr %p1
br label %endif
false_branch:
call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %p2)]
store i8 33, ptr %p1
store i8 44, ptr %p2
%loadofstore_false = load i8, ptr %p1
br label %endif
endif:
%loadofstore = phi i8 [ %loadofstore_true, %true_branch ], [ %loadofstore_false, %false_branch ]
ret i8 %loadofstore
}
define i8 @flow_sensitive_with_dominator(ptr %p1, ptr %p2, i1 %cond) {
; CHECK-LABEL: @flow_sensitive_with_dominator(
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[P1:%.*]], ptr [[P2:%.*]]) ]
; CHECK-NEXT: br i1 [[COND:%.*]], label [[TRUE_BRANCH:%.*]], label [[FALSE_BRANCH:%.*]]
; CHECK: true_branch:
; CHECK-NEXT: store i8 11, ptr [[P1]], align 1
; CHECK-NEXT: store i8 22, ptr [[P2]], align 1
; CHECK-NEXT: br label [[ENDIF:%.*]]
; CHECK: false_branch:
; CHECK-NEXT: store i8 33, ptr [[P1]], align 1
; CHECK-NEXT: store i8 44, ptr [[P2]], align 1
; CHECK-NEXT: br label [[ENDIF]]
; CHECK: endif:
; CHECK-NEXT: [[LOADOFSTORE:%.*]] = phi i8 [ 11, [[TRUE_BRANCH]] ], [ 33, [[FALSE_BRANCH]] ]
; CHECK-NEXT: ret i8 [[LOADOFSTORE]]
;
entry:
call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %p2)]
br i1 %cond, label %true_branch, label %false_branch
true_branch:
store i8 11, ptr %p1
store i8 22, ptr %p2
%loadofstore_true = load i8, ptr %p1
br label %endif
false_branch:
store i8 33, ptr %p1
store i8 44, ptr %p2
%loadofstore_false = load i8, ptr %p1
br label %endif
endif:
%loadofstore = phi i8 [ %loadofstore_true, %true_branch ], [ %loadofstore_false, %false_branch ]
ret i8 %loadofstore
}
; Hints are relative to entire regions of storage, not particular pointers
; inside them. We should know that the whole ranges are disjoint given hints at
; offsets.
define i8 @offset_agnostic(ptr %p1, ptr %p2) {
; CHECK-LABEL: @offset_agnostic(
; CHECK-NEXT: [[ACCESS1:%.*]] = getelementptr inbounds i8, ptr [[P1:%.*]], i64 12
; CHECK-NEXT: [[ACCESS2:%.*]] = getelementptr inbounds i8, ptr [[P2:%.*]], i64 34
; CHECK-NEXT: [[HINT1:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 56
; CHECK-NEXT: [[HINT2:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 78
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[HINT1]], ptr [[HINT2]]) ]
; CHECK-NEXT: store i8 0, ptr [[ACCESS1]], align 1
; CHECK-NEXT: store i8 1, ptr [[ACCESS2]], align 1
; CHECK-NEXT: ret i8 0
;
%access1 = getelementptr inbounds i8, ptr %p1, i64 12
%access2 = getelementptr inbounds i8, ptr %p2, i64 34
%hint1 = getelementptr inbounds i8, ptr %p1, i64 56
%hint2 = getelementptr inbounds i8, ptr %p2, i64 78
call void @llvm.assume(i1 1) ["separate_storage"(ptr %hint1, ptr %hint2)]
store i8 0, ptr %access1
store i8 1, ptr %access2
%loadofstore = load i8, ptr %access1
ret i8 %loadofstore
}
|