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:
parent
1d84e4592c
commit
b1f95e7f28
@ -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
|
||||
--------------------
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
29
test/CodeGen/AArch64/lower-ptrmask.ll
Normal file
29
test/CodeGen/AArch64/lower-ptrmask.ll
Normal 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
|
||||
}
|
31
test/CodeGen/X86/lower-ptrmask.ll
Normal file
31
test/CodeGen/X86/lower-ptrmask.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user