Index: include/polly/CodeGen/IslNodeBuilder.h =================================================================== --- include/polly/CodeGen/IslNodeBuilder.h +++ include/polly/CodeGen/IslNodeBuilder.h @@ -14,8 +14,10 @@ #define POLLY_ISL_NODE_BUILDER_H #include "polly/CodeGen/BlockGenerators.h" + #include "polly/CodeGen/IslExprBuilder.h" #include "polly/CodeGen/LoopGenerators.h" +#include "polly/ScopInfo.h" #include "isl/ctx.h" #include "isl/union_map.h" @@ -205,7 +207,7 @@ /// @brief Preload the memory access at @p AccessRange with @p Build. Value *preloadUnconditionally(__isl_take isl_set *AccessRange, - isl_ast_build *Build); + isl_ast_build *Build, Type *AccInstTy); /// @brief Preload the memory load access @p MA. /// @@ -218,8 +220,9 @@ /// MA_preload = load MA; /// use MA_preload Value *preloadInvariantLoad(const MemoryAccess &MA, - __isl_take isl_set *Domain, - __isl_keep isl_ast_build *Build); + __isl_take isl_set *Domain); + + void preloadInvariantEquivClass(const InvariantEquivClassTy &IAClass); void createForVector(__isl_take isl_ast_node *For, int VectorWidth); void createForSequential(__isl_take isl_ast_node *For); Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -677,17 +677,12 @@ /// @brief Ordered list type to hold accesses. using MemoryAccessList = std::forward_list; -/// @brief Type for invariant memory accesses and their domain context. -using InvariantAccessTy = std::pair; +/// @brief Type for equivalent invariant accesses and their domain context. +using InvariantEquivClassTy = + std::tuple; -/// @brief Type for an ordered list of invariant accesses. -using InvariantAccessListTy = std::forward_list; - -/// @brief Type for a class of equivalent invariant memory accesses. -using InvariantEquivClassTy = std::pair; - -/// @brief Type for multiple invariant memory accesses and their domain context. -using InvariantAccessesTy = SmallVector; +/// @brief Type for invariant accesses equivalence classes. +using InvariantEquivClassesTy = SmallVector; ///===----------------------------------------------------------------------===// /// @brief Statement of the Scop @@ -912,12 +907,11 @@ /// @brief Add @p Access to this statement's list of accesses. void addAccess(MemoryAccess *Access); - /// @brief Move the memory access in @p InvMAs to @p InvariantEquivClasses. + /// @brief Remove the memory access in @p InvMAs. /// /// Note that scalar accesses that are caused by any access in @p InvMAs will /// be eliminated too. - void hoistMemoryAccesses(MemoryAccessList &InvMAs, - InvariantAccessesTy &InvariantEquivClasses); + void removeMemoryAccesses(MemoryAccessList &InvMAs); typedef MemoryAccessVec::iterator iterator; typedef MemoryAccessVec::const_iterator const_iterator; @@ -1140,8 +1134,12 @@ /// group to ensure the SCoP is executed in an alias free environment. MinMaxVectorPairVectorTy MinMaxAliasGroups; + /// @brief Mapping from invariant loads to the representing invariant load of + /// their equivalnce class. + ValueToValueMap ParameterVMap; + /// @brief List of invariant accesses. - InvariantAccessesTy InvariantEquivClasses; + InvariantEquivClassesTy InvariantEquivClasses; /// @brief Scop constructor; invoked from ScopInfo::buildScop. Scop(Region &R, AccFuncMapType &AccFuncMap, ScopDetection &SD, @@ -1225,6 +1223,9 @@ /// Required inv. loads: LB[0], LB[1], (V, if it may alias with A or LB) void hoistInvariantLoads(); + /// @brief Add invairant loads in @p InvMAs to @p Stmt. + void addInvariantLoads(ScopStmt &Stmt, MemoryAccessList &InvMAs); + /// @brief Build the Context of the Scop. void buildContext(); @@ -1251,7 +1252,7 @@ /// @param S The SCEV to normalize. /// /// @return The representing SCEV for invariant loads or @p S if none. - const SCEV *getRepresentingInvariantLoadSCEV(const SCEV *S) const; + const SCEV *getRepresentingInvariantLoadSCEV(const SCEV *S); /// @brief Create a new SCoP statement for either @p BB or @p R. /// @@ -1345,7 +1346,7 @@ /// @param Parameter A SCEV that was recognized as a Parameter. /// /// @return The corresponding isl_id or NULL otherwise. - isl_id *getIdForParam(const SCEV *Parameter) const; + isl_id *getIdForParam(const SCEV *Parameter); /// @name Parameter Iterators /// @@ -1371,8 +1372,11 @@ /// @return The maximum depth of the loop. inline unsigned getMaxLoopDepth() const { return MaxLoopDepth; } + /// @brief Return the invariant equivalence class for @p Val if any. + const InvariantEquivClassTy *lookupInvariantEquivClass(Value *Val) const; + /// @brief Return the set of invariant accesses. - const InvariantAccessesTy &getInvariantAccesses() const { + const InvariantEquivClassesTy &getInvariantAccesses() const { return InvariantEquivClasses; } Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -1384,8 +1384,7 @@ void ScopStmt::dump() const { print(dbgs()); } -void ScopStmt::hoistMemoryAccesses(MemoryAccessList &InvMAs, - InvariantAccessesTy &InvariantEquivClasses) { +void ScopStmt::removeMemoryAccesses(MemoryAccessList &InvMAs) { // Remove all memory accesses in @p InvMAs from this statement together // with all scalar accesses that were caused by them. The tricky iteration @@ -1410,79 +1409,6 @@ InstructionToAccess.erase(MA->getAccessInstruction()); delete &MAL; } - - // Get the context under which this statement, hence the memory accesses, are - // executed. - isl_set *DomainCtx = isl_set_params(getDomain()); - DomainCtx = isl_set_remove_redundancies(DomainCtx); - DomainCtx = isl_set_detect_equalities(DomainCtx); - DomainCtx = isl_set_coalesce(DomainCtx); - - Scop &S = *getParent(); - ScalarEvolution &SE = *S.getSE(); - - // Project out all parameters that relate to loads in this statement that - // we will hoist. Otherwise we would have cyclic dependences on the - // constraints under which the hoisted loads are executed and we could not - // determine an order in which to preload them. This happens because not only - // lower bounds are part of the domain but also upper bounds. - for (MemoryAccess *MA : InvMAs) { - Instruction *AccInst = MA->getAccessInstruction(); - if (SE.isSCEVable(AccInst->getType())) { - isl_id *ParamId = S.getIdForParam(SE.getSCEV(AccInst)); - if (ParamId) { - int Dim = isl_set_find_dim_by_id(DomainCtx, isl_dim_param, ParamId); - DomainCtx = isl_set_eliminate(DomainCtx, isl_dim_param, Dim, 1); - } - isl_id_free(ParamId); - } - } - - for (MemoryAccess *MA : InvMAs) { - - // Check for another invariant access that accesses the same location as - // MA and if found consolidate them. Otherwise create a new equivalence - // class at the end of InvariantEquivClasses. - LoadInst *LInst = cast(MA->getAccessInstruction()); - const SCEV *PointerSCEV = SE.getSCEV(LInst->getPointerOperand()); - bool Consolidated = false; - - for (auto &IAClass : InvariantEquivClasses) { - const SCEV *ClassPointerSCEV = IAClass.first; - if (PointerSCEV != ClassPointerSCEV) - continue; - - Consolidated = true; - - // We created empty equivalence classes for required invariant loads - // in the beginning and might encounter one of them here. If so, this - // MA will be the first in that equivalence class. - auto &ClassList = IAClass.second; - if (ClassList.empty()) { - ClassList.push_front(std::make_pair(MA, isl_set_copy(DomainCtx))); - break; - } - - // If the equivalence class for MA is not empty we unify the execution - // context and add MA to the list of accesses that are in this class. - isl_set *IAClassDomainCtx = IAClass.second.front().second; - IAClassDomainCtx = - isl_set_union(IAClassDomainCtx, isl_set_copy(DomainCtx)); - ClassList.push_front(std::make_pair(MA, IAClassDomainCtx)); - break; - } - - if (Consolidated) - continue; - - // If we did not consolidate MA, thus did not find an equivalence class - // that for it, we create a new one. - InvariantAccessTy IA = std::make_pair(MA, isl_set_copy(DomainCtx)); - InvariantEquivClasses.emplace_back(InvariantEquivClassTy( - std::make_pair(PointerSCEV, InvariantAccessListTy({IA})))); - } - - isl_set_free(DomainCtx); } //===----------------------------------------------------------------------===// @@ -1494,25 +1420,8 @@ Context = NewContext; } -const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *S) const { - const SCEVUnknown *SU = dyn_cast_or_null(S); - if (!SU) - return S; - - LoadInst *LInst = dyn_cast(SU->getValue()); - if (!LInst) - return S; - - // Try to find an equivalence class for the load, if found return - // the SCEV for the representing element, otherwise return S. - const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); - for (const InvariantEquivClassTy &IAClass : InvariantEquivClasses) { - const SCEV *ClassPointerSCEV = IAClass.first; - if (ClassPointerSCEV == PointerSCEV) - return ClassPointerSCEV; - } - - return S; +const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *S) { + return SCEVParameterRewriter::rewrite(S, *SE, ParameterVMap); } void Scop::addParams(std::vector NewParameters) { @@ -1532,7 +1441,7 @@ } } -__isl_give isl_id *Scop::getIdForParam(const SCEV *Parameter) const { +__isl_give isl_id *Scop::getIdForParam(const SCEV *Parameter) { // Normalize the SCEV to get the representing element for an invariant load. Parameter = getRepresentingInvariantLoadSCEV(Parameter); @@ -1614,17 +1523,17 @@ } void Scop::buildInvariantEquivalenceClasses() { + DenseMap EquivClasses; + const InvariantLoadsSetTy &RIL = *SD.getRequiredInvariantLoads(&getRegion()); - SmallPtrSet ClassPointerSet; for (LoadInst *LInst : RIL) { const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); - // Skip the load if we already have a equivalence class for the pointer. - if (!ClassPointerSet.insert(PointerSCEV).second) - continue; - - InvariantEquivClasses.emplace_back(InvariantEquivClassTy( - std::make_pair(PointerSCEV, InvariantAccessListTy()))); + LoadInst *&ClassRep = EquivClasses[PointerSCEV]; + if (!ClassRep) + ClassRep = LInst; + else + ParameterVMap[LInst] = ClassRep; } } @@ -2504,8 +2413,7 @@ } for (const auto &IAClass : InvariantEquivClasses) - if (!IAClass.second.empty()) - isl_set_free(IAClass.second.front().second); + isl_set_free(std::get<2>(IAClass)); } void Scop::updateAccessDimensionality() { @@ -2540,6 +2448,85 @@ } } +const InvariantEquivClassTy *Scop::lookupInvariantEquivClass(Value *Val) const { + LoadInst *LInst = dyn_cast(Val); + if (!LInst) + return nullptr; + + if (Value *Rep = ParameterVMap.lookup(LInst)) + LInst = cast(Rep); + + const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); + for (auto &IAClass : InvariantEquivClasses) + if (PointerSCEV == std::get<0>(IAClass)) + return &IAClass; + + return nullptr; +} + +void Scop::addInvariantLoads(ScopStmt &Stmt, MemoryAccessList &InvMAs) { + + // Get the context under which the statement is executed. + isl_set *DomainCtx = isl_set_params(Stmt.getDomain()); + DomainCtx = isl_set_remove_redundancies(DomainCtx); + DomainCtx = isl_set_detect_equalities(DomainCtx); + DomainCtx = isl_set_coalesce(DomainCtx); + + // Project out all parameters that relate to loads in this statement that + // we will hoist. Otherwise we would have cyclic dependences on the + // constraints under which the hoisted loads are executed and we could not + // determine an order in which to preload them. This happens because not only + // lower bounds are part of the domain but also upper bounds. + for (MemoryAccess *MA : InvMAs) { + Instruction *AccInst = MA->getAccessInstruction(); + if (SE->isSCEVable(AccInst->getType())) { + isl_id *ParamId = getIdForParam(SE->getSCEV(AccInst)); + if (ParamId) { + int Dim = isl_set_find_dim_by_id(DomainCtx, isl_dim_param, ParamId); + DomainCtx = isl_set_eliminate(DomainCtx, isl_dim_param, Dim, 1); + } + isl_id_free(ParamId); + } + } + + for (MemoryAccess *MA : InvMAs) { + + // Check for another invariant access that accesses the same location as + // MA and if found consolidate them. Otherwise create a new equivalence + // class at the end of InvariantEquivClasses. + LoadInst *LInst = cast(MA->getAccessInstruction()); + const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); + + bool Consolidated = false; + for (auto &IAClass : InvariantEquivClasses) { + if (PointerSCEV != std::get<0>(IAClass)) + continue; + + Consolidated = true; + + // Add MA to the list of accesses that are in this class. + auto &MAs = std::get<1>(IAClass); + MAs.push_front(MA); + + // Unify the execution context of the class and this statement. + isl_set *&IAClassDomainCtx = std::get<2>(IAClass); + IAClassDomainCtx = isl_set_coalesce( + isl_set_union(IAClassDomainCtx, isl_set_copy(DomainCtx))); + break; + } + + if (Consolidated) + continue; + + // If we did not consolidate MA, thus did not find an equivalence class + // for it, we create a new one. + InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList{MA}, + isl_set_copy(DomainCtx)); + } + + isl_set_free(DomainCtx); +} + void Scop::hoistInvariantLoads() { isl_union_map *Writes = getWrites(); for (ScopStmt &Stmt : *this) { @@ -2594,7 +2581,8 @@ InvMAs.reverse(); // Transfer the memory access from the statement to the SCoP. - Stmt.hoistMemoryAccesses(InvMAs, InvariantEquivClasses); + Stmt.removeMemoryAccesses(InvMAs); + addInvariantLoads(Stmt, InvMAs); isl_set_free(Domain); } @@ -2617,67 +2605,6 @@ return; } } - - // We want invariant accesses to be sorted in a "natural order" because there - // might be dependences between invariant loads. These can be caused by - // indirect loads but also because an invariant load is only conditionally - // executed and the condition is dependent on another invariant load. As we - // want to do code generation in a straight forward way, e.g., preload the - // accesses in the list one after another, we sort them such that the - // preloaded values needed in the conditions will always be in front. Before - // we already ordered the accesses such that indirect loads can be resolved, - // thus we use a stable sort here. - - auto compareInvariantAccesses = [this]( - const InvariantEquivClassTy &IAClass0, - const InvariantEquivClassTy &IAClass1) { - const InvariantAccessTy &IA0 = IAClass0.second.front(); - const InvariantAccessTy &IA1 = IAClass1.second.front(); - - Instruction *AI0 = IA0.first->getAccessInstruction(); - Instruction *AI1 = IA1.first->getAccessInstruction(); - - const SCEV *S0 = - SE->isSCEVable(AI0->getType()) ? SE->getSCEV(AI0) : nullptr; - const SCEV *S1 = - SE->isSCEVable(AI1->getType()) ? SE->getSCEV(AI1) : nullptr; - - isl_id *Id0 = getIdForParam(S0); - isl_id *Id1 = getIdForParam(S1); - - if (Id0 && !Id1) { - isl_id_free(Id0); - isl_id_free(Id1); - return true; - } - - if (!Id0) { - isl_id_free(Id0); - isl_id_free(Id1); - return false; - } - - assert(Id0 && Id1); - - isl_set *Dom0 = IA0.second; - isl_set *Dom1 = IA1.second; - - int Dim0 = isl_set_find_dim_by_id(Dom0, isl_dim_param, Id0); - - bool Involves1Id0 = isl_set_involves_dims(Dom1, isl_dim_param, Dim0, 1); - assert(!Involves1Id0 || - !isl_set_involves_dims( - Dom0, isl_dim_param, - isl_set_find_dim_by_id(Dom0, isl_dim_param, Id1), 1)); - - isl_id_free(Id0); - isl_id_free(Id1); - - return Involves1Id0; - }; - - std::stable_sort(InvariantEquivClasses.begin(), InvariantEquivClasses.end(), - compareInvariantAccesses); } const ScopArrayInfo * @@ -2862,12 +2789,12 @@ OS.indent(4) << "Max Loop Depth: " << getMaxLoopDepth() << "\n"; OS.indent(4) << "Invariant Accesses: {\n"; for (const auto &IAClass : InvariantEquivClasses) { - if (IAClass.second.empty()) { - OS.indent(12) << "Class Pointer: " << IAClass.first << "\n"; + const auto &MAs = std::get<1>(IAClass); + if (MAs.empty()) { + OS.indent(12) << "Class Pointer: " << *std::get<0>(IAClass) << "\n"; } else { - IAClass.second.front().first->print(OS); - OS.indent(12) << "Execution Context: " << IAClass.second.front().second - << "\n"; + MAs.front()->print(OS); + OS.indent(12) << "Execution Context: " << std::get<2>(IAClass) << "\n"; } } OS.indent(4) << "}\n"; Index: lib/CodeGen/BlockGenerators.cpp =================================================================== --- lib/CodeGen/BlockGenerators.cpp +++ lib/CodeGen/BlockGenerators.cpp @@ -549,8 +549,10 @@ Value *ScalarAddr = EscapeMappingValue.first; // Reload the demoted instruction in the optimized version of the SCoP. - Instruction *EscapeInstReload = + Value *EscapeInstReload = Builder.CreateLoad(ScalarAddr, EscapeInst->getName() + ".final_reload"); + EscapeInstReload = + Builder.CreateBitOrPointerCast(EscapeInstReload, EscapeInst->getType()); // Create the merge PHI that merges the optimized and unoptimized version. PHINode *MergePHI = PHINode::Create(EscapeInst->getType(), 2, Index: lib/CodeGen/IslNodeBuilder.cpp =================================================================== --- lib/CodeGen/IslNodeBuilder.cpp +++ lib/CodeGen/IslNodeBuilder.cpp @@ -818,7 +818,15 @@ void IslNodeBuilder::materializeValue(isl_id *Id) { // If the Id is already mapped, skip it. if (!IDToValue.count(Id)) { - auto V = generateSCEV((const SCEV *)isl_id_get_user(Id)); + auto *ParamSCEV = (const SCEV *)isl_id_get_user(Id); + + SetVector Values; + findValues(ParamSCEV, Values); + for (auto *Val : Values) + if (const auto *IAClass = S.lookupInvariantEquivClass(Val)) + preloadInvariantEquivClass(*IAClass); + + auto *V = generateSCEV(ParamSCEV); IDToValue[Id] = V; } @@ -835,18 +843,22 @@ } Value *IslNodeBuilder::preloadUnconditionally(isl_set *AccessRange, - isl_ast_build *Build) { + isl_ast_build *Build, + Type *AccInstTy) { isl_pw_multi_aff *PWAccRel = isl_pw_multi_aff_from_set(AccessRange); PWAccRel = isl_pw_multi_aff_gist_params(PWAccRel, S.getContext()); isl_ast_expr *Access = isl_ast_build_access_from_pw_multi_aff(Build, PWAccRel); - return ExprBuilder.create(Access); + Value *PreloadVal = ExprBuilder.create(Access); + if (PreloadVal->getType() != AccInstTy) + PreloadVal = Builder.CreateBitOrPointerCast(PreloadVal, AccInstTy); + return PreloadVal; } Value *IslNodeBuilder::preloadInvariantLoad(const MemoryAccess &MA, - isl_set *Domain, - isl_ast_build *Build) { + isl_set *Domain) { + auto *Build = isl_ast_build_from_context(isl_set_universe(S.getParamSpace())); isl_set *AccessRange = isl_map_range(MA.getAccessRelation()); materializeParameters(AccessRange, false); @@ -854,9 +866,13 @@ bool AlwaysExecuted = isl_set_is_equal(Domain, Universe); isl_set_free(Universe); + Instruction *AccInst = MA.getAccessInstruction(); + Type *AccInstTy = AccInst->getType(); + + Value *PreloadVal; if (AlwaysExecuted) { isl_set_free(Domain); - return preloadUnconditionally(AccessRange, Build); + PreloadVal = preloadUnconditionally(AccessRange, Build, AccInstTy); } else { materializeParameters(Domain, false); @@ -890,67 +906,74 @@ Builder.CreateBr(MergeBB); Builder.SetInsertPoint(ExecBB->getTerminator()); - Instruction *AccInst = MA.getAccessInstruction(); - Type *AccInstTy = AccInst->getType(); - Value *PreAccInst = preloadUnconditionally(AccessRange, Build); + Value *PreAccInst = preloadUnconditionally(AccessRange, Build, AccInstTy); Builder.SetInsertPoint(MergeBB->getTerminator()); auto *MergePHI = Builder.CreatePHI( AccInstTy, 2, "polly.preload." + AccInst->getName() + ".merge"); MergePHI->addIncoming(PreAccInst, ExecBB); MergePHI->addIncoming(Constant::getNullValue(AccInstTy), CondBB); - - return MergePHI; + PreloadVal = MergePHI; } -} -void IslNodeBuilder::preloadInvariantLoads() { + isl_ast_build_free(Build); + return PreloadVal; +} - const auto &InvariantEquivClasses = S.getInvariantAccesses(); - if (InvariantEquivClasses.empty()) +void IslNodeBuilder::preloadInvariantEquivClass( + const InvariantEquivClassTy &IAClass) { + // For an equivalence class of invariant loads we pre-load the representing + // element with the unified execution context. However, we have to map all + // elements of the class to the one preloaded load as they are referenced + // during the code generation and therefor need to be mapped. + const MemoryAccessList &MAs = std::get<1>(IAClass); + assert(!MAs.empty()); + MemoryAccess *MA = MAs.front(); + assert(MA->isExplicit() && MA->isRead()); + + // If the access function was already mapped the preload of this equivalence + // class was triggered earlier already and doesn't need to be done again. + if (ValueMap.count(MA->getAccessInstruction())) return; - const Region &R = S.getRegion(); - BasicBlock *EntryBB = &Builder.GetInsertBlock()->getParent()->getEntryBlock(); + Instruction *AccInst = MA->getAccessInstruction(); + Type *AccInstTy = AccInst->getType(); - BasicBlock *PreLoadBB = - SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), &DT, &LI); - PreLoadBB->setName("polly.preload.begin"); - Builder.SetInsertPoint(PreLoadBB->begin()); + isl_set *Domain = isl_set_copy(std::get<2>(IAClass)); + Value *PreloadVal = preloadInvariantLoad(*MA, Domain); + assert(PreloadVal->getType() == AccInst->getType()); + for (const MemoryAccess *MA : MAs) { + Instruction *MAAccInst = MA->getAccessInstruction(); + ValueMap[MAAccInst] = + Builder.CreateBitOrPointerCast(PreloadVal, MAAccInst->getType()); + } - isl_ast_build *Build = - isl_ast_build_from_context(isl_set_universe(S.getParamSpace())); + if (SE.isSCEVable(AccInstTy)) { + isl_id *ParamId = S.getIdForParam(SE.getSCEV(AccInst)); + if (ParamId) + IDToValue[ParamId] = PreloadVal; + isl_id_free(ParamId); + } - // For each equivalence class of invariant loads we pre-load the representing - // element with the unified execution context. However, we have to map all - // elements of the class to the one preloaded load as they are referenced - // during the code generation and therefor need to be mapped. - for (const auto &IAClass : InvariantEquivClasses) { - - MemoryAccess *MA = IAClass.second.front().first; - assert(!MA->isImplicit()); - - isl_set *Domain = isl_set_copy(IAClass.second.front().second); - Instruction *AccInst = MA->getAccessInstruction(); - Value *PreloadVal = preloadInvariantLoad(*MA, Domain, Build); - for (const InvariantAccessTy &IA : IAClass.second) - ValueMap[IA.first->getAccessInstruction()] = PreloadVal; - - if (SE.isSCEVable(AccInst->getType())) { - isl_id *ParamId = S.getIdForParam(SE.getSCEV(AccInst)); - if (ParamId) - IDToValue[ParamId] = PreloadVal; - isl_id_free(ParamId); - } + auto *SAI = S.getScopArrayInfo(MA->getBaseAddr()); + for (auto *DerivedSAI : SAI->getDerivedSAIs()) { + Value *BasePtr = DerivedSAI->getBasePtr(); + BasePtr = Builder.CreateBitOrPointerCast(PreloadVal, BasePtr->getType()); + DerivedSAI->setBasePtr(BasePtr); + } - auto *SAI = S.getScopArrayInfo(MA->getBaseAddr()); - for (auto *DerivedSAI : SAI->getDerivedSAIs()) - DerivedSAI->setBasePtr(PreloadVal); + BasicBlock *EntryBB = &Builder.GetInsertBlock()->getParent()->getEntryBlock(); + auto *Alloca = new AllocaInst(AccInstTy, AccInst->getName() + ".preload.s2a"); + Alloca->insertBefore(EntryBB->getFirstInsertionPt()); + Builder.CreateStore(PreloadVal, Alloca); - // Use the escape system to get the correct value to users outside - // the SCoP. + const Region &R = S.getRegion(); + for (const MemoryAccess *MA : MAs) { + + Instruction *MAAccInst = MA->getAccessInstruction(); + // Use the escape system to get the correct value to users outside the SCoP. BlockGenerator::EscapeUserVectorTy EscapeUsers; - for (auto *U : AccInst->users()) + for (auto *U : MAAccInst->users()) if (Instruction *UI = dyn_cast(U)) if (!R.contains(UI)) EscapeUsers.push_back(UI); @@ -958,15 +981,24 @@ if (EscapeUsers.empty()) continue; - auto *Ty = AccInst->getType(); - auto *Alloca = new AllocaInst(Ty, AccInst->getName() + ".preload.s2a"); - Alloca->insertBefore(EntryBB->getFirstInsertionPt()); - Builder.CreateStore(PreloadVal, Alloca); - - EscapeMap[AccInst] = std::make_pair(Alloca, std::move(EscapeUsers)); + EscapeMap[MA->getAccessInstruction()] = + std::make_pair(Alloca, std::move(EscapeUsers)); } +} - isl_ast_build_free(Build); +void IslNodeBuilder::preloadInvariantLoads() { + + const auto &InvariantEquivClasses = S.getInvariantAccesses(); + if (InvariantEquivClasses.empty()) + return; + + BasicBlock *PreLoadBB = + SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), &DT, &LI); + PreLoadBB->setName("polly.preload.begin"); + Builder.SetInsertPoint(PreLoadBB->begin()); + + for (const auto &IAClass : InvariantEquivClasses) + preloadInvariantEquivClass(IAClass); } void IslNodeBuilder::addParameters(__isl_take isl_set *Context) { Index: test/Isl/CodeGen/inv-load-lnt-crash-cyclic-dependences.ll =================================================================== --- /dev/null +++ test/Isl/CodeGen/inv-load-lnt-crash-cyclic-dependences.ll @@ -0,0 +1,427 @@ +; RUN: opt %loadPolly -polly-codegen -S < %s +; +; This crashed at some point as we did not simplify the unified execution domain of the +; invariant load equivalence classes and therefor had cyclic dependences. Just verify +; it doesn't crash again. +; +; ModuleID = 'cyclicdep.ll' +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +%struct.CHpoints = type { i32, %struct.point, i32, %struct.CHpoints*, %struct.CHpoints* } +%struct.point = type { i32, i32 } + +@CHno = external global i32, align 4 + +; Function Attrs: nounwind argmemonly +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0 + +; Function Attrs: nounwind uwtable +define %struct.CHpoints* @remove_points(%struct.CHpoints* %PL) #1 { +entry: + %PL.addr = alloca %struct.CHpoints*, align 8 + %temp = alloca %struct.CHpoints*, align 8 + %rem = alloca %struct.CHpoints*, align 8 + %a = alloca %struct.point, align 4 + %c = alloca %struct.point, align 4 + %b = alloca %struct.point, align 4 + %i = alloca i32, align 4 + %done = alloca i32, align 4 + store %struct.CHpoints* %PL, %struct.CHpoints** %PL.addr, align 8 + store i32 0, i32* %i, align 4 + store i32 0, i32* %done, align 4 + %0 = load %struct.CHpoints*, %struct.CHpoints** %PL.addr, align 8 + %next = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %0, i32 0, i32 3 + %1 = load %struct.CHpoints*, %struct.CHpoints** %next, align 8 + store %struct.CHpoints* %1, %struct.CHpoints** %temp, align 8 + br label %while.cond + +while.cond: ; preds = %if.end, %entry + %2 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %3 = load %struct.CHpoints*, %struct.CHpoints** %PL.addr, align 8 + %cmp = icmp ne %struct.CHpoints* %2, %3 + br i1 %cmp, label %land.rhs, label %land.end + +land.rhs: ; preds = %while.cond + %4 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %next1 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %4, i32 0, i32 3 + %5 = load %struct.CHpoints*, %struct.CHpoints** %next1, align 8 + %6 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %cmp2 = icmp ne %struct.CHpoints* %5, %6 + br label %land.end + +land.end: ; preds = %land.rhs, %while.cond + %7 = phi i1 [ false, %while.cond ], [ %cmp2, %land.rhs ] + br i1 %7, label %while.body, label %while.end + +while.body: ; preds = %land.end + %8 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %prev = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %8, i32 0, i32 4 + %9 = load %struct.CHpoints*, %struct.CHpoints** %prev, align 8 + %node = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %9, i32 0, i32 1 + %10 = bitcast %struct.point* %a to i8* + %11 = bitcast %struct.point* %node to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %10, i8* %11, i64 8, i32 4, i1 false) + %12 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %node3 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %12, i32 0, i32 1 + %13 = bitcast %struct.point* %b to i8* + %14 = bitcast %struct.point* %node3 to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %13, i8* %14, i64 8, i32 4, i1 false) + %15 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %next4 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %15, i32 0, i32 3 + %16 = load %struct.CHpoints*, %struct.CHpoints** %next4, align 8 + %node5 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %16, i32 0, i32 1 + %17 = bitcast %struct.point* %c to i8* + %18 = bitcast %struct.point* %node5 to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %17, i8* %18, i64 8, i32 4, i1 false) + %y = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %19 = load i32, i32* %y, align 4 + %y6 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 1 + %20 = load i32, i32* %y6, align 4 + %sub = sub nsw i32 %19, %20 + %x = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %21 = load i32, i32* %x, align 4 + %x7 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %22 = load i32, i32* %x7, align 4 + %sub8 = sub nsw i32 %21, %22 + %mul = mul nsw i32 %sub, %sub8 + %x9 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 0 + %23 = load i32, i32* %x9, align 4 + %x10 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %24 = load i32, i32* %x10, align 4 + %sub11 = sub nsw i32 %23, %24 + %y12 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %25 = load i32, i32* %y12, align 4 + %y13 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 1 + %26 = load i32, i32* %y13, align 4 + %sub14 = sub nsw i32 %25, %26 + %mul15 = mul nsw i32 %sub11, %sub14 + %add = add nsw i32 %mul, %mul15 + %cmp16 = icmp eq i32 %add, 0 + br i1 %cmp16, label %land.lhs.true, label %if.else + +land.lhs.true: ; preds = %while.body + %x17 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %27 = load i32, i32* %x17, align 4 + %x18 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %28 = load i32, i32* %x18, align 4 + %cmp19 = icmp slt i32 %27, %28 + br i1 %cmp19, label %land.lhs.true.20, label %lor.lhs.false + +land.lhs.true.20: ; preds = %land.lhs.true + %x21 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %29 = load i32, i32* %x21, align 4 + %x22 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 0 + %30 = load i32, i32* %x22, align 4 + %cmp23 = icmp slt i32 %29, %30 + br i1 %cmp23, label %if.then, label %lor.lhs.false + +lor.lhs.false: ; preds = %land.lhs.true.20, %land.lhs.true + %x24 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %31 = load i32, i32* %x24, align 4 + %x25 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %32 = load i32, i32* %x25, align 4 + %cmp26 = icmp sgt i32 %31, %32 + br i1 %cmp26, label %land.lhs.true.27, label %lor.lhs.false.31 + +land.lhs.true.27: ; preds = %lor.lhs.false + %x28 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %33 = load i32, i32* %x28, align 4 + %x29 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 0 + %34 = load i32, i32* %x29, align 4 + %cmp30 = icmp sgt i32 %33, %34 + br i1 %cmp30, label %if.then, label %lor.lhs.false.31 + +lor.lhs.false.31: ; preds = %land.lhs.true.27, %lor.lhs.false + %x32 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %35 = load i32, i32* %x32, align 4 + %x33 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %36 = load i32, i32* %x33, align 4 + %cmp34 = icmp eq i32 %35, %36 + br i1 %cmp34, label %land.lhs.true.35, label %lor.lhs.false.47 + +land.lhs.true.35: ; preds = %lor.lhs.false.31 + %x36 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %37 = load i32, i32* %x36, align 4 + %x37 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 0 + %38 = load i32, i32* %x37, align 4 + %cmp38 = icmp eq i32 %37, %38 + br i1 %cmp38, label %land.lhs.true.39, label %lor.lhs.false.47 + +land.lhs.true.39: ; preds = %land.lhs.true.35 + %y40 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 1 + %39 = load i32, i32* %y40, align 4 + %y41 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %40 = load i32, i32* %y41, align 4 + %cmp42 = icmp slt i32 %39, %40 + br i1 %cmp42, label %land.lhs.true.43, label %lor.lhs.false.47 + +land.lhs.true.43: ; preds = %land.lhs.true.39 + %y44 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %41 = load i32, i32* %y44, align 4 + %y45 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 1 + %42 = load i32, i32* %y45, align 4 + %cmp46 = icmp slt i32 %41, %42 + br i1 %cmp46, label %if.then, label %lor.lhs.false.47 + +lor.lhs.false.47: ; preds = %land.lhs.true.43, %land.lhs.true.39, %land.lhs.true.35, %lor.lhs.false.31 + %x48 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %43 = load i32, i32* %x48, align 4 + %x49 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %44 = load i32, i32* %x49, align 4 + %cmp50 = icmp eq i32 %43, %44 + br i1 %cmp50, label %land.lhs.true.51, label %if.else + +land.lhs.true.51: ; preds = %lor.lhs.false.47 + %x52 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %45 = load i32, i32* %x52, align 4 + %x53 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 0 + %46 = load i32, i32* %x53, align 4 + %cmp54 = icmp eq i32 %45, %46 + br i1 %cmp54, label %land.lhs.true.55, label %if.else + +land.lhs.true.55: ; preds = %land.lhs.true.51 + %y56 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 1 + %47 = load i32, i32* %y56, align 4 + %y57 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %48 = load i32, i32* %y57, align 4 + %cmp58 = icmp sgt i32 %47, %48 + br i1 %cmp58, label %land.lhs.true.59, label %if.else + +land.lhs.true.59: ; preds = %land.lhs.true.55 + %y60 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %49 = load i32, i32* %y60, align 4 + %y61 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 1 + %50 = load i32, i32* %y61, align 4 + %cmp62 = icmp sgt i32 %49, %50 + br i1 %cmp62, label %if.then, label %if.else + +if.then: ; preds = %land.lhs.true.59, %land.lhs.true.43, %land.lhs.true.27, %land.lhs.true.20 + %51 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + store %struct.CHpoints* %51, %struct.CHpoints** %rem, align 8 + %52 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %prev63 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %52, i32 0, i32 4 + %53 = load %struct.CHpoints*, %struct.CHpoints** %prev63, align 8 + %54 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %next64 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %54, i32 0, i32 3 + %55 = load %struct.CHpoints*, %struct.CHpoints** %next64, align 8 + %prev65 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %55, i32 0, i32 4 + store %struct.CHpoints* %53, %struct.CHpoints** %prev65, align 8 + %56 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %next66 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %56, i32 0, i32 3 + %57 = load %struct.CHpoints*, %struct.CHpoints** %next66, align 8 + %58 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %prev67 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %58, i32 0, i32 4 + %59 = load %struct.CHpoints*, %struct.CHpoints** %prev67, align 8 + %next68 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %59, i32 0, i32 3 + store %struct.CHpoints* %57, %struct.CHpoints** %next68, align 8 + %60 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %next69 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %60, i32 0, i32 3 + %61 = load %struct.CHpoints*, %struct.CHpoints** %next69, align 8 + store %struct.CHpoints* %61, %struct.CHpoints** %temp, align 8 + %62 = load %struct.CHpoints*, %struct.CHpoints** %rem, align 8 + %63 = bitcast %struct.CHpoints* %62 to i8* + call void @free(i8* %63) #3 + %64 = load i32, i32* @CHno, align 4 + %dec = add nsw i32 %64, -1 + store i32 %dec, i32* @CHno, align 4 + br label %if.end + +if.else: ; preds = %land.lhs.true.59, %land.lhs.true.55, %land.lhs.true.51, %lor.lhs.false.47, %while.body + %65 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %next70 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %65, i32 0, i32 3 + %66 = load %struct.CHpoints*, %struct.CHpoints** %next70, align 8 + store %struct.CHpoints* %66, %struct.CHpoints** %temp, align 8 + br label %if.end + +if.end: ; preds = %if.else, %if.then + br label %while.cond + +while.end: ; preds = %land.end + %67 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %prev71 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %67, i32 0, i32 4 + %68 = load %struct.CHpoints*, %struct.CHpoints** %prev71, align 8 + %node72 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %68, i32 0, i32 1 + %69 = bitcast %struct.point* %a to i8* + %70 = bitcast %struct.point* %node72 to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %69, i8* %70, i64 8, i32 4, i1 false) + %71 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %node73 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %71, i32 0, i32 1 + %72 = bitcast %struct.point* %b to i8* + %73 = bitcast %struct.point* %node73 to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %72, i8* %73, i64 8, i32 4, i1 false) + %74 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %next74 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %74, i32 0, i32 3 + %75 = load %struct.CHpoints*, %struct.CHpoints** %next74, align 8 + %node75 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %75, i32 0, i32 1 + %76 = bitcast %struct.point* %c to i8* + %77 = bitcast %struct.point* %node75 to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %76, i8* %77, i64 8, i32 4, i1 false) + %y76 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %78 = load i32, i32* %y76, align 4 + %y77 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 1 + %79 = load i32, i32* %y77, align 4 + %sub78 = sub nsw i32 %78, %79 + %x79 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %80 = load i32, i32* %x79, align 4 + %x80 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %81 = load i32, i32* %x80, align 4 + %sub81 = sub nsw i32 %80, %81 + %mul82 = mul nsw i32 %sub78, %sub81 + %x83 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 0 + %82 = load i32, i32* %x83, align 4 + %x84 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %83 = load i32, i32* %x84, align 4 + %sub85 = sub nsw i32 %82, %83 + %y86 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %84 = load i32, i32* %y86, align 4 + %y87 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 1 + %85 = load i32, i32* %y87, align 4 + %sub88 = sub nsw i32 %84, %85 + %mul89 = mul nsw i32 %sub85, %sub88 + %add90 = add nsw i32 %mul82, %mul89 + %cmp91 = icmp eq i32 %add90, 0 + br i1 %cmp91, label %land.lhs.true.92, label %if.end.149 + +land.lhs.true.92: ; preds = %while.end + %x93 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %86 = load i32, i32* %x93, align 4 + %x94 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %87 = load i32, i32* %x94, align 4 + %cmp95 = icmp slt i32 %86, %87 + br i1 %cmp95, label %land.lhs.true.96, label %lor.lhs.false.100 + +land.lhs.true.96: ; preds = %land.lhs.true.92 + %x97 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %88 = load i32, i32* %x97, align 4 + %x98 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 0 + %89 = load i32, i32* %x98, align 4 + %cmp99 = icmp slt i32 %88, %89 + br i1 %cmp99, label %if.then.140, label %lor.lhs.false.100 + +lor.lhs.false.100: ; preds = %land.lhs.true.96, %land.lhs.true.92 + %x101 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %90 = load i32, i32* %x101, align 4 + %x102 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %91 = load i32, i32* %x102, align 4 + %cmp103 = icmp sgt i32 %90, %91 + br i1 %cmp103, label %land.lhs.true.104, label %lor.lhs.false.108 + +land.lhs.true.104: ; preds = %lor.lhs.false.100 + %x105 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %92 = load i32, i32* %x105, align 4 + %x106 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 0 + %93 = load i32, i32* %x106, align 4 + %cmp107 = icmp sgt i32 %92, %93 + br i1 %cmp107, label %if.then.140, label %lor.lhs.false.108 + +lor.lhs.false.108: ; preds = %land.lhs.true.104, %lor.lhs.false.100 + %x109 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %94 = load i32, i32* %x109, align 4 + %x110 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %95 = load i32, i32* %x110, align 4 + %cmp111 = icmp eq i32 %94, %95 + br i1 %cmp111, label %land.lhs.true.112, label %lor.lhs.false.124 + +land.lhs.true.112: ; preds = %lor.lhs.false.108 + %x113 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %96 = load i32, i32* %x113, align 4 + %x114 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 0 + %97 = load i32, i32* %x114, align 4 + %cmp115 = icmp eq i32 %96, %97 + br i1 %cmp115, label %land.lhs.true.116, label %lor.lhs.false.124 + +land.lhs.true.116: ; preds = %land.lhs.true.112 + %y117 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 1 + %98 = load i32, i32* %y117, align 4 + %y118 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %99 = load i32, i32* %y118, align 4 + %cmp119 = icmp slt i32 %98, %99 + br i1 %cmp119, label %land.lhs.true.120, label %lor.lhs.false.124 + +land.lhs.true.120: ; preds = %land.lhs.true.116 + %y121 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %100 = load i32, i32* %y121, align 4 + %y122 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 1 + %101 = load i32, i32* %y122, align 4 + %cmp123 = icmp slt i32 %100, %101 + br i1 %cmp123, label %if.then.140, label %lor.lhs.false.124 + +lor.lhs.false.124: ; preds = %land.lhs.true.120, %land.lhs.true.116, %land.lhs.true.112, %lor.lhs.false.108 + %x125 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %102 = load i32, i32* %x125, align 4 + %x126 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 0 + %103 = load i32, i32* %x126, align 4 + %cmp127 = icmp eq i32 %102, %103 + br i1 %cmp127, label %land.lhs.true.128, label %if.end.149 + +land.lhs.true.128: ; preds = %lor.lhs.false.124 + %x129 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 0 + %104 = load i32, i32* %x129, align 4 + %x130 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 0 + %105 = load i32, i32* %x130, align 4 + %cmp131 = icmp eq i32 %104, %105 + br i1 %cmp131, label %land.lhs.true.132, label %if.end.149 + +land.lhs.true.132: ; preds = %land.lhs.true.128 + %y133 = getelementptr inbounds %struct.point, %struct.point* %a, i32 0, i32 1 + %106 = load i32, i32* %y133, align 4 + %y134 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %107 = load i32, i32* %y134, align 4 + %cmp135 = icmp sgt i32 %106, %107 + br i1 %cmp135, label %land.lhs.true.136, label %if.end.149 + +land.lhs.true.136: ; preds = %land.lhs.true.132 + %y137 = getelementptr inbounds %struct.point, %struct.point* %b, i32 0, i32 1 + %108 = load i32, i32* %y137, align 4 + %y138 = getelementptr inbounds %struct.point, %struct.point* %c, i32 0, i32 1 + %109 = load i32, i32* %y138, align 4 + %cmp139 = icmp sgt i32 %108, %109 + br i1 %cmp139, label %if.then.140, label %if.end.149 + +if.then.140: ; preds = %land.lhs.true.136, %land.lhs.true.120, %land.lhs.true.104, %land.lhs.true.96 + %110 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + store %struct.CHpoints* %110, %struct.CHpoints** %rem, align 8 + %111 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %prev141 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %111, i32 0, i32 4 + %112 = load %struct.CHpoints*, %struct.CHpoints** %prev141, align 8 + %113 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %next142 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %113, i32 0, i32 3 + %114 = load %struct.CHpoints*, %struct.CHpoints** %next142, align 8 + %prev143 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %114, i32 0, i32 4 + store %struct.CHpoints* %112, %struct.CHpoints** %prev143, align 8 + %115 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %next144 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %115, i32 0, i32 3 + %116 = load %struct.CHpoints*, %struct.CHpoints** %next144, align 8 + %117 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %prev145 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %117, i32 0, i32 4 + %118 = load %struct.CHpoints*, %struct.CHpoints** %prev145, align 8 + %next146 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %118, i32 0, i32 3 + store %struct.CHpoints* %116, %struct.CHpoints** %next146, align 8 + %119 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + %next147 = getelementptr inbounds %struct.CHpoints, %struct.CHpoints* %119, i32 0, i32 3 + %120 = load %struct.CHpoints*, %struct.CHpoints** %next147, align 8 + store %struct.CHpoints* %120, %struct.CHpoints** %temp, align 8 + %121 = load %struct.CHpoints*, %struct.CHpoints** %rem, align 8 + %122 = bitcast %struct.CHpoints* %121 to i8* + call void @free(i8* %122) #3 + %123 = load i32, i32* @CHno, align 4 + %dec148 = add nsw i32 %123, -1 + store i32 %dec148, i32* @CHno, align 4 + br label %if.end.149 + +if.end.149: ; preds = %if.then.140, %land.lhs.true.136, %land.lhs.true.132, %land.lhs.true.128, %lor.lhs.false.124, %while.end + %124 = load %struct.CHpoints*, %struct.CHpoints** %temp, align 8 + ret %struct.CHpoints* %124 +} + +; Function Attrs: nounwind +declare void @free(i8*) #2 + +attributes #0 = { nounwind argmemonly } +attributes #1 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind } + +!llvm.ident = !{!0} + +!0 = !{!"clang version 3.8.0 (http://llvm.org/git/clang.git 5e171f9c91fb59933382f67a589af82fd8409eb7)"} Index: test/Isl/CodeGen/inv-load-lnt-crash-empty-equiv-class.ll =================================================================== --- /dev/null +++ test/Isl/CodeGen/inv-load-lnt-crash-empty-equiv-class.ll @@ -0,0 +1,364 @@ +; RUN: opt %loadPolly -polly-codegen -S < %s +; +; This crashed at some point as we did not handle empty equivalence classes +; well. Now we just verify it doesn't crash again. +; +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +%struct._tagTreeCCContext = type { [512 x %struct._tagTreeCCNode*], [512 x %struct._tagTreeCCOperation*], %struct.TreeCCInput*, %struct._tagTreeCCStream*, %struct._tagTreeCCStream*, %struct._tagTreeCCStream*, %struct._tagTreeCCStream*, %struct._tagTreeCCStream*, i16, i8*, i8*, i8*, i32, i32, i32, i8*, i8* } +%struct._tagTreeCCNode = type { %struct._tagTreeCCNode*, %struct._tagTreeCCNode*, %struct._tagTreeCCNode*, %struct._tagTreeCCNode*, i8*, i32, i32, i32, i8*, i64, %struct._tagTreeCCField*, %struct._tagTreeCCVirtual*, %struct._tagTreeCCNode*, %struct._tagTreeCCStream*, %struct._tagTreeCCStream* } +%struct._tagTreeCCField = type { i8*, i8*, i8*, i32, i8*, i64, %struct._tagTreeCCField* } +%struct._tagTreeCCVirtual = type { i8*, i8*, %struct._tagTreeCCParam*, %struct._tagTreeCCOperation*, %struct._tagTreeCCVirtual* } +%struct._tagTreeCCParam = type { i8*, i8*, i32, i32, %struct._tagTreeCCParam* } +%struct.TreeCCInput = type { i32, i8*, i8*, %struct._IO_FILE*, i8*, i64, i64, i32, i32, i32, i32, [1024 x i8] } +%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] } +%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 } +%struct._tagTreeCCStream = type { %struct._tagTreeCCContext*, i8*, i8*, i64, %struct._tagTreeCCStreamBuf*, %struct._tagTreeCCStreamBuf*, i32, i8, %struct._tagTreeCCStreamDefn*, %struct._tagTreeCCStreamDefn*, %struct._tagTreeCCStream* } +%struct._tagTreeCCStreamBuf = type { [2048 x i8], %struct._tagTreeCCStreamBuf* } +%struct._tagTreeCCStreamDefn = type { i8*, i8*, i64, i32, i32, %struct._tagTreeCCStreamDefn* } +%struct.TreeCCNonVirtual = type { void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperation*)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperation*)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperation*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i8*, i32, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCNode*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperationCase*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperationCase*, i32, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperationCase*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperationCase*, i32, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperation*)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperation*)* } +%struct._tagTreeCCOperation = type { i8*, i8*, i8*, i8*, %struct._tagTreeCCParam*, i32, i32, i8*, i64, %struct._tagTreeCCOperation*, %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase**, i32, %struct._tagTreeCCStream*, %struct._tagTreeCCStream* } +%struct._tagTreeCCOperationCase = type { %struct._tagTreeCCTrigger*, i8*, %struct._tagTreeCCOperation*, i32, i8*, i64, i8*, i64, %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase* } +%struct._tagTreeCCTrigger = type { %struct._tagTreeCCNode*, %struct._tagTreeCCTrigger* } + +@.str = external hidden unnamed_addr constant [6 x i8], align 1 +@.str.1 = external hidden unnamed_addr constant [39 x i8], align 1 + +; Function Attrs: nounwind uwtable +define hidden %struct._tagTreeCCOperationCase* @GenerateSwitch(%struct._tagTreeCCContext* %context, %struct._tagTreeCCStream* %stream, %struct.TreeCCNonVirtual* %nonVirt, %struct._tagTreeCCOperation* %oper, %struct._tagTreeCCOperationCase* %operCase, i32 %triggerNum) #0 { +entry: + %retval = alloca %struct._tagTreeCCOperationCase*, align 8 + %context.addr = alloca %struct._tagTreeCCContext*, align 8 + %stream.addr = alloca %struct._tagTreeCCStream*, align 8 + %nonVirt.addr = alloca %struct.TreeCCNonVirtual*, align 8 + %oper.addr = alloca %struct._tagTreeCCOperation*, align 8 + %operCase.addr = alloca %struct._tagTreeCCOperationCase*, align 8 + %triggerNum.addr = alloca i32, align 4 + %param = alloca %struct._tagTreeCCParam*, align 8 + %num = alloca i32, align 4 + %markBit = alloca i32, align 4 + %paramNum = alloca i32, align 4 + %firstCase = alloca %struct._tagTreeCCOperationCase*, align 8 + %trigger = alloca %struct._tagTreeCCTrigger*, align 8 + %node = alloca %struct._tagTreeCCNode*, align 8 + %isEnum = alloca i32, align 4 + %paramName = alloca [64 x i8], align 16 + store %struct._tagTreeCCContext* %context, %struct._tagTreeCCContext** %context.addr, align 8 + store %struct._tagTreeCCStream* %stream, %struct._tagTreeCCStream** %stream.addr, align 8 + store %struct.TreeCCNonVirtual* %nonVirt, %struct.TreeCCNonVirtual** %nonVirt.addr, align 8 + store %struct._tagTreeCCOperation* %oper, %struct._tagTreeCCOperation** %oper.addr, align 8 + store %struct._tagTreeCCOperationCase* %operCase, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + store i32 %triggerNum, i32* %triggerNum.addr, align 4 + %0 = load %struct._tagTreeCCOperation*, %struct._tagTreeCCOperation** %oper.addr, align 8 + %params = getelementptr inbounds %struct._tagTreeCCOperation, %struct._tagTreeCCOperation* %0, i32 0, i32 4 + %1 = load %struct._tagTreeCCParam*, %struct._tagTreeCCParam** %params, align 8 + store %struct._tagTreeCCParam* %1, %struct._tagTreeCCParam** %param, align 8 + store i32 0, i32* %num, align 4 + store i32 1, i32* %paramNum, align 4 + br label %while.cond + +while.cond: ; preds = %if.end.7, %entry + %2 = load %struct._tagTreeCCParam*, %struct._tagTreeCCParam** %param, align 8 + %cmp = icmp ne %struct._tagTreeCCParam* %2, null + br i1 %cmp, label %while.body, label %while.end + +while.body: ; preds = %while.cond + %3 = load %struct._tagTreeCCParam*, %struct._tagTreeCCParam** %param, align 8 + %flags = getelementptr inbounds %struct._tagTreeCCParam, %struct._tagTreeCCParam* %3, i32 0, i32 2 + %4 = load i32, i32* %flags, align 8 + %and = and i32 %4, 1 + %cmp1 = icmp ne i32 %and, 0 + br i1 %cmp1, label %if.then, label %if.end.4 + +if.then: ; preds = %while.body + %5 = load i32, i32* %num, align 4 + %6 = load i32, i32* %triggerNum.addr, align 4 + %cmp2 = icmp eq i32 %5, %6 + br i1 %cmp2, label %if.then.3, label %if.end + +if.then.3: ; preds = %if.then + br label %while.end + +if.end: ; preds = %if.then + %7 = load i32, i32* %num, align 4 + %inc = add nsw i32 %7, 1 + store i32 %inc, i32* %num, align 4 + br label %if.end.4 + +if.end.4: ; preds = %if.end, %while.body + %8 = load %struct._tagTreeCCParam*, %struct._tagTreeCCParam** %param, align 8 + %name = getelementptr inbounds %struct._tagTreeCCParam, %struct._tagTreeCCParam* %8, i32 0, i32 0 + %9 = load i8*, i8** %name, align 8 + %tobool = icmp ne i8* %9, null + br i1 %tobool, label %if.end.7, label %if.then.5 + +if.then.5: ; preds = %if.end.4 + %10 = load i32, i32* %paramNum, align 4 + %inc6 = add nsw i32 %10, 1 + store i32 %inc6, i32* %paramNum, align 4 + br label %if.end.7 + +if.end.7: ; preds = %if.then.5, %if.end.4 + %11 = load %struct._tagTreeCCParam*, %struct._tagTreeCCParam** %param, align 8 + %next = getelementptr inbounds %struct._tagTreeCCParam, %struct._tagTreeCCParam* %11, i32 0, i32 4 + %12 = load %struct._tagTreeCCParam*, %struct._tagTreeCCParam** %next, align 8 + store %struct._tagTreeCCParam* %12, %struct._tagTreeCCParam** %param, align 8 + br label %while.cond + +while.end: ; preds = %if.then.3, %while.cond + %13 = load %struct._tagTreeCCParam*, %struct._tagTreeCCParam** %param, align 8 + %tobool8 = icmp ne %struct._tagTreeCCParam* %13, null + br i1 %tobool8, label %if.end.17, label %if.then.9 + +if.then.9: ; preds = %while.end + %14 = load %struct._tagTreeCCOperation*, %struct._tagTreeCCOperation** %oper.addr, align 8 + %flags10 = getelementptr inbounds %struct._tagTreeCCOperation, %struct._tagTreeCCOperation* %14, i32 0, i32 5 + %15 = load i32, i32* %flags10, align 8 + %and11 = and i32 %15, 2 + %cmp12 = icmp ne i32 %and11, 0 + br i1 %cmp12, label %if.then.13, label %if.else + +if.then.13: ; preds = %if.then.9 + %16 = load %struct.TreeCCNonVirtual*, %struct.TreeCCNonVirtual** %nonVirt.addr, align 8 + %genCaseInline = getelementptr inbounds %struct.TreeCCNonVirtual, %struct.TreeCCNonVirtual* %16, i32 0, i32 8 + %17 = load void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperationCase*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperationCase*, i32)** %genCaseInline, align 8 + %18 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %19 = load %struct._tagTreeCCStream*, %struct._tagTreeCCStream** %stream.addr, align 8 + %20 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %21 = load i32, i32* %triggerNum.addr, align 4 + %sub = sub nsw i32 %21, 1 + call void %17(%struct._tagTreeCCContext* %18, %struct._tagTreeCCStream* %19, %struct._tagTreeCCOperationCase* %20, i32 %sub) + br label %if.end.15 + +if.else: ; preds = %if.then.9 + %22 = load %struct.TreeCCNonVirtual*, %struct.TreeCCNonVirtual** %nonVirt.addr, align 8 + %genCaseCall = getelementptr inbounds %struct.TreeCCNonVirtual, %struct.TreeCCNonVirtual* %22, i32 0, i32 7 + %23 = load void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperationCase*, i32, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct._tagTreeCCOperationCase*, i32, i32)** %genCaseCall, align 8 + %24 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %25 = load %struct._tagTreeCCStream*, %struct._tagTreeCCStream** %stream.addr, align 8 + %26 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %27 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %number = getelementptr inbounds %struct._tagTreeCCOperationCase, %struct._tagTreeCCOperationCase* %27, i32 0, i32 3 + %28 = load i32, i32* %number, align 8 + %29 = load i32, i32* %triggerNum.addr, align 4 + %sub14 = sub nsw i32 %29, 1 + call void %23(%struct._tagTreeCCContext* %24, %struct._tagTreeCCStream* %25, %struct._tagTreeCCOperationCase* %26, i32 %28, i32 %sub14) + br label %if.end.15 + +if.end.15: ; preds = %if.else, %if.then.13 + %30 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %next16 = getelementptr inbounds %struct._tagTreeCCOperationCase, %struct._tagTreeCCOperationCase* %30, i32 0, i32 8 + %31 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %next16, align 8 + store %struct._tagTreeCCOperationCase* %31, %struct._tagTreeCCOperationCase** %retval, align 8 + br label %return + +if.end.17: ; preds = %while.end + %32 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %33 = load %struct._tagTreeCCParam*, %struct._tagTreeCCParam** %param, align 8 + %type = getelementptr inbounds %struct._tagTreeCCParam, %struct._tagTreeCCParam* %33, i32 0, i32 1 + %34 = load i8*, i8** %type, align 8 + %call = call %struct._tagTreeCCNode* @TreeCCNodeFindByType(%struct._tagTreeCCContext* %32, i8* %34) + store %struct._tagTreeCCNode* %call, %struct._tagTreeCCNode** %node, align 8 + %35 = load %struct._tagTreeCCNode*, %struct._tagTreeCCNode** %node, align 8 + %flags18 = getelementptr inbounds %struct._tagTreeCCNode, %struct._tagTreeCCNode* %35, i32 0, i32 5 + %36 = load i32, i32* %flags18, align 8 + %and19 = and i32 %36, 8 + %cmp20 = icmp ne i32 %and19, 0 + %conv = zext i1 %cmp20 to i32 + store i32 %conv, i32* %isEnum, align 4 + %37 = load %struct._tagTreeCCParam*, %struct._tagTreeCCParam** %param, align 8 + %name21 = getelementptr inbounds %struct._tagTreeCCParam, %struct._tagTreeCCParam* %37, i32 0, i32 0 + %38 = load i8*, i8** %name21, align 8 + %tobool22 = icmp ne i8* %38, null + br i1 %tobool22, label %if.then.23, label %if.else.25 + +if.then.23: ; preds = %if.end.17 + %39 = load %struct.TreeCCNonVirtual*, %struct.TreeCCNonVirtual** %nonVirt.addr, align 8 + %genSwitchHead = getelementptr inbounds %struct.TreeCCNonVirtual, %struct.TreeCCNonVirtual* %39, i32 0, i32 3 + %40 = load void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i8*, i32, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i8*, i32, i32)** %genSwitchHead, align 8 + %41 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %42 = load %struct._tagTreeCCStream*, %struct._tagTreeCCStream** %stream.addr, align 8 + %43 = load %struct._tagTreeCCParam*, %struct._tagTreeCCParam** %param, align 8 + %name24 = getelementptr inbounds %struct._tagTreeCCParam, %struct._tagTreeCCParam* %43, i32 0, i32 0 + %44 = load i8*, i8** %name24, align 8 + %45 = load i32, i32* %triggerNum.addr, align 4 + %46 = load i32, i32* %isEnum, align 4 + call void %40(%struct._tagTreeCCContext* %41, %struct._tagTreeCCStream* %42, i8* %44, i32 %45, i32 %46) + br label %if.end.29 + +if.else.25: ; preds = %if.end.17 + %arraydecay = getelementptr inbounds [64 x i8], [64 x i8]* %paramName, i32 0, i32 0 + %47 = load i32, i32* %paramNum, align 4 + %call26 = call i32 (i8*, i8*, ...) @sprintf(i8* %arraydecay, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0), i32 %47) #3 + %48 = load %struct.TreeCCNonVirtual*, %struct.TreeCCNonVirtual** %nonVirt.addr, align 8 + %genSwitchHead27 = getelementptr inbounds %struct.TreeCCNonVirtual, %struct.TreeCCNonVirtual* %48, i32 0, i32 3 + %49 = load void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i8*, i32, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i8*, i32, i32)** %genSwitchHead27, align 8 + %50 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %51 = load %struct._tagTreeCCStream*, %struct._tagTreeCCStream** %stream.addr, align 8 + %arraydecay28 = getelementptr inbounds [64 x i8], [64 x i8]* %paramName, i32 0, i32 0 + %52 = load i32, i32* %triggerNum.addr, align 4 + %53 = load i32, i32* %isEnum, align 4 + call void %49(%struct._tagTreeCCContext* %50, %struct._tagTreeCCStream* %51, i8* %arraydecay28, i32 %52, i32 %53) + br label %if.end.29 + +if.end.29: ; preds = %if.else.25, %if.then.23 + %54 = load i32, i32* %triggerNum.addr, align 4 + %shl = shl i32 256, %54 + store i32 %shl, i32* %markBit, align 4 + %55 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %56 = load i32, i32* %markBit, align 4 + call void @TreeCCNodeClearMarking(%struct._tagTreeCCContext* %55, i32 %56) + %57 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + store %struct._tagTreeCCOperationCase* %57, %struct._tagTreeCCOperationCase** %firstCase, align 8 + br label %do.body + +do.body: ; preds = %land.end.53, %if.end.29 + %58 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %triggers = getelementptr inbounds %struct._tagTreeCCOperationCase, %struct._tagTreeCCOperationCase* %58, i32 0, i32 0 + %59 = load %struct._tagTreeCCTrigger*, %struct._tagTreeCCTrigger** %triggers, align 8 + store %struct._tagTreeCCTrigger* %59, %struct._tagTreeCCTrigger** %trigger, align 8 + store i32 0, i32* %num, align 4 + br label %while.cond.30 + +while.cond.30: ; preds = %while.body.35, %do.body + %60 = load %struct._tagTreeCCTrigger*, %struct._tagTreeCCTrigger** %trigger, align 8 + %cmp31 = icmp ne %struct._tagTreeCCTrigger* %60, null + br i1 %cmp31, label %land.rhs, label %land.end + +land.rhs: ; preds = %while.cond.30 + %61 = load i32, i32* %num, align 4 + %62 = load i32, i32* %triggerNum.addr, align 4 + %cmp33 = icmp slt i32 %61, %62 + br label %land.end + +land.end: ; preds = %land.rhs, %while.cond.30 + %63 = phi i1 [ false, %while.cond.30 ], [ %cmp33, %land.rhs ] + br i1 %63, label %while.body.35, label %while.end.38 + +while.body.35: ; preds = %land.end + %64 = load i32, i32* %num, align 4 + %inc36 = add nsw i32 %64, 1 + store i32 %inc36, i32* %num, align 4 + %65 = load %struct._tagTreeCCTrigger*, %struct._tagTreeCCTrigger** %trigger, align 8 + %next37 = getelementptr inbounds %struct._tagTreeCCTrigger, %struct._tagTreeCCTrigger* %65, i32 0, i32 1 + %66 = load %struct._tagTreeCCTrigger*, %struct._tagTreeCCTrigger** %next37, align 8 + store %struct._tagTreeCCTrigger* %66, %struct._tagTreeCCTrigger** %trigger, align 8 + br label %while.cond.30 + +while.end.38: ; preds = %land.end + %67 = load %struct._tagTreeCCTrigger*, %struct._tagTreeCCTrigger** %trigger, align 8 + %tobool39 = icmp ne %struct._tagTreeCCTrigger* %67, null + br i1 %tobool39, label %if.then.40, label %if.end.46 + +if.then.40: ; preds = %while.end.38 + %68 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %69 = load %struct._tagTreeCCStream*, %struct._tagTreeCCStream** %stream.addr, align 8 + %70 = load %struct.TreeCCNonVirtual*, %struct.TreeCCNonVirtual** %nonVirt.addr, align 8 + %71 = load %struct._tagTreeCCTrigger*, %struct._tagTreeCCTrigger** %trigger, align 8 + %node41 = getelementptr inbounds %struct._tagTreeCCTrigger, %struct._tagTreeCCTrigger* %71, i32 0, i32 0 + %72 = load %struct._tagTreeCCNode*, %struct._tagTreeCCNode** %node41, align 8 + %73 = load i32, i32* %markBit, align 4 + %74 = load i32, i32* %triggerNum.addr, align 4 + %call42 = call i32 @GenerateSelectors(%struct._tagTreeCCContext* %68, %struct._tagTreeCCStream* %69, %struct.TreeCCNonVirtual* %70, %struct._tagTreeCCNode* %72, i32 %73, i32 %74) + %tobool43 = icmp ne i32 %call42, 0 + br i1 %tobool43, label %if.end.45, label %if.then.44 + +if.then.44: ; preds = %if.then.40 + %75 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %input = getelementptr inbounds %struct._tagTreeCCContext, %struct._tagTreeCCContext* %75, i32 0, i32 2 + %76 = load %struct.TreeCCInput*, %struct.TreeCCInput** %input, align 8 + %77 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %filename = getelementptr inbounds %struct._tagTreeCCOperationCase, %struct._tagTreeCCOperationCase* %77, i32 0, i32 4 + %78 = load i8*, i8** %filename, align 8 + %79 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %linenum = getelementptr inbounds %struct._tagTreeCCOperationCase, %struct._tagTreeCCOperationCase* %79, i32 0, i32 5 + %80 = load i64, i64* %linenum, align 8 + call void (%struct.TreeCCInput*, i8*, i64, i8*, ...) @TreeCCErrorOnLine(%struct.TreeCCInput* %76, i8* %78, i64 %80, i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.1, i32 0, i32 0)) + br label %if.end.45 + +if.end.45: ; preds = %if.then.44, %if.then.40 + br label %if.end.46 + +if.end.46: ; preds = %if.end.45, %while.end.38 + %81 = load %struct.TreeCCNonVirtual*, %struct.TreeCCNonVirtual** %nonVirt.addr, align 8 + %genEndSelectors = getelementptr inbounds %struct.TreeCCNonVirtual, %struct.TreeCCNonVirtual* %81, i32 0, i32 5 + %82 = load void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i32)** %genEndSelectors, align 8 + %83 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %84 = load %struct._tagTreeCCStream*, %struct._tagTreeCCStream** %stream.addr, align 8 + %85 = load i32, i32* %triggerNum.addr, align 4 + call void %82(%struct._tagTreeCCContext* %83, %struct._tagTreeCCStream* %84, i32 %85) + %86 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %87 = load %struct._tagTreeCCStream*, %struct._tagTreeCCStream** %stream.addr, align 8 + %88 = load %struct.TreeCCNonVirtual*, %struct.TreeCCNonVirtual** %nonVirt.addr, align 8 + %89 = load %struct._tagTreeCCOperation*, %struct._tagTreeCCOperation** %oper.addr, align 8 + %90 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %91 = load i32, i32* %triggerNum.addr, align 4 + %add = add nsw i32 %91, 1 + %call47 = call %struct._tagTreeCCOperationCase* @GenerateSwitch(%struct._tagTreeCCContext* %86, %struct._tagTreeCCStream* %87, %struct.TreeCCNonVirtual* %88, %struct._tagTreeCCOperation* %89, %struct._tagTreeCCOperationCase* %90, i32 %add) + store %struct._tagTreeCCOperationCase* %call47, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %92 = load %struct.TreeCCNonVirtual*, %struct.TreeCCNonVirtual** %nonVirt.addr, align 8 + %genEndCase = getelementptr inbounds %struct.TreeCCNonVirtual, %struct.TreeCCNonVirtual* %92, i32 0, i32 10 + %93 = load void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i32)** %genEndCase, align 8 + %94 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %95 = load %struct._tagTreeCCStream*, %struct._tagTreeCCStream** %stream.addr, align 8 + %96 = load i32, i32* %triggerNum.addr, align 4 + call void %93(%struct._tagTreeCCContext* %94, %struct._tagTreeCCStream* %95, i32 %96) + br label %do.cond + +do.cond: ; preds = %if.end.46 + %97 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %cmp48 = icmp ne %struct._tagTreeCCOperationCase* %97, null + br i1 %cmp48, label %land.rhs.50, label %land.end.53 + +land.rhs.50: ; preds = %do.cond + %98 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %firstCase, align 8 + %99 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + %100 = load i32, i32* %triggerNum.addr, align 4 + %call51 = call i32 @LevelsMatch(%struct._tagTreeCCOperationCase* %98, %struct._tagTreeCCOperationCase* %99, i32 %100) + %tobool52 = icmp ne i32 %call51, 0 + br label %land.end.53 + +land.end.53: ; preds = %land.rhs.50, %do.cond + %101 = phi i1 [ false, %do.cond ], [ %tobool52, %land.rhs.50 ] + br i1 %101, label %do.body, label %do.end + +do.end: ; preds = %land.end.53 + %102 = load %struct.TreeCCNonVirtual*, %struct.TreeCCNonVirtual** %nonVirt.addr, align 8 + %genEndSwitch = getelementptr inbounds %struct.TreeCCNonVirtual, %struct.TreeCCNonVirtual* %102, i32 0, i32 11 + %103 = load void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i32)*, void (%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, i32)** %genEndSwitch, align 8 + %104 = load %struct._tagTreeCCContext*, %struct._tagTreeCCContext** %context.addr, align 8 + %105 = load %struct._tagTreeCCStream*, %struct._tagTreeCCStream** %stream.addr, align 8 + %106 = load i32, i32* %triggerNum.addr, align 4 + call void %103(%struct._tagTreeCCContext* %104, %struct._tagTreeCCStream* %105, i32 %106) + %107 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %operCase.addr, align 8 + store %struct._tagTreeCCOperationCase* %107, %struct._tagTreeCCOperationCase** %retval, align 8 + br label %return + +return: ; preds = %do.end, %if.end.15 + %108 = load %struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase** %retval, align 8 + ret %struct._tagTreeCCOperationCase* %108 +} + +declare %struct._tagTreeCCNode* @TreeCCNodeFindByType(%struct._tagTreeCCContext*, i8*) #1 + +; Function Attrs: nounwind +declare i32 @sprintf(i8*, i8*, ...) #2 + +declare void @TreeCCNodeClearMarking(%struct._tagTreeCCContext*, i32) #1 + +; Function Attrs: nounwind uwtable +declare hidden i32 @GenerateSelectors(%struct._tagTreeCCContext*, %struct._tagTreeCCStream*, %struct.TreeCCNonVirtual*, %struct._tagTreeCCNode*, i32, i32) #0 + +declare void @TreeCCErrorOnLine(%struct.TreeCCInput*, i8*, i64, i8*, ...) #1 + +; Function Attrs: nounwind uwtable +declare hidden i32 @LevelsMatch(%struct._tagTreeCCOperationCase*, %struct._tagTreeCCOperationCase*, i32) #0 + +attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind } + +!llvm.ident = !{!0} + +!0 = !{!"clang version 3.8.0 (http://llvm.org/git/clang.git 5e171f9c91fb59933382f67a589af82fd8409eb7)"} Index: test/Isl/CodeGen/inv-load-lnt-crash-wrong-order-2.ll =================================================================== --- /dev/null +++ test/Isl/CodeGen/inv-load-lnt-crash-wrong-order-2.ll @@ -0,0 +1,1089 @@ +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; +; This crashed our codegen at some point, verify it runs through +; +; CHECK: polly.start +; +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +%struct.Rule = type { i32, %struct.Production*, i32, i32, i32, i32, %struct.anon.0, %struct.Elem*, %struct.Code, %struct.Code, %struct.anon.1, i32, %struct.Rule* } +%struct.Production = type { i8*, i32, %struct.anon, i32, i8, %struct.Rule*, [8 x %struct.Production*], [8 x %struct.Declaration*], %struct.State*, %struct.Elem*, %struct.Term*, %struct.Production* } +%struct.anon = type { i32, i32, %struct.Rule**, [3 x %struct.Rule*] } +%struct.Declaration = type { %struct.Elem*, i32, i32 } +%struct.State = type { i32, i64, %struct.anon.2, %struct.anon.3, %struct.VecGoto, %struct.VecAction, %struct.VecAction, %struct.VecHint, %struct.VecHint, %struct.Scanner, i8, i8*, i32, %struct.State*, %struct.State*, %struct.Rule*, %struct.Rule* } +%struct.anon.2 = type { i32, i32, %struct.Elem**, [3 x %struct.Elem*] } +%struct.anon.3 = type { i32, i32, %struct.Elem**, [3 x %struct.Elem*] } +%struct.VecGoto = type { i32, i32, %struct.Goto**, [3 x %struct.Goto*] } +%struct.Goto = type { %struct.Elem*, %struct.State* } +%struct.VecAction = type { i32, i32, %struct.Action**, [3 x %struct.Action*] } +%struct.Action = type { i32, %struct.Term*, %struct.Rule*, %struct.State*, i32, i8* } +%struct.VecHint = type { i32, i32, %struct.Hint**, [3 x %struct.Hint*] } +%struct.Hint = type { i32, %struct.State*, %struct.Rule* } +%struct.Scanner = type { %struct.VecScanState, %struct.VecScanStateTransition } +%struct.VecScanState = type { i32, i32, %struct.ScanState**, [3 x %struct.ScanState*] } +%struct.ScanState = type { i32, [256 x %struct.ScanState*], %struct.VecAction, %struct.VecAction, [256 x %struct.ScanStateTransition*] } +%struct.ScanStateTransition = type { i32, %struct.VecAction, %struct.VecAction } +%struct.VecScanStateTransition = type { i32, i32, %struct.ScanStateTransition**, [3 x %struct.ScanStateTransition*] } +%struct.Term = type { i32, i32, i32, i32, i32, i8*, i32, i8, %struct.Production* } +%struct.anon.0 = type { i32, i32, %struct.Elem**, [3 x %struct.Elem*] } +%struct.Elem = type { i32, i32, %struct.Rule*, %union.anon } +%union.anon = type { %struct.Unresolved } +%struct.Unresolved = type { i8*, i32 } +%struct.Code = type { i8*, i32 } +%struct.anon.1 = type { i32, i32, %struct.Code**, [3 x %struct.Code*] } +%struct.Grammar = type { i8*, %struct.anon.4, %struct.anon.5, %struct.anon.6, %struct.Code, %struct.Code*, i32, %struct.anon.7, %struct.anon.8, i8*, i32, i32, i32, i32, i32, i32, i32, [256 x i8], i32, i32, i32, i32, i32, %struct.Production*, %struct.Rule*, %struct.Elem*, i32, i32, i32, i32 } +%struct.anon.4 = type { i32, i32, %struct.Production**, [3 x %struct.Production*] } +%struct.anon.5 = type { i32, i32, %struct.Term**, [3 x %struct.Term*] } +%struct.anon.6 = type { i32, i32, %struct.State**, [3 x %struct.State*] } +%struct.anon.7 = type { i32, i32, %struct.Declaration**, [3 x %struct.Declaration*] } +%struct.anon.8 = type { i32, i32, %struct.D_Pass**, [3 x %struct.D_Pass*] } +%struct.D_Pass = type { i8*, i32, i32, i32 } +%struct.EqState = type { %struct.State*, %struct.Rule*, %struct.State* } + +@.str.32 = external hidden unnamed_addr constant [2 x i8], align 1 +@verbose_level = external global i32, align 4 +@.str.37 = external hidden unnamed_addr constant [10 x i8], align 1 +@.str.38 = external hidden unnamed_addr constant [20 x i8], align 1 +@.str.39 = external hidden unnamed_addr constant [11 x i8], align 1 +@.str.40 = external hidden unnamed_addr constant [3 x i8], align 1 +@.str.41 = external hidden unnamed_addr constant [4 x i8], align 1 +@.str.42 = external hidden unnamed_addr constant [2 x i8], align 1 +@.str.43 = external hidden unnamed_addr constant [18 x i8], align 1 + +; Function Attrs: nounwind +declare noalias i8* @malloc(i64) #0 + +; Function Attrs: nounwind argmemonly +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) #1 + +declare i32 @printf(i8*, ...) #2 + +; Function Attrs: nounwind +declare void @free(i8*) #0 + +; Function Attrs: nounwind uwtable +declare void @print_rule(%struct.Rule*) #3 + +; Function Attrs: nounwind uwtable +define void @build_eq(%struct.Grammar* %g) #3 { +entry: + %g.addr = alloca %struct.Grammar*, align 8 + %i = alloca i32, align 4 + %j = alloca i32, align 4 + %k = alloca i32, align 4 + %changed = alloca i32, align 4 + %x = alloca i32, align 4 + %xx = alloca i32, align 4 + %s = alloca %struct.State*, align 8 + %ss = alloca %struct.State*, align 8 + %eq = alloca %struct.EqState*, align 8 + %e = alloca %struct.EqState*, align 8 + %ee = alloca %struct.EqState*, align 8 + %ge = alloca %struct.EqState*, align 8 + %gee = alloca %struct.EqState*, align 8 + store %struct.Grammar* %g, %struct.Grammar** %g.addr, align 8 + store i32 1, i32* %changed, align 4 + %0 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states = getelementptr inbounds %struct.Grammar, %struct.Grammar* %0, i32 0, i32 3 + %n = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states, i32 0, i32 0 + %1 = load i32, i32* %n, align 8 + %conv = zext i32 %1 to i64 + %mul = mul i64 24, %conv + %call = call noalias i8* @malloc(i64 %mul) #4 + %2 = bitcast i8* %call to %struct.EqState* + store %struct.EqState* %2, %struct.EqState** %eq, align 8 + %3 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %4 = bitcast %struct.EqState* %3 to i8* + %5 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states1 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %5, i32 0, i32 3 + %n2 = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states1, i32 0, i32 0 + %6 = load i32, i32* %n2, align 8 + %conv3 = zext i32 %6 to i64 + %mul4 = mul i64 24, %conv3 + call void @llvm.memset.p0i8.i64(i8* %4, i8 0, i64 %mul4, i32 8, i1 false) + br label %while.cond + +while.cond: ; preds = %for.end.259, %entry + %7 = load i32, i32* %changed, align 4 + %tobool = icmp ne i32 %7, 0 + br i1 %tobool, label %while.body, label %while.end + +while.body: ; preds = %while.cond + store i32 0, i32* %changed, align 4 + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc.257, %while.body + %8 = load i32, i32* %i, align 4 + %9 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states5 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %9, i32 0, i32 3 + %n6 = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states5, i32 0, i32 0 + %10 = load i32, i32* %n6, align 8 + %cmp = icmp ult i32 %8, %10 + br i1 %cmp, label %for.body, label %for.end.259 + +for.body: ; preds = %for.cond + %11 = load i32, i32* %i, align 4 + %idxprom = sext i32 %11 to i64 + %12 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states8 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %12, i32 0, i32 3 + %v = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states8, i32 0, i32 2 + %13 = load %struct.State**, %struct.State*** %v, align 8 + %arrayidx = getelementptr inbounds %struct.State*, %struct.State** %13, i64 %idxprom + %14 = load %struct.State*, %struct.State** %arrayidx, align 8 + store %struct.State* %14, %struct.State** %s, align 8 + %15 = load %struct.State*, %struct.State** %s, align 8 + %index = getelementptr inbounds %struct.State, %struct.State* %15, i32 0, i32 0 + %16 = load i32, i32* %index, align 8 + %idxprom9 = zext i32 %16 to i64 + %17 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx10 = getelementptr inbounds %struct.EqState, %struct.EqState* %17, i64 %idxprom9 + store %struct.EqState* %arrayidx10, %struct.EqState** %e, align 8 + %18 = load i32, i32* %i, align 4 + %add = add nsw i32 %18, 1 + store i32 %add, i32* %j, align 4 + br label %for.cond.11 + +for.cond.11: ; preds = %for.inc.254, %for.body + %19 = load i32, i32* %j, align 4 + %20 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states12 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %20, i32 0, i32 3 + %n13 = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states12, i32 0, i32 0 + %21 = load i32, i32* %n13, align 8 + %cmp14 = icmp ult i32 %19, %21 + br i1 %cmp14, label %for.body.16, label %for.end.256 + +for.body.16: ; preds = %for.cond.11 + %22 = load i32, i32* %j, align 4 + %idxprom17 = sext i32 %22 to i64 + %23 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states18 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %23, i32 0, i32 3 + %v19 = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states18, i32 0, i32 2 + %24 = load %struct.State**, %struct.State*** %v19, align 8 + %arrayidx20 = getelementptr inbounds %struct.State*, %struct.State** %24, i64 %idxprom17 + %25 = load %struct.State*, %struct.State** %arrayidx20, align 8 + store %struct.State* %25, %struct.State** %ss, align 8 + %26 = load %struct.State*, %struct.State** %ss, align 8 + %index21 = getelementptr inbounds %struct.State, %struct.State* %26, i32 0, i32 0 + %27 = load i32, i32* %index21, align 8 + %idxprom22 = zext i32 %27 to i64 + %28 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx23 = getelementptr inbounds %struct.EqState, %struct.EqState* %28, i64 %idxprom22 + store %struct.EqState* %arrayidx23, %struct.EqState** %ee, align 8 + %29 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq24 = getelementptr inbounds %struct.EqState, %struct.EqState* %29, i32 0, i32 0 + %30 = load %struct.State*, %struct.State** %eq24, align 8 + %tobool25 = icmp ne %struct.State* %30, null + br i1 %tobool25, label %if.then, label %lor.lhs.false + +lor.lhs.false: ; preds = %for.body.16 + %31 = load %struct.EqState*, %struct.EqState** %ee, align 8 + %eq26 = getelementptr inbounds %struct.EqState, %struct.EqState* %31, i32 0, i32 0 + %32 = load %struct.State*, %struct.State** %eq26, align 8 + %tobool27 = icmp ne %struct.State* %32, null + br i1 %tobool27, label %if.then, label %if.end + +if.then: ; preds = %lor.lhs.false, %for.body.16 + br label %for.inc.254 + +if.end: ; preds = %lor.lhs.false + %33 = load %struct.State*, %struct.State** %s, align 8 + %same_shifts = getelementptr inbounds %struct.State, %struct.State* %33, i32 0, i32 13 + %34 = load %struct.State*, %struct.State** %same_shifts, align 8 + %35 = load %struct.State*, %struct.State** %ss, align 8 + %same_shifts28 = getelementptr inbounds %struct.State, %struct.State* %35, i32 0, i32 13 + %36 = load %struct.State*, %struct.State** %same_shifts28, align 8 + %cmp29 = icmp ne %struct.State* %34, %36 + br i1 %cmp29, label %land.lhs.true, label %if.end.35 + +land.lhs.true: ; preds = %if.end + %37 = load %struct.State*, %struct.State** %ss, align 8 + %same_shifts31 = getelementptr inbounds %struct.State, %struct.State* %37, i32 0, i32 13 + %38 = load %struct.State*, %struct.State** %same_shifts31, align 8 + %39 = load %struct.State*, %struct.State** %s, align 8 + %cmp32 = icmp ne %struct.State* %38, %39 + br i1 %cmp32, label %if.then.34, label %if.end.35 + +if.then.34: ; preds = %land.lhs.true + br label %for.inc.254 + +if.end.35: ; preds = %land.lhs.true, %if.end + %40 = load %struct.State*, %struct.State** %s, align 8 + %gotos = getelementptr inbounds %struct.State, %struct.State* %40, i32 0, i32 4 + %n36 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos, i32 0, i32 0 + %41 = load i32, i32* %n36, align 8 + %42 = load %struct.State*, %struct.State** %ss, align 8 + %gotos37 = getelementptr inbounds %struct.State, %struct.State* %42, i32 0, i32 4 + %n38 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos37, i32 0, i32 0 + %43 = load i32, i32* %n38, align 8 + %cmp39 = icmp ne i32 %41, %43 + br i1 %cmp39, label %if.then.41, label %if.end.42 + +if.then.41: ; preds = %if.end.35 + br label %for.inc.254 + +if.end.42: ; preds = %if.end.35 + store i32 0, i32* %k, align 4 + br label %for.cond.43 + +for.cond.43: ; preds = %for.inc, %if.end.42 + %44 = load i32, i32* %k, align 4 + %45 = load %struct.State*, %struct.State** %s, align 8 + %gotos44 = getelementptr inbounds %struct.State, %struct.State* %45, i32 0, i32 4 + %n45 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos44, i32 0, i32 0 + %46 = load i32, i32* %n45, align 8 + %cmp46 = icmp ult i32 %44, %46 + br i1 %cmp46, label %for.body.48, label %for.end + +for.body.48: ; preds = %for.cond.43 + %47 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %48 = load i32, i32* %k, align 4 + %idxprom49 = sext i32 %48 to i64 + %49 = load %struct.State*, %struct.State** %s, align 8 + %gotos50 = getelementptr inbounds %struct.State, %struct.State* %49, i32 0, i32 4 + %v51 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos50, i32 0, i32 2 + %50 = load %struct.Goto**, %struct.Goto*** %v51, align 8 + %arrayidx52 = getelementptr inbounds %struct.Goto*, %struct.Goto** %50, i64 %idxprom49 + %51 = load %struct.Goto*, %struct.Goto** %arrayidx52, align 8 + %elem = getelementptr inbounds %struct.Goto, %struct.Goto* %51, i32 0, i32 0 + %52 = load %struct.Elem*, %struct.Elem** %elem, align 8 + %call53 = call i32 @elem_symbol(%struct.Grammar* %47, %struct.Elem* %52) + %53 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %54 = load i32, i32* %k, align 4 + %idxprom54 = sext i32 %54 to i64 + %55 = load %struct.State*, %struct.State** %ss, align 8 + %gotos55 = getelementptr inbounds %struct.State, %struct.State* %55, i32 0, i32 4 + %v56 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos55, i32 0, i32 2 + %56 = load %struct.Goto**, %struct.Goto*** %v56, align 8 + %arrayidx57 = getelementptr inbounds %struct.Goto*, %struct.Goto** %56, i64 %idxprom54 + %57 = load %struct.Goto*, %struct.Goto** %arrayidx57, align 8 + %elem58 = getelementptr inbounds %struct.Goto, %struct.Goto* %57, i32 0, i32 0 + %58 = load %struct.Elem*, %struct.Elem** %elem58, align 8 + %call59 = call i32 @elem_symbol(%struct.Grammar* %53, %struct.Elem* %58) + %cmp60 = icmp ne i32 %call53, %call59 + br i1 %cmp60, label %if.then.62, label %if.end.63 + +if.then.62: ; preds = %for.body.48 + br label %Lcontinue + +if.end.63: ; preds = %for.body.48 + %59 = load i32, i32* %k, align 4 + %idxprom64 = sext i32 %59 to i64 + %60 = load %struct.State*, %struct.State** %s, align 8 + %gotos65 = getelementptr inbounds %struct.State, %struct.State* %60, i32 0, i32 4 + %v66 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos65, i32 0, i32 2 + %61 = load %struct.Goto**, %struct.Goto*** %v66, align 8 + %arrayidx67 = getelementptr inbounds %struct.Goto*, %struct.Goto** %61, i64 %idxprom64 + %62 = load %struct.Goto*, %struct.Goto** %arrayidx67, align 8 + %state = getelementptr inbounds %struct.Goto, %struct.Goto* %62, i32 0, i32 1 + %63 = load %struct.State*, %struct.State** %state, align 8 + %64 = load i32, i32* %k, align 4 + %idxprom68 = sext i32 %64 to i64 + %65 = load %struct.State*, %struct.State** %ss, align 8 + %gotos69 = getelementptr inbounds %struct.State, %struct.State* %65, i32 0, i32 4 + %v70 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos69, i32 0, i32 2 + %66 = load %struct.Goto**, %struct.Goto*** %v70, align 8 + %arrayidx71 = getelementptr inbounds %struct.Goto*, %struct.Goto** %66, i64 %idxprom68 + %67 = load %struct.Goto*, %struct.Goto** %arrayidx71, align 8 + %state72 = getelementptr inbounds %struct.Goto, %struct.Goto* %67, i32 0, i32 1 + %68 = load %struct.State*, %struct.State** %state72, align 8 + %cmp73 = icmp ne %struct.State* %63, %68 + br i1 %cmp73, label %if.then.75, label %if.end.155 + +if.then.75: ; preds = %if.end.63 + %69 = load i32, i32* %k, align 4 + %idxprom76 = sext i32 %69 to i64 + %70 = load %struct.State*, %struct.State** %s, align 8 + %gotos77 = getelementptr inbounds %struct.State, %struct.State* %70, i32 0, i32 4 + %v78 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos77, i32 0, i32 2 + %71 = load %struct.Goto**, %struct.Goto*** %v78, align 8 + %arrayidx79 = getelementptr inbounds %struct.Goto*, %struct.Goto** %71, i64 %idxprom76 + %72 = load %struct.Goto*, %struct.Goto** %arrayidx79, align 8 + %state80 = getelementptr inbounds %struct.Goto, %struct.Goto* %72, i32 0, i32 1 + %73 = load %struct.State*, %struct.State** %state80, align 8 + %index81 = getelementptr inbounds %struct.State, %struct.State* %73, i32 0, i32 0 + %74 = load i32, i32* %index81, align 8 + %idxprom82 = zext i32 %74 to i64 + %75 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx83 = getelementptr inbounds %struct.EqState, %struct.EqState* %75, i64 %idxprom82 + store %struct.EqState* %arrayidx83, %struct.EqState** %ge, align 8 + %76 = load i32, i32* %k, align 4 + %idxprom84 = sext i32 %76 to i64 + %77 = load %struct.State*, %struct.State** %ss, align 8 + %gotos85 = getelementptr inbounds %struct.State, %struct.State* %77, i32 0, i32 4 + %v86 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos85, i32 0, i32 2 + %78 = load %struct.Goto**, %struct.Goto*** %v86, align 8 + %arrayidx87 = getelementptr inbounds %struct.Goto*, %struct.Goto** %78, i64 %idxprom84 + %79 = load %struct.Goto*, %struct.Goto** %arrayidx87, align 8 + %state88 = getelementptr inbounds %struct.Goto, %struct.Goto* %79, i32 0, i32 1 + %80 = load %struct.State*, %struct.State** %state88, align 8 + %index89 = getelementptr inbounds %struct.State, %struct.State* %80, i32 0, i32 0 + %81 = load i32, i32* %index89, align 8 + %idxprom90 = zext i32 %81 to i64 + %82 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx91 = getelementptr inbounds %struct.EqState, %struct.EqState* %82, i64 %idxprom90 + store %struct.EqState* %arrayidx91, %struct.EqState** %gee, align 8 + %83 = load %struct.EqState*, %struct.EqState** %ge, align 8 + %eq92 = getelementptr inbounds %struct.EqState, %struct.EqState* %83, i32 0, i32 0 + %84 = load %struct.State*, %struct.State** %eq92, align 8 + %85 = load i32, i32* %k, align 4 + %idxprom93 = sext i32 %85 to i64 + %86 = load %struct.State*, %struct.State** %ss, align 8 + %gotos94 = getelementptr inbounds %struct.State, %struct.State* %86, i32 0, i32 4 + %v95 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos94, i32 0, i32 2 + %87 = load %struct.Goto**, %struct.Goto*** %v95, align 8 + %arrayidx96 = getelementptr inbounds %struct.Goto*, %struct.Goto** %87, i64 %idxprom93 + %88 = load %struct.Goto*, %struct.Goto** %arrayidx96, align 8 + %state97 = getelementptr inbounds %struct.Goto, %struct.Goto* %88, i32 0, i32 1 + %89 = load %struct.State*, %struct.State** %state97, align 8 + %cmp98 = icmp ne %struct.State* %84, %89 + br i1 %cmp98, label %land.lhs.true.100, label %if.end.110 + +land.lhs.true.100: ; preds = %if.then.75 + %90 = load %struct.EqState*, %struct.EqState** %gee, align 8 + %eq101 = getelementptr inbounds %struct.EqState, %struct.EqState* %90, i32 0, i32 0 + %91 = load %struct.State*, %struct.State** %eq101, align 8 + %92 = load i32, i32* %k, align 4 + %idxprom102 = sext i32 %92 to i64 + %93 = load %struct.State*, %struct.State** %s, align 8 + %gotos103 = getelementptr inbounds %struct.State, %struct.State* %93, i32 0, i32 4 + %v104 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos103, i32 0, i32 2 + %94 = load %struct.Goto**, %struct.Goto*** %v104, align 8 + %arrayidx105 = getelementptr inbounds %struct.Goto*, %struct.Goto** %94, i64 %idxprom102 + %95 = load %struct.Goto*, %struct.Goto** %arrayidx105, align 8 + %state106 = getelementptr inbounds %struct.Goto, %struct.Goto* %95, i32 0, i32 1 + %96 = load %struct.State*, %struct.State** %state106, align 8 + %cmp107 = icmp ne %struct.State* %91, %96 + br i1 %cmp107, label %if.then.109, label %if.end.110 + +if.then.109: ; preds = %land.lhs.true.100 + br label %Lcontinue + +if.end.110: ; preds = %land.lhs.true.100, %if.then.75 + %97 = load %struct.EqState*, %struct.EqState** %ee, align 8 + %diff_state = getelementptr inbounds %struct.EqState, %struct.EqState* %97, i32 0, i32 2 + %98 = load %struct.State*, %struct.State** %diff_state, align 8 + %tobool111 = icmp ne %struct.State* %98, null + br i1 %tobool111, label %land.lhs.true.112, label %lor.lhs.false.125 + +land.lhs.true.112: ; preds = %if.end.110 + %99 = load %struct.EqState*, %struct.EqState** %ee, align 8 + %diff_state113 = getelementptr inbounds %struct.EqState, %struct.EqState* %99, i32 0, i32 2 + %100 = load %struct.State*, %struct.State** %diff_state113, align 8 + %101 = load i32, i32* %k, align 4 + %idxprom114 = sext i32 %101 to i64 + %102 = load %struct.State*, %struct.State** %ss, align 8 + %gotos115 = getelementptr inbounds %struct.State, %struct.State* %102, i32 0, i32 4 + %v116 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos115, i32 0, i32 2 + %103 = load %struct.Goto**, %struct.Goto*** %v116, align 8 + %arrayidx117 = getelementptr inbounds %struct.Goto*, %struct.Goto** %103, i64 %idxprom114 + %104 = load %struct.Goto*, %struct.Goto** %arrayidx117, align 8 + %state118 = getelementptr inbounds %struct.Goto, %struct.Goto* %104, i32 0, i32 1 + %105 = load %struct.State*, %struct.State** %state118, align 8 + %index119 = getelementptr inbounds %struct.State, %struct.State* %105, i32 0, i32 0 + %106 = load i32, i32* %index119, align 8 + %idxprom120 = zext i32 %106 to i64 + %107 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx121 = getelementptr inbounds %struct.EqState, %struct.EqState* %107, i64 %idxprom120 + %eq122 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx121, i32 0, i32 0 + %108 = load %struct.State*, %struct.State** %eq122, align 8 + %cmp123 = icmp ne %struct.State* %100, %108 + br i1 %cmp123, label %if.then.141, label %lor.lhs.false.125 + +lor.lhs.false.125: ; preds = %land.lhs.true.112, %if.end.110 + %109 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_state126 = getelementptr inbounds %struct.EqState, %struct.EqState* %109, i32 0, i32 2 + %110 = load %struct.State*, %struct.State** %diff_state126, align 8 + %tobool127 = icmp ne %struct.State* %110, null + br i1 %tobool127, label %land.lhs.true.128, label %if.end.142 + +land.lhs.true.128: ; preds = %lor.lhs.false.125 + %111 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_state129 = getelementptr inbounds %struct.EqState, %struct.EqState* %111, i32 0, i32 2 + %112 = load %struct.State*, %struct.State** %diff_state129, align 8 + %113 = load i32, i32* %k, align 4 + %idxprom130 = sext i32 %113 to i64 + %114 = load %struct.State*, %struct.State** %s, align 8 + %gotos131 = getelementptr inbounds %struct.State, %struct.State* %114, i32 0, i32 4 + %v132 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos131, i32 0, i32 2 + %115 = load %struct.Goto**, %struct.Goto*** %v132, align 8 + %arrayidx133 = getelementptr inbounds %struct.Goto*, %struct.Goto** %115, i64 %idxprom130 + %116 = load %struct.Goto*, %struct.Goto** %arrayidx133, align 8 + %state134 = getelementptr inbounds %struct.Goto, %struct.Goto* %116, i32 0, i32 1 + %117 = load %struct.State*, %struct.State** %state134, align 8 + %index135 = getelementptr inbounds %struct.State, %struct.State* %117, i32 0, i32 0 + %118 = load i32, i32* %index135, align 8 + %idxprom136 = zext i32 %118 to i64 + %119 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx137 = getelementptr inbounds %struct.EqState, %struct.EqState* %119, i64 %idxprom136 + %eq138 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx137, i32 0, i32 0 + %120 = load %struct.State*, %struct.State** %eq138, align 8 + %cmp139 = icmp ne %struct.State* %112, %120 + br i1 %cmp139, label %if.then.141, label %if.end.142 + +if.then.141: ; preds = %land.lhs.true.128, %land.lhs.true.112 + br label %Lcontinue + +if.end.142: ; preds = %land.lhs.true.128, %lor.lhs.false.125 + %121 = load i32, i32* %k, align 4 + %idxprom143 = sext i32 %121 to i64 + %122 = load %struct.State*, %struct.State** %ss, align 8 + %gotos144 = getelementptr inbounds %struct.State, %struct.State* %122, i32 0, i32 4 + %v145 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos144, i32 0, i32 2 + %123 = load %struct.Goto**, %struct.Goto*** %v145, align 8 + %arrayidx146 = getelementptr inbounds %struct.Goto*, %struct.Goto** %123, i64 %idxprom143 + %124 = load %struct.Goto*, %struct.Goto** %arrayidx146, align 8 + %state147 = getelementptr inbounds %struct.Goto, %struct.Goto* %124, i32 0, i32 1 + %125 = load %struct.State*, %struct.State** %state147, align 8 + %126 = load %struct.EqState*, %struct.EqState** %ee, align 8 + %diff_state148 = getelementptr inbounds %struct.EqState, %struct.EqState* %126, i32 0, i32 2 + store %struct.State* %125, %struct.State** %diff_state148, align 8 + %127 = load i32, i32* %k, align 4 + %idxprom149 = sext i32 %127 to i64 + %128 = load %struct.State*, %struct.State** %s, align 8 + %gotos150 = getelementptr inbounds %struct.State, %struct.State* %128, i32 0, i32 4 + %v151 = getelementptr inbounds %struct.VecGoto, %struct.VecGoto* %gotos150, i32 0, i32 2 + %129 = load %struct.Goto**, %struct.Goto*** %v151, align 8 + %arrayidx152 = getelementptr inbounds %struct.Goto*, %struct.Goto** %129, i64 %idxprom149 + %130 = load %struct.Goto*, %struct.Goto** %arrayidx152, align 8 + %state153 = getelementptr inbounds %struct.Goto, %struct.Goto* %130, i32 0, i32 1 + %131 = load %struct.State*, %struct.State** %state153, align 8 + %132 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_state154 = getelementptr inbounds %struct.EqState, %struct.EqState* %132, i32 0, i32 2 + store %struct.State* %131, %struct.State** %diff_state154, align 8 + br label %if.end.155 + +if.end.155: ; preds = %if.end.142, %if.end.63 + br label %for.inc + +for.inc: ; preds = %if.end.155 + %133 = load i32, i32* %k, align 4 + %inc = add nsw i32 %133, 1 + store i32 %inc, i32* %k, align 4 + br label %for.cond.43 + +for.end: ; preds = %for.cond.43 + %134 = load %struct.State*, %struct.State** %s, align 8 + %reduce_actions = getelementptr inbounds %struct.State, %struct.State* %134, i32 0, i32 6 + %n156 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions, i32 0, i32 0 + %135 = load i32, i32* %n156, align 8 + %136 = load %struct.State*, %struct.State** %ss, align 8 + %reduce_actions157 = getelementptr inbounds %struct.State, %struct.State* %136, i32 0, i32 6 + %n158 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions157, i32 0, i32 0 + %137 = load i32, i32* %n158, align 8 + %cmp159 = icmp ne i32 %135, %137 + br i1 %cmp159, label %if.then.161, label %if.end.162 + +if.then.161: ; preds = %for.end + br label %for.inc.254 + +if.end.162: ; preds = %for.end + store i32 0, i32* %k, align 4 + br label %for.cond.163 + +for.cond.163: ; preds = %for.inc.250, %if.end.162 + %138 = load i32, i32* %k, align 4 + %139 = load %struct.State*, %struct.State** %s, align 8 + %reduce_actions164 = getelementptr inbounds %struct.State, %struct.State* %139, i32 0, i32 6 + %n165 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions164, i32 0, i32 0 + %140 = load i32, i32* %n165, align 8 + %cmp166 = icmp ult i32 %138, %140 + br i1 %cmp166, label %for.body.168, label %for.end.252 + +for.body.168: ; preds = %for.cond.163 + %141 = load i32, i32* %k, align 4 + %idxprom169 = sext i32 %141 to i64 + %142 = load %struct.State*, %struct.State** %s, align 8 + %reduce_actions170 = getelementptr inbounds %struct.State, %struct.State* %142, i32 0, i32 6 + %v171 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions170, i32 0, i32 2 + %143 = load %struct.Action**, %struct.Action*** %v171, align 8 + %arrayidx172 = getelementptr inbounds %struct.Action*, %struct.Action** %143, i64 %idxprom169 + %144 = load %struct.Action*, %struct.Action** %arrayidx172, align 8 + %rule = getelementptr inbounds %struct.Action, %struct.Action* %144, i32 0, i32 2 + %145 = load %struct.Rule*, %struct.Rule** %rule, align 8 + %146 = load i32, i32* %k, align 4 + %idxprom173 = sext i32 %146 to i64 + %147 = load %struct.State*, %struct.State** %ss, align 8 + %reduce_actions174 = getelementptr inbounds %struct.State, %struct.State* %147, i32 0, i32 6 + %v175 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions174, i32 0, i32 2 + %148 = load %struct.Action**, %struct.Action*** %v175, align 8 + %arrayidx176 = getelementptr inbounds %struct.Action*, %struct.Action** %148, i64 %idxprom173 + %149 = load %struct.Action*, %struct.Action** %arrayidx176, align 8 + %rule177 = getelementptr inbounds %struct.Action, %struct.Action* %149, i32 0, i32 2 + %150 = load %struct.Rule*, %struct.Rule** %rule177, align 8 + %cmp178 = icmp eq %struct.Rule* %145, %150 + br i1 %cmp178, label %if.then.180, label %if.end.181 + +if.then.180: ; preds = %for.body.168 + br label %for.inc.250 + +if.end.181: ; preds = %for.body.168 + %151 = load i32, i32* %k, align 4 + %idxprom182 = sext i32 %151 to i64 + %152 = load %struct.State*, %struct.State** %s, align 8 + %reduce_actions183 = getelementptr inbounds %struct.State, %struct.State* %152, i32 0, i32 6 + %v184 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions183, i32 0, i32 2 + %153 = load %struct.Action**, %struct.Action*** %v184, align 8 + %arrayidx185 = getelementptr inbounds %struct.Action*, %struct.Action** %153, i64 %idxprom182 + %154 = load %struct.Action*, %struct.Action** %arrayidx185, align 8 + %rule186 = getelementptr inbounds %struct.Action, %struct.Action* %154, i32 0, i32 2 + %155 = load %struct.Rule*, %struct.Rule** %rule186, align 8 + %prod = getelementptr inbounds %struct.Rule, %struct.Rule* %155, i32 0, i32 1 + %156 = load %struct.Production*, %struct.Production** %prod, align 8 + %157 = load i32, i32* %k, align 4 + %idxprom187 = sext i32 %157 to i64 + %158 = load %struct.State*, %struct.State** %ss, align 8 + %reduce_actions188 = getelementptr inbounds %struct.State, %struct.State* %158, i32 0, i32 6 + %v189 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions188, i32 0, i32 2 + %159 = load %struct.Action**, %struct.Action*** %v189, align 8 + %arrayidx190 = getelementptr inbounds %struct.Action*, %struct.Action** %159, i64 %idxprom187 + %160 = load %struct.Action*, %struct.Action** %arrayidx190, align 8 + %rule191 = getelementptr inbounds %struct.Action, %struct.Action* %160, i32 0, i32 2 + %161 = load %struct.Rule*, %struct.Rule** %rule191, align 8 + %prod192 = getelementptr inbounds %struct.Rule, %struct.Rule* %161, i32 0, i32 1 + %162 = load %struct.Production*, %struct.Production** %prod192, align 8 + %cmp193 = icmp ne %struct.Production* %156, %162 + br i1 %cmp193, label %if.then.195, label %if.end.196 + +if.then.195: ; preds = %if.end.181 + br label %Lcontinue + +if.end.196: ; preds = %if.end.181 + %163 = load i32, i32* %k, align 4 + %idxprom197 = sext i32 %163 to i64 + %164 = load %struct.State*, %struct.State** %s, align 8 + %reduce_actions198 = getelementptr inbounds %struct.State, %struct.State* %164, i32 0, i32 6 + %v199 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions198, i32 0, i32 2 + %165 = load %struct.Action**, %struct.Action*** %v199, align 8 + %arrayidx200 = getelementptr inbounds %struct.Action*, %struct.Action** %165, i64 %idxprom197 + %166 = load %struct.Action*, %struct.Action** %arrayidx200, align 8 + %rule201 = getelementptr inbounds %struct.Action, %struct.Action* %166, i32 0, i32 2 + %167 = load %struct.Rule*, %struct.Rule** %rule201, align 8 + %elems = getelementptr inbounds %struct.Rule, %struct.Rule* %167, i32 0, i32 6 + %n202 = getelementptr inbounds %struct.anon.0, %struct.anon.0* %elems, i32 0, i32 0 + %168 = load i32, i32* %n202, align 8 + store i32 %168, i32* %x, align 4 + %169 = load i32, i32* %k, align 4 + %idxprom203 = sext i32 %169 to i64 + %170 = load %struct.State*, %struct.State** %ss, align 8 + %reduce_actions204 = getelementptr inbounds %struct.State, %struct.State* %170, i32 0, i32 6 + %v205 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions204, i32 0, i32 2 + %171 = load %struct.Action**, %struct.Action*** %v205, align 8 + %arrayidx206 = getelementptr inbounds %struct.Action*, %struct.Action** %171, i64 %idxprom203 + %172 = load %struct.Action*, %struct.Action** %arrayidx206, align 8 + %rule207 = getelementptr inbounds %struct.Action, %struct.Action* %172, i32 0, i32 2 + %173 = load %struct.Rule*, %struct.Rule** %rule207, align 8 + %elems208 = getelementptr inbounds %struct.Rule, %struct.Rule* %173, i32 0, i32 6 + %n209 = getelementptr inbounds %struct.anon.0, %struct.anon.0* %elems208, i32 0, i32 0 + %174 = load i32, i32* %n209, align 8 + store i32 %174, i32* %xx, align 4 + %cmp210 = icmp ne i32 %168, %174 + br i1 %cmp210, label %if.then.212, label %if.end.249 + +if.then.212: ; preds = %if.end.196 + %175 = load %struct.EqState*, %struct.EqState** %ee, align 8 + %diff_rule = getelementptr inbounds %struct.EqState, %struct.EqState* %175, i32 0, i32 1 + %176 = load %struct.Rule*, %struct.Rule** %diff_rule, align 8 + %tobool213 = icmp ne %struct.Rule* %176, null + br i1 %tobool213, label %land.lhs.true.214, label %lor.lhs.false.223 + +land.lhs.true.214: ; preds = %if.then.212 + %177 = load %struct.EqState*, %struct.EqState** %ee, align 8 + %diff_rule215 = getelementptr inbounds %struct.EqState, %struct.EqState* %177, i32 0, i32 1 + %178 = load %struct.Rule*, %struct.Rule** %diff_rule215, align 8 + %179 = load i32, i32* %k, align 4 + %idxprom216 = sext i32 %179 to i64 + %180 = load %struct.State*, %struct.State** %ss, align 8 + %reduce_actions217 = getelementptr inbounds %struct.State, %struct.State* %180, i32 0, i32 6 + %v218 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions217, i32 0, i32 2 + %181 = load %struct.Action**, %struct.Action*** %v218, align 8 + %arrayidx219 = getelementptr inbounds %struct.Action*, %struct.Action** %181, i64 %idxprom216 + %182 = load %struct.Action*, %struct.Action** %arrayidx219, align 8 + %rule220 = getelementptr inbounds %struct.Action, %struct.Action* %182, i32 0, i32 2 + %183 = load %struct.Rule*, %struct.Rule** %rule220, align 8 + %cmp221 = icmp ne %struct.Rule* %178, %183 + br i1 %cmp221, label %if.then.235, label %lor.lhs.false.223 + +lor.lhs.false.223: ; preds = %land.lhs.true.214, %if.then.212 + %184 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_rule224 = getelementptr inbounds %struct.EqState, %struct.EqState* %184, i32 0, i32 1 + %185 = load %struct.Rule*, %struct.Rule** %diff_rule224, align 8 + %tobool225 = icmp ne %struct.Rule* %185, null + br i1 %tobool225, label %land.lhs.true.226, label %if.end.236 + +land.lhs.true.226: ; preds = %lor.lhs.false.223 + %186 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_rule227 = getelementptr inbounds %struct.EqState, %struct.EqState* %186, i32 0, i32 1 + %187 = load %struct.Rule*, %struct.Rule** %diff_rule227, align 8 + %188 = load i32, i32* %k, align 4 + %idxprom228 = sext i32 %188 to i64 + %189 = load %struct.State*, %struct.State** %s, align 8 + %reduce_actions229 = getelementptr inbounds %struct.State, %struct.State* %189, i32 0, i32 6 + %v230 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions229, i32 0, i32 2 + %190 = load %struct.Action**, %struct.Action*** %v230, align 8 + %arrayidx231 = getelementptr inbounds %struct.Action*, %struct.Action** %190, i64 %idxprom228 + %191 = load %struct.Action*, %struct.Action** %arrayidx231, align 8 + %rule232 = getelementptr inbounds %struct.Action, %struct.Action* %191, i32 0, i32 2 + %192 = load %struct.Rule*, %struct.Rule** %rule232, align 8 + %cmp233 = icmp ne %struct.Rule* %187, %192 + br i1 %cmp233, label %if.then.235, label %if.end.236 + +if.then.235: ; preds = %land.lhs.true.226, %land.lhs.true.214 + br label %Lcontinue + +if.end.236: ; preds = %land.lhs.true.226, %lor.lhs.false.223 + %193 = load i32, i32* %k, align 4 + %idxprom237 = sext i32 %193 to i64 + %194 = load %struct.State*, %struct.State** %ss, align 8 + %reduce_actions238 = getelementptr inbounds %struct.State, %struct.State* %194, i32 0, i32 6 + %v239 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions238, i32 0, i32 2 + %195 = load %struct.Action**, %struct.Action*** %v239, align 8 + %arrayidx240 = getelementptr inbounds %struct.Action*, %struct.Action** %195, i64 %idxprom237 + %196 = load %struct.Action*, %struct.Action** %arrayidx240, align 8 + %rule241 = getelementptr inbounds %struct.Action, %struct.Action* %196, i32 0, i32 2 + %197 = load %struct.Rule*, %struct.Rule** %rule241, align 8 + %198 = load %struct.EqState*, %struct.EqState** %ee, align 8 + %diff_rule242 = getelementptr inbounds %struct.EqState, %struct.EqState* %198, i32 0, i32 1 + store %struct.Rule* %197, %struct.Rule** %diff_rule242, align 8 + %199 = load i32, i32* %k, align 4 + %idxprom243 = sext i32 %199 to i64 + %200 = load %struct.State*, %struct.State** %s, align 8 + %reduce_actions244 = getelementptr inbounds %struct.State, %struct.State* %200, i32 0, i32 6 + %v245 = getelementptr inbounds %struct.VecAction, %struct.VecAction* %reduce_actions244, i32 0, i32 2 + %201 = load %struct.Action**, %struct.Action*** %v245, align 8 + %arrayidx246 = getelementptr inbounds %struct.Action*, %struct.Action** %201, i64 %idxprom243 + %202 = load %struct.Action*, %struct.Action** %arrayidx246, align 8 + %rule247 = getelementptr inbounds %struct.Action, %struct.Action* %202, i32 0, i32 2 + %203 = load %struct.Rule*, %struct.Rule** %rule247, align 8 + %204 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_rule248 = getelementptr inbounds %struct.EqState, %struct.EqState* %204, i32 0, i32 1 + store %struct.Rule* %203, %struct.Rule** %diff_rule248, align 8 + br label %if.end.249 + +if.end.249: ; preds = %if.end.236, %if.end.196 + br label %for.inc.250 + +for.inc.250: ; preds = %if.end.249, %if.then.180 + %205 = load i32, i32* %k, align 4 + %inc251 = add nsw i32 %205, 1 + store i32 %inc251, i32* %k, align 4 + br label %for.cond.163 + +for.end.252: ; preds = %for.cond.163 + %206 = load %struct.State*, %struct.State** %s, align 8 + %207 = load %struct.EqState*, %struct.EqState** %ee, align 8 + %eq253 = getelementptr inbounds %struct.EqState, %struct.EqState* %207, i32 0, i32 0 + store %struct.State* %206, %struct.State** %eq253, align 8 + store i32 1, i32* %changed, align 4 + br label %Lcontinue + +Lcontinue: ; preds = %for.end.252, %if.then.235, %if.then.195, %if.then.141, %if.then.109, %if.then.62 + br label %for.inc.254 + +for.inc.254: ; preds = %Lcontinue, %if.then.161, %if.then.41, %if.then.34, %if.then + %208 = load i32, i32* %j, align 4 + %inc255 = add nsw i32 %208, 1 + store i32 %inc255, i32* %j, align 4 + br label %for.cond.11 + +for.end.256: ; preds = %for.cond.11 + br label %for.inc.257 + +for.inc.257: ; preds = %for.end.256 + %209 = load i32, i32* %i, align 4 + %inc258 = add nsw i32 %209, 1 + store i32 %inc258, i32* %i, align 4 + br label %for.cond + +for.end.259: ; preds = %for.cond + br label %while.cond + +while.end: ; preds = %while.cond + store i32 0, i32* %i, align 4 + br label %for.cond.260 + +for.cond.260: ; preds = %for.inc.313, %while.end + %210 = load i32, i32* %i, align 4 + %211 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states261 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %211, i32 0, i32 3 + %n262 = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states261, i32 0, i32 0 + %212 = load i32, i32* %n262, align 8 + %cmp263 = icmp ult i32 %210, %212 + br i1 %cmp263, label %for.body.265, label %for.end.315 + +for.body.265: ; preds = %for.cond.260 + %213 = load i32, i32* %i, align 4 + %idxprom266 = sext i32 %213 to i64 + %214 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states267 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %214, i32 0, i32 3 + %v268 = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states267, i32 0, i32 2 + %215 = load %struct.State**, %struct.State*** %v268, align 8 + %arrayidx269 = getelementptr inbounds %struct.State*, %struct.State** %215, i64 %idxprom266 + %216 = load %struct.State*, %struct.State** %arrayidx269, align 8 + store %struct.State* %216, %struct.State** %s, align 8 + %217 = load %struct.State*, %struct.State** %s, align 8 + %index270 = getelementptr inbounds %struct.State, %struct.State* %217, i32 0, i32 0 + %218 = load i32, i32* %index270, align 8 + %idxprom271 = zext i32 %218 to i64 + %219 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx272 = getelementptr inbounds %struct.EqState, %struct.EqState* %219, i64 %idxprom271 + store %struct.EqState* %arrayidx272, %struct.EqState** %e, align 8 + %220 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq273 = getelementptr inbounds %struct.EqState, %struct.EqState* %220, i32 0, i32 0 + %221 = load %struct.State*, %struct.State** %eq273, align 8 + %tobool274 = icmp ne %struct.State* %221, null + br i1 %tobool274, label %if.then.275, label %if.end.312 + +if.then.275: ; preds = %for.body.265 + %222 = load i32, i32* @verbose_level, align 4 + %cmp276 = icmp sgt i32 %222, 2 + br i1 %cmp276, label %if.then.278, label %if.end.311 + +if.then.278: ; preds = %if.then.275 + %223 = load %struct.State*, %struct.State** %s, align 8 + %index279 = getelementptr inbounds %struct.State, %struct.State* %223, i32 0, i32 0 + %224 = load i32, i32* %index279, align 8 + %225 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq280 = getelementptr inbounds %struct.EqState, %struct.EqState* %225, i32 0, i32 0 + %226 = load %struct.State*, %struct.State** %eq280, align 8 + %index281 = getelementptr inbounds %struct.State, %struct.State* %226, i32 0, i32 0 + %227 = load i32, i32* %index281, align 8 + %call282 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.37, i32 0, i32 0), i32 %224, i32 %227) + %228 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_state283 = getelementptr inbounds %struct.EqState, %struct.EqState* %228, i32 0, i32 2 + %229 = load %struct.State*, %struct.State** %diff_state283, align 8 + %tobool284 = icmp ne %struct.State* %229, null + br i1 %tobool284, label %if.then.285, label %if.end.295 + +if.then.285: ; preds = %if.then.278 + %230 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_state286 = getelementptr inbounds %struct.EqState, %struct.EqState* %230, i32 0, i32 2 + %231 = load %struct.State*, %struct.State** %diff_state286, align 8 + %index287 = getelementptr inbounds %struct.State, %struct.State* %231, i32 0, i32 0 + %232 = load i32, i32* %index287, align 8 + %233 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq288 = getelementptr inbounds %struct.EqState, %struct.EqState* %233, i32 0, i32 0 + %234 = load %struct.State*, %struct.State** %eq288, align 8 + %index289 = getelementptr inbounds %struct.State, %struct.State* %234, i32 0, i32 0 + %235 = load i32, i32* %index289, align 8 + %idxprom290 = zext i32 %235 to i64 + %236 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx291 = getelementptr inbounds %struct.EqState, %struct.EqState* %236, i64 %idxprom290 + %diff_state292 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx291, i32 0, i32 2 + %237 = load %struct.State*, %struct.State** %diff_state292, align 8 + %index293 = getelementptr inbounds %struct.State, %struct.State* %237, i32 0, i32 0 + %238 = load i32, i32* %index293, align 8 + %call294 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.38, i32 0, i32 0), i32 %232, i32 %238) + br label %if.end.295 + +if.end.295: ; preds = %if.then.285, %if.then.278 + %239 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_rule296 = getelementptr inbounds %struct.EqState, %struct.EqState* %239, i32 0, i32 1 + %240 = load %struct.Rule*, %struct.Rule** %diff_rule296, align 8 + %tobool297 = icmp ne %struct.Rule* %240, null + br i1 %tobool297, label %if.then.298, label %if.end.309 + +if.then.298: ; preds = %if.end.295 + %call299 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.39, i32 0, i32 0)) + %call300 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.40, i32 0, i32 0)) + %241 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_rule301 = getelementptr inbounds %struct.EqState, %struct.EqState* %241, i32 0, i32 1 + %242 = load %struct.Rule*, %struct.Rule** %diff_rule301, align 8 + call void @print_rule(%struct.Rule* %242) + %call302 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.41, i32 0, i32 0)) + %243 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq303 = getelementptr inbounds %struct.EqState, %struct.EqState* %243, i32 0, i32 0 + %244 = load %struct.State*, %struct.State** %eq303, align 8 + %index304 = getelementptr inbounds %struct.State, %struct.State* %244, i32 0, i32 0 + %245 = load i32, i32* %index304, align 8 + %idxprom305 = zext i32 %245 to i64 + %246 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx306 = getelementptr inbounds %struct.EqState, %struct.EqState* %246, i64 %idxprom305 + %diff_rule307 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx306, i32 0, i32 1 + %247 = load %struct.Rule*, %struct.Rule** %diff_rule307, align 8 + call void @print_rule(%struct.Rule* %247) + %call308 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.42, i32 0, i32 0)) + br label %if.end.309 + +if.end.309: ; preds = %if.then.298, %if.end.295 + %call310 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.32, i32 0, i32 0)) + br label %if.end.311 + +if.end.311: ; preds = %if.end.309, %if.then.275 + br label %if.end.312 + +if.end.312: ; preds = %if.end.311, %for.body.265 + br label %for.inc.313 + +for.inc.313: ; preds = %if.end.312 + %248 = load i32, i32* %i, align 4 + %inc314 = add nsw i32 %248, 1 + store i32 %inc314, i32* %i, align 4 + br label %for.cond.260 + +for.end.315: ; preds = %for.cond.260 + store i32 0, i32* %i, align 4 + br label %for.cond.316 + +for.cond.316: ; preds = %for.inc.397, %for.end.315 + %249 = load i32, i32* %i, align 4 + %250 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states317 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %250, i32 0, i32 3 + %n318 = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states317, i32 0, i32 0 + %251 = load i32, i32* %n318, align 8 + %cmp319 = icmp ult i32 %249, %251 + br i1 %cmp319, label %for.body.321, label %for.end.399 + +for.body.321: ; preds = %for.cond.316 + %252 = load i32, i32* %i, align 4 + %idxprom322 = sext i32 %252 to i64 + %253 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states323 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %253, i32 0, i32 3 + %v324 = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states323, i32 0, i32 2 + %254 = load %struct.State**, %struct.State*** %v324, align 8 + %arrayidx325 = getelementptr inbounds %struct.State*, %struct.State** %254, i64 %idxprom322 + %255 = load %struct.State*, %struct.State** %arrayidx325, align 8 + store %struct.State* %255, %struct.State** %s, align 8 + %256 = load %struct.State*, %struct.State** %s, align 8 + %index326 = getelementptr inbounds %struct.State, %struct.State* %256, i32 0, i32 0 + %257 = load i32, i32* %index326, align 8 + %idxprom327 = zext i32 %257 to i64 + %258 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx328 = getelementptr inbounds %struct.EqState, %struct.EqState* %258, i64 %idxprom327 + store %struct.EqState* %arrayidx328, %struct.EqState** %e, align 8 + %259 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq329 = getelementptr inbounds %struct.EqState, %struct.EqState* %259, i32 0, i32 0 + %260 = load %struct.State*, %struct.State** %eq329, align 8 + %tobool330 = icmp ne %struct.State* %260, null + br i1 %tobool330, label %land.lhs.true.331, label %if.end.396 + +land.lhs.true.331: ; preds = %for.body.321 + %261 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_state332 = getelementptr inbounds %struct.EqState, %struct.EqState* %261, i32 0, i32 2 + %262 = load %struct.State*, %struct.State** %diff_state332, align 8 + %tobool333 = icmp ne %struct.State* %262, null + br i1 %tobool333, label %if.then.334, label %if.end.396 + +if.then.334: ; preds = %land.lhs.true.331 + %263 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_state335 = getelementptr inbounds %struct.EqState, %struct.EqState* %263, i32 0, i32 2 + %264 = load %struct.State*, %struct.State** %diff_state335, align 8 + %index336 = getelementptr inbounds %struct.State, %struct.State* %264, i32 0, i32 0 + %265 = load i32, i32* %index336, align 8 + %idxprom337 = zext i32 %265 to i64 + %266 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx338 = getelementptr inbounds %struct.EqState, %struct.EqState* %266, i64 %idxprom337 + %diff_rule339 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx338, i32 0, i32 1 + %267 = load %struct.Rule*, %struct.Rule** %diff_rule339, align 8 + %tobool340 = icmp ne %struct.Rule* %267, null + br i1 %tobool340, label %land.lhs.true.341, label %if.else + +land.lhs.true.341: ; preds = %if.then.334 + %268 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_state342 = getelementptr inbounds %struct.EqState, %struct.EqState* %268, i32 0, i32 2 + %269 = load %struct.State*, %struct.State** %diff_state342, align 8 + %index343 = getelementptr inbounds %struct.State, %struct.State* %269, i32 0, i32 0 + %270 = load i32, i32* %index343, align 8 + %idxprom344 = zext i32 %270 to i64 + %271 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx345 = getelementptr inbounds %struct.EqState, %struct.EqState* %271, i64 %idxprom344 + %diff_rule346 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx345, i32 0, i32 1 + %272 = load %struct.Rule*, %struct.Rule** %diff_rule346, align 8 + %elems347 = getelementptr inbounds %struct.Rule, %struct.Rule* %272, i32 0, i32 6 + %n348 = getelementptr inbounds %struct.anon.0, %struct.anon.0* %elems347, i32 0, i32 0 + %273 = load i32, i32* %n348, align 8 + %cmp349 = icmp eq i32 %273, 2 + br i1 %cmp349, label %if.then.351, label %if.else + +if.then.351: ; preds = %land.lhs.true.341 + %274 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq352 = getelementptr inbounds %struct.EqState, %struct.EqState* %274, i32 0, i32 0 + %275 = load %struct.State*, %struct.State** %eq352, align 8 + %276 = load %struct.State*, %struct.State** %s, align 8 + %reduces_to = getelementptr inbounds %struct.State, %struct.State* %276, i32 0, i32 14 + store %struct.State* %275, %struct.State** %reduces_to, align 8 + %277 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq353 = getelementptr inbounds %struct.EqState, %struct.EqState* %277, i32 0, i32 0 + %278 = load %struct.State*, %struct.State** %eq353, align 8 + %index354 = getelementptr inbounds %struct.State, %struct.State* %278, i32 0, i32 0 + %279 = load i32, i32* %index354, align 8 + %idxprom355 = zext i32 %279 to i64 + %280 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx356 = getelementptr inbounds %struct.EqState, %struct.EqState* %280, i64 %idxprom355 + %diff_rule357 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx356, i32 0, i32 1 + %281 = load %struct.Rule*, %struct.Rule** %diff_rule357, align 8 + %282 = load %struct.State*, %struct.State** %s, align 8 + %reduces_with = getelementptr inbounds %struct.State, %struct.State* %282, i32 0, i32 15 + store %struct.Rule* %281, %struct.Rule** %reduces_with, align 8 + %283 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_rule358 = getelementptr inbounds %struct.EqState, %struct.EqState* %283, i32 0, i32 1 + %284 = load %struct.Rule*, %struct.Rule** %diff_rule358, align 8 + %285 = load %struct.State*, %struct.State** %s, align 8 + %reduces_to_then_with = getelementptr inbounds %struct.State, %struct.State* %285, i32 0, i32 16 + store %struct.Rule* %284, %struct.Rule** %reduces_to_then_with, align 8 + br label %if.end.395 + +if.else: ; preds = %land.lhs.true.341, %if.then.334 + %286 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq359 = getelementptr inbounds %struct.EqState, %struct.EqState* %286, i32 0, i32 0 + %287 = load %struct.State*, %struct.State** %eq359, align 8 + %index360 = getelementptr inbounds %struct.State, %struct.State* %287, i32 0, i32 0 + %288 = load i32, i32* %index360, align 8 + %idxprom361 = zext i32 %288 to i64 + %289 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx362 = getelementptr inbounds %struct.EqState, %struct.EqState* %289, i64 %idxprom361 + %diff_state363 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx362, i32 0, i32 2 + %290 = load %struct.State*, %struct.State** %diff_state363, align 8 + %index364 = getelementptr inbounds %struct.State, %struct.State* %290, i32 0, i32 0 + %291 = load i32, i32* %index364, align 8 + %idxprom365 = zext i32 %291 to i64 + %292 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx366 = getelementptr inbounds %struct.EqState, %struct.EqState* %292, i64 %idxprom365 + %diff_rule367 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx366, i32 0, i32 1 + %293 = load %struct.Rule*, %struct.Rule** %diff_rule367, align 8 + %tobool368 = icmp ne %struct.Rule* %293, null + br i1 %tobool368, label %land.lhs.true.369, label %if.end.394 + +land.lhs.true.369: ; preds = %if.else + %294 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq370 = getelementptr inbounds %struct.EqState, %struct.EqState* %294, i32 0, i32 0 + %295 = load %struct.State*, %struct.State** %eq370, align 8 + %index371 = getelementptr inbounds %struct.State, %struct.State* %295, i32 0, i32 0 + %296 = load i32, i32* %index371, align 8 + %idxprom372 = zext i32 %296 to i64 + %297 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx373 = getelementptr inbounds %struct.EqState, %struct.EqState* %297, i64 %idxprom372 + %diff_state374 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx373, i32 0, i32 2 + %298 = load %struct.State*, %struct.State** %diff_state374, align 8 + %index375 = getelementptr inbounds %struct.State, %struct.State* %298, i32 0, i32 0 + %299 = load i32, i32* %index375, align 8 + %idxprom376 = zext i32 %299 to i64 + %300 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx377 = getelementptr inbounds %struct.EqState, %struct.EqState* %300, i64 %idxprom376 + %diff_rule378 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx377, i32 0, i32 1 + %301 = load %struct.Rule*, %struct.Rule** %diff_rule378, align 8 + %elems379 = getelementptr inbounds %struct.Rule, %struct.Rule* %301, i32 0, i32 6 + %n380 = getelementptr inbounds %struct.anon.0, %struct.anon.0* %elems379, i32 0, i32 0 + %302 = load i32, i32* %n380, align 8 + %cmp381 = icmp eq i32 %302, 2 + br i1 %cmp381, label %if.then.383, label %if.end.394 + +if.then.383: ; preds = %land.lhs.true.369 + %303 = load %struct.State*, %struct.State** %s, align 8 + %304 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq384 = getelementptr inbounds %struct.EqState, %struct.EqState* %304, i32 0, i32 0 + %305 = load %struct.State*, %struct.State** %eq384, align 8 + %reduces_to385 = getelementptr inbounds %struct.State, %struct.State* %305, i32 0, i32 14 + store %struct.State* %303, %struct.State** %reduces_to385, align 8 + %306 = load %struct.EqState*, %struct.EqState** %e, align 8 + %diff_rule386 = getelementptr inbounds %struct.EqState, %struct.EqState* %306, i32 0, i32 1 + %307 = load %struct.Rule*, %struct.Rule** %diff_rule386, align 8 + %308 = load %struct.State*, %struct.State** %s, align 8 + %reduces_with387 = getelementptr inbounds %struct.State, %struct.State* %308, i32 0, i32 15 + store %struct.Rule* %307, %struct.Rule** %reduces_with387, align 8 + %309 = load %struct.EqState*, %struct.EqState** %e, align 8 + %eq388 = getelementptr inbounds %struct.EqState, %struct.EqState* %309, i32 0, i32 0 + %310 = load %struct.State*, %struct.State** %eq388, align 8 + %index389 = getelementptr inbounds %struct.State, %struct.State* %310, i32 0, i32 0 + %311 = load i32, i32* %index389, align 8 + %idxprom390 = zext i32 %311 to i64 + %312 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %arrayidx391 = getelementptr inbounds %struct.EqState, %struct.EqState* %312, i64 %idxprom390 + %diff_rule392 = getelementptr inbounds %struct.EqState, %struct.EqState* %arrayidx391, i32 0, i32 1 + %313 = load %struct.Rule*, %struct.Rule** %diff_rule392, align 8 + %314 = load %struct.State*, %struct.State** %s, align 8 + %reduces_to_then_with393 = getelementptr inbounds %struct.State, %struct.State* %314, i32 0, i32 16 + store %struct.Rule* %313, %struct.Rule** %reduces_to_then_with393, align 8 + br label %if.end.394 + +if.end.394: ; preds = %if.then.383, %land.lhs.true.369, %if.else + br label %if.end.395 + +if.end.395: ; preds = %if.end.394, %if.then.351 + br label %if.end.396 + +if.end.396: ; preds = %if.end.395, %land.lhs.true.331, %for.body.321 + br label %for.inc.397 + +for.inc.397: ; preds = %if.end.396 + %315 = load i32, i32* %i, align 4 + %inc398 = add nsw i32 %315, 1 + store i32 %inc398, i32* %i, align 4 + br label %for.cond.316 + +for.end.399: ; preds = %for.cond.316 + store i32 0, i32* %i, align 4 + br label %for.cond.400 + +for.cond.400: ; preds = %for.inc.421, %for.end.399 + %316 = load i32, i32* %i, align 4 + %317 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states401 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %317, i32 0, i32 3 + %n402 = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states401, i32 0, i32 0 + %318 = load i32, i32* %n402, align 8 + %cmp403 = icmp ult i32 %316, %318 + br i1 %cmp403, label %for.body.405, label %for.end.423 + +for.body.405: ; preds = %for.cond.400 + %319 = load i32, i32* %i, align 4 + %idxprom406 = sext i32 %319 to i64 + %320 = load %struct.Grammar*, %struct.Grammar** %g.addr, align 8 + %states407 = getelementptr inbounds %struct.Grammar, %struct.Grammar* %320, i32 0, i32 3 + %v408 = getelementptr inbounds %struct.anon.6, %struct.anon.6* %states407, i32 0, i32 2 + %321 = load %struct.State**, %struct.State*** %v408, align 8 + %arrayidx409 = getelementptr inbounds %struct.State*, %struct.State** %321, i64 %idxprom406 + %322 = load %struct.State*, %struct.State** %arrayidx409, align 8 + store %struct.State* %322, %struct.State** %s, align 8 + %323 = load %struct.State*, %struct.State** %s, align 8 + %reduces_to410 = getelementptr inbounds %struct.State, %struct.State* %323, i32 0, i32 14 + %324 = load %struct.State*, %struct.State** %reduces_to410, align 8 + %tobool411 = icmp ne %struct.State* %324, null + br i1 %tobool411, label %if.then.412, label %if.end.420 + +if.then.412: ; preds = %for.body.405 + %325 = load i32, i32* @verbose_level, align 4 + %tobool413 = icmp ne i32 %325, 0 + br i1 %tobool413, label %if.then.414, label %if.end.419 + +if.then.414: ; preds = %if.then.412 + %326 = load %struct.State*, %struct.State** %s, align 8 + %index415 = getelementptr inbounds %struct.State, %struct.State* %326, i32 0, i32 0 + %327 = load i32, i32* %index415, align 8 + %328 = load %struct.State*, %struct.State** %s, align 8 + %reduces_to416 = getelementptr inbounds %struct.State, %struct.State* %328, i32 0, i32 14 + %329 = load %struct.State*, %struct.State** %reduces_to416, align 8 + %index417 = getelementptr inbounds %struct.State, %struct.State* %329, i32 0, i32 0 + %330 = load i32, i32* %index417, align 8 + %call418 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.43, i32 0, i32 0), i32 %327, i32 %330) + br label %if.end.419 + +if.end.419: ; preds = %if.then.414, %if.then.412 + br label %if.end.420 + +if.end.420: ; preds = %if.end.419, %for.body.405 + br label %for.inc.421 + +for.inc.421: ; preds = %if.end.420 + %331 = load i32, i32* %i, align 4 + %inc422 = add nsw i32 %331, 1 + store i32 %inc422, i32* %i, align 4 + br label %for.cond.400 + +for.end.423: ; preds = %for.cond.400 + %332 = load %struct.EqState*, %struct.EqState** %eq, align 8 + %333 = bitcast %struct.EqState* %332 to i8* + call void @free(i8* %333) #4 + ret void +} + +declare i32 @elem_symbol(%struct.Grammar*, %struct.Elem*) #2 + +attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind argmemonly } +attributes #2 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #4 = { nounwind } + +!llvm.ident = !{!0} + +!0 = !{!"clang version 3.8.0 (http://llvm.org/git/clang.git 5e171f9c91fb59933382f67a589af82fd8409eb7)"} Index: test/ScopInfo/invariant_load_access_classes_different_base_type.ll =================================================================== --- /dev/null +++ test/ScopInfo/invariant_load_access_classes_different_base_type.ll @@ -0,0 +1,66 @@ +; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN +; +; struct { +; int a; +; float b; +; } S; +; +; void f(int *A) { +; for (int i = 0; i < 1000; i++) +; A[i] = S.a + S.b; +; } +; +; CHECK: Invariant Accesses: { +; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK: { Stmt_for_body[i0] -> MemRef_S[0] }; +; CHECK: Execution Context: { : } +; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK: { Stmt_for_body[i0] -> MemRef_S[1] }; +; CHECK: Execution Context: { : } +; CHECK: } +; +; CODEGEN: %S.b.preload.s2a = alloca float +; CODEGEN: %S.a.preload.s2a = alloca i32 +; +; CODEGEN: %.load = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @S, i32 0, i32 0) +; CODEGEN: store i32 %.load, i32* %S.a.preload.s2a +; CODEGEN: %.load1 = load i32, i32* getelementptr (i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @S, i32 0, i32 0), i64 1) +; CODEGEN: %0 = bitcast i32 %.load1 to float +; CODEGEN: store float %0, float* %S.b.preload.s2a +; +; CODEGEN: polly.stmt.for.body: +; CODEGEN: %p_conv = sitofp i32 %.load to float +; CODEGEN: %p_add = fadd float %p_conv, %0 +; CODEGEN: %p_conv1 = fptosi float %p_add to i32 + +%struct.anon = type { i32, float } + +@S = common global %struct.anon zeroinitializer, align 4 + +define void @f(i32* %A) { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ] + %exitcond = icmp ne i64 %indvars.iv, 1000 + br i1 %exitcond, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %S.a = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @S, i64 0, i32 0), align 4 + %conv = sitofp i32 %S.a to float + %S.b = load float, float* getelementptr inbounds (%struct.anon, %struct.anon* @S, i64 0, i32 1), align 4 + %add = fadd float %conv, %S.b + %conv1 = fptosi float %add to i32 + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + store i32 %conv1, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: ; preds = %for.body + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} Index: test/ScopInfo/invariant_load_access_classes_different_base_type_escaping.ll =================================================================== --- /dev/null +++ test/ScopInfo/invariant_load_access_classes_different_base_type_escaping.ll @@ -0,0 +1,99 @@ +; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN +; +; struct { +; int a; +; float b; +; } S; +; +; float f(int *A) { +; int x; +; float y; +; int i = 0; +; do { +; x = S.a; +; y = S.b; +; A[i] = x + y; +; } while (i++ < 1000); +; return x + y; +; } +; +; CHECK: Invariant Accesses: { +; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK: { Stmt_do_body[i0] -> MemRef_S[0] }; +; CHECK: Execution Context: { : } +; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK: { Stmt_do_body[i0] -> MemRef_S[1] }; +; CHECK: Execution Context: { : } +; CHECK: } +; +; CHECK: Statements { +; CHECK-NOT: Access +; CHECK: Stmt_do_body +; CHECK: Domain := +; CHECK: { Stmt_do_body[i0] : i0 <= 1000 and i0 >= 0 }; +; CHECK: Schedule := +; CHECK: { Stmt_do_body[i0] -> [i0] }; +; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK: { Stmt_do_body[i0] -> MemRef_A[i0] }; +; CHECK-NOT: Access +; CHECK: } +; +; CODEGEN: entry: +; CODEGEN: %S.b.preload.s2a = alloca float +; CODEGEN: %S.a.preload.s2a = alloca i32 +; +; CODEGEN: polly.preload.begin: +; CODEGEN: %.load = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @S, i32 0, i32 0) +; CODEGEN: %0 = bitcast i32 %.load to float +; CODEGEN: store i32 %.load, i32* %S.a.preload.s2a +; CODEGEN: %.load1 = load i32, i32* getelementptr (i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @S, i32 0, i32 0), i64 1) +; CODEGEN: %1 = bitcast i32 %.load1 to float +; CODEGEN: %2 = bitcast float %1 to i32 +; CODEGEN: store float %1, float* %S.b.preload.s2a +; +; CODEGEN: polly.merge_new_and_old: +; CODEGEN-DAG: %S.b.merge = phi float [ %S.b.final_reload, %polly.loop_exit ], [ %S.b, %do.cond ] +; CODEGEN-DAG: %S.a.merge = phi i32 [ %S.a.final_reload, %polly.loop_exit ], [ %S.a, %do.cond ] +; +; CODEGEN: do.end: +; CODEGEN: %conv3 = sitofp i32 %S.a.merge to float +; CODEGEN: %add4 = fadd float %conv3, %S.b.merge +; CODEGEN: ret float %add4 +; +; CODEGEN: polly.loop_exit: +; CODEGEN-DAG: %S.b.final_reload = load float, float* %S.b.preload.s2a +; CODEGEN-DAG: %S.a.final_reload = load i32, i32* %S.a.preload.s2a + +; +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +%struct.anon = type { i32, float } + +@S = common global %struct.anon zeroinitializer, align 4 + +define float @f(i32* %A) { +entry: + br label %do.body + +do.body: ; preds = %do.cond, %entry + %indvars.iv = phi i64 [ %indvars.iv.next, %do.cond ], [ 0, %entry ] + %S.a = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @S, i64 0, i32 0), align 4 + %S.b = load float, float* getelementptr inbounds (%struct.anon, %struct.anon* @S, i64 0, i32 1), align 4 + %conv = sitofp i32 %S.a to float + %add = fadd float %conv, %S.b + %conv1 = fptosi float %add to i32 + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + store i32 %conv1, i32* %arrayidx, align 4 + br label %do.cond + +do.cond: ; preds = %do.body + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp ne i64 %indvars.iv.next, 1001 + br i1 %exitcond, label %do.body, label %do.end + +do.end: ; preds = %do.cond + %conv3 = sitofp i32 %S.a to float + %add4 = fadd float %conv3, %S.b + ret float %add4 +} Index: test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer.ll =================================================================== --- /dev/null +++ test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer.ll @@ -0,0 +1,77 @@ +; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN +; +; int U; +; void f(int *A) { +; for (int i = 0; i < 1000; i++) +; A[i] = (*(int *)&U) + (int)(*(float *)&U); +; } +; +; CHECK: Invariant Accesses: { +; CHECK-NOT: ReadAccess +; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK: { Stmt_for_body[i0] -> MemRef_U[0] }; +; CHECK: Execution Context: { : } +; CHECK-NOT: ReadAccess +; CHECK: } +; +; CHECK: Statements { +; CHECK: Stmt_for_body +; CHECK: Domain := +; CHECK: { Stmt_for_body[i0] : i0 <= 999 and i0 >= 0 }; +; CHECK: Schedule := +; CHECK: { Stmt_for_body[i0] -> [i0] }; +; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK: { Stmt_for_body[i0] -> MemRef_A[i0] }; +; CHECK: } +; +; CODEGEN: entry: +; CODEGEN: %U.f.preload.s2a = alloca float +; CODEGEN: br label %polly.split_new_and_old +; +; CODEGEN: polly.preload.begin: +; CODEGEN: %U.load = load i32, i32* @U +; CODEGEN: %0 = bitcast i32 %U.load to float +; CODEGEN: %1 = bitcast float %0 to i32 +; CODEGEN: store float %0, float* %U.f.preload.s2a +; +; CODEGEN: polly.merge_new_and_old: +; CODEGEN-NOT: merge = phi +; +; CODEGEN: polly.loop_exit: +; CODEGEN-NOT: final_reload +; +; CODEGEN: polly.stmt.for.body: +; CODEGEN: %p_conv = fptosi float %0 to i32 +; CODEGEN: %p_add = add nsw i32 %1, %p_conv +; +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +@U = common global i32 0, align 4 + +define void @f(i32* %A) { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ] + %exitcond = icmp ne i64 %indvars.iv, 1000 + br i1 %exitcond, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %U.i = load i32, i32* @U, align 4 + %U.cast = bitcast i32 *@U to float* + %U.f = load float, float* %U.cast, align 4 + %conv = fptosi float %U.f to i32 + %add = add nsw i32 %U.i, %conv + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + store i32 %add, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: ; preds = %for.body + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} Index: test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer_escaping.ll =================================================================== --- /dev/null +++ test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer_escaping.ll @@ -0,0 +1,84 @@ +; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN +; +; int U; +; int f(int *A) { +; int i = 0, x, y; +; do { +; x = (*(int *)&U); +; y = (int)(*(float *)&U); +; A[i] = x + y; +; } while (i++ < 100); +; return x + y; +; } +; +; CHECK: Invariant Accesses: { +; CHECK-NOT: ReadAccess +; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK: { Stmt_do_body[i0] -> MemRef_U[0] }; +; CHECK: Execution Context: { : } +; CHECK-NOT: ReadAccess +; CHECK: } +; +; CHECK: Statements { +; CHECK: Stmt_do_body +; CHECK: Domain := +; CHECK: { Stmt_do_body[i0] : i0 <= 100 and i0 >= 0 }; +; CHECK: Schedule := +; CHECK: { Stmt_do_body[i0] -> [i0] }; +; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK: { Stmt_do_body[i0] -> MemRef_A[i0] }; +; CHECK: } +; +; CODEGEN: entry: +; CODEGEN: %U.f.preload.s2a = alloca float +; CODEGEN: br label %polly.split_new_and_old +; +; CODEGEN: polly.preload.begin: +; CODEGEN: %U.load = load i32, i32* @U +; CODEGEN: %0 = bitcast i32 %U.load to float +; CODEGEN: %1 = bitcast float %0 to i32 +; CODEGEN: store float %0, float* %U.f.preload.s2a +; +; CODEGEN: polly.merge_new_and_old: +; CODEGEN-DAG: %U.f.merge = phi float [ %U.f.final_reload, %polly.loop_exit ], [ %U.f, %do.cond ] +; CODEGEN-DAG: %U.i.merge = phi i32 [ %7, %polly.loop_exit ], [ %U.i, %do.cond ] +; +; CODEGEN: polly.loop_exit: +; CODEGEN-DAG: %U.f.final_reload = load float, float* %U.f.preload.s2a +; CODEGEN-DAG: %U.i.final_reload = load float, float* %U.f.preload.s2a +; CODEGEN-DAG: %7 = bitcast float %U.i.final_reload to i32 +; +; CODEGEN: polly.stmt.do.body: +; CODEGEN: %p_conv = fptosi float %0 to i32 +; CODEGEN: %p_add = add nsw i32 %1, %p_conv +; +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +@U = common global i32 0, align 4 + +define i32 @f(i32* %A) { +entry: + br label %do.body + +do.body: ; preds = %do.cond, %entry + %indvars.iv = phi i64 [ %indvars.iv.next, %do.cond ], [ 0, %entry ] + %U.i = load i32, i32* @U, align 4 + %U.cast = bitcast i32 *@U to float* + %U.f = load float, float* %U.cast, align 4 + %conv = fptosi float %U.f to i32 + %add = add nsw i32 %U.i, %conv + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + store i32 %add, i32* %arrayidx, align 4 + br label %do.cond + +do.cond: ; preds = %do.body + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp ne i64 %indvars.iv.next, 101 + br i1 %exitcond, label %do.body, label %do.end + +do.end: ; preds = %do.cond + %conv2 = fptosi float %U.f to i32 + %add2 = add nsw i32 %U.i, %conv2 + ret i32 %add2 +} Index: test/ScopInfo/invariant_loads_complicated_dependences.ll =================================================================== --- test/ScopInfo/invariant_loads_complicated_dependences.ll +++ test/ScopInfo/invariant_loads_complicated_dependences.ll @@ -2,10 +2,7 @@ ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: [LB, UB] -> { Stmt_for_body[i0] -> MemRef_LB[0] }; -; CHECK-NEXT: Execution Context: [LB, UB] -> { : } -; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: [LB, UB] -> { Stmt_do_cond[i0, i1] -> MemRef_UB[0] }; +; CHECK-NEXT: [LB, UB] -> { Stmt_for_body[i0] -> MemRef_LBptr[0] }; ; CHECK-NEXT: Execution Context: [LB, UB] -> { : } ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] ; CHECK-NEXT: [LB, UB] -> { Stmt_if_then[i0, i1] -> MemRef_V[0] }; @@ -13,6 +10,9 @@ ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] ; CHECK-NEXT: [LB, UB] -> { Stmt_if_else[i0, i1] -> MemRef_U[0] }; ; CHECK-NEXT: Execution Context: [LB, UB] -> { : LB <= 5 } +; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: [LB, UB] -> { Stmt_do_cond[i0, i1] -> MemRef_UBptr[0] }; +; CHECK-NEXT: Execution Context: [LB, UB] -> { : } ; CHECK-NEXT: } ; ; void f(int *restrict A, int *restrict V, int *restrict U, int *restrict UB, @@ -30,7 +30,7 @@ ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -define void @f(i32* noalias %A, i32* noalias %V, i32* noalias %U, i32* noalias %UB, i32* noalias %LB) { +define void @f(i32* noalias %A, i32* noalias %V, i32* noalias %U, i32* noalias %UBptr, i32* noalias %LBptr) { entry: br label %for.cond @@ -40,11 +40,11 @@ br i1 %exitcond, label %for.body, label %for.end for.body: ; preds = %for.cond - %tmp = load i32, i32* %LB, align 4 + %LB = load i32, i32* %LBptr, align 4 br label %do.body do.body: ; preds = %do.cond, %for.body - %j.0 = phi i32 [ %tmp, %for.body ], [ %inc, %do.cond ] + %j.0 = phi i32 [ %LB, %for.body ], [ %inc, %do.cond ] %cmp1 = icmp sgt i32 %j.0, 5 br i1 %cmp1, label %if.then, label %if.else @@ -69,8 +69,8 @@ do.cond: ; preds = %if.end %inc = add nsw i32 %j.0, 1 - %tmp5 = load i32, i32* %UB, align 4 - %cmp5 = icmp slt i32 %j.0, %tmp5 + %UB = load i32, i32* %UBptr, align 4 + %cmp5 = icmp slt i32 %j.0, %UB br i1 %cmp5, label %do.body, label %do.end do.end: ; preds = %do.cond Index: test/ScopInfo/invariant_loop_bounds.ll =================================================================== --- test/ScopInfo/invariant_loop_bounds.ll +++ test/ScopInfo/invariant_loop_bounds.ll @@ -3,28 +3,28 @@ ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] ; CHECK-NEXT: MemRef_bounds[2] -; CHECK-NEXT: Execution Context: [p_0, p_1, bounds] -> { : } +; CHECK-NEXT: Execution Context: [bounds2, bounds1, bounds0] -> { : } ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] ; CHECK-NEXT: MemRef_bounds[1] -; CHECK-NEXT: Execution Context: [p_0, p_1, bounds] -> { : p_0 >= 1 } +; CHECK-NEXT: Execution Context: [bounds2, bounds1, bounds0] -> { : bounds2 >= 1 } ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] ; CHECK-NEXT: MemRef_bounds[0] -; CHECK-NEXT: Execution Context: [p_0, p_1, bounds] -> { : p_1 >= 1 and p_0 >= 1 } +; CHECK-NEXT: Execution Context: [bounds2, bounds1, bounds0] -> { : bounds1 >= 1 and bounds2 >= 1 } ; CHECK-NEXT: } ; -; CHECK: p0: (8 + @bounds) -; CHECK: p1: (4 + @bounds) -; CHECK: p2: @bounds +; CHECK: p0: %bounds2 +; CHECK: p1: %bounds1 +; CHECK: p2: %bounds0 ; CHECK: Statements { ; CHECK: Stmt_for_body_6 ; CHECK: Domain := -; CHECK: [p_0, p_1, bounds] -> { Stmt_for_body_6[i0, i1, i2] : i0 >= 0 and i0 <= -1 + p_0 and i1 >= 0 and i1 <= -1 + p_1 and i2 >= 0 and i2 <= -1 + bounds }; +; CHECK: [bounds2, bounds1, bounds0] -> { Stmt_for_body_6[i0, i1, i2] : i0 >= 0 and i0 <= -1 + bounds2 and i1 >= 0 and i1 <= -1 + bounds1 and i2 >= 0 and i2 <= -1 + bounds0 }; ; CHECK: Schedule := -; CHECK: [p_0, p_1, bounds] -> { Stmt_for_body_6[i0, i1, i2] -> [i0, i1, i2] }; +; CHECK: [bounds2, bounds1, bounds0] -> { Stmt_for_body_6[i0, i1, i2] -> [i0, i1, i2] }; ; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK: [p_0, p_1, bounds] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; +; CHECK: [bounds2, bounds1, bounds0] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; ; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK: [p_0, p_1, bounds] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; +; CHECK: [bounds2, bounds1, bounds0] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; ; CHECK: } ; ; int bounds[3]; @@ -49,8 +49,8 @@ for.cond: ; preds = %for.inc.16, %entry %indvars.iv5 = phi i64 [ %indvars.iv.next6, %for.inc.16 ], [ 0, %entry ] - %tmp = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @bounds, i64 0, i64 2), align 4 - %tmp7 = sext i32 %tmp to i64 + %bounds2 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @bounds, i64 0, i64 2), align 4 + %tmp7 = sext i32 %bounds2 to i64 %cmp = icmp slt i64 %indvars.iv5, %tmp7 br i1 %cmp, label %for.body, label %for.end.18 @@ -59,8 +59,8 @@ for.cond.1: ; preds = %for.inc.13, %for.body %indvars.iv3 = phi i64 [ %indvars.iv.next4, %for.inc.13 ], [ 0, %for.body ] - %tmp8 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @bounds, i64 0, i64 1), align 4 - %tmp9 = sext i32 %tmp8 to i64 + %bounds1 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @bounds, i64 0, i64 1), align 4 + %tmp9 = sext i32 %bounds1 to i64 %cmp2 = icmp slt i64 %indvars.iv3, %tmp9 br i1 %cmp2, label %for.body.3, label %for.end.15 @@ -69,8 +69,8 @@ for.cond.4: ; preds = %for.inc, %for.body.3 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %for.body.3 ] - %tmp10 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @bounds, i64 0, i64 0), align 4 - %tmp11 = sext i32 %tmp10 to i64 + %bounds0 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @bounds, i64 0, i64 0), align 4 + %tmp11 = sext i32 %bounds0 to i64 %cmp5 = icmp slt i64 %indvars.iv, %tmp11 br i1 %cmp5, label %for.body.6, label %for.end Index: test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll =================================================================== --- test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll +++ test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll @@ -8,21 +8,21 @@ ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] ; CHECK-NEXT: MemRef_bounds[0] -; CHECK-NEXT: Execution Context: [bounds] -> { : } +; CHECK-NEXT: Execution Context: [bounds0l0] -> { : } ; CHECK-NEXT: } ; -; CHECK: p0: @bounds +; CHECK: p0: %bounds0l0 ; CHECK-NOT: p1 ; CHECK: Statements { ; CHECK: Stmt_for_body_6 ; CHECK: Domain := -; CHECK: [bounds] -> { Stmt_for_body_6[i0, i1, i2] : i0 >= 0 and i0 <= -1 + bounds and i1 >= 0 and i1 <= -1 + bounds and i2 >= 0 and i2 <= -1 + bounds }; +; CHECK: [bounds0l0] -> { Stmt_for_body_6[i0, i1, i2] : i0 >= 0 and i0 <= -1 + bounds0l0 and i1 >= 0 and i1 <= -1 + bounds0l0 and i2 >= 0 and i2 <= -1 + bounds0l0 }; ; CHECK: Schedule := -; CHECK: [bounds] -> { Stmt_for_body_6[i0, i1, i2] -> [i0, i1, i2] }; +; CHECK: [bounds0l0] -> { Stmt_for_body_6[i0, i1, i2] -> [i0, i1, i2] }; ; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK: [bounds] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; +; CHECK: [bounds0l0] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; ; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK: [bounds] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; +; CHECK: [bounds0l0] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; ; CHECK: } ; ; int bounds[1]; @@ -47,8 +47,8 @@ for.cond: ; preds = %for.inc.16, %entry %indvars.iv5 = phi i64 [ %indvars.iv.next6, %for.inc.16 ], [ 0, %entry ] - %tmp = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 - %tmp7 = sext i32 %tmp to i64 + %bounds0l0 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 + %tmp7 = sext i32 %bounds0l0 to i64 %cmp = icmp slt i64 %indvars.iv5, %tmp7 br i1 %cmp, label %for.body, label %for.end.18 @@ -57,8 +57,8 @@ for.cond.1: ; preds = %for.inc.13, %for.body %indvars.iv3 = phi i64 [ %indvars.iv.next4, %for.inc.13 ], [ 0, %for.body ] - %tmp8 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 - %tmp9 = sext i32 %tmp8 to i64 + %bounds0l1 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 + %tmp9 = sext i32 %bounds0l1 to i64 %cmp2 = icmp slt i64 %indvars.iv3, %tmp9 br i1 %cmp2, label %for.body.3, label %for.end.15 @@ -67,8 +67,8 @@ for.cond.4: ; preds = %for.inc, %for.body.3 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %for.body.3 ] - %tmp10 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 - %tmp11 = sext i32 %tmp10 to i64 + %bounds0l2 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 + %tmp11 = sext i32 %bounds0l2 to i64 %cmp5 = icmp slt i64 %indvars.iv, %tmp11 br i1 %cmp5, label %for.body.6, label %for.end Index: test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll =================================================================== --- test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll +++ test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll @@ -8,22 +8,22 @@ ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] ; CHECK-NEXT: MemRef_bounds[0] -; CHECK-NEXT: Execution Context: [bounds, p] -> { : } +; CHECK-NEXT: Execution Context: [bounds0l0, p] -> { : } ; CHECK-NEXT: } ; -; CHECK: p0: @bounds +; CHECK: p0: %bounds0l0 ; CHECK: p1: %p ; CHECK-NOT: p2: ; CHECK: Statements { ; CHECK: Stmt_for_body_6 ; CHECK: Domain := -; CHECK: [bounds, p] -> { Stmt_for_body_6[i0, i1, i2] : p = 0 and i0 >= 0 and i0 <= -1 + bounds and i1 >= 0 and i1 <= -1 + bounds and i2 >= 0 and i2 <= -1 + bounds }; +; CHECK: [bounds0l0, p] -> { Stmt_for_body_6[i0, i1, i2] : p = 0 and i0 >= 0 and i0 <= -1 + bounds0l0 and i1 >= 0 and i1 <= -1 + bounds0l0 and i2 >= 0 and i2 <= -1 + bounds0l0 }; ; CHECK: Schedule := -; CHECK: [bounds, p] -> { Stmt_for_body_6[i0, i1, i2] -> [i0, i1, i2] }; +; CHECK: [bounds0l0, p] -> { Stmt_for_body_6[i0, i1, i2] -> [i0, i1, i2] }; ; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK: [bounds, p] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; +; CHECK: [bounds0l0, p] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; ; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK: [bounds, p] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; +; CHECK: [bounds0l0, p] -> { Stmt_for_body_6[i0, i1, i2] -> MemRef_data[i0, i1, i2] }; ; CHECK: } ; ; int bounds[1]; @@ -49,8 +49,8 @@ for.cond: ; preds = %for.inc.16, %entry %indvars.iv5 = phi i64 [ %indvars.iv.next6, %for.inc.16 ], [ 0, %entry ] - %tmp = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 - %tmp7 = sext i32 %tmp to i64 + %bounds0l0 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 + %tmp7 = sext i32 %bounds0l0 to i64 %cmp = icmp slt i64 %indvars.iv5, %tmp7 br i1 %cmp, label %for.body, label %for.end.18 @@ -60,8 +60,8 @@ for.cond.1: ; preds = %for.inc.13, %for.body %indvars.iv3 = phi i64 [ %indvars.iv.next4, %for.inc.13 ], [ 0, %for.body ] - %tmp8 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 - %tmp9 = sext i32 %tmp8 to i64 + %bounds0l1 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 + %tmp9 = sext i32 %bounds0l1 to i64 %cmp2 = icmp slt i64 %indvars.iv3, %tmp9 br i1 %cmp2, label %for.body.3, label %for.end.15 @@ -70,8 +70,8 @@ for.cond.4: ; preds = %for.inc, %for.body.3 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %for.body.3 ] - %tmp10 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 - %tmp11 = sext i32 %tmp10 to i64 + %bounds0l2 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @bounds, i64 0, i64 0), align 4 + %tmp11 = sext i32 %bounds0l2 to i64 %cmp5 = icmp slt i64 %indvars.iv, %tmp11 br i1 %cmp5, label %for.body.6, label %for.end Index: test/ScopInfo/multidim_parameter_addrec_product.ll =================================================================== --- test/ScopInfo/multidim_parameter_addrec_product.ll +++ test/ScopInfo/multidim_parameter_addrec_product.ll @@ -8,14 +8,14 @@ ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: [p] -> { Stmt_bb5[i0, i1] -> MemRef_p[0] }; -; CHECK-NEXT: Execution Context: [p] -> { : } +; CHECK-NEXT: [pval] -> { Stmt_bb5[i0, i1] -> MemRef_p[0] }; +; CHECK-NEXT: Execution Context: [pval] -> { : } ; CHECK-NEXT: } ; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK: [p] -> { Stmt_bb5[i0, i1] -> MemRef_A[i0, i1] }; +; CHECK: [pval] -> { Stmt_bb5[i0, i1] -> MemRef_A[i0, i1] }; ; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK: [p] -> { Stmt_bb5[i0, i1] -> MemRef_A[i0, i1] }; +; CHECK: [pval] -> { Stmt_bb5[i0, i1] -> MemRef_A[i0, i1] }; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ScopInfo/required-invariant-loop-bounds.ll =================================================================== --- test/ScopInfo/required-invariant-loop-bounds.ll +++ test/ScopInfo/required-invariant-loop-bounds.ll @@ -3,10 +3,10 @@ ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] ; CHECK-NEXT: MemRef_bounds[0] -; CHECK-NEXT: Execution Context: [bounds, p_1] -> { : } +; CHECK-NEXT: Execution Context: [bounds0, bounds1] -> { : } ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] ; CHECK-NEXT: MemRef_bounds[1] -; CHECK-NEXT: Execution Context: [bounds, p_1] -> { : bounds >= 0 } +; CHECK-NEXT: Execution Context: [bounds0, bounds1] -> { : bounds0 >= 0 } ; CHECK: } ; double A[1000][1000]; @@ -30,8 +30,8 @@ for.cond: ; preds = %for.inc.6, %entry %i.0 = phi i64 [ 0, %entry ], [ %inc7, %for.inc.6 ] - %tmp = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @bounds, i64 0, i64 0), align 16 - %cmp = icmp sgt i64 %i.0, %tmp + %bounds0 = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @bounds, i64 0, i64 0), align 16 + %cmp = icmp sgt i64 %i.0, %bounds0 br i1 %cmp, label %for.end.8, label %for.body for.body: ; preds = %for.cond @@ -39,8 +39,8 @@ for.cond.1: ; preds = %for.inc, %for.body %j.0 = phi i64 [ 0, %for.body ], [ %inc, %for.inc ] - %tmp1 = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @bounds, i64 0, i64 1), align 8 - %cmp2 = icmp sgt i64 %j.0, %tmp1 + %bounds1 = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @bounds, i64 0, i64 1), align 8 + %cmp2 = icmp sgt i64 %j.0, %bounds1 br i1 %cmp2, label %for.end, label %for.body.3 for.body.3: ; preds = %for.cond.1