From 9bc1464094b7b6fc9e832b6753a591158829b0a6 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 28 Apr 2007 00:57:34 +0000 Subject: [PATCH] Implement PR1345 and Transforms/InstCombine/bitcast-gep.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36521 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 132 ++++++++++++++---- 1 file changed, 104 insertions(+), 28 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 40e7624b199..f43655c22c2 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -4358,15 +4358,27 @@ static Value *EmitGEPOffset(User *GEP, Instruction &I, InstCombiner &IC) { } } else { // Convert to correct type. - Op = IC.InsertNewInstBefore(CastInst::createSExtOrBitCast(Op, IntPtrTy, - Op->getName()+".c"), I); - if (Size != 1) - // We'll let instcombine(mul) convert this to a shl if possible. - Op = IC.InsertNewInstBefore(BinaryOperator::createMul(Op, Scale, + if (Op->getType() != IntPtrTy) { + if (Constant *OpC = dyn_cast(Op)) + Op = ConstantExpr::getSExt(OpC, IntPtrTy); + else + Op = IC.InsertNewInstBefore(new SExtInst(Op, IntPtrTy, + Op->getName()+".c"), I); + } + if (Size != 1) { + if (Constant *OpC = dyn_cast(Op)) + Op = ConstantExpr::getMul(OpC, Scale); + else // We'll let instcombine(mul) convert this to a shl if possible. + Op = IC.InsertNewInstBefore(BinaryOperator::createMul(Op, Scale, GEP->getName()+".idx"), I); + } // Emit an add instruction. - Result = IC.InsertNewInstBefore(BinaryOperator::createAdd(Op, Result, + if (isa(Op) && isa(Result)) + Result = ConstantExpr::getAdd(cast(Op), + cast(Result)); + else + Result = IC.InsertNewInstBefore(BinaryOperator::createAdd(Op, Result, GEP->getName()+".offs"), I); } } @@ -6343,17 +6355,96 @@ Instruction *InstCombiner::commonCastTransforms(CastInst &CI) { Instruction *InstCombiner::commonPointerCastTransforms(CastInst &CI) { Value *Src = CI.getOperand(0); - // If casting the result of a getelementptr instruction with no offset, turn - // this into a cast of the original pointer! - // if (GetElementPtrInst *GEP = dyn_cast(Src)) { + // If casting the result of a getelementptr instruction with no offset, turn + // this into a cast of the original pointer! if (GEP->hasAllZeroIndices()) { // Changing the cast operand is usually not a good idea but it is safe // here because the pointer operand is being replaced with another // pointer operand so the opcode doesn't need to change. + AddToWorkList(GEP); CI.setOperand(0, GEP->getOperand(0)); return &CI; } + + // If the GEP has a single use, and the base pointer is a bitcast, and the + // GEP computes a constant offset, see if we can convert these three + // instructions into fewer. This typically happens with unions and other + // non-type-safe code. + if (GEP->hasOneUse() && isa(GEP->getOperand(0))) { + if (GEP->hasAllConstantIndices()) { + // We are guaranteed to get a constant from EmitGEPOffset. + ConstantInt *OffsetV = cast(EmitGEPOffset(GEP, CI, *this)); + int64_t Offset = OffsetV->getSExtValue(); + + // Get the base pointer input of the bitcast, and the type it points to. + Value *OrigBase = cast(GEP->getOperand(0))->getOperand(0); + const Type *GEPIdxTy = + cast(OrigBase->getType())->getElementType(); + if (GEPIdxTy->isSized()) { + SmallVector NewIndices; + + // Start with the index over the outer type. + const Type *IntPtrTy = TD->getIntPtrType(); + int64_t TySize = TD->getTypeSize(GEPIdxTy); + int64_t FirstIdx = Offset/TySize; + Offset %= TySize; + + // Handle silly modulus not returning values values [0..TySize). + if (Offset < 0) { + assert(FirstIdx == 0); + FirstIdx = -1; + Offset += TySize; + assert(Offset >= 0); + } + + NewIndices.push_back(ConstantInt::get(IntPtrTy, FirstIdx)); + assert((uint64_t)Offset < (uint64_t)TySize && "Out of range offset"); + + // Index into the types. If we fail, set OrigBase to null. + while (Offset) { + if (const StructType *STy = dyn_cast(GEPIdxTy)) { + const StructLayout *SL = TD->getStructLayout(STy); + unsigned Elt = SL->getElementContainingOffset(Offset); + NewIndices.push_back(ConstantInt::get(Type::Int32Ty, Elt)); + + Offset -= SL->getElementOffset(Elt); + GEPIdxTy = STy->getElementType(Elt); + } else if (isa(GEPIdxTy) || isa(GEPIdxTy)) { + const SequentialType *STy = cast(GEPIdxTy); + uint64_t EltSize = TD->getTypeSize(STy->getElementType()); + NewIndices.push_back(ConstantInt::get(IntPtrTy, Offset/EltSize)); + Offset %= EltSize; + GEPIdxTy = STy->getElementType(); + } else { + // Otherwise, we can't index into this, bail out. + Offset = 0; + OrigBase = 0; + } + } + if (OrigBase) { + // If we were able to index down into an element, create the GEP + // and bitcast the result. This eliminates one bitcast, potentially + // two. + Instruction *NGEP = new GetElementPtrInst(OrigBase, &NewIndices[0], + NewIndices.size(), ""); + InsertNewInstBefore(NGEP, CI); + NGEP->takeName(GEP); + + cerr << "\nZAP: " << *GEP->getOperand(0); + cerr << "ZAP: " << *GEP; + cerr << "ZAP: " << CI << "\n"; + + cerr << "NEW: " << *NGEP << "\n"; + + if (isa(CI)) + return new BitCastInst(NGEP, CI.getType()); + assert(isa(CI)); + return new PtrToIntInst(NGEP, CI.getType()); + } + } + } + } } return commonCastTransforms(CI); @@ -7306,10 +7397,7 @@ static unsigned GetKnownAlignment(Value *V, TargetData *TD) { if (isa(CI->getOperand(0)->getType())) return GetKnownAlignment(CI->getOperand(0), TD); return 0; - } else if (isa(V) || - (isa(V) && - cast(V)->getOpcode()==Instruction::GetElementPtr)) { - User *GEPI = cast(V); + } else if (User *GEPI = dyn_castGetElementPtr(V)) { unsigned BaseAlignment = GetKnownAlignment(GEPI->getOperand(0), TD); if (BaseAlignment == 0) return 0; @@ -8107,7 +8195,7 @@ static Value *InsertCastToIntPtrTy(Value *V, const Type *DTy, Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { Value *PtrOp = GEP.getOperand(0); - // Is it 'getelementptr %P, long 0' or 'getelementptr %P' + // Is it 'getelementptr %P, i32 0' or 'getelementptr %P' // If so, eliminate the noop. if (GEP.getNumOperands() == 1) return ReplaceInstUsesWith(GEP, PtrOp); @@ -8122,22 +8210,11 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { if (GEP.getNumOperands() == 2 && HasZeroPointerIndex) return ReplaceInstUsesWith(GEP, PtrOp); - // Keep track of whether all indices are zero constants integers. - bool AllZeroIndices = true; - // Eliminate unneeded casts for indices. bool MadeChange = false; gep_type_iterator GTI = gep_type_begin(GEP); for (unsigned i = 1, e = GEP.getNumOperands(); i != e; ++i, ++GTI) { - // Track whether this GEP has all zero indices, if so, it doesn't move the - // input pointer, it just changes its type. - if (AllZeroIndices) { - if (ConstantInt *CI = dyn_cast(GEP.getOperand(i))) - AllZeroIndices = CI->isZero(); - else - AllZeroIndices = false; - } if (isa(*GTI)) { if (CastInst *CI = dyn_cast(GEP.getOperand(i))) { if (CI->getOpcode() == Instruction::ZExt || @@ -8173,7 +8250,7 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { // If this GEP instruction doesn't move the pointer, and if the input operand // is a bitcast of another pointer, just replace the GEP with a bitcast of the // real input to the dest type. - if (AllZeroIndices && isa(GEP.getOperand(0))) + if (GEP.hasAllZeroIndices() && isa(GEP.getOperand(0))) return new BitCastInst(cast(GEP.getOperand(0))->getOperand(0), GEP.getType()); @@ -8573,8 +8650,7 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { } if (GetElementPtrInst *GEPI = dyn_cast(Op)) - if (isa(GEPI->getOperand(0)) || - isa(GEPI->getOperand(0))) { + if (isa(GEPI->getOperand(0))) { // Insert a new store to null instruction before the load to indicate // that this code is not reachable. We do this instead of inserting // an unreachable instruction directly because we cannot modify the -- 2.34.1