Skip to content

Commit 7534495

Browse files
committed
Move isPointerOffset function to ValueTracking (NFC).
Summary: To be reused in MemTag sanitizer. Reviewers: pcc, vitalybuka, ostannard Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66165 llvm-svn: 369062
1 parent 0ffe687 commit 7534495

File tree

3 files changed

+91
-86
lines changed

3 files changed

+91
-86
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

+6
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,12 @@ class Value;
660660
Optional<bool> isImpliedByDomCondition(const Value *Cond,
661661
const Instruction *ContextI,
662662
const DataLayout &DL);
663+
664+
/// Return true if Ptr1 is provably equal to Ptr2 plus a constant offset, and
665+
/// return that constant offset. For example, Ptr1 might be &A[42], and Ptr2
666+
/// might be &A[40]. In this case offset would be -8.
667+
bool isPointerOffset(Value *Ptr1, Value *Ptr2, int64_t &Offset,
668+
const DataLayout &DL);
663669
} // end namespace llvm
664670

665671
#endif // LLVM_ANALYSIS_VALUETRACKING_H

llvm/lib/Analysis/ValueTracking.cpp

+83
Original file line numberDiff line numberDiff line change
@@ -5701,3 +5701,86 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo) {
57015701

57025702
return CR;
57035703
}
5704+
5705+
static int64_t getOffsetFromIndex(const GEPOperator *GEP, unsigned Idx,
5706+
bool &VariableIdxFound,
5707+
const DataLayout &DL) {
5708+
// Skip over the first indices.
5709+
gep_type_iterator GTI = gep_type_begin(GEP);
5710+
for (unsigned i = 1; i != Idx; ++i, ++GTI)
5711+
/*skip along*/;
5712+
5713+
// Compute the offset implied by the rest of the indices.
5714+
int64_t Offset = 0;
5715+
for (unsigned i = Idx, e = GEP->getNumOperands(); i != e; ++i, ++GTI) {
5716+
ConstantInt *OpC = dyn_cast<ConstantInt>(GEP->getOperand(i));
5717+
if (!OpC)
5718+
return VariableIdxFound = true;
5719+
if (OpC->isZero())
5720+
continue; // No offset.
5721+
5722+
// Handle struct indices, which add their field offset to the pointer.
5723+
if (StructType *STy = GTI.getStructTypeOrNull()) {
5724+
Offset += DL.getStructLayout(STy)->getElementOffset(OpC->getZExtValue());
5725+
continue;
5726+
}
5727+
5728+
// Otherwise, we have a sequential type like an array or vector. Multiply
5729+
// the index by the ElementSize.
5730+
uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType());
5731+
Offset += Size * OpC->getSExtValue();
5732+
}
5733+
5734+
return Offset;
5735+
}
5736+
5737+
bool llvm::isPointerOffset(Value *Ptr1, Value *Ptr2, int64_t &Offset,
5738+
const DataLayout &DL) {
5739+
Ptr1 = Ptr1->stripPointerCasts();
5740+
Ptr2 = Ptr2->stripPointerCasts();
5741+
5742+
// Handle the trivial case first.
5743+
if (Ptr1 == Ptr2) {
5744+
Offset = 0;
5745+
return true;
5746+
}
5747+
5748+
GEPOperator *GEP1 = dyn_cast<GEPOperator>(Ptr1);
5749+
GEPOperator *GEP2 = dyn_cast<GEPOperator>(Ptr2);
5750+
5751+
bool VariableIdxFound = false;
5752+
5753+
// If one pointer is a GEP and the other isn't, then see if the GEP is a
5754+
// constant offset from the base, as in "P" and "gep P, 1".
5755+
if (GEP1 && !GEP2 && GEP1->getOperand(0)->stripPointerCasts() == Ptr2) {
5756+
Offset = -getOffsetFromIndex(GEP1, 1, VariableIdxFound, DL);
5757+
return !VariableIdxFound;
5758+
}
5759+
5760+
if (GEP2 && !GEP1 && GEP2->getOperand(0)->stripPointerCasts() == Ptr1) {
5761+
Offset = getOffsetFromIndex(GEP2, 1, VariableIdxFound, DL);
5762+
return !VariableIdxFound;
5763+
}
5764+
5765+
// Right now we handle the case when Ptr1/Ptr2 are both GEPs with an identical
5766+
// base. After that base, they may have some number of common (and
5767+
// potentially variable) indices. After that they handle some constant
5768+
// offset, which determines their offset from each other. At this point, we
5769+
// handle no other case.
5770+
if (!GEP1 || !GEP2 || GEP1->getOperand(0) != GEP2->getOperand(0))
5771+
return false;
5772+
5773+
// Skip any common indices and track the GEP types.
5774+
unsigned Idx = 1;
5775+
for (; Idx != GEP1->getNumOperands() && Idx != GEP2->getNumOperands(); ++Idx)
5776+
if (GEP1->getOperand(Idx) != GEP2->getOperand(Idx))
5777+
break;
5778+
5779+
int64_t Offset1 = getOffsetFromIndex(GEP1, Idx, VariableIdxFound, DL);
5780+
int64_t Offset2 = getOffsetFromIndex(GEP2, Idx, VariableIdxFound, DL);
5781+
if (VariableIdxFound)
5782+
return false;
5783+
5784+
Offset = Offset2 - Offset1;
5785+
return true;
5786+
}

llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp

+2-86
Original file line numberDiff line numberDiff line change
@@ -69,90 +69,6 @@ STATISTIC(NumMemSetInfer, "Number of memsets inferred");
6969
STATISTIC(NumMoveToCpy, "Number of memmoves converted to memcpy");
7070
STATISTIC(NumCpyToSet, "Number of memcpys converted to memset");
7171

72-
static int64_t GetOffsetFromIndex(const GEPOperator *GEP, unsigned Idx,
73-
bool &VariableIdxFound,
74-
const DataLayout &DL) {
75-
// Skip over the first indices.
76-
gep_type_iterator GTI = gep_type_begin(GEP);
77-
for (unsigned i = 1; i != Idx; ++i, ++GTI)
78-
/*skip along*/;
79-
80-
// Compute the offset implied by the rest of the indices.
81-
int64_t Offset = 0;
82-
for (unsigned i = Idx, e = GEP->getNumOperands(); i != e; ++i, ++GTI) {
83-
ConstantInt *OpC = dyn_cast<ConstantInt>(GEP->getOperand(i));
84-
if (!OpC)
85-
return VariableIdxFound = true;
86-
if (OpC->isZero()) continue; // No offset.
87-
88-
// Handle struct indices, which add their field offset to the pointer.
89-
if (StructType *STy = GTI.getStructTypeOrNull()) {
90-
Offset += DL.getStructLayout(STy)->getElementOffset(OpC->getZExtValue());
91-
continue;
92-
}
93-
94-
// Otherwise, we have a sequential type like an array or vector. Multiply
95-
// the index by the ElementSize.
96-
uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType());
97-
Offset += Size*OpC->getSExtValue();
98-
}
99-
100-
return Offset;
101-
}
102-
103-
/// Return true if Ptr1 is provably equal to Ptr2 plus a constant offset, and
104-
/// return that constant offset. For example, Ptr1 might be &A[42], and Ptr2
105-
/// might be &A[40]. In this case offset would be -8.
106-
static bool IsPointerOffset(Value *Ptr1, Value *Ptr2, int64_t &Offset,
107-
const DataLayout &DL) {
108-
Ptr1 = Ptr1->stripPointerCasts();
109-
Ptr2 = Ptr2->stripPointerCasts();
110-
111-
// Handle the trivial case first.
112-
if (Ptr1 == Ptr2) {
113-
Offset = 0;
114-
return true;
115-
}
116-
117-
GEPOperator *GEP1 = dyn_cast<GEPOperator>(Ptr1);
118-
GEPOperator *GEP2 = dyn_cast<GEPOperator>(Ptr2);
119-
120-
bool VariableIdxFound = false;
121-
122-
// If one pointer is a GEP and the other isn't, then see if the GEP is a
123-
// constant offset from the base, as in "P" and "gep P, 1".
124-
if (GEP1 && !GEP2 && GEP1->getOperand(0)->stripPointerCasts() == Ptr2) {
125-
Offset = -GetOffsetFromIndex(GEP1, 1, VariableIdxFound, DL);
126-
return !VariableIdxFound;
127-
}
128-
129-
if (GEP2 && !GEP1 && GEP2->getOperand(0)->stripPointerCasts() == Ptr1) {
130-
Offset = GetOffsetFromIndex(GEP2, 1, VariableIdxFound, DL);
131-
return !VariableIdxFound;
132-
}
133-
134-
// Right now we handle the case when Ptr1/Ptr2 are both GEPs with an identical
135-
// base. After that base, they may have some number of common (and
136-
// potentially variable) indices. After that they handle some constant
137-
// offset, which determines their offset from each other. At this point, we
138-
// handle no other case.
139-
if (!GEP1 || !GEP2 || GEP1->getOperand(0) != GEP2->getOperand(0))
140-
return false;
141-
142-
// Skip any common indices and track the GEP types.
143-
unsigned Idx = 1;
144-
for (; Idx != GEP1->getNumOperands() && Idx != GEP2->getNumOperands(); ++Idx)
145-
if (GEP1->getOperand(Idx) != GEP2->getOperand(Idx))
146-
break;
147-
148-
int64_t Offset1 = GetOffsetFromIndex(GEP1, Idx, VariableIdxFound, DL);
149-
int64_t Offset2 = GetOffsetFromIndex(GEP2, Idx, VariableIdxFound, DL);
150-
if (VariableIdxFound) return false;
151-
152-
Offset = Offset2-Offset1;
153-
return true;
154-
}
155-
15672
namespace {
15773

15874
/// Represents a range of memset'd bytes with the ByteVal value.
@@ -420,7 +336,7 @@ Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,
420336

421337
// Check to see if this store is to a constant offset from the start ptr.
422338
int64_t Offset;
423-
if (!IsPointerOffset(StartPtr, NextStore->getPointerOperand(), Offset,
339+
if (!isPointerOffset(StartPtr, NextStore->getPointerOperand(), Offset,
424340
DL))
425341
break;
426342

@@ -434,7 +350,7 @@ Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,
434350

435351
// Check to see if this store is to a constant offset from the start ptr.
436352
int64_t Offset;
437-
if (!IsPointerOffset(StartPtr, MSI->getDest(), Offset, DL))
353+
if (!isPointerOffset(StartPtr, MSI->getDest(), Offset, DL))
438354
break;
439355

440356
Ranges.addMemSet(Offset, MSI);

0 commit comments

Comments
 (0)