Generate more efficient for regular varying 'if' statements.
For the case where we have a regular (i.e. non-'cif') 'if' statement, the generated code just simply checks to see if any program instance is running before running the corresponding statements. This is a lighter-weight check than IfStmt::emitMaskMixed() was performing.
This commit is contained in:
52
stmt.cpp
52
stmt.cpp
@@ -405,9 +405,9 @@ DeclStmt::Print(int indent) const {
|
|||||||
IfStmt::IfStmt(Expr *t, Stmt *ts, Stmt *fs, bool checkCoherence, SourcePos p)
|
IfStmt::IfStmt(Expr *t, Stmt *ts, Stmt *fs, bool checkCoherence, SourcePos p)
|
||||||
: Stmt(p), test(t), trueStmts(ts), falseStmts(fs),
|
: Stmt(p), test(t), trueStmts(ts), falseStmts(fs),
|
||||||
doAllCheck(checkCoherence &&
|
doAllCheck(checkCoherence &&
|
||||||
(test->GetType() != NULL) &&
|
!g->opt.disableCoherentControlFlow),
|
||||||
test->GetType()->IsVaryingType() &&
|
doAnyCheck(test->GetType() != NULL &&
|
||||||
!g->opt.disableCoherentControlFlow) {
|
test->GetType()->IsVaryingType()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -541,7 +541,7 @@ IfStmt::Print(int indent) const {
|
|||||||
|
|
||||||
|
|
||||||
/** Emit code to run both the true and false statements for the if test,
|
/** Emit code to run both the true and false statements for the if test,
|
||||||
with the mask set appropriately before runnign each one.
|
with the mask set appropriately before running each one.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
IfStmt::emitMaskedTrueAndFalse(FunctionEmitContext *ctx, llvm::Value *oldMask,
|
IfStmt::emitMaskedTrueAndFalse(FunctionEmitContext *ctx, llvm::Value *oldMask,
|
||||||
@@ -606,15 +606,45 @@ IfStmt::emitVaryingIf(FunctionEmitContext *ctx, llvm::Value *ltest) const {
|
|||||||
// paths above jump to when they're done.
|
// paths above jump to when they're done.
|
||||||
ctx->SetCurrentBasicBlock(bDone);
|
ctx->SetCurrentBasicBlock(bDone);
|
||||||
}
|
}
|
||||||
else {
|
else if (trueStmts != NULL || falseStmts != NULL) {
|
||||||
llvm::BasicBlock *bDone = ctx->CreateBasicBlock("cif_done");
|
assert(doAnyCheck);
|
||||||
|
|
||||||
// Emit emit code for the mixed mask case
|
ctx->StartVaryingIf(oldMask);
|
||||||
emitMaskMixed(ctx, oldMask, ltest, bDone);
|
llvm::BasicBlock *bNext = ctx->CreateBasicBlock("safe_if_after_true");
|
||||||
|
if (trueStmts != NULL) {
|
||||||
|
llvm::BasicBlock *bRunTrue = ctx->CreateBasicBlock("safe_if_run_true");
|
||||||
|
ctx->MaskAnd(oldMask, ltest);
|
||||||
|
|
||||||
// When done, set the current basic block to the block that the two
|
// Do any of the program instances want to run the 'true'
|
||||||
// paths above jump to when they're done.
|
// block? If not, jump ahead to bNext.
|
||||||
ctx->SetCurrentBasicBlock(bDone);
|
llvm::Value *maskAnyQ = ctx->Any(ctx->GetMask());
|
||||||
|
ctx->BranchInst(bRunTrue, bNext, maskAnyQ);
|
||||||
|
|
||||||
|
// Emit statements for true
|
||||||
|
ctx->SetCurrentBasicBlock(bRunTrue);
|
||||||
|
lEmitIfStatements(ctx, trueStmts, "if: expr mixed, true statements");
|
||||||
|
assert(ctx->GetCurrentBasicBlock());
|
||||||
|
ctx->BranchInst(bNext);
|
||||||
|
ctx->SetCurrentBasicBlock(bNext);
|
||||||
|
}
|
||||||
|
if (falseStmts != NULL) {
|
||||||
|
llvm::BasicBlock *bRunFalse = ctx->CreateBasicBlock("safe_if_run_false");
|
||||||
|
bNext = ctx->CreateBasicBlock("safe_if_after_false");
|
||||||
|
ctx->MaskAndNot(oldMask, ltest);
|
||||||
|
|
||||||
|
// Similarly, check to see if any of the instances want to run
|
||||||
|
// run the 'false' block...
|
||||||
|
llvm::Value *maskAnyQ = ctx->Any(ctx->GetMask());
|
||||||
|
ctx->BranchInst(bRunFalse, bNext, maskAnyQ);
|
||||||
|
|
||||||
|
// Emit code for false
|
||||||
|
ctx->SetCurrentBasicBlock(bRunFalse);
|
||||||
|
lEmitIfStatements(ctx, falseStmts, "if: expr mixed, false statements");
|
||||||
|
assert(ctx->GetCurrentBasicBlock());
|
||||||
|
ctx->BranchInst(bNext);
|
||||||
|
ctx->SetCurrentBasicBlock(bNext);
|
||||||
|
}
|
||||||
|
ctx->EndIf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
stmt.h
1
stmt.h
@@ -126,6 +126,7 @@ private:
|
|||||||
active program instances want to follow just one of the 'true' or
|
active program instances want to follow just one of the 'true' or
|
||||||
'false' blocks. */
|
'false' blocks. */
|
||||||
const bool doAllCheck;
|
const bool doAllCheck;
|
||||||
|
const bool doAnyCheck;
|
||||||
|
|
||||||
void emitMaskedTrueAndFalse(FunctionEmitContext *ctx, llvm::Value *oldMask,
|
void emitMaskedTrueAndFalse(FunctionEmitContext *ctx, llvm::Value *oldMask,
|
||||||
llvm::Value *test) const;
|
llvm::Value *test) const;
|
||||||
|
|||||||
Reference in New Issue
Block a user