1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

Add ptrmask intrinsic

This patch adds a ptrmask intrinsic which allows masking out bits of a
pointer that must be zero when accessing it, because of ABI alignment
requirements or a restriction of the meaningful bits of a pointer
through the data layout.

This avoids doing a ptrtoint/inttoptr round trip in some cases (e.g. tagged
pointers) and allows us to not lose information about the underlying
object.

Reviewers: nlopes, efriedma, hfinkel, sanjoy, jdoerfert, aqjune

Reviewed by: sanjoy, jdoerfert

Differential Revision: https://reviews.llvm.org/D59065

llvm-svn: 368986
This commit is contained in:
Florian Hahn 2019-08-15 10:12:26 +00:00
parent 1d84e4592c
commit b1f95e7f28
5 changed files with 111 additions and 0 deletions

View File

@ -16895,6 +16895,42 @@ a constant.
On the other hand, if constant folding is not run, it will never
evaluate to true, even in simple cases.
.. _int_ptrmask:
'``llvm.ptrmask``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
::
declare ptrty llvm.ptrmask(ptrty %ptr, intty %mask) readnone speculatable
Arguments:
""""""""""
The first argument is a pointer. The second argument is an integer.
Overview:
""""""""""
The ``llvm.ptrmask`` intrinsic masks out bits of the pointer according to a mask.
This allows stripping data from tagged pointers without converting them to an
integer (ptrtoint/inttoptr). As a consequence, we can preserve more information
to facilitate alias analysis and underlying-object detection.
Semantics:
""""""""""
The result of ``ptrmask(ptr, mask)`` is equivalent to
``getelementptr ptr, (ptrtoint(ptr) & mask) - ptrtoint(ptr)``. Both the returned
pointer and the first argument are based on the same underlying object (for more
information on the *based on* terminology see
:ref:`the pointer aliasing rules <pointeraliasing>`). If the bitwidth of the
mask argument does not match the pointer size of the target, the mask is
zero-extended or truncated accordingly.
Stack Map Intrinsics
--------------------

View File

@ -1059,6 +1059,10 @@ def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
// Intrinsic to detect whether its argument is a constant.
def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem, IntrWillReturn], "llvm.is.constant">;
// Intrinsic to mask out bits of a pointer.
def int_ptrmask: Intrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty, llvm_anyint_ty],
[IntrNoMem, IntrSpeculatable, IntrWillReturn]>;
//===-------------------------- Masked Intrinsics -------------------------===//
//
def int_masked_store : Intrinsic<[], [llvm_anyvector_ty,

View File

@ -6859,6 +6859,17 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
setValue(&I, Val);
return;
}
case Intrinsic::ptrmask: {
SDValue Ptr = getValue(I.getOperand(0));
SDValue Const = getValue(I.getOperand(1));
EVT DestVT =
EVT(DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout()));
setValue(&I, DAG.getNode(ISD::AND, getCurSDLoc(), DestVT, Ptr,
DAG.getZExtOrTrunc(Const, getCurSDLoc(), DestVT)));
return;
}
}
}

View File

@ -0,0 +1,29 @@
; RUN: llc -mtriple=arm64-apple-iphoneos -stop-after=finalize-isel %s -o - | FileCheck %s
declare i8* @llvm.ptrmask.p0i8.i64(i8* , i64)
; CHECK-LABEL: name: test1
; CHECK: %0:gpr64 = COPY $x0
; CHECK-NEXT: %1:gpr64sp = ANDXri %0, 8052
; CHECK-NEXT: $x0 = COPY %1
; CHECK-NEXT: RET_ReallyLR implicit $x0
define i8* @test1(i8* %src) {
%ptr = call i8* @llvm.ptrmask.p0i8.i64(i8* %src, i64 72057594037927928)
ret i8* %ptr
}
declare i8* @llvm.ptrmask.p0i8.i32(i8*, i32)
; CHECK-LABEL: name: test2
; CHECK: %0:gpr64 = COPY $x0
; CHECK-NEXT: %1:gpr32 = MOVi32imm 10000
; CHECK-NEXT: %2:gpr64 = SUBREG_TO_REG 0, killed %1, %subreg.sub_32
; CHECK-NEXT: %3:gpr64 = ANDXrr %0, killed %2
; CHECK-NEXT: $x0 = COPY %3
; CHECK-NEXT: RET_ReallyLR implicit $x0
define i8* @test2(i8* %src) {
%ptr = call i8* @llvm.ptrmask.p0i8.i32(i8* %src, i32 10000)
ret i8* %ptr
}

View File

@ -0,0 +1,31 @@
; RUN: llc -mtriple=x86_64-apple-macosx -stop-after=finalize-isel %s -o - | FileCheck %s
declare i8* @llvm.ptrmask.p0i8.i64(i8* , i64)
; CHECK-LABEL: name: test1
; CHECK: %0:gr64 = COPY $rdi
; CHECK-NEXT: %1:gr64 = MOV64ri 72057594037927928
; CHECK-NEXT: %2:gr64 = AND64rr %0, killed %1, implicit-def dead $eflags
; CHECK-NEXT: $rax = COPY %2
; CHECK-NEXT: RET 0, $rax
define i8* @test1(i8* %src) {
%ptr = call i8* @llvm.ptrmask.p0i8.i64(i8* %src, i64 72057594037927928)
ret i8* %ptr
}
declare i8* @llvm.ptrmask.p0i8.i32(i8*, i32)
; CHECK-LABEL: name: test2
; CHECK: %0:gr64 = COPY $rdi
; CHECK-NEXT: %1:gr32 = COPY %0.sub_32bit
; CHECK-NEXT: %2:gr32 = AND32ri %1, 10000, implicit-def dead $eflags
; CHECK-NEXT: %3:gr64 = SUBREG_TO_REG 0, killed %2, %subreg.sub_32bit
; CHECK-NEXT: $rax = COPY %3
; CHECK-NEXT: RET 0, $rax
define i8* @test2(i8* %src) {
%ptr = call i8* @llvm.ptrmask.p0i8.i32(i8* %src, i32 10000)
ret i8* %ptr
}