[PATCH] D61607: Introduce an option to stripPointerCasts to force the same bit pattern

Johannes Doerfert via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon May 6 12:50:37 PDT 2019


jdoerfert created this revision.
jdoerfert added reviewers: hfinkel, arsenm, reames.
Herald added subscribers: bollu, hiraditya, wdng.
Herald added a project: LLVM.

This patch allows users of Value::stripPointerCasts() to force the
result of the function to be bit-equal to the value it was called on.
This is useful in various cases, e.g., (non-)null checks.

The new option has a default value so we do not change the current
behavior. We can flip the default value around later to prioritize
correctness over performance.

In this patch only a single call site was adjusted to fix an existing
misuse (which is hard to test).

For a discussion on this topic, please see [0].

[0] http://lists.llvm.org/pipermail/llvm-dev/2018-December/128423.html


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D61607

Files:
  llvm/include/llvm/IR/Value.h
  llvm/lib/Analysis/LazyValueInfo.cpp
  llvm/lib/IR/Value.cpp


Index: llvm/lib/IR/Value.cpp
===================================================================
--- llvm/lib/IR/Value.cpp
+++ llvm/lib/IR/Value.cpp
@@ -466,10 +466,24 @@
 };
 
 template <PointerStripKind StripKind>
-static const Value *stripPointerCastsAndOffsets(const Value *V) {
+static const Value *stripPointerCastsAndOffsets(const Value *V,
+                                                bool KeepBitPattern = false) {
   if (!V->getType()->isPointerTy())
     return V;
 
+  // Sanity check, no-op in non-assert builds and for ZeroIndice StripKinds.
+  switch (StripKind) {
+  case PSK_ZeroIndicesAndAliases:
+  case PSK_ZeroIndicesAndAliasesAndInvariantGroups:
+  case PSK_ZeroIndices:
+    // For these kinds it makes sense to force keeping the bit pattern.
+    break;
+  default:
+    assert(!KeepBitPattern &&
+           "Cannot keep the bit pattern and strip GEP indices!");
+    break;
+  }
+
   // Even though we don't look through PHI nodes, we could be called on an
   // instruction in an unreachable block, which may be on a cycle.
   SmallPtrSet<const Value *, 4> Visited;
@@ -494,7 +508,9 @@
         break;
       }
       V = GEP->getPointerOperand();
-    } else if (Operator::getOpcode(V) == Instruction::BitCast ||
+    } else if (Operator::getOpcode(V) == Instruction::BitCast) {
+      V = cast<Operator>(V)->getOperand(0);
+    } else if (!KeepBitPattern &&
                Operator::getOpcode(V) == Instruction::AddrSpaceCast) {
       V = cast<Operator>(V)->getOperand(0);
     } else if (auto *GA = dyn_cast<GlobalAlias>(V)) {
@@ -526,8 +542,9 @@
 }
 } // end anonymous namespace
 
-const Value *Value::stripPointerCasts() const {
-  return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliases>(this);
+const Value *Value::stripPointerCasts(bool KeepBitPattern) const {
+  return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliases>(this,
+                                                                KeepBitPattern);
 }
 
 const Value *Value::stripPointerCastsNoFollowAliases() const {
Index: llvm/lib/Analysis/LazyValueInfo.cpp
===================================================================
--- llvm/lib/Analysis/LazyValueInfo.cpp
+++ llvm/lib/Analysis/LazyValueInfo.cpp
@@ -1739,7 +1739,7 @@
   // through would still be correct.
   const DataLayout &DL = CxtI->getModule()->getDataLayout();
   if (V->getType()->isPointerTy() && C->isNullValue() &&
-      isKnownNonZero(V->stripPointerCasts(), DL)) {
+      isKnownNonZero(V->stripPointerCasts(/* KeepBitPattern */ true), DL)) {
     if (Pred == ICmpInst::ICMP_EQ)
       return LazyValueInfo::False;
     else if (Pred == ICmpInst::ICMP_NE)
Index: llvm/include/llvm/IR/Value.h
===================================================================
--- llvm/include/llvm/IR/Value.h
+++ llvm/include/llvm/IR/Value.h
@@ -493,12 +493,15 @@
   /// swifterror attribute.
   bool isSwiftError() const;
 
-  /// Strip off pointer casts, all-zero GEPs, and aliases.
+  /// Strip off pointer casts, all-zero GEPs, address space casts, and aliases.
+  ///
+  /// \param KeepBitPattern If set, the bit pattern of the result is guaranteed
+  ///                       to be equal to the bit pattern of this value.
   ///
   /// Returns the original uncasted value.  If this is called on a non-pointer
   /// value, it returns 'this'.
-  const Value *stripPointerCasts() const;
-  Value *stripPointerCasts() {
+  const Value *stripPointerCasts(bool KeepBitPattern = false) const;
+  Value *stripPointerCasts(bool KeepBitPattern = false) {
     return const_cast<Value *>(
                          static_cast<const Value *>(this)->stripPointerCasts());
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D61607.198326.patch
Type: text/x-patch
Size: 3645 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190506/f123ee5d/attachment.bin>


More information about the llvm-commits mailing list