diff options
Diffstat (limited to 'lib/Transforms/Utils/VNCoercion.cpp')
-rw-r--r-- | lib/Transforms/Utils/VNCoercion.cpp | 66 |
1 files changed, 52 insertions, 14 deletions
diff --git a/lib/Transforms/Utils/VNCoercion.cpp b/lib/Transforms/Utils/VNCoercion.cpp index 948d9bd5baad..a77bf50fe10b 100644 --- a/lib/Transforms/Utils/VNCoercion.cpp +++ b/lib/Transforms/Utils/VNCoercion.cpp @@ -14,13 +14,17 @@ namespace VNCoercion { /// Return true if coerceAvailableValueToLoadType will succeed. bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, const DataLayout &DL) { + Type *StoredTy = StoredVal->getType(); + if (StoredTy == LoadTy) + return true; + // If the loaded or stored value is an first class array or struct, don't try // to transform them. We need to be able to bitcast to integer. - if (LoadTy->isStructTy() || LoadTy->isArrayTy() || - StoredVal->getType()->isStructTy() || StoredVal->getType()->isArrayTy()) + if (LoadTy->isStructTy() || LoadTy->isArrayTy() || StoredTy->isStructTy() || + StoredTy->isArrayTy()) return false; - uint64_t StoreSize = DL.getTypeSizeInBits(StoredVal->getType()); + uint64_t StoreSize = DL.getTypeSizeInBits(StoredTy); // The store size must be byte-aligned to support future type casts. if (llvm::alignTo(StoreSize, 8) != StoreSize) @@ -31,10 +35,16 @@ bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, return false; // Don't coerce non-integral pointers to integers or vice versa. - if (DL.isNonIntegralPointerType(StoredVal->getType()) != - DL.isNonIntegralPointerType(LoadTy)) + if (DL.isNonIntegralPointerType(StoredVal->getType()->getScalarType()) != + DL.isNonIntegralPointerType(LoadTy->getScalarType())) { + // As a special case, allow coercion of memset used to initialize + // an array w/null. Despite non-integral pointers not generally having a + // specific bit pattern, we do assume null is zero. + if (auto *CI = dyn_cast<Constant>(StoredVal)) + return CI->isNullValue(); return false; - + } + return true; } @@ -207,11 +217,22 @@ static int analyzeLoadFromClobberingWrite(Type *LoadTy, Value *LoadPtr, /// memdep query of a load that ends up being a clobbering store. int analyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr, StoreInst *DepSI, const DataLayout &DL) { + auto *StoredVal = DepSI->getValueOperand(); + // Cannot handle reading from store of first-class aggregate yet. - if (DepSI->getValueOperand()->getType()->isStructTy() || - DepSI->getValueOperand()->getType()->isArrayTy()) + if (StoredVal->getType()->isStructTy() || + StoredVal->getType()->isArrayTy()) return -1; + // Don't coerce non-integral pointers to integers or vice versa. + if (DL.isNonIntegralPointerType(StoredVal->getType()->getScalarType()) != + DL.isNonIntegralPointerType(LoadTy->getScalarType())) { + // Allow casts of zero values to null as a special case + auto *CI = dyn_cast<Constant>(StoredVal); + if (!CI || !CI->isNullValue()) + return -1; + } + Value *StorePtr = DepSI->getPointerOperand(); uint64_t StoreSize = DL.getTypeSizeInBits(DepSI->getValueOperand()->getType()); @@ -228,6 +249,11 @@ int analyzeLoadFromClobberingLoad(Type *LoadTy, Value *LoadPtr, LoadInst *DepLI, if (DepLI->getType()->isStructTy() || DepLI->getType()->isArrayTy()) return -1; + // Don't coerce non-integral pointers to integers or vice versa. + if (DL.isNonIntegralPointerType(DepLI->getType()->getScalarType()) != + DL.isNonIntegralPointerType(LoadTy->getScalarType())) + return -1; + Value *DepPtr = DepLI->getPointerOperand(); uint64_t DepSize = DL.getTypeSizeInBits(DepLI->getType()); int R = analyzeLoadFromClobberingWrite(LoadTy, LoadPtr, DepPtr, DepSize, DL); @@ -264,9 +290,15 @@ int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, // If this is memset, we just need to see if the offset is valid in the size // of the memset.. - if (MI->getIntrinsicID() == Intrinsic::memset) + if (MI->getIntrinsicID() == Intrinsic::memset) { + if (DL.isNonIntegralPointerType(LoadTy->getScalarType())) { + auto *CI = dyn_cast<ConstantInt>(cast<MemSetInst>(MI)->getValue()); + if (!CI || !CI->isZero()) + return -1; + } return analyzeLoadFromClobberingWrite(LoadTy, LoadPtr, MI->getDest(), MemSizeInBits, DL); + } // If we have a memcpy/memmove, the only case we can handle is if this is a // copy from constant memory. In that case, we can read directly from the @@ -278,7 +310,7 @@ int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, return -1; GlobalVariable *GV = dyn_cast<GlobalVariable>(GetUnderlyingObject(Src, DL)); - if (!GV || !GV->isConstant()) + if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer()) return -1; // See if the access is within the bounds of the transfer. @@ -287,6 +319,12 @@ int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, if (Offset == -1) return Offset; + // Don't coerce non-integral pointers to integers or vice versa, and the + // memtransfer is implicitly a raw byte code + if (DL.isNonIntegralPointerType(LoadTy->getScalarType())) + // TODO: Can allow nullptrs from constant zeros + return -1; + unsigned AS = Src->getType()->getPointerAddressSpace(); // Otherwise, see if we can constant fold a load from the constant with the // offset applied as appropriate. @@ -386,12 +424,12 @@ Value *getLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, Type *LoadTy, // memdep queries will find the new load. We can't easily remove the old // load completely because it is already in the value numbering table. IRBuilder<> Builder(SrcVal->getParent(), ++BasicBlock::iterator(SrcVal)); - Type *DestPTy = IntegerType::get(LoadTy->getContext(), NewLoadSize * 8); - DestPTy = - PointerType::get(DestPTy, PtrVal->getType()->getPointerAddressSpace()); + Type *DestTy = IntegerType::get(LoadTy->getContext(), NewLoadSize * 8); + Type *DestPTy = + PointerType::get(DestTy, PtrVal->getType()->getPointerAddressSpace()); Builder.SetCurrentDebugLocation(SrcVal->getDebugLoc()); PtrVal = Builder.CreateBitCast(PtrVal, DestPTy); - LoadInst *NewLoad = Builder.CreateLoad(PtrVal); + LoadInst *NewLoad = Builder.CreateLoad(DestTy, PtrVal); NewLoad->takeName(SrcVal); NewLoad->setAlignment(SrcVal->getAlignment()); |