Merge pull request #856 from jbrodman/master
Fix issue where break stmts would in executing with mask all off.
This commit is contained in:
13
ctx.cpp
13
ctx.cpp
@@ -741,6 +741,7 @@ FunctionEmitContext::Break(bool doCoherenceCheck) {
|
||||
// that have executed a 'break' statement:
|
||||
// breakLanes = breakLanes | mask
|
||||
AssertPos(currentPos, breakLanesPtr != NULL);
|
||||
|
||||
llvm::Value *mask = GetInternalMask();
|
||||
llvm::Value *breakMask = LoadInst(breakLanesPtr,
|
||||
"break_mask");
|
||||
@@ -879,7 +880,7 @@ FunctionEmitContext::jumpIfAllLoopLanesAreDone(llvm::BasicBlock *target) {
|
||||
finishedLanes = BinaryOperator(llvm::Instruction::Or, finishedLanes,
|
||||
continued, "returned|breaked|continued");
|
||||
}
|
||||
|
||||
|
||||
finishedLanes = BinaryOperator(llvm::Instruction::And,
|
||||
finishedLanes, GetFunctionMask(),
|
||||
"finished&func");
|
||||
@@ -923,6 +924,16 @@ FunctionEmitContext::RestoreContinuedLanes() {
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FunctionEmitContext::ClearBreakLanes() {
|
||||
if (breakLanesPtr == NULL)
|
||||
return;
|
||||
|
||||
// breakLanes = 0
|
||||
StoreInst(LLVMMaskAllOff, breakLanesPtr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FunctionEmitContext::StartSwitch(bool cfIsUniform, llvm::BasicBlock *bbBreak) {
|
||||
llvm::Value *oldMask = GetInternalMask();
|
||||
|
||||
7
ctx.h
7
ctx.h
@@ -195,6 +195,13 @@ public:
|
||||
'continue' statement when going through the loop body in the
|
||||
previous iteration. */
|
||||
void RestoreContinuedLanes();
|
||||
|
||||
/** This method is called by code emitting IR for a loop. It clears
|
||||
any lanes that contained a break since the mask has been updated to take
|
||||
them into account. This is necessary as all the bail out checks for
|
||||
breaks are meant to only deal with lanes breaking on the current iteration.
|
||||
*/
|
||||
void ClearBreakLanes();
|
||||
|
||||
/** Indicates that code generation for a "switch" statement is about to
|
||||
start. isUniform indicates whether the "switch" value is uniform,
|
||||
|
||||
7
stmt.cpp
7
stmt.cpp
@@ -532,7 +532,6 @@ IfStmt::emitMaskedTrueAndFalse(FunctionEmitContext *ctx, llvm::Value *oldMask,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Emit code for an if test that checks the mask and the test values and
|
||||
tries to be smart about jumping over code that doesn't need to be run.
|
||||
*/
|
||||
@@ -902,8 +901,10 @@ void DoStmt::EmitCode(FunctionEmitContext *ctx) const {
|
||||
// the code for the test. This is only necessary for varying loops;
|
||||
// 'uniform' loops just jump when they hit a continue statement and
|
||||
// don't mess with the mask.
|
||||
if (!uniformTest)
|
||||
if (!uniformTest) {
|
||||
ctx->RestoreContinuedLanes();
|
||||
ctx->ClearBreakLanes();
|
||||
}
|
||||
llvm::Value *testValue = testExpr->GetValue(ctx);
|
||||
if (!testValue)
|
||||
return;
|
||||
@@ -1111,6 +1112,8 @@ ForStmt::EmitCode(FunctionEmitContext *ctx) const {
|
||||
// test code.
|
||||
ctx->SetCurrentBasicBlock(bstep);
|
||||
ctx->RestoreContinuedLanes();
|
||||
ctx->ClearBreakLanes();
|
||||
|
||||
if (step)
|
||||
step->EmitCode(ctx);
|
||||
ctx->BranchInst(btest);
|
||||
|
||||
Reference in New Issue
Block a user