Index: llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp =================================================================== --- llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp +++ llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp @@ -179,7 +179,8 @@ Root = 0x01, Internal = 0x02, Used = 0x04, - InBounds = 0x08 + InBounds = 0x08, + FirstGEPIndex = 0x10, }; uint32_t Flags = 0; @@ -188,10 +189,11 @@ Value *BaseVal; }; Value *Idx = nullptr; - Type *PTy = nullptr; // Type of the pointer operand. + Type *ElTy = nullptr; // Element type being GEPed here GepNode() : Parent(nullptr) {} - GepNode(const GepNode *N) : Flags(N->Flags), Idx(N->Idx), PTy(N->PTy) { + GepNode(const GepNode *N) + : Flags(N->Flags), Idx(N->Idx), ElTy(N->ElTy) { if (Flags & Root) BaseVal = N->BaseVal; else @@ -201,12 +203,6 @@ friend raw_ostream &operator<< (raw_ostream &OS, const GepNode &GN); }; - Type *next_type(Type *Ty, Value *Idx) { - if (auto *PTy = dyn_cast(Ty)) - return PTy->getElementType(); - return GetElementPtrInst::getTypeAtIndex(Ty, Idx); - } - raw_ostream &operator<< (raw_ostream &OS, const GepNode &GN) { OS << "{ {"; bool Comma = false; @@ -230,6 +226,11 @@ OS << ','; OS << "inbounds"; } + if (GN.Flags & GepNode::FirstGEPIndex) { + if (Comma) + OS << ','; + OS << "firstindex"; + } OS << "} "; if (GN.Flags & GepNode::Root) OS << "BaseVal:" << GN.BaseVal->getName() << '(' << GN.BaseVal << ')'; @@ -244,16 +245,16 @@ else OS << " =" << *GN.Idx; - OS << " PTy:"; - if (GN.PTy->isStructTy()) { - StructType *STy = cast(GN.PTy); + OS << " ElTy:"; + if (GN.ElTy->isStructTy()) { + StructType *STy = cast(GN.ElTy); if (!STy->isLiteral()) - OS << GN.PTy->getStructName(); + OS << GN.ElTy->getStructName(); else OS << ":" << *STy; } else - OS << *GN.PTy; + OS << *GN.ElTy; OS << " }"; return OS; } @@ -347,7 +348,8 @@ // chain. Link to it here. N->Parent = F->second; } - N->PTy = PtrOp->getType(); + N->Flags |= GepNode::FirstGEPIndex; + N->ElTy = GepI->getSourceElementType(); N->Idx = *GepI->idx_begin(); // Collect the list of users of this GEP instruction. Will add it to the @@ -370,20 +372,20 @@ // Skip the first index operand, since we only handle 0. This dereferences // the pointer operand. GepNode *PN = N; - Type *PtrTy = cast(PtrOp->getType())->getElementType(); + Type *ElTy = GepI->getSourceElementType(); for (User::op_iterator OI = GepI->idx_begin()+1, OE = GepI->idx_end(); OI != OE; ++OI) { Value *Op = *OI; GepNode *Nx = new (*Mem) GepNode; Nx->Parent = PN; // Link Nx to the previous node. Nx->Flags |= GepNode::Internal | InBounds; - Nx->PTy = PtrTy; + Nx->ElTy = ElTy; Nx->Idx = Op; Nodes.push_back(Nx); NodeOrder.insert(Nx); PN = Nx; - PtrTy = next_type(PtrTy, Op); + ElTy = GetElementPtrInst::getTypeAtIndex(ElTy, Op); } // After last node has been created, update the use information. @@ -482,7 +484,7 @@ // Include everything except flags and parent. FoldingSetNodeID ID; ID.AddPointer(N->Idx); - ID.AddPointer(N->PTy); + ID.AddPointer(N->ElTy); return ID.ComputeHash(); } @@ -1088,14 +1090,15 @@ GetElementPtrInst *NewInst = nullptr; Value *Input = RN->BaseVal; + Type *ElTy = RN->ElTy; Value **IdxList = new Value*[Num+1]; unsigned nax = 0; do { unsigned IdxC = 0; - // If the type of the input of the first node is not a pointer, - // we need to add an artificial i32 0 to the indices (because the - // actual input in the IR will be a pointer). - if (!NA[nax]->PTy->isPointerTy()) { + // If we're starting a new GEP but the first index is supposed to + // destructure, we need to add an artificial 0 index to skip the array + // dereference part. + if (!(NA[nax]->Flags & GepNode::FirstGEPIndex)) { Type *Int32Ty = Type::getInt32Ty(*Ctx); IdxList[IdxC++] = ConstantInt::get(Int32Ty, 0); } @@ -1106,20 +1109,18 @@ GepNode *N = NA[nax-1]; IdxList[IdxC++] = N->Idx; if (nax < Num) { - // We have to stop, if the expected type of the output of this node - // is not the same as the input type of the next node. - Type *NextTy = next_type(N->PTy, N->Idx); - if (NextTy != NA[nax]->PTy) + // We have to stop, if the next node was the start of a new GEP because + // that's an outer array access. + if (NA[nax]->Flags & GepNode::FirstGEPIndex) break; } } ArrayRef A(IdxList, IdxC); - Type *InpTy = Input->getType(); - Type *ElTy = cast(InpTy->getScalarType())->getElementType(); NewInst = GetElementPtrInst::Create(ElTy, Input, A, "cgep", &*At); NewInst->setIsInBounds(RN->Flags & GepNode::InBounds); LLVM_DEBUG(dbgs() << "new GEP: " << *NewInst << '\n'); Input = NewInst; + ElTy = NewInst->getResultElementType(); } while (nax <= Num); delete[] IdxList;