diff options
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 2c9ba203fbf..08a7a068af2 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -681,6 +681,42 @@ static Instruction *shrinkInsertElt(CastInst &Trunc, return nullptr; } +static Instruction *narrowLoad(TruncInst &Trunc, + InstCombiner::BuilderTy &Builder, + const DataLayout &DL) { + // Check the layout to ensure we are not creating an unsupported operation. + // TODO: Create a GEP to offset the load? + if (!DL.isLittleEndian()) + return nullptr; + unsigned NarrowBitWidth = Trunc.getDestTy()->getPrimitiveSizeInBits(); + if (!DL.isLegalInteger(NarrowBitWidth)) + return nullptr; + + // Match a truncated load with no other uses. + Value *X; + if (!match(Trunc.getOperand(0), m_OneUse(m_Load(m_Value(X))))) + return nullptr; + LoadInst *WideLoad = cast<LoadInst>(Trunc.getOperand(0)); + if (!WideLoad->isSimple()) + return nullptr; + + // Don't narrow this load if we would lose information about the + // dereferenceable range. + bool CanBeNull; + uint64_t DerefBits = X->getPointerDereferenceableBytes(DL, CanBeNull) * 8; + if (DerefBits < WideLoad->getType()->getPrimitiveSizeInBits()) + return nullptr; + + // trunc (load X) --> load (bitcast X) + PointerType *PtrTy = PointerType::get(Trunc.getDestTy(), + WideLoad->getPointerAddressSpace()); + Value *Bitcast = Builder.CreatePointerCast(X, PtrTy); + LoadInst *NarrowLoad = new LoadInst(Trunc.getDestTy(), Bitcast); + NarrowLoad->setAlignment(WideLoad->getAlignment()); + copyMetadataForLoad(*NarrowLoad, *WideLoad); + return NarrowLoad; +} + Instruction *InstCombiner::visitTrunc(TruncInst &CI) { if (Instruction *Result = commonCastTransforms(CI)) return Result; @@ -840,6 +876,9 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) { if (Instruction *I = foldVecTruncToExtElt(CI, *this)) return I; + if (Instruction *NewLoad = narrowLoad(CI, Builder, DL)) + return NewLoad; + return nullptr; } |