[llvm] 8086f9d - [ConstFold] Simplify a load's GEP operand through local aliases
Arthur Eubanks via llvm-commits
llvm-commits at lists.llvm.org
Thu May 27 16:04:42 PDT 2021
Author: Arthur Eubanks
Date: 2021-05-27T16:04:19-07:00
New Revision: 8086f9d87ee81aacf829bdad94744a75cf692ebc
URL: https://github.com/llvm/llvm-project/commit/8086f9d87ee81aacf829bdad94744a75cf692ebc
DIFF: https://github.com/llvm/llvm-project/commit/8086f9d87ee81aacf829bdad94744a75cf692ebc.diff
LOG: [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
Added:
llvm/test/Transforms/InstSimplify/ConstProp/gep-alias-gep-load.ll
Modified:
llvm/lib/Analysis/ConstantFolding.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 7d4fcdc456fec..989379d22c615 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],
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/gep-alias-gep-load.ll b/llvm/test/Transforms/InstSimplify/ConstProp/gep-alias-gep-load.ll
new file mode 100644
index 0000000000000..703f242739e6d
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/gep-alias-gep-load.ll
@@ -0,0 +1,35 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=instsimplify -S < %s | FileCheck %s
+
+ at a1 = internal alias i32, getelementptr ({[3 x i32]}, {[3 x i32]}* @b, i32 0, i32 0, i32 1)
+ at a2 = weak alias i32, getelementptr ({[3 x i32]}, {[3 x i32]}* @b, i32 0, i32 0, i32 1)
+ at b = internal constant {[3 x i32]} {[3 x i32] [i32 2, i32 3, i32 4]}
+
+ at c = internal alias i32, getelementptr ({[3 x i32]}, {[3 x i32]}* @d, i32 0, i32 0, i32 1)
+ at d = weak constant {[3 x i32]} {[3 x i32] [i32 2, i32 3, i32 4]}
+
+define i32 @f() {
+; CHECK-LABEL: @f(
+; CHECK-NEXT: ret i32 4
+;
+ %a = load i32, i32* getelementptr (i32, i32* @a1, i64 1)
+ ret i32 %a
+}
+
+define i32 @g() {
+; CHECK-LABEL: @g(
+; CHECK-NEXT: [[A:%.*]] = load i32, i32* getelementptr (i32, i32* @a2, i64 1), align 4
+; CHECK-NEXT: ret i32 [[A]]
+;
+ %a = load i32, i32* getelementptr (i32, i32* @a2, i64 1)
+ ret i32 %a
+}
+
+define i32 @h() {
+; CHECK-LABEL: @h(
+; CHECK-NEXT: [[A:%.*]] = load i32, i32* getelementptr (i32, i32* @c, i64 1), align 4
+; CHECK-NEXT: ret i32 [[A]]
+;
+ %a = load i32, i32* getelementptr (i32, i32* @c, i64 1)
+ ret i32 %a
+}
More information about the llvm-commits
mailing list