diff options
author | John Brawn <john.brawn@arm.com> | 2017-11-24 14:10:45 +0000 |
---|---|---|
committer | John Brawn <john.brawn@arm.com> | 2017-11-24 14:10:45 +0000 |
commit | 70cdb5b3914803ca89a96a867a47936d049a4b32 (patch) | |
tree | 41ed4c542765843f1e4ca8864af8b42a937cea24 /llvm/lib/CodeGen/CodeGenPrepare.cpp | |
parent | 590f0793e8c7f25a7d993031436928823cd2c95a (diff) | |
download | bcm5719-llvm-70cdb5b3914803ca89a96a867a47936d049a4b32.tar.gz bcm5719-llvm-70cdb5b3914803ca89a96a867a47936d049a4b32.zip |
[CGP] Make optimizeMemoryInst able to combine more kinds of ExtAddrMode fields
This patch extends the recent work in optimizeMemoryInst to make it able to
combine more ExtAddrMode fields than just the BaseReg.
This fixes some benchmark regressions introduced by r309397, where GVN PRE is
hoisting a getelementptr such that it can no longer be combined into the
addressing mode of the load or store that uses it.
Differential Revision: https://reviews.llvm.org/D38133
llvm-svn: 318949
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenPrepare.cpp')
-rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 106 |
1 files changed, 94 insertions, 12 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index e60e1e2d294..cacabba5f26 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -202,6 +202,22 @@ static cl::opt<bool> AddrSinkNewSelects("addr-sink-new-select", cl::Hidden, cl::init(false), cl::desc("Allow creation of selects in Address sinking.")); +static cl::opt<bool> AddrSinkCombineBaseReg( + "addr-sink-combine-base-reg", cl::Hidden, cl::init(true), + cl::desc("Allow combining of BaseReg field in Address sinking.")); + +static cl::opt<bool> AddrSinkCombineBaseGV( + "addr-sink-combine-base-gv", cl::Hidden, cl::init(true), + cl::desc("Allow combining of BaseGV field in Address sinking.")); + +static cl::opt<bool> AddrSinkCombineBaseOffs( + "addr-sink-combine-base-offs", cl::Hidden, cl::init(true), + cl::desc("Allow combining of BaseOffs field in Address sinking.")); + +static cl::opt<bool> AddrSinkCombineScaledReg( + "addr-sink-combine-scaled-reg", cl::Hidden, cl::init(true), + cl::desc("Allow combining of ScaledReg field in Address sinking.")); + namespace { using SetOfInstrs = SmallPtrSet<Instruction *, 16>; @@ -2073,6 +2089,59 @@ struct ExtAddrMode : public TargetLowering::AddrMode { return false; } + + Value *GetFieldAsValue(FieldName Field, Type *IntPtrTy) { + switch (Field) { + default: + return nullptr; + case BaseRegField: + return BaseReg; + case BaseGVField: + return BaseGV; + case ScaledRegField: + return ScaledReg; + case BaseOffsField: + return ConstantInt::get(IntPtrTy, BaseOffs); + } + } + + void SetCombinedField(FieldName Field, Value *V, + const SmallVectorImpl<ExtAddrMode> &AddrModes) { + switch (Field) { + default: + llvm_unreachable("Unhandled fields are expected to be rejected earlier"); + break; + case ExtAddrMode::BaseRegField: + BaseReg = V; + break; + case ExtAddrMode::BaseGVField: + // A combined BaseGV is an Instruction, not a GlobalValue, so it goes + // in the BaseReg field. + assert(BaseReg == nullptr); + BaseReg = V; + BaseGV = nullptr; + break; + case ExtAddrMode::ScaledRegField: + ScaledReg = V; + // If we have a mix of scaled and unscaled addrmodes then we want scale + // to be the scale and not zero. + if (!Scale) + for (const ExtAddrMode &AM : AddrModes) + if (AM.Scale) { + Scale = AM.Scale; + break; + } + break; + case ExtAddrMode::BaseOffsField: + // The offset is no longer a constant, so it goes in ScaledReg with a + // scale of 1. + assert(ScaledReg == nullptr); + ScaledReg = V; + Scale = 1; + BaseOffs = 0; + break; + } + } }; } // end anonymous namespace @@ -2800,12 +2869,14 @@ public: else if (DifferentField != ThisDifferentField) DifferentField = ExtAddrMode::MultipleFields; - // If NewAddrMode differs in only one dimension then we can handle it by + // If NewAddrMode differs in only one dimension, and that dimension isn't + // the amount that ScaledReg is scaled by, then we can handle it by // inserting a phi/select later on. Even if NewAddMode is the same // we still need to collect it due to original value is different. // And later we will need all original values as anchors during // finding the common Phi node. - if (DifferentField != ExtAddrMode::MultipleFields) { + if (DifferentField != ExtAddrMode::MultipleFields && + DifferentField != ExtAddrMode::ScaleField) { AddrModes.emplace_back(NewAddrMode); return true; } @@ -2833,12 +2904,7 @@ public: if (AllAddrModesTrivial) return false; - if (DisableComplexAddrModes) - return false; - - // For now we support only different base registers. - // TODO: enable others. - if (DifferentField != ExtAddrMode::BaseRegField) + if (!addrModeCombiningAllowed()) return false; // Build a map between <original value, basic block where we saw it> to @@ -2848,7 +2914,7 @@ public: Value *CommonValue = findCommon(Map); if (CommonValue) - AddrModes[0].BaseReg = CommonValue; + AddrModes[0].SetCombinedField(DifferentField, CommonValue, AddrModes); return CommonValue != nullptr; } @@ -2862,14 +2928,13 @@ private: // Keep track of keys where the value is null. We will need to replace it // with constant null when we know the common type. SmallVector<ValueInBB, 2> NullValue; + Type *IntPtrTy = SQ.DL.getIntPtrType(AddrModes[0].OriginalValue->getType()); for (auto &AM : AddrModes) { BasicBlock *BB = nullptr; if (Instruction *I = dyn_cast<Instruction>(AM.OriginalValue)) BB = I->getParent(); - // For now we support only base register as different field. - // TODO: Enable others. - Value *DV = AM.BaseReg; + Value *DV = AM.GetFieldAsValue(DifferentField, IntPtrTy); if (DV) { if (CommonType) assert(CommonType == DV->getType() && "Different types detected!"); @@ -3182,6 +3247,23 @@ private: } } } + + bool addrModeCombiningAllowed() { + if (DisableComplexAddrModes) + return false; + switch (DifferentField) { + default: + return false; + case ExtAddrMode::BaseRegField: + return AddrSinkCombineBaseReg; + case ExtAddrMode::BaseGVField: + return AddrSinkCombineBaseGV; + case ExtAddrMode::BaseOffsField: + return AddrSinkCombineBaseOffs; + case ExtAddrMode::ScaledRegField: + return AddrSinkCombineScaledReg; + } + } }; } // end anonymous namespace |