From 620ce1466653cad650950215e7525d4ef3b41cd6 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 7 May 2004 22:09:22 +0000 Subject: [PATCH] Implement folding of GEP's like: %tmp.0 = getelementptr [50 x sbyte]* %ar, uint 0, int 5 ; [#uses=2] %tmp.7 = getelementptr sbyte* %tmp.0, int 8 ; [#uses=1] together. This patch actually allows us to simplify and generalize the code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13415 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/InstructionCombining.cpp | 96 ++++++++++++-------------- 1 file changed, 43 insertions(+), 53 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 0ad4ad44da0..11f6937a8ee 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -2535,17 +2535,18 @@ static Value *InsertSignExtendToPtrTy(Value *V, const Type *DTy, Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { + Value *PtrOp = GEP.getOperand(0); // Is it 'getelementptr %P, long 0' or 'getelementptr %P' // If so, eliminate the noop. if (GEP.getNumOperands() == 1) - return ReplaceInstUsesWith(GEP, GEP.getOperand(0)); + return ReplaceInstUsesWith(GEP, PtrOp); bool HasZeroPointerIndex = false; if (Constant *C = dyn_cast(GEP.getOperand(1))) HasZeroPointerIndex = C->isNullValue(); if (GEP.getNumOperands() == 2 && HasZeroPointerIndex) - return ReplaceInstUsesWith(GEP, GEP.getOperand(0)); + return ReplaceInstUsesWith(GEP, PtrOp); // Eliminate unneeded casts for indices. bool MadeChange = false; @@ -2601,46 +2602,37 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { // getelementptr instructions into a single instruction. // std::vector SrcGEPOperands; - if (GetElementPtrInst *Src = dyn_cast(GEP.getOperand(0))) { + if (GetElementPtrInst *Src = dyn_cast(PtrOp)) { SrcGEPOperands.assign(Src->op_begin(), Src->op_end()); - } else if (ConstantExpr *CE = dyn_cast(GEP.getOperand(0))) { + } else if (ConstantExpr *CE = dyn_cast(PtrOp)) { if (CE->getOpcode() == Instruction::GetElementPtr) SrcGEPOperands.assign(CE->op_begin(), CE->op_end()); } if (!SrcGEPOperands.empty()) { + // Note that if our source is a gep chain itself that we wait for that + // chain to be resolved before we perform this transformation. This + // avoids us creating a TON of code in some cases. + // + if (isa(SrcGEPOperands[0]) && + cast(SrcGEPOperands[0])->getNumOperands() == 2) + return 0; // Wait until our source is folded to completion. + std::vector Indices; + + // Find out whether the last index in the source GEP is a sequential idx. + bool EndsWithSequential = false; + for (gep_type_iterator I = gep_type_begin(*cast(PtrOp)), + E = gep_type_end(*cast(PtrOp)); I != E; ++I) + if (!isa(*I)) + EndsWithSequential = true; // Can we combine the two pointer arithmetics offsets? - if (SrcGEPOperands.size() == 2 && isa(SrcGEPOperands[1]) && - isa(GEP.getOperand(1))) { - Constant *SGC = cast(SrcGEPOperands[1]); - Constant *GC = cast(GEP.getOperand(1)); - if (SGC->getType() != GC->getType()) { - SGC = ConstantExpr::getSignExtend(SGC, Type::LongTy); - GC = ConstantExpr::getSignExtend(GC, Type::LongTy); - } - - // Replace: gep (gep %P, long C1), long C2, ... - // With: gep %P, long (C1+C2), ... - GEP.setOperand(0, SrcGEPOperands[0]); - GEP.setOperand(1, ConstantExpr::getAdd(SGC, GC)); - if (Instruction *I = dyn_cast(GEP.getOperand(0))) - AddUsersToWorkList(*I); // Reduce use count of Src - return &GEP; - } else if (SrcGEPOperands.size() == 2) { + if (EndsWithSequential) { // Replace: gep (gep %P, long B), long A, ... // With: T = long A+B; gep %P, T, ... // - // Note that if our source is a gep chain itself that we wait for that - // chain to be resolved before we perform this transformation. This - // avoids us creating a TON of code in some cases. - // - if (isa(SrcGEPOperands[0]) && - cast(SrcGEPOperands[0])->getNumOperands() == 2) - return 0; // Wait until our source is folded to completion. - - Value *Sum, *SO1 = SrcGEPOperands[1], *GO1 = GEP.getOperand(1); + Value *Sum, *SO1 = SrcGEPOperands.back(), *GO1 = GEP.getOperand(1); if (SO1 == Constant::getNullValue(SO1->getType())) { Sum = GO1; } else if (GO1 == Constant::getNullValue(GO1->getType())) { @@ -2670,13 +2662,26 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { } } } - Sum = BinaryOperator::create(Instruction::Add, SO1, GO1, - GEP.getOperand(0)->getName()+".sum", &GEP); - WorkList.push_back(cast(Sum)); + if (isa(SO1) && isa(GO1)) + Sum = ConstantExpr::getAdd(cast(SO1), cast(GO1)); + else { + Sum = BinaryOperator::create(Instruction::Add, SO1, GO1, + PtrOp->getName()+".sum", &GEP); + WorkList.push_back(cast(Sum)); + } + } + + // Recycle the GEP we already have if possible. + if (SrcGEPOperands.size() == 2) { + GEP.setOperand(0, SrcGEPOperands[0]); + GEP.setOperand(1, Sum); + return &GEP; + } else { + Indices.insert(Indices.end(), SrcGEPOperands.begin()+1, + SrcGEPOperands.end()-1); + Indices.push_back(Sum); + Indices.insert(Indices.end(), GEP.op_begin()+2, GEP.op_end()); } - GEP.setOperand(0, SrcGEPOperands[0]); - GEP.setOperand(1, Sum); - return &GEP; } else if (isa(*GEP.idx_begin()) && cast(*GEP.idx_begin())->isNullValue() && SrcGEPOperands.size() != 1) { @@ -2684,27 +2689,12 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { Indices.insert(Indices.end(), SrcGEPOperands.begin()+1, SrcGEPOperands.end()); Indices.insert(Indices.end(), GEP.idx_begin()+1, GEP.idx_end()); - } else if (SrcGEPOperands.back() == - Constant::getNullValue(SrcGEPOperands.back()->getType())) { - // We have to check to make sure this really is an ARRAY index we are - // ending up with, not a struct index. - generic_gep_type_iterator::iterator> - GTI = gep_type_begin(SrcGEPOperands[0]->getType(), - SrcGEPOperands.begin()+1, SrcGEPOperands.end()); - std::advance(GTI, SrcGEPOperands.size()-2); - if (isa(*GTI)) { - // If the src gep ends with a constant array index, merge this get into - // it, even if we have a non-zero array index. - Indices.insert(Indices.end(), SrcGEPOperands.begin()+1, - SrcGEPOperands.end()-1); - Indices.insert(Indices.end(), GEP.idx_begin(), GEP.idx_end()); - } } if (!Indices.empty()) return new GetElementPtrInst(SrcGEPOperands[0], Indices, GEP.getName()); - } else if (GlobalValue *GV = dyn_cast(GEP.getOperand(0))) { + } else if (GlobalValue *GV = dyn_cast(PtrOp)) { // GEP of global variable. If all of the indices for this GEP are // constants, we can promote this to a constexpr instead of an instruction. @@ -2721,7 +2711,7 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { // Replace all uses of the GEP with the new constexpr... return ReplaceInstUsesWith(GEP, CE); } - } else if (ConstantExpr *CE = dyn_cast(GEP.getOperand(0))) { + } else if (ConstantExpr *CE = dyn_cast(PtrOp)) { if (CE->getOpcode() == Instruction::Cast) { if (HasZeroPointerIndex) { // transform: GEP (cast [10 x ubyte]* X to [0 x ubyte]*), long 0, ... -- 2.11.0