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.
This commit is contained in:
Matt Pharr
2012-06-22 06:04:00 -07:00
parent 2b4a3b22bf
commit ed13dd066b
3 changed files with 41 additions and 24 deletions

38
ctx.cpp
View File

@@ -68,7 +68,8 @@ struct CFInfo {
llvm::Value *savedContinueLanesPtr, llvm::Value *savedContinueLanesPtr,
llvm::Value *savedMask, llvm::Value *savedLoopMask); 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::BasicBlock *continueTarget,
llvm::Value *savedBreakLanesPtr, llvm::Value *savedBreakLanesPtr,
llvm::Value *savedContinueLanesPtr, llvm::Value *savedContinueLanesPtr,
@@ -87,12 +88,13 @@ struct CFInfo {
bool IsIf() { return type == If; } bool IsIf() { return type == If; }
bool IsLoop() { return type == Loop; } bool IsLoop() { return type == Loop; }
bool IsForeach() { return type == Foreach; } bool IsForeach() { return (type == ForeachRegular ||
type == ForeachUnique); }
bool IsSwitch() { return type == Switch; } bool IsSwitch() { return type == Switch; }
bool IsVarying() { return !isUniform; } bool IsVarying() { return !isUniform; }
bool IsUniform() { return isUniform; } bool IsUniform() { return isUniform; }
enum CFType { If, Loop, Foreach, Switch }; enum CFType { If, Loop, ForeachRegular, ForeachUnique, Switch };
CFType type; CFType type;
bool isUniform; bool isUniform;
llvm::BasicBlock *savedBreakTarget, *savedContinueTarget; llvm::BasicBlock *savedBreakTarget, *savedContinueTarget;
@@ -141,7 +143,7 @@ private:
CFInfo(CFType t, llvm::BasicBlock *bt, llvm::BasicBlock *ct, CFInfo(CFType t, llvm::BasicBlock *bt, llvm::BasicBlock *ct,
llvm::Value *sb, llvm::Value *sc, llvm::Value *sm, llvm::Value *sb, llvm::Value *sc, llvm::Value *sm,
llvm::Value *lm) { llvm::Value *lm) {
Assert(t == Foreach); Assert(t == ForeachRegular || t == ForeachUnique);
type = t; type = t;
isUniform = false; isUniform = false;
savedBreakTarget = bt; savedBreakTarget = bt;
@@ -177,12 +179,25 @@ CFInfo::GetLoop(bool isUniform, llvm::BasicBlock *breakTarget,
CFInfo * CFInfo *
CFInfo::GetForeach(llvm::BasicBlock *breakTarget, CFInfo::GetForeach(FunctionEmitContext::ForeachType ft,
llvm::BasicBlock *breakTarget,
llvm::BasicBlock *continueTarget, llvm::BasicBlock *continueTarget,
llvm::Value *savedBreakLanesPtr, llvm::Value *savedBreakLanesPtr,
llvm::Value *savedContinueLanesPtr, llvm::Value *savedContinueLanesPtr,
llvm::Value *savedMask, llvm::Value *savedForeachMask) { 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, savedBreakLanesPtr, savedContinueLanesPtr,
savedMask, savedForeachMask); savedMask, savedForeachMask);
} }
@@ -583,11 +598,13 @@ FunctionEmitContext::EndLoop() {
void void
FunctionEmitContext::StartForeach() { FunctionEmitContext::StartForeach(ForeachType ft) {
// Issue an error if we're in a nested foreach... // Issue an error if we're in a nested foreach...
if (ft == FOREACH_REGULAR) {
for (int i = 0; i < (int)controlFlowInfo.size(); ++i) { for (int i = 0; i < (int)controlFlowInfo.size(); ++i) {
if (controlFlowInfo[i]->type == CFInfo::Foreach) { if (controlFlowInfo[i]->type == CFInfo::ForeachRegular) {
Error(currentPos, "Nested \"foreach\" statements are currently illegal."); Error(currentPos, "Nested \"foreach\" statements are currently "
"illegal.");
break; break;
// Don't return here, however, and in turn allow the caller to // Don't return here, however, and in turn allow the caller to
// do the rest of its codegen and then call EndForeach() // do the rest of its codegen and then call EndForeach()
@@ -595,11 +612,12 @@ FunctionEmitContext::StartForeach() {
// any other errors inside the body of the foreach loop... // any other errors inside the body of the foreach loop...
} }
} }
}
// Store the current values of various loop-related state so that we // Store the current values of various loop-related state so that we
// can restore it when we exit this loop. // can restore it when we exit this loop.
llvm::Value *oldMask = GetInternalMask(); llvm::Value *oldMask = GetInternalMask();
controlFlowInfo.push_back(CFInfo::GetForeach(breakTarget, continueTarget, controlFlowInfo.push_back(CFInfo::GetForeach(ft, breakTarget, continueTarget,
breakLanesPtr, continueLanesPtr, breakLanesPtr, continueLanesPtr,
oldMask, loopMask)); oldMask, loopMask));
breakLanesPtr = NULL; breakLanesPtr = NULL;

7
ctx.h
View File

@@ -160,9 +160,10 @@ public:
finished. */ finished. */
void EndLoop(); void EndLoop();
/** Indicates that code generation for a 'foreach' or 'foreach_tiled' /** Indicates that code generation for a 'foreach', 'foreach_tiled', or
loop is about to start. */ 'foreach_unique' loop is about to start. */
void StartForeach(); enum ForeachType { FOREACH_REGULAR, FOREACH_UNIQUE };
void StartForeach(ForeachType ft);
void EndForeach(); void EndForeach();
/** Emit code for a 'break' statement in a loop. If doCoherenceCheck /** Emit code for a 'break' statement in a loop. If doCoherenceCheck

View File

@@ -1458,7 +1458,7 @@ ForeachStmt::EmitCode(FunctionEmitContext *ctx) const {
ctx->StoreInst(LLVMMaskAllOn, extrasMaskPtrs[i]); ctx->StoreInst(LLVMMaskAllOn, extrasMaskPtrs[i]);
} }
ctx->StartForeach(); ctx->StartForeach(FunctionEmitContext::FOREACH_REGULAR);
// On to the outermost loop's test // On to the outermost loop's test
ctx->BranchInst(bbTest[0]); ctx->BranchInst(bbTest[0]);
@@ -1970,10 +1970,8 @@ ForeachUniqueStmt::EmitCode(FunctionEmitContext *ctx) const {
llvm::Value *movmsk = ctx->LaneMask(oldFullMask); llvm::Value *movmsk = ctx->LaneMask(oldFullMask);
ctx->StoreInst(movmsk, maskBitsPtr); ctx->StoreInst(movmsk, maskBitsPtr);
// Officially start the loop; as far as the FunctionEmitContext is // Officially start the loop.
// concerned, this can be handled the same way as a regular foreach ctx->StartForeach(FunctionEmitContext::FOREACH_UNIQUE);
// loop (continue allowed but not break and return, etc.)
ctx->StartForeach();
ctx->SetContinueTarget(bbCheckForMore); ctx->SetContinueTarget(bbCheckForMore);
// Evaluate the varying expression we're iterating over just once. // Evaluate the varying expression we're iterating over just once.