소스 검색

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368986 91177308-0d34-0410-b5e6-96231b3b80d8
Florian Hahn 6 년 전
부모
커밋
913636c883
5개의 변경된 파일111개의 추가작업 그리고 0개의 파일을 삭제
  1. 36 0
      docs/LangRef.rst
  2. 4 0
      include/llvm/IR/Intrinsics.td
  3. 11 0
      lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  4. 29 0
      test/CodeGen/AArch64/lower-ptrmask.ll
  5. 31 0
      test/CodeGen/X86/lower-ptrmask.ll

+ 36 - 0
docs/LangRef.rst

@@ -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
 --------------------
 --------------------
 
 

+ 4 - 0
include/llvm/IR/Intrinsics.td

@@ -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,

+ 11 - 0
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

@@ -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;
+  }
   }
   }
 }
 }
 
 

+ 29 - 0
test/CodeGen/AArch64/lower-ptrmask.ll

@@ -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 - 0
test/CodeGen/X86/lower-ptrmask.ll

@@ -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
+}