Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Debug the newly generalised partial load code; passes all existing tests

  • Loading branch information...
commit 960ca52074baadc88aa4ccac3d77c3bb025c6188 1 parent 70a299c
@smowton authored
View
56 llvm/include/llvm/Analysis/HypotheticalConstantFolder.h
@@ -105,6 +105,26 @@ struct PartialVal {
};
+#define PVNull PartialVal()
+
+inline bool operator==(PartialVal V1, PartialVal V2) {
+ if(V1.type == PVInvalid && V2.type == PVInvalid)
+ return true;
+ else if(V1.type == PVTotal && V2.type == PVTotal)
+ return V1.TotalVC == V2.TotalVC;
+ else if(V1.type == PVPartial && V2.type == PVPartial)
+ return ((V1.FirstDef == V2.FirstDef) &&
+ (V1.FirstNotDef == V2.FirstNotDef) &&
+ (V1.C == V2.C) &&
+ (V1.ReadOffset == V2.ReadOffset));
+
+ return false;
+}
+
+inline bool operator!=(PartialVal V1, PartialVal V2) {
+ return !(V1 == V2);
+}
+
enum SymSubclasses {
SThunk,
@@ -231,6 +251,7 @@ class HCFParentCallbacks {
virtual bool isResolvedVFSCall(const Instruction*) = 0;
virtual AliasAnalysis* getAA() = 0;
virtual void queueLoopExpansionBlockedLoad(Instruction*, IntegrationAttempt*, LoadInst*) = 0;
+ virtual bool hasParent() = 0;
};
@@ -345,6 +366,8 @@ class IntegrationAttempt : public HCFParentCallbacks {
bool shouldForwardValue(ValCtx);
virtual ValCtx getUltimateUnderlyingObject(Value*);
+
+ virtual bool hasParent();
// Pure virtuals to be implemented by PeelIteration or InlineAttempt:
@@ -452,26 +475,35 @@ class IntegrationAttempt : public HCFParentCallbacks {
ValCtx handleTotalDefn(LoadForwardAttempt&, ValCtx);
ValCtx handleTotalDefn(LoadForwardAttempt&, Constant*);
- int AnalyzeLoadFromClobberingWrite(LoadForwardAttempt&,
+ bool AnalyzeLoadFromClobberingWrite(LoadForwardAttempt&,
Value *WritePtr, HCFParentCallbacks* WriteCtx,
uint64_t WriteSizeInBits,
- uint64_t* FirstDef = 0, uint64_t* FirstNotDef = 0);
+ uint64_t& FirstDef,
+ uint64_t& FirstNotDef,
+ uint64_t& ReadOffset);
- int AnalyzeLoadFromClobberingWrite(LoadForwardAttempt&,
- ValCtx StoreBase, int64_t StoreOffset,
+ bool AnalyzeLoadFromClobberingWrite(LoadForwardAttempt&,
+ ValCtx StoreBase, uint64_t StoreOffset,
uint64_t WriteSizeInBits,
- uint64_t* FirstDef = 0, uint64_t* FirstNotDef = 0);
+ uint64_t& FirstDef,
+ uint64_t& FirstNotDef,
+ uint64_t& ReadOffset);
- int AnalyzeLoadFromClobberingStore(LoadForwardAttempt&, StoreInst *DepSI, HCFParentCallbacks* DepSICtx,
- uint64_t* FirstDef = 0, uint64_t* FirstNotDef = 0);
- int AnalyzeLoadFromClobberingMemInst(LoadForwardAttempt&, MemIntrinsic *MI, HCFParentCallbacks* MICtx,
- uint64_t* FirstDef = 0, uint64_t* FirstNotDef = 0);
+ bool AnalyzeLoadFromClobberingStore(LoadForwardAttempt&, StoreInst *DepSI, HCFParentCallbacks* DepSICtx,
+ uint64_t& FirstDef,
+ uint64_t& FirstNotDef,
+ uint64_t& ReadOffset);
+
+ bool AnalyzeLoadFromClobberingMemInst(LoadForwardAttempt&, MemIntrinsic *MI, HCFParentCallbacks* MICtx,
+ uint64_t& FirstDef,
+ uint64_t& FirstNotDef,
+ uint64_t& ReadOffset);
Constant* offsetConstantInt(Constant* SourceC, int64_t Offset, const Type* targetTy);
ValCtx GetBaseWithConstantOffset(Value *Ptr, HCFParentCallbacks* PtrCtx, int64_t &Offset);
bool CanCoerceMustAliasedValueToLoad(Value *StoredVal, const Type *LoadTy);
Constant* CoerceConstExprToLoadType(Constant *StoredVal, const Type *LoadedTy);
- ValCtx tryResolveClobber(LoadForwardAttempt& LFA, ValCtx Clobber);
+ PartialVal tryResolveClobber(LoadForwardAttempt& LFA, ValCtx Clobber);
// Stat collection and printing:
@@ -693,8 +725,8 @@ class LoadForwardAttempt : public LFAQueryable {
bool isComplete();
ValCtx getResult();
- Constant* extractAggregateMemberAt(Constant* From, uint64_t Offset, const Type* Target);
- Constant* constFromBytes(char*, const Type*);
+ Constant* extractAggregateMemberAt(Constant* From, uint64_t Offset, const Type* Target, uint64_t TargetSize);
+ Constant* constFromBytes(unsigned char*, const Type*);
uint64_t markPaddingBytes(bool*, const Type*);
LoadForwardAttempt(LoadInst* _LI, IntegrationAttempt* C, TargetData*, const Type* T = 0);
View
92 llvm/lib/Analysis/Integrator/LoopPeelHeuristics.cpp
@@ -660,6 +660,12 @@ Instruction* PeelIteration::getEntryInstruction() {
}
+bool IntegrationAttempt::hasParent() {
+
+ return (parent != 0);
+
+}
+
ValCtx InlineAttempt::getImprovedCallArgument(Argument* A) {
return parent->getReplacement(CI->getArgOperand(A->getArgNo()));
@@ -843,7 +849,6 @@ ValCtx IntegrationAttempt::tryForwardLoad(LoadForwardAttempt& LFA, Instruction*
ValCtx IntegrationAttempt::getForwardedValue(LoadForwardAttempt& LFA, MemDepResult Res) {
LoadInst* LoadI = LFA.getOriginalInst();
- const Type* targetType = LFA.getTargetTy();
IntegrationAttempt* ResAttempt = (Res.getCookie() ? (IntegrationAttempt*)Res.getCookie() : this);
ValCtx Result = VCNull;
PartialVal PV = PVNull;
@@ -857,6 +862,9 @@ ValCtx IntegrationAttempt::getForwardedValue(LoadForwardAttempt& LFA, MemDepResu
PV = PartialVal::getTotal(DefResult);
}
+ if(PV == PVNull)
+ return VCNull;
+
// Might fail if it turns out the constant is unreadable,
// for example because it contains global variable of function pointers.
if(!LFA.addPartialVal(PV)) {
@@ -874,7 +882,7 @@ ValCtx IntegrationAttempt::getForwardedValue(LoadForwardAttempt& LFA, MemDepResu
else {
BasicBlock* ResBB = Res.getInst()->getParent();
- if(ResBB == ResBB->getParent()->getEntryBlock() && Res.getInst() == ResBB->begin() && !ResAttempt->hasParent()) {
+ if(ResBB == &(ResBB->getParent()->getEntryBlock()) && Res.getInst() == ResBB->begin() && !ResAttempt->hasParent()) {
LPDEBUG("This does not complete the load, and there are no further predecessors\n");
return VCNull;
@@ -882,7 +890,7 @@ ValCtx IntegrationAttempt::getForwardedValue(LoadForwardAttempt& LFA, MemDepResu
}
else {
- LPDEBUG("This does not complete the load: requerying starting at " << Defn << "\n");
+ LPDEBUG("This does not complete the load: requerying starting at " << *(Res.getInst()) << "\n");
return ResAttempt->tryForwardLoad(LFA, Res.getInst());
}
@@ -2084,14 +2092,14 @@ std::string PeelAttempt::nestingIndent() const {
}
-bool containsPointerTypes(const Type* Ty) {
+bool llvm::containsPointerTypes(const Type* Ty) {
if(Ty->isPointerTy())
return true;
for(Type::subtype_iterator it = Ty->subtype_begin(), it2 = Ty->subtype_end(); it != it2; ++it) {
- if(containsPointerTypes(it))
+ if(containsPointerTypes(*it))
return true;
}
@@ -2259,20 +2267,20 @@ uint64_t LoadForwardAttempt::markPaddingBytes(bool* validBuf, const Type* Ty) {
uint64_t marked = 0;
- if(StructType* STy = dyn_cast<StructType>(Ty)) {
+ if(const StructType* STy = dyn_cast<StructType>(Ty)) {
- StructLayout* SL = TD->getStructLayout(STy);
+ const StructLayout* SL = TD->getStructLayout(STy);
if(!SL) {
- LPDEBUG("Couldn't get struct layout for type " << *SL << "\n");
+ LPDEBUG("Couldn't get struct layout for type " << *STy << "\n");
return 0;
}
uint64_t EIdx = 0;
for(StructType::element_iterator EI = STy->element_begin(), EE = STy->element_end(); EI != EE; ++EI, ++EIdx) {
- marked += markPaddingBytes(&(validBuf[SL->getElementOffset(EIdx)]), EI);
+ marked += markPaddingBytes(&(validBuf[SL->getElementOffset(EIdx)]), *EI);
uint64_t ThisEStart = SL->getElementOffset(EIdx);
- uint64_t ESize = (TD->getTypeSizeInBits(EI) + 7) / 8;
+ uint64_t ESize = (TD->getTypeSizeInBits(*EI) + 7) / 8;
uint64_t NextEStart = (EIdx + 1 == STy->getNumElements()) ? SL->getSizeInBytes() : SL->getElementOffset(EIdx + 1);
for(uint64_t i = ThisEStart + ESize; i < NextEStart; ++i, ++marked) {
@@ -2283,7 +2291,7 @@ uint64_t LoadForwardAttempt::markPaddingBytes(bool* validBuf, const Type* Ty) {
}
}
- else if(ArrayType* ATy = dyn_cast<ArrayType>(Ty)) {
+ else if(const ArrayType* ATy = dyn_cast<ArrayType>(Ty)) {
uint64_t ECount = ATy->getNumElements();
const Type* EType = ATy->getElementType();
@@ -2403,6 +2411,18 @@ bool LoadForwardAttempt::allowTotalDefnImplicitCast(const Type* From, const Type
Constant* LoadForwardAttempt::extractAggregateMemberAt(Constant* FromC, uint64_t Offset, const Type* Target, uint64_t TargetSize) {
+ const Type* FromType = FromC->getType();
+ uint64_t FromSize = (TD->getTypeSizeInBits(FromType) + 7) / 8;
+
+ if(Offset == 0 && TargetSize == FromSize) {
+ if(allowTotalDefnImplicitCast(Target, FromType))
+ return FromC;
+ else {
+ LPDEBUG("Can't use simple element extraction because load implies cast from " << (*(FromType)) << " to " << (*Target) << "\n");
+ return 0;
+ }
+ }
+
uint64_t StartE, StartOff, EndE, EndOff;
bool mightWork = false;
@@ -2423,9 +2443,9 @@ Constant* LoadForwardAttempt::extractAggregateMemberAt(Constant* FromC, uint64_t
mightWork = true;
- StructLayout* SL = TD->getStructLayout(STy);
+ const StructLayout* SL = TD->getStructLayout(CS->getType());
if(!SL) {
- LPDEBUG("Couldn't get struct layout for type " << *SL << "\n");
+ LPDEBUG("Couldn't get struct layout for type " << *(CS->getType()) << "\n");
return 0;
}
@@ -2437,25 +2457,9 @@ Constant* LoadForwardAttempt::extractAggregateMemberAt(Constant* FromC, uint64_t
}
if(mightWork) {
- if(StartE == EndE) {
+ if(StartE == EndE || (StartE + 1 == EndE && !EndOff)) {
// This is a sub-access within this element.
- return extractAggregateMemberAt(FromC->getOperand(StartE), StartOff, Target, TargetSize);
- }
- else if(StartE + 1 == EndE && !EndOff) {
- if(!StartOff) {
- // This is accessing the entire element
- Constant* R = CA->getOperand(StartE);
- const Type* RType = R->getType();
- if(allowTotalDefnImplicitCast(Target, RType)) {
- return R;
- }
- else {
- LPDEBUG("Can't use simple element extraction because implies cast from " << (*RType) << " to " << (*Taret) << "\n");
- }
- }
- else {
- return extractAggregateMemberAt(FromC->getOperand(StartE), StartOff, Target, TargetSize);
- }
+ return extractAggregateMemberAt(cast<Constant>(FromC->getOperand(StartE)), StartOff, Target, TargetSize);
}
LPDEBUG("Can't use simple element extraction because load spans multiple elements\n");
}
@@ -2469,7 +2473,7 @@ Constant* LoadForwardAttempt::extractAggregateMemberAt(Constant* FromC, uint64_t
bool LoadForwardAttempt::addPartialVal(PartialVal& PV) {
- if(PV.isTotal() && allowTotalDefnImplicitCast(targetType, PV.TotalVC.first.getType()) && !partialBuf) {
+ if(PV.isTotal() && allowTotalDefnImplicitCast(targetType, PV.TotalVC.first->getType()) && !partialBuf) {
LPDEBUG("Accepting " << PV.TotalVC << " as a total definition\n");
Result = PV.TotalVC;
return true;
@@ -2488,8 +2492,9 @@ bool LoadForwardAttempt::addPartialVal(PartialVal& PV) {
if(SalvageC && (PV.isTotal() || (PV.FirstDef == 0 && PV.FirstNotDef == LoadSize)) && !partialBuf) {
uint64_t Offset = PV.isTotal() ? 0 : PV.ReadOffset;
+
if(Constant* Extracted = extractAggregateMemberAt(SalvageC, Offset, targetType, LoadSize)) {
- LPDEBUG("Successfully extracted a whole aggregate element: " << *Extracted << "\n");
+ LPDEBUG("Successfully extracted an entire field: " << *Extracted << "\n");
Result = const_vc(Extracted);
return true;
}
@@ -2520,7 +2525,7 @@ bool LoadForwardAttempt::addPartialVal(PartialVal& PV) {
// Fall through to the partial definition case.
- LPDEBUG("This store can satisfy bytes (" << FirstDef << "-" << FirstNotDef << "] of the source load\n");
+ LPDEBUG("This store can satisfy bytes (" << PV.FirstDef << "-" << PV.FirstNotDef << "] of the source load\n");
// Store defined some of the bytes we need! Grab those, then perhaps complete the load.
unsigned char* partialBuf = getPartialBuf(LoadSize);
@@ -2564,12 +2569,14 @@ bool LoadForwardAttempt::addPartialVal(PartialVal& PV) {
return false;
}
else {
- LPDEBUG("This store completes the load (final value: " << Ret << ")\n");
+ LPDEBUG("This store completes the load (final value: " << Result << ")\n");
return true;
}
}
+ return true;
+
}
bool LoadForwardAttempt::isComplete() {
@@ -2584,7 +2591,7 @@ ValCtx LoadForwardAttempt::getResult() {
}
-Constant* LoadForwardAttempt::constFromBytes(char* Bytes, const Type* Ty) {
+Constant* LoadForwardAttempt::constFromBytes(unsigned char* Bytes, const Type* Ty) {
if(Ty->isVectorTy() || Ty->isFloatingPointTy() || Ty->isIntegerTy()) {
@@ -2612,7 +2619,7 @@ Constant* LoadForwardAttempt::constFromBytes(char* Bytes, const Type* Ty) {
}
}
- else if(ArrayType* ATy = dyn_cast<ArrayType>(Ty)) {
+ else if(const ArrayType* ATy = dyn_cast<ArrayType>(Ty)) {
uint64_t ECount = ATy->getNumElements();
if(ECount == 0) {
@@ -2639,11 +2646,11 @@ Constant* LoadForwardAttempt::constFromBytes(char* Bytes, const Type* Ty) {
return ConstantArray::get(ATy, Elems);
}
- else if(StructType* STy = dyn_cast<StructType>(Ty)) {
+ else if(const StructType* STy = dyn_cast<StructType>(Ty)) {
- StructLayout* SL = TD->getStructLayout(STy);
+ const StructLayout* SL = TD->getStructLayout(STy);
if(!SL) {
- LPDEBUG("Couldn't get struct layout for type " << *SL << "\n");
+ LPDEBUG("Couldn't get struct layout for type " << *STy << "\n");
return 0;
}
@@ -2654,9 +2661,8 @@ Constant* LoadForwardAttempt::constFromBytes(char* Bytes, const Type* Ty) {
uint64_t EIdx = 0;
for(StructType::element_iterator EI = STy->element_begin(), EE = STy->element_end(); EI != EE; ++EI, ++EIdx) {
- const Type* EType = EI;
- uint64_t EOffset = getElementOffset(EIdx);
- uint64_t ESize = (TD->getTypeSizeInBits(EType) + 7) / 8;
+ const Type* EType = *EI;
+ uint64_t EOffset = SL->getElementOffset(EIdx);
Constant* NextE = constFromBytes(&(Bytes[EOffset]), EType);
if(!NextE)
return 0;
View
30 llvm/lib/Analysis/Integrator/PartialLoadForward.cpp
@@ -33,15 +33,16 @@ using namespace llvm;
/// up. This returns -1 if we have to give up, or a byte number in the stored
/// value of the piece that feeds the load.
bool IntegrationAttempt::AnalyzeLoadFromClobberingWrite(LoadForwardAttempt& LFA,
- Value *WritePtr, HCFParentCallbacks* WriteCtx,
- uint64_t WriteSizeInBits,
- uint64_t* FirstDef, uint64_t* FirstNotDef) {
- const Type* LoadTy = LFA.getOriginalInst()->getType();
-
+ Value *WritePtr, HCFParentCallbacks* WriteCtx,
+ uint64_t WriteSizeInBits,
+ /* Out params: */
+ uint64_t& FirstDef,
+ uint64_t& FirstNotDef,
+ uint64_t& ReadOffset) {
int64_t StoreOffset = 0;
ValCtx StoreBase = GetBaseWithConstantOffset(WritePtr, WriteCtx, StoreOffset);
- return AnalyzeLoadFromClobberingWrite(LFA, StoreBase, StoreOffset, WriteSizeInBits, FirstDef, FirstNotDef);
+ return AnalyzeLoadFromClobberingWrite(LFA, StoreBase, StoreOffset, WriteSizeInBits, FirstDef, FirstNotDef, ReadOffset);
}
@@ -69,7 +70,7 @@ bool IntegrationAttempt::AnalyzeLoadFromClobberingWrite(LoadForwardAttempt& LFA,
return false;
}
- LoadOffset = LFA.getSymExprOffset(); // Succeeds if canBuildSymExpr does
+ uint64_t LoadOffset = LFA.getSymExprOffset(); // Succeeds if canBuildSymExpr does
// If the load and store don't overlap at all, the store doesn't provide
// anything to the load. In this case, they really don't alias at all, AA
@@ -207,7 +208,7 @@ ValCtx IntegrationAttempt::GetBaseWithConstantOffset(Value *Ptr, HCFParentCallba
}
-Constant* intFromBytes(const uint64_t* data, unsigned data_length, unsigned data_bits, LLVMContext& Context) {
+Constant* llvm::intFromBytes(const uint64_t* data, unsigned data_length, unsigned data_bits, LLVMContext& Context) {
APInt AP(data_bits, data_length, data);
return ConstantInt::get(Context, AP);
@@ -296,7 +297,7 @@ PartialVal IntegrationAttempt::tryResolveClobber(LoadForwardAttempt& LFA, ValCtx
if(!AnalyzeLoadFromClobberingStore(LFA, DepSI, Clobber.second, FirstDef, FirstNotDef, ReadOffset))
return PartialVal();
- return PartailVal::getPartial(FirstDef, FirstNotDef, StoreC, ReadOffset);
+ return PartialVal::getPartial(FirstDef, FirstNotDef, StoreC, ReadOffset);
}
@@ -349,7 +350,7 @@ PartialVal IntegrationAttempt::tryResolveClobber(LoadForwardAttempt& LFA, ValCtx
const Type* byteArrayType = Type::getInt8PtrTy(LI->getContext());
const Type* subTargetType;
- uint64_t DefSize = FirstNonDef - FirstDef;
+ uint64_t DefSize = FirstNotDef - FirstDef;
if(DefSize != LoadSize) {
// This memcpy/move is partially defining the load
@@ -473,14 +474,13 @@ PartialVal IntegrationAttempt::tryResolveClobber(LoadForwardAttempt& LFA, ValCtx
uint64_t FirstDef, FirstNotDef, loadOffset;
if(!AnalyzeLoadFromClobberingWrite(LFA, CI->getArgOperand(1), Clobber.second, RF->readSize * 8, FirstDef, FirstNotDef, loadOffset))
- return false;
+ return VCNull;
uint64_t nbytes = FirstNotDef - FirstDef;
uint64_t nqwords = (nbytes + 7) / 8;
uint64_t bufsize = nqwords * 8;
uint8_t* buffer = (uint8_t*)alloca(bufsize);
- uint64_t thisReadSize;
int fd = open(RF->openArg->Name.c_str(), O_RDONLY);
if(fd == -1) {
@@ -489,8 +489,8 @@ PartialVal IntegrationAttempt::tryResolveClobber(LoadForwardAttempt& LFA, ValCtx
}
unsigned bytes_read = 0;
- while(bytes_read < thisReadSize) {
- int this_read = pread(fd, ((char*)buffer) + bytes_read, thisReadSize - bytes_read, RF->incomingOffset + loadOffset + bytes_read);
+ while(bytes_read < nbytes) {
+ int this_read = pread(fd, ((char*)buffer) + bytes_read, nbytes - bytes_read, RF->incomingOffset + loadOffset + bytes_read);
if(this_read == 0)
break;
else if(this_read == -1 && errno != EINTR)
@@ -505,7 +505,7 @@ PartialVal IntegrationAttempt::tryResolveClobber(LoadForwardAttempt& LFA, ValCtx
return PartialVal();
}
- Constant* Result = intFromBytes((uint64_t*)buffer, nqwords, nbytes * 8, MSI->getContext());
+ Constant* Result = intFromBytes((uint64_t*)buffer, nqwords, nbytes * 8, CI->getContext());
return PartialVal::getPartial(FirstDef, FirstNotDef, Result, 0);
}
Please sign in to comment.
Something went wrong with that request. Please try again.