diff options
| author | Eli Friedman <efriedma@codeaurora.org> | 2018-09-28 20:27:31 +0000 |
|---|---|---|
| committer | Eli Friedman <efriedma@codeaurora.org> | 2018-09-28 20:27:31 +0000 |
| commit | 5ab09a684fd8759bac3cc824bb4550b0e5d7f4b8 (patch) | |
| tree | e133f4a45df8c997819a53e79a34f3f2c4bcf4ca /llvm/lib | |
| parent | 6f11db137034b38dbe2aabfa823ac0f2a7e3f9b9 (diff) | |
| download | bcm5719-llvm-5ab09a684fd8759bac3cc824bb4550b0e5d7f4b8.tar.gz bcm5719-llvm-5ab09a684fd8759bac3cc824bb4550b0e5d7f4b8.zip | |
[ARM] Fix correctness checks in promoteToConstantPool.
Correctly check for relocations in the constant to promote. And don't
allow promoting a constant multiple times.
This partially fixes https://bugs.llvm.org//show_bug.cgi?id=32780 ;
it's not a complete fix because we also need to prevent
ARMConstantIslands from cloning the constant.
(-arm-promote-constant is currently off by default, and it stays off
with this patch. I'll look into turning it on again when all the known
issues are fixed.)
Differential Revision: https://reviews.llvm.org/D51472
llvm-svn: 343361
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.cpp | 61 |
1 files changed, 15 insertions, 46 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 15b64ef1173..bfff368a8fe 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -3072,41 +3072,8 @@ static bool allUsersAreInFunction(const Value *V, const Function *F) { return true; } -/// Return true if all users of V are within some (any) function, looking through -/// ConstantExprs. In other words, are there any global constant users? -static bool allUsersAreInFunctions(const Value *V) { - SmallVector<const User*,4> Worklist; - for (auto *U : V->users()) - Worklist.push_back(U); - while (!Worklist.empty()) { - auto *U = Worklist.pop_back_val(); - if (isa<ConstantExpr>(U)) { - for (auto *UU : U->users()) - Worklist.push_back(UU); - continue; - } - - if (!isa<Instruction>(U)) - return false; - } - return true; -} - -// Return true if T is an integer, float or an array/vector of either. -static bool isSimpleType(Type *T) { - if (T->isIntegerTy() || T->isFloatingPointTy()) - return true; - Type *SubT = nullptr; - if (T->isArrayTy()) - SubT = T->getArrayElementType(); - else if (T->isVectorTy()) - SubT = T->getVectorElementType(); - else - return false; - return SubT->isIntegerTy() || SubT->isFloatingPointTy(); -} - -static SDValue promoteToConstantPool(const GlobalValue *GV, SelectionDAG &DAG, +static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, + const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl) { // If we're creating a pool entry for a constant global with unnamed address, // and the global is small enough, we can emit it inline into the constant pool @@ -3133,11 +3100,11 @@ static SDValue promoteToConstantPool(const GlobalValue *GV, SelectionDAG &DAG, !GVar->hasLocalLinkage()) return SDValue(); - // Ensure that we don't try and inline any type that contains pointers. If - // we inline a value that contains relocations, we move the relocations from - // .data to .text which is not ideal. + // If we inline a value that contains relocations, we move the relocations + // from .data to .text. This is not allowed in position-independent code. auto *Init = GVar->getInitializer(); - if (!isSimpleType(Init->getType())) + if ((TLI->isPositionIndependent() || TLI->getSubtarget()->isROPI()) && + Init->needsRelocation()) return SDValue(); // The constant islands pass can only really deal with alignment requests @@ -3169,12 +3136,14 @@ static SDValue promoteToConstantPool(const GlobalValue *GV, SelectionDAG &DAG, ConstpoolPromotionMaxTotal) return SDValue(); - // This is only valid if all users are in a single function OR it has users - // in multiple functions but it no larger than a pointer. We also check if - // GVar has constant (non-ConstantExpr) users. If so, it essentially has its - // address taken. - if (!allUsersAreInFunction(GVar, &F) && - !(Size <= 4 && allUsersAreInFunctions(GVar))) + // This is only valid if all users are in a single function; we can't clone + // the constant in general. The LLVM IR unnamed_addr allows merging + // constants, but not cloning them. + // + // We could potentially allow cloning if we could prove all uses of the + // constant in the current function don't care about the address, like + // printf format strings. But that isn't implemented for now. + if (!allUsersAreInFunction(GVar, &F)) return SDValue(); // We're going to inline this global. Pad it out if needed. @@ -3230,7 +3199,7 @@ SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op, // promoteToConstantPool only if not generating XO text section if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV) && !Subtarget->genExecuteOnly()) - if (SDValue V = promoteToConstantPool(GV, DAG, PtrVT, dl)) + if (SDValue V = promoteToConstantPool(this, GV, DAG, PtrVT, dl)) return V; if (isPositionIndependent()) { |

