From ed13dd066b3e5fce633942b5aa19103e8a8cf935 Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Fri, 22 Jun 2012 06:04:00 -0700 Subject: [PATCH] Distinguish between 'regular' foreach and foreach_unique in FunctionEmitContext We need to do this since it's illegal to have nested foreach statements, but nested foreach_unique, or foreach_unique inside foreach, etc., are all fine. --- ctx.cpp | 50 ++++++++++++++++++++++++++++++++++---------------- ctx.h | 7 ++++--- stmt.cpp | 8 +++----- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/ctx.cpp b/ctx.cpp index 63a4391e..194ca30b 100644 --- a/ctx.cpp +++ b/ctx.cpp @@ -68,7 +68,8 @@ struct CFInfo { llvm::Value *savedContinueLanesPtr, llvm::Value *savedMask, llvm::Value *savedLoopMask); - static CFInfo *GetForeach(llvm::BasicBlock *breakTarget, + static CFInfo *GetForeach(FunctionEmitContext::ForeachType ft, + llvm::BasicBlock *breakTarget, llvm::BasicBlock *continueTarget, llvm::Value *savedBreakLanesPtr, llvm::Value *savedContinueLanesPtr, @@ -87,12 +88,13 @@ struct CFInfo { bool IsIf() { return type == If; } bool IsLoop() { return type == Loop; } - bool IsForeach() { return type == Foreach; } + bool IsForeach() { return (type == ForeachRegular || + type == ForeachUnique); } bool IsSwitch() { return type == Switch; } bool IsVarying() { return !isUniform; } bool IsUniform() { return isUniform; } - enum CFType { If, Loop, Foreach, Switch }; + enum CFType { If, Loop, ForeachRegular, ForeachUnique, Switch }; CFType type; bool isUniform; llvm::BasicBlock *savedBreakTarget, *savedContinueTarget; @@ -141,7 +143,7 @@ private: CFInfo(CFType t, llvm::BasicBlock *bt, llvm::BasicBlock *ct, llvm::Value *sb, llvm::Value *sc, llvm::Value *sm, llvm::Value *lm) { - Assert(t == Foreach); + Assert(t == ForeachRegular || t == ForeachUnique); type = t; isUniform = false; savedBreakTarget = bt; @@ -177,12 +179,25 @@ CFInfo::GetLoop(bool isUniform, llvm::BasicBlock *breakTarget, CFInfo * -CFInfo::GetForeach(llvm::BasicBlock *breakTarget, +CFInfo::GetForeach(FunctionEmitContext::ForeachType ft, + llvm::BasicBlock *breakTarget, llvm::BasicBlock *continueTarget, llvm::Value *savedBreakLanesPtr, llvm::Value *savedContinueLanesPtr, llvm::Value *savedMask, llvm::Value *savedForeachMask) { - return new CFInfo(Foreach, breakTarget, continueTarget, + CFType cfType; + switch (ft) { + case FunctionEmitContext::FOREACH_REGULAR: + cfType = ForeachRegular; + break; + case FunctionEmitContext::FOREACH_UNIQUE: + cfType = ForeachUnique; + break; + default: + FATAL("Unhandled foreach type"); + } + + return new CFInfo(cfType, breakTarget, continueTarget, savedBreakLanesPtr, savedContinueLanesPtr, savedMask, savedForeachMask); } @@ -583,23 +598,26 @@ FunctionEmitContext::EndLoop() { void -FunctionEmitContext::StartForeach() { +FunctionEmitContext::StartForeach(ForeachType ft) { // Issue an error if we're in a nested foreach... - for (int i = 0; i < (int)controlFlowInfo.size(); ++i) { - if (controlFlowInfo[i]->type == CFInfo::Foreach) { - Error(currentPos, "Nested \"foreach\" statements are currently illegal."); - break; - // Don't return here, however, and in turn allow the caller to - // do the rest of its codegen and then call EndForeach() - // normally--the idea being that this gives a chance to find - // any other errors inside the body of the foreach loop... + if (ft == FOREACH_REGULAR) { + for (int i = 0; i < (int)controlFlowInfo.size(); ++i) { + if (controlFlowInfo[i]->type == CFInfo::ForeachRegular) { + Error(currentPos, "Nested \"foreach\" statements are currently " + "illegal."); + break; + // Don't return here, however, and in turn allow the caller to + // do the rest of its codegen and then call EndForeach() + // normally--the idea being that this gives a chance to find + // any other errors inside the body of the foreach loop... + } } } // Store the current values of various loop-related state so that we // can restore it when we exit this loop. llvm::Value *oldMask = GetInternalMask(); - controlFlowInfo.push_back(CFInfo::GetForeach(breakTarget, continueTarget, + controlFlowInfo.push_back(CFInfo::GetForeach(ft, breakTarget, continueTarget, breakLanesPtr, continueLanesPtr, oldMask, loopMask)); breakLanesPtr = NULL; diff --git a/ctx.h b/ctx.h index 10a22115..a37842af 100644 --- a/ctx.h +++ b/ctx.h @@ -160,9 +160,10 @@ public: finished. */ void EndLoop(); - /** Indicates that code generation for a 'foreach' or 'foreach_tiled' - loop is about to start. */ - void StartForeach(); + /** Indicates that code generation for a 'foreach', 'foreach_tiled', or + 'foreach_unique' loop is about to start. */ + enum ForeachType { FOREACH_REGULAR, FOREACH_UNIQUE }; + void StartForeach(ForeachType ft); void EndForeach(); /** Emit code for a 'break' statement in a loop. If doCoherenceCheck diff --git a/stmt.cpp b/stmt.cpp index f4339f6f..e6622bb2 100644 --- a/stmt.cpp +++ b/stmt.cpp @@ -1458,7 +1458,7 @@ ForeachStmt::EmitCode(FunctionEmitContext *ctx) const { ctx->StoreInst(LLVMMaskAllOn, extrasMaskPtrs[i]); } - ctx->StartForeach(); + ctx->StartForeach(FunctionEmitContext::FOREACH_REGULAR); // On to the outermost loop's test ctx->BranchInst(bbTest[0]); @@ -1970,10 +1970,8 @@ ForeachUniqueStmt::EmitCode(FunctionEmitContext *ctx) const { llvm::Value *movmsk = ctx->LaneMask(oldFullMask); ctx->StoreInst(movmsk, maskBitsPtr); - // Officially start the loop; as far as the FunctionEmitContext is - // concerned, this can be handled the same way as a regular foreach - // loop (continue allowed but not break and return, etc.) - ctx->StartForeach(); + // Officially start the loop. + ctx->StartForeach(FunctionEmitContext::FOREACH_UNIQUE); ctx->SetContinueTarget(bbCheckForMore); // Evaluate the varying expression we're iterating over just once.