|
| 1 | +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --force-update |
| 2 | +;; Check folds for CHERI intrinsics that have both get and set variants |
| 3 | +; RUN: sed 's/FIELD/address/' %s | opt -S -passes=instsimplify | FileCheck %s --check-prefixes=ADDRESS |
| 4 | +; RUN: sed 's/FIELD/flags/' %s | opt -S -passes=instsimplify | FileCheck %s --check-prefixes=FLAGS |
| 5 | +; RUN: sed 's/FIELD/high/' %s | opt -S -passes=instsimplify | FileCheck %s --check-prefixes=HIGH |
| 6 | +; RUN: sed 's/FIELD/offset/' %s | opt -S -passes=instsimplify | FileCheck %s --check-prefixes=OFFSET |
| 7 | +target datalayout = "pf200:128:128:128:64-A200-P200-G200" |
| 8 | + |
| 9 | +declare i64 @check_fold(i64) nounwind |
| 10 | +declare i64 @llvm.cheri.cap.FIELD.get.i64(ptr addrspace(200)) nounwind |
| 11 | +declare ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200), i64) nounwind |
| 12 | + |
| 13 | + |
| 14 | +;; This is a no-op and should be folded to ret %arg |
| 15 | +define ptr addrspace(200) @fold_set_of_get(ptr addrspace(200) %arg) nounwind { |
| 16 | +; ADDRESS-LABEL: define {{[^@]+}}@fold_set_of_get |
| 17 | +; ADDRESS-SAME: (ptr addrspace(200) [[ARG:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] { |
| 18 | +; ADDRESS-NEXT: ret ptr addrspace(200) [[ARG]] |
| 19 | +; |
| 20 | +; FLAGS-LABEL: define {{[^@]+}}@fold_set_of_get |
| 21 | +; FLAGS-SAME: (ptr addrspace(200) [[ARG:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] { |
| 22 | +; FLAGS-NEXT: [[VALUE:%.*]] = tail call i64 @llvm.cheri.cap.flags.get.i64(ptr addrspace(200) [[ARG]]) |
| 23 | +; FLAGS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.flags.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 24 | +; FLAGS-NEXT: ret ptr addrspace(200) [[RET]] |
| 25 | +; |
| 26 | +; HIGH-LABEL: define {{[^@]+}}@fold_set_of_get |
| 27 | +; HIGH-SAME: (ptr addrspace(200) [[ARG:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] { |
| 28 | +; HIGH-NEXT: [[VALUE:%.*]] = tail call i64 @llvm.cheri.cap.high.get.i64(ptr addrspace(200) [[ARG]]) |
| 29 | +; HIGH-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 30 | +; HIGH-NEXT: ret ptr addrspace(200) [[RET]] |
| 31 | +; |
| 32 | +; OFFSET-LABEL: define {{[^@]+}}@fold_set_of_get |
| 33 | +; OFFSET-SAME: (ptr addrspace(200) [[ARG:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] { |
| 34 | +; OFFSET-NEXT: ret ptr addrspace(200) [[ARG]] |
| 35 | +; |
| 36 | + %value = tail call i64 @llvm.cheri.cap.FIELD.get.i64(ptr addrspace(200) %arg) |
| 37 | + %ret = tail call ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200) %arg, i64 %value) |
| 38 | + ret ptr addrspace(200) %ret |
| 39 | +} |
| 40 | + |
| 41 | +;; negative test - get of a different value should not be folded to ret %arg |
| 42 | +define ptr addrspace(200) @fold_set_of_get_bad(ptr addrspace(200) %arg, ptr addrspace(200) %other) nounwind { |
| 43 | +; ADDRESS-LABEL: define {{[^@]+}}@fold_set_of_get_bad |
| 44 | +; ADDRESS-SAME: (ptr addrspace(200) [[ARG:%.*]], ptr addrspace(200) [[OTHER:%.*]]) addrspace(200) #[[ATTR0]] { |
| 45 | +; ADDRESS-NEXT: [[VALUE:%.*]] = tail call i64 @llvm.cheri.cap.address.get.i64(ptr addrspace(200) [[OTHER]]) |
| 46 | +; ADDRESS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.address.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 47 | +; ADDRESS-NEXT: ret ptr addrspace(200) [[RET]] |
| 48 | +; |
| 49 | +; FLAGS-LABEL: define {{[^@]+}}@fold_set_of_get_bad |
| 50 | +; FLAGS-SAME: (ptr addrspace(200) [[ARG:%.*]], ptr addrspace(200) [[OTHER:%.*]]) addrspace(200) #[[ATTR0]] { |
| 51 | +; FLAGS-NEXT: [[VALUE:%.*]] = tail call i64 @llvm.cheri.cap.flags.get.i64(ptr addrspace(200) [[OTHER]]) |
| 52 | +; FLAGS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.flags.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 53 | +; FLAGS-NEXT: ret ptr addrspace(200) [[RET]] |
| 54 | +; |
| 55 | +; HIGH-LABEL: define {{[^@]+}}@fold_set_of_get_bad |
| 56 | +; HIGH-SAME: (ptr addrspace(200) [[ARG:%.*]], ptr addrspace(200) [[OTHER:%.*]]) addrspace(200) #[[ATTR0]] { |
| 57 | +; HIGH-NEXT: [[VALUE:%.*]] = tail call i64 @llvm.cheri.cap.high.get.i64(ptr addrspace(200) [[OTHER]]) |
| 58 | +; HIGH-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 59 | +; HIGH-NEXT: ret ptr addrspace(200) [[RET]] |
| 60 | +; |
| 61 | +; OFFSET-LABEL: define {{[^@]+}}@fold_set_of_get_bad |
| 62 | +; OFFSET-SAME: (ptr addrspace(200) [[ARG:%.*]], ptr addrspace(200) [[OTHER:%.*]]) addrspace(200) #[[ATTR0]] { |
| 63 | +; OFFSET-NEXT: [[VALUE:%.*]] = tail call i64 @llvm.cheri.cap.offset.get.i64(ptr addrspace(200) [[OTHER]]) |
| 64 | +; OFFSET-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.offset.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 65 | +; OFFSET-NEXT: ret ptr addrspace(200) [[RET]] |
| 66 | +; |
| 67 | + %value = tail call i64 @llvm.cheri.cap.FIELD.get.i64(ptr addrspace(200) %other) |
| 68 | + %ret = tail call ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200) %arg, i64 %value) |
| 69 | + ret ptr addrspace(200) %ret |
| 70 | +} |
| 71 | + |
| 72 | +;; For almost all intrinsics this get-of-set pair can be elided |
| 73 | +;; NB: This is not true for flags where the value written by set could be truncated to another value |
| 74 | +;; FIXME: high.get should be folded. |
| 75 | +define i64 @fold_get_of_set(ptr addrspace(200) %arg, i64 %value) nounwind { |
| 76 | +; ADDRESS-LABEL: define {{[^@]+}}@fold_get_of_set |
| 77 | +; ADDRESS-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 78 | +; ADDRESS-NEXT: ret i64 [[VALUE]] |
| 79 | +; |
| 80 | +; FLAGS-LABEL: define {{[^@]+}}@fold_get_of_set |
| 81 | +; FLAGS-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 82 | +; FLAGS-NEXT: [[MODIFIED:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.flags.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 83 | +; FLAGS-NEXT: [[RET:%.*]] = tail call i64 @llvm.cheri.cap.flags.get.i64(ptr addrspace(200) [[MODIFIED]]) |
| 84 | +; FLAGS-NEXT: ret i64 [[RET]] |
| 85 | +; |
| 86 | +; HIGH-LABEL: define {{[^@]+}}@fold_get_of_set |
| 87 | +; HIGH-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 88 | +; HIGH-NEXT: [[MODIFIED:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 89 | +; HIGH-NEXT: [[RET:%.*]] = tail call i64 @llvm.cheri.cap.high.get.i64(ptr addrspace(200) [[MODIFIED]]) |
| 90 | +; HIGH-NEXT: ret i64 [[RET]] |
| 91 | +; |
| 92 | +; OFFSET-LABEL: define {{[^@]+}}@fold_get_of_set |
| 93 | +; OFFSET-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 94 | +; OFFSET-NEXT: ret i64 [[VALUE]] |
| 95 | +; |
| 96 | + %modified = tail call ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200) %arg, i64 %value) |
| 97 | + %ret = tail call i64 @llvm.cheri.cap.FIELD.get.i64(ptr addrspace(200) %modified) |
| 98 | + ret i64 %ret |
| 99 | +} |
| 100 | + |
| 101 | +;; Negative test -- get is used on other intrinsic |
| 102 | +define i64 @fold_get_of_set_bad(ptr addrspace(200) %arg, ptr addrspace(200) %other, i64 %value) nounwind { |
| 103 | +; ADDRESS-LABEL: define {{[^@]+}}@fold_get_of_set_bad |
| 104 | +; ADDRESS-SAME: (ptr addrspace(200) [[ARG:%.*]], ptr addrspace(200) [[OTHER:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 105 | +; ADDRESS-NEXT: [[RET:%.*]] = tail call i64 @llvm.cheri.cap.address.get.i64(ptr addrspace(200) [[ARG]]) |
| 106 | +; ADDRESS-NEXT: ret i64 [[RET]] |
| 107 | +; |
| 108 | +; FLAGS-LABEL: define {{[^@]+}}@fold_get_of_set_bad |
| 109 | +; FLAGS-SAME: (ptr addrspace(200) [[ARG:%.*]], ptr addrspace(200) [[OTHER:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 110 | +; FLAGS-NEXT: [[RET:%.*]] = tail call i64 @llvm.cheri.cap.flags.get.i64(ptr addrspace(200) [[ARG]]) |
| 111 | +; FLAGS-NEXT: ret i64 [[RET]] |
| 112 | +; |
| 113 | +; HIGH-LABEL: define {{[^@]+}}@fold_get_of_set_bad |
| 114 | +; HIGH-SAME: (ptr addrspace(200) [[ARG:%.*]], ptr addrspace(200) [[OTHER:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 115 | +; HIGH-NEXT: [[RET:%.*]] = tail call i64 @llvm.cheri.cap.high.get.i64(ptr addrspace(200) [[ARG]]) |
| 116 | +; HIGH-NEXT: ret i64 [[RET]] |
| 117 | +; |
| 118 | +; OFFSET-LABEL: define {{[^@]+}}@fold_get_of_set_bad |
| 119 | +; OFFSET-SAME: (ptr addrspace(200) [[ARG:%.*]], ptr addrspace(200) [[OTHER:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 120 | +; OFFSET-NEXT: [[RET:%.*]] = tail call i64 @llvm.cheri.cap.offset.get.i64(ptr addrspace(200) [[ARG]]) |
| 121 | +; OFFSET-NEXT: ret i64 [[RET]] |
| 122 | +; |
| 123 | + %modified = tail call ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200) %other, i64 %value) |
| 124 | + %ret = tail call i64 @llvm.cheri.cap.FIELD.get.i64(ptr addrspace(200) %arg) |
| 125 | + ret i64 %ret |
| 126 | +} |
| 127 | + |
| 128 | +define i64 @fold_get_on_null() nounwind { |
| 129 | +; ADDRESS-LABEL: define {{[^@]+}}@fold_get_on_null |
| 130 | +; ADDRESS-SAME: () addrspace(200) #[[ATTR0]] { |
| 131 | +; ADDRESS-NEXT: ret i64 0 |
| 132 | +; |
| 133 | +; FLAGS-LABEL: define {{[^@]+}}@fold_get_on_null |
| 134 | +; FLAGS-SAME: () addrspace(200) #[[ATTR0]] { |
| 135 | +; FLAGS-NEXT: ret i64 0 |
| 136 | +; |
| 137 | +; HIGH-LABEL: define {{[^@]+}}@fold_get_on_null |
| 138 | +; HIGH-SAME: () addrspace(200) #[[ATTR0]] { |
| 139 | +; HIGH-NEXT: [[RET:%.*]] = tail call i64 @llvm.cheri.cap.high.get.i64(ptr addrspace(200) null) |
| 140 | +; HIGH-NEXT: ret i64 [[RET]] |
| 141 | +; |
| 142 | +; OFFSET-LABEL: define {{[^@]+}}@fold_get_on_null |
| 143 | +; OFFSET-SAME: () addrspace(200) #[[ATTR0]] { |
| 144 | +; OFFSET-NEXT: ret i64 0 |
| 145 | +; |
| 146 | + %ret = tail call i64 @llvm.cheri.cap.FIELD.get.i64(ptr addrspace(200) null) |
| 147 | + ret i64 %ret |
| 148 | +} |
| 149 | + |
| 150 | +define i64 @fold_get_on_null_with_gep(i64 %value, i64 %gepoff) nounwind { |
| 151 | +; ADDRESS-LABEL: define {{[^@]+}}@fold_get_on_null_with_gep |
| 152 | +; ADDRESS-SAME: (i64 [[VALUE:%.*]], i64 [[GEPOFF:%.*]]) addrspace(200) #[[ATTR0]] { |
| 153 | +; ADDRESS-NEXT: ret i64 [[GEPOFF]] |
| 154 | +; |
| 155 | +; FLAGS-LABEL: define {{[^@]+}}@fold_get_on_null_with_gep |
| 156 | +; FLAGS-SAME: (i64 [[VALUE:%.*]], i64 [[GEPOFF:%.*]]) addrspace(200) #[[ATTR0]] { |
| 157 | +; FLAGS-NEXT: ret i64 0 |
| 158 | +; |
| 159 | +; HIGH-LABEL: define {{[^@]+}}@fold_get_on_null_with_gep |
| 160 | +; HIGH-SAME: (i64 [[VALUE:%.*]], i64 [[GEPOFF:%.*]]) addrspace(200) #[[ATTR0]] { |
| 161 | +; HIGH-NEXT: [[TMP:%.*]] = getelementptr i8, ptr addrspace(200) null, i64 [[GEPOFF]] |
| 162 | +; HIGH-NEXT: [[RET:%.*]] = tail call i64 @llvm.cheri.cap.high.get.i64(ptr addrspace(200) [[TMP]]) |
| 163 | +; HIGH-NEXT: ret i64 [[RET]] |
| 164 | +; |
| 165 | +; OFFSET-LABEL: define {{[^@]+}}@fold_get_on_null_with_gep |
| 166 | +; OFFSET-SAME: (i64 [[VALUE:%.*]], i64 [[GEPOFF:%.*]]) addrspace(200) #[[ATTR0]] { |
| 167 | +; OFFSET-NEXT: ret i64 [[GEPOFF]] |
| 168 | +; |
| 169 | + %tmp = getelementptr i8, ptr addrspace(200) null, i64 %gepoff |
| 170 | + %ret = tail call i64 @llvm.cheri.cap.FIELD.get.i64(ptr addrspace(200) %tmp) |
| 171 | + ret i64 %ret |
| 172 | +} |
| 173 | + |
| 174 | +;; TODO: Setting is idempotent, so the first call should be elided |
| 175 | +define ptr addrspace(200) @set_idempotent(ptr addrspace(200) %arg, i64 %value) nounwind { |
| 176 | +; ADDRESS-LABEL: define {{[^@]+}}@set_idempotent |
| 177 | +; ADDRESS-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 178 | +; ADDRESS-NEXT: [[MODIFIED:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.address.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 179 | +; ADDRESS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.address.set.i64(ptr addrspace(200) [[MODIFIED]], i64 [[VALUE]]) |
| 180 | +; ADDRESS-NEXT: ret ptr addrspace(200) [[RET]] |
| 181 | +; |
| 182 | +; FLAGS-LABEL: define {{[^@]+}}@set_idempotent |
| 183 | +; FLAGS-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 184 | +; FLAGS-NEXT: [[MODIFIED:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.flags.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 185 | +; FLAGS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.flags.set.i64(ptr addrspace(200) [[MODIFIED]], i64 [[VALUE]]) |
| 186 | +; FLAGS-NEXT: ret ptr addrspace(200) [[RET]] |
| 187 | +; |
| 188 | +; HIGH-LABEL: define {{[^@]+}}@set_idempotent |
| 189 | +; HIGH-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 190 | +; HIGH-NEXT: [[MODIFIED:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 191 | +; HIGH-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[MODIFIED]], i64 [[VALUE]]) |
| 192 | +; HIGH-NEXT: ret ptr addrspace(200) [[RET]] |
| 193 | +; |
| 194 | +; OFFSET-LABEL: define {{[^@]+}}@set_idempotent |
| 195 | +; OFFSET-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 196 | +; OFFSET-NEXT: [[MODIFIED:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.offset.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 197 | +; OFFSET-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.offset.set.i64(ptr addrspace(200) [[MODIFIED]], i64 [[VALUE]]) |
| 198 | +; OFFSET-NEXT: ret ptr addrspace(200) [[RET]] |
| 199 | +; |
| 200 | + %modified = tail call ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200) %arg, i64 %value) |
| 201 | + %ret = tail call ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200) %modified, i64 %value) |
| 202 | + ret ptr addrspace(200) %ret |
| 203 | +} |
| 204 | + |
| 205 | + |
| 206 | +;; Negative test - calls with the same base argument are not yet elided if the |
| 207 | +;; second argument is different since they could have side-effects such as |
| 208 | +;; clearing the tag. For example `setoffset(setoffset(x, <LARGE>), <SMALL>)` |
| 209 | +;; would result in an untagged value if the first setoffset went outside the |
| 210 | +;; representable range but that detagging would not happen if we elide it. |
| 211 | +;; TODO: Maybe we should do this fold since people should not be relying on |
| 212 | +;; representability to clear tags of capabilities. |
| 213 | +define ptr addrspace(200) @set_different_values(ptr addrspace(200) %arg, i64 %value, i64 %value2) nounwind { |
| 214 | +; ADDRESS-LABEL: define {{[^@]+}}@set_different_values |
| 215 | +; ADDRESS-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]], i64 [[VALUE2:%.*]]) addrspace(200) #[[ATTR0]] { |
| 216 | +; ADDRESS-NEXT: [[MODIFIED:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.address.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 217 | +; ADDRESS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.address.set.i64(ptr addrspace(200) [[MODIFIED]], i64 [[VALUE]]) |
| 218 | +; ADDRESS-NEXT: ret ptr addrspace(200) [[RET]] |
| 219 | +; |
| 220 | +; FLAGS-LABEL: define {{[^@]+}}@set_different_values |
| 221 | +; FLAGS-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]], i64 [[VALUE2:%.*]]) addrspace(200) #[[ATTR0]] { |
| 222 | +; FLAGS-NEXT: [[MODIFIED:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.flags.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 223 | +; FLAGS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.flags.set.i64(ptr addrspace(200) [[MODIFIED]], i64 [[VALUE]]) |
| 224 | +; FLAGS-NEXT: ret ptr addrspace(200) [[RET]] |
| 225 | +; |
| 226 | +; HIGH-LABEL: define {{[^@]+}}@set_different_values |
| 227 | +; HIGH-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]], i64 [[VALUE2:%.*]]) addrspace(200) #[[ATTR0]] { |
| 228 | +; HIGH-NEXT: [[MODIFIED:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 229 | +; HIGH-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[MODIFIED]], i64 [[VALUE]]) |
| 230 | +; HIGH-NEXT: ret ptr addrspace(200) [[RET]] |
| 231 | +; |
| 232 | +; OFFSET-LABEL: define {{[^@]+}}@set_different_values |
| 233 | +; OFFSET-SAME: (ptr addrspace(200) [[ARG:%.*]], i64 [[VALUE:%.*]], i64 [[VALUE2:%.*]]) addrspace(200) #[[ATTR0]] { |
| 234 | +; OFFSET-NEXT: [[MODIFIED:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.offset.set.i64(ptr addrspace(200) [[ARG]], i64 [[VALUE]]) |
| 235 | +; OFFSET-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.offset.set.i64(ptr addrspace(200) [[MODIFIED]], i64 [[VALUE]]) |
| 236 | +; OFFSET-NEXT: ret ptr addrspace(200) [[RET]] |
| 237 | +; |
| 238 | + %modified = tail call ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200) %arg, i64 %value) |
| 239 | + %ret = tail call ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200) %modified, i64 %value) |
| 240 | + ret ptr addrspace(200) %ret |
| 241 | +} |
| 242 | + |
| 243 | +define ptr addrspace(200) @fold_set_on_null(i64 %value) nounwind { |
| 244 | +; ADDRESS-LABEL: define {{[^@]+}}@fold_set_on_null |
| 245 | +; ADDRESS-SAME: (i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 246 | +; ADDRESS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.address.set.i64(ptr addrspace(200) null, i64 [[VALUE]]) |
| 247 | +; ADDRESS-NEXT: ret ptr addrspace(200) [[RET]] |
| 248 | +; |
| 249 | +; FLAGS-LABEL: define {{[^@]+}}@fold_set_on_null |
| 250 | +; FLAGS-SAME: (i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 251 | +; FLAGS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.flags.set.i64(ptr addrspace(200) null, i64 [[VALUE]]) |
| 252 | +; FLAGS-NEXT: ret ptr addrspace(200) [[RET]] |
| 253 | +; |
| 254 | +; HIGH-LABEL: define {{[^@]+}}@fold_set_on_null |
| 255 | +; HIGH-SAME: (i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 256 | +; HIGH-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) null, i64 [[VALUE]]) |
| 257 | +; HIGH-NEXT: ret ptr addrspace(200) [[RET]] |
| 258 | +; |
| 259 | +; OFFSET-LABEL: define {{[^@]+}}@fold_set_on_null |
| 260 | +; OFFSET-SAME: (i64 [[VALUE:%.*]]) addrspace(200) #[[ATTR0]] { |
| 261 | +; OFFSET-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.offset.set.i64(ptr addrspace(200) null, i64 [[VALUE]]) |
| 262 | +; OFFSET-NEXT: ret ptr addrspace(200) [[RET]] |
| 263 | +; |
| 264 | + %ret = tail call ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200) null, i64 %value) |
| 265 | + ret ptr addrspace(200) %ret |
| 266 | +} |
| 267 | + |
| 268 | +define ptr addrspace(200) @fold_set_on_null_with_gep(i64 %value, i64 %gepoff) nounwind { |
| 269 | +; ADDRESS-LABEL: define {{[^@]+}}@fold_set_on_null_with_gep |
| 270 | +; ADDRESS-SAME: (i64 [[VALUE:%.*]], i64 [[GEPOFF:%.*]]) addrspace(200) #[[ATTR0]] { |
| 271 | +; ADDRESS-NEXT: [[TMP:%.*]] = getelementptr i8, ptr addrspace(200) null, i64 [[GEPOFF]] |
| 272 | +; ADDRESS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.address.set.i64(ptr addrspace(200) [[TMP]], i64 [[VALUE]]) |
| 273 | +; ADDRESS-NEXT: ret ptr addrspace(200) [[RET]] |
| 274 | +; |
| 275 | +; FLAGS-LABEL: define {{[^@]+}}@fold_set_on_null_with_gep |
| 276 | +; FLAGS-SAME: (i64 [[VALUE:%.*]], i64 [[GEPOFF:%.*]]) addrspace(200) #[[ATTR0]] { |
| 277 | +; FLAGS-NEXT: [[TMP:%.*]] = getelementptr i8, ptr addrspace(200) null, i64 [[GEPOFF]] |
| 278 | +; FLAGS-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.flags.set.i64(ptr addrspace(200) [[TMP]], i64 [[VALUE]]) |
| 279 | +; FLAGS-NEXT: ret ptr addrspace(200) [[RET]] |
| 280 | +; |
| 281 | +; HIGH-LABEL: define {{[^@]+}}@fold_set_on_null_with_gep |
| 282 | +; HIGH-SAME: (i64 [[VALUE:%.*]], i64 [[GEPOFF:%.*]]) addrspace(200) #[[ATTR0]] { |
| 283 | +; HIGH-NEXT: [[TMP:%.*]] = getelementptr i8, ptr addrspace(200) null, i64 [[GEPOFF]] |
| 284 | +; HIGH-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[TMP]], i64 [[VALUE]]) |
| 285 | +; HIGH-NEXT: ret ptr addrspace(200) [[RET]] |
| 286 | +; |
| 287 | +; OFFSET-LABEL: define {{[^@]+}}@fold_set_on_null_with_gep |
| 288 | +; OFFSET-SAME: (i64 [[VALUE:%.*]], i64 [[GEPOFF:%.*]]) addrspace(200) #[[ATTR0]] { |
| 289 | +; OFFSET-NEXT: [[TMP:%.*]] = getelementptr i8, ptr addrspace(200) null, i64 [[GEPOFF]] |
| 290 | +; OFFSET-NEXT: [[RET:%.*]] = tail call ptr addrspace(200) @llvm.cheri.cap.offset.set.i64(ptr addrspace(200) [[TMP]], i64 [[VALUE]]) |
| 291 | +; OFFSET-NEXT: ret ptr addrspace(200) [[RET]] |
| 292 | +; |
| 293 | + %tmp = getelementptr i8, ptr addrspace(200) null, i64 %gepoff |
| 294 | + %ret = tail call ptr addrspace(200) @llvm.cheri.cap.FIELD.set.i64(ptr addrspace(200) %tmp, i64 %value) |
| 295 | + ret ptr addrspace(200) %ret |
| 296 | +} |
0 commit comments