Skip to content

Commit 624b2e4

Browse files
committed
[Intrinsics] Add @llvm.dereferenceable intrinsic.
This patch adds a @llvm.dereferenceable intrinsic that can be used to mark pointers as dereferenceable at the point the intrinsic is called. The semantics match the meaning of the dereferenceable function argument attribute. The goal of the intrinsic is the preserve dereferenceability information after moving memory instructions. This allows us to vectorize cases such as https://clang.godbolt.org/z/Y1bedbhs3, where we currently fail due to instcombine sinking the load into then/else blocks. Alternatively we could use an assume bundle with a dereferenceable attribute. But as a follow-up I would like to allow non-immediate size arguments, and this may not mesh well with the attribute.
1 parent 811f2a6 commit 624b2e4

File tree

5 files changed

+71
-0
lines changed

5 files changed

+71
-0
lines changed

llvm/docs/LangRef.rst

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29153,6 +29153,45 @@ attach various forms of information to operands that dominate specific
2915329153
uses. It is not meant for general use, only for building temporary
2915429154
renaming forms that require value splits at certain points.
2915529155

29156+
.. _int_dereferenceable:
29157+
29158+
'``llvm.dereferenceable``' Intrinsic
29159+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29160+
29161+
Syntax:
29162+
"""""""
29163+
29164+
::
29165+
29166+
declare void @llvm.dereferenceable(ptr %p, i64 <size>)
29167+
29168+
Overview:
29169+
"""""""""
29170+
29171+
The ``llvm.dereferenceable`` allows the optimizer to assume that the returned
29172+
pointer is dereferenceable at the point the intrinsic is called.
29173+
29174+
Arguments:
29175+
""""""""""
29176+
29177+
The arguments of the call are the pointer which will be marked as
29178+
dereferenceable and the number of bytes known to be dereferenceable. ``<size>``
29179+
must be a constant.
29180+
29181+
Semantics:
29182+
""""""""""
29183+
29184+
The intrinsic returns the input pointer. The returned pointer is dereferenceable
29185+
at the point the intrinsic is called. A pointer that is dereferenceable can be
29186+
loaded from speculatively without a risk of trapping. This implies that the
29187+
input pointer is not null and neither undef or poison. The number of bytes known
29188+
to be dereferenceable is provided as second argument. It is legal for the number
29189+
of bytes to be less than the size of the pointee type.
29190+
29191+
The semantics above match the semantics of the ``dereferenceable(<n>)``
29192+
parameter attribute.
29193+
29194+
2915629195
.. _type.test:
2915729196

2915829197
'``llvm.type.test``' Intrinsic

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,10 @@ def int_call_preallocated_teardown : DefaultAttrsIntrinsic<[], [llvm_token_ty]>;
954954
def int_callbr_landingpad : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>],
955955
[IntrNoMerge]>;
956956

957+
// Attach dereferenceability information to a pointer.
958+
def int_dereferenceable: DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty],
959+
[IntrInaccessibleMemOnly, ImmArg<ArgIndex<1>>]>;
960+
957961
//===------------------- Standard C Library Intrinsics --------------------===//
958962
//
959963

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8293,6 +8293,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
82938293
visitVectorExtractLastActive(I, Intrinsic);
82948294
return;
82958295
}
8296+
case Intrinsic::dereferenceable:
8297+
setValue(&I, getValue(I.getArgOperand(0)));
8298+
return;
82968299
}
82978300
}
82988301

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=arm64-apple-macosx -o - %s | FileCheck %s
3+
4+
declare ptr @llvm.dereferenceable(ptr, i64 immarg)
5+
6+
define i64 @foo(ptr %a) {
7+
; CHECK-LABEL: foo:
8+
; CHECK: ; %bb.0:
9+
; CHECK-NEXT: ldr x0, [x0]
10+
; CHECK-NEXT: ret
11+
%d = call ptr @llvm.dereferenceable(ptr %a, i64 4)
12+
%l = load i64, ptr %d
13+
ret i64 %l
14+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
2+
3+
declare ptr @llvm.dereferenceable(ptr, i64 immarg)
4+
5+
define void @transpose(ptr %p, i64 %x) {
6+
; CHECK: immarg operand has non-immediate parameter
7+
%d.0 = call ptr @llvm.dereferenceable(ptr %p, i64 4)
8+
%d.1 = call ptr @llvm.dereferenceable(ptr %p, i64 %x)
9+
ret void
10+
}
11+

0 commit comments

Comments
 (0)