aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ConstantFolding.cpp
diff options
context:
space:
mode:
authorArthur Eubanks <aeubanks@google.com>2021-04-22 12:04:14 -0700
committerArthur Eubanks <aeubanks@google.com>2021-05-27 16:04:19 -0700
commit8086f9d87ee81aacf829bdad94744a75cf692ebc (patch)
treefa4085f9d4c627ed99d62d7b1cd8cc1a8786e867 /llvm/lib/Analysis/ConstantFolding.cpp
parent0fa5aac292b8e1bafb00b55233c78466b06bc323 (diff)
downloadllvm-8086f9d87ee81aacf829bdad94744a75cf692ebc.zip
llvm-8086f9d87ee81aacf829bdad94744a75cf692ebc.tar.gz
llvm-8086f9d87ee81aacf829bdad94744a75cf692ebc.tar.bz2
[ConstFold] Simplify a load's GEP operand through local aliases
MSVC-style RTTI produces loads through a GEP of a local alias which itself is a GEP. Currently we aren't able to devirtualize any virtual calls when MSVC RTTI is enabled. This patch attempts to simplify a load's GEP operand by calling SymbolicallyEvaluateGEP() with an option to look through local aliases. Differential Revision: https://reviews.llvm.org/D101100
Diffstat (limited to 'llvm/lib/Analysis/ConstantFolding.cpp')
-rw-r--r--llvm/lib/Analysis/ConstantFolding.cpp52
1 files changed, 47 insertions, 5 deletions
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 7d4fcdc..989379d 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -63,6 +63,11 @@
using namespace llvm;
namespace {
+Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
+ ArrayRef<Constant *> Ops,
+ const DataLayout &DL,
+ const TargetLibraryInfo *TLI,
+ bool ForLoadOperand);
//===----------------------------------------------------------------------===//
// Constant Folding internal helper functions
@@ -690,6 +695,33 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty,
GV->getInitializer(), CE, Ty, DL))
return V;
}
+ } else {
+ // Try to simplify GEP if the pointer operand wasn't a GlobalVariable.
+ // SymbolicallyEvaluateGEP() with `ForLoadOperand = true` can potentially
+ // simplify the GEP more than it normally would have been, but should only
+ // be used for const folding loads.
+ SmallVector<Constant *> Ops;
+ for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)
+ Ops.push_back(cast<Constant>(CE->getOperand(I)));
+ if (auto *Simplified = dyn_cast_or_null<ConstantExpr>(
+ SymbolicallyEvaluateGEP(cast<GEPOperator>(CE), Ops, DL, nullptr,
+ /*ForLoadOperand*/ true))) {
+ // If the symbolically evaluated GEP is another GEP, we can only const
+ // fold it if the resulting pointer operand is a GlobalValue. Otherwise
+ // there is nothing else to simplify since the GEP is already in the
+ // most simplified form.
+ if (auto *SimplifiedGEP = dyn_cast<GEPOperator>(Simplified)) {
+ if (auto *GV = dyn_cast<GlobalVariable>(Simplified->getOperand(0))) {
+ if (GV->isConstant() && GV->hasDefinitiveInitializer()) {
+ if (Constant *V = ConstantFoldLoadThroughGEPConstantExpr(
+ GV->getInitializer(), Simplified, Ty, DL))
+ return V;
+ }
+ }
+ } else {
+ return ConstantFoldLoadFromConstPtr(Simplified, Ty, DL);
+ }
+ }
}
}
@@ -835,10 +867,18 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops,
}
/// Strip the pointer casts, but preserve the address space information.
-Constant *StripPtrCastKeepAS(Constant *Ptr, Type *&ElemTy) {
+Constant *StripPtrCastKeepAS(Constant *Ptr, Type *&ElemTy,
+ bool ForLoadOperand) {
assert(Ptr->getType()->isPointerTy() && "Not a pointer type");
auto *OldPtrTy = cast<PointerType>(Ptr->getType());
Ptr = cast<Constant>(Ptr->stripPointerCasts());
+ if (ForLoadOperand) {
+ while (isa<GlobalAlias>(Ptr) && !cast<GlobalAlias>(Ptr)->isInterposable() &&
+ !cast<GlobalAlias>(Ptr)->getBaseObject()->isInterposable()) {
+ Ptr = cast<GlobalAlias>(Ptr)->getAliasee();
+ }
+ }
+
auto *NewPtrTy = cast<PointerType>(Ptr->getType());
ElemTy = NewPtrTy->getPointerElementType();
@@ -855,7 +895,8 @@ Constant *StripPtrCastKeepAS(Constant *Ptr, Type *&ElemTy) {
Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
ArrayRef<Constant *> Ops,
const DataLayout &DL,
- const TargetLibraryInfo *TLI) {
+ const TargetLibraryInfo *TLI,
+ bool ForLoadOperand) {
const GEPOperator *InnermostGEP = GEP;
bool InBounds = GEP->isInBounds();
@@ -903,7 +944,7 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
DL.getIndexedOffsetInType(
SrcElemTy,
makeArrayRef((Value * const *)Ops.data() + 1, Ops.size() - 1)));
- Ptr = StripPtrCastKeepAS(Ptr, SrcElemTy);
+ Ptr = StripPtrCastKeepAS(Ptr, SrcElemTy, ForLoadOperand);
// If this is a GEP of a GEP, fold it all into a single GEP.
while (auto *GEP = dyn_cast<GEPOperator>(Ptr)) {
@@ -925,7 +966,7 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
Ptr = cast<Constant>(GEP->getOperand(0));
SrcElemTy = GEP->getSourceElementType();
Offset += APInt(BitWidth, DL.getIndexedOffsetInType(SrcElemTy, NestedOps));
- Ptr = StripPtrCastKeepAS(Ptr, SrcElemTy);
+ Ptr = StripPtrCastKeepAS(Ptr, SrcElemTy, ForLoadOperand);
}
// If the base value for this address is a literal integer value, fold the
@@ -1062,7 +1103,8 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode,
return ConstantFoldCastOperand(Opcode, Ops[0], DestTy, DL);
if (auto *GEP = dyn_cast<GEPOperator>(InstOrCE)) {
- if (Constant *C = SymbolicallyEvaluateGEP(GEP, Ops, DL, TLI))
+ if (Constant *C = SymbolicallyEvaluateGEP(GEP, Ops, DL, TLI,
+ /*ForLoadOperand*/ false))
return C;
return ConstantExpr::getGetElementPtr(GEP->getSourceElementType(), Ops[0],