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 On the other hand, if constant folding is not run, it will never
evaluate to true, even in simple cases. 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 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. // 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">; 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 -------------------------===// //===-------------------------- Masked Intrinsics -------------------------===//
// //
def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, def int_masked_store : Intrinsic<[], [llvm_anyvector_ty,

View File

@ -6859,6 +6859,17 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
setValue(&I, Val); setValue(&I, Val);
return; 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
}