From f06caabb07358bcd6e81ca58441bb4741c52b1d5 Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Wed, 6 Jun 2012 11:04:09 -0700 Subject: [PATCH] Generate better code for break statements in varying loops (sometimes). If we have a simple varying 'if' statement where the only code in the body is a single 'break', then emit special case code that just updates the execution mask directly. Surprisingly, this leads to better generated code (e.g. Mandelbrot 7.1x on AVX vs 5.8x before). It's not clear why the general code generation path for break doesn't generate the equivalent code; this topic should be investigated further. (Issue #277). --- stmt.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/stmt.cpp b/stmt.cpp index eb626c0b..974af871 100644 --- a/stmt.cpp +++ b/stmt.cpp @@ -362,6 +362,28 @@ lEmitIfStatements(FunctionEmitContext *ctx, Stmt *stmts, const char *trueOrFalse } +/** Returns true if the "true" block for the if statement consists of a + single 'break' statement, and the "false" block is empty. */ +static bool +lCanApplyBreakOptimization(Stmt *trueStmts, Stmt *falseStmts) { + if (falseStmts != NULL) { + if (StmtList *sl = dynamic_cast(falseStmts)) { + return (sl->stmts.size() == 0); + } + else + return false; + } + + if (dynamic_cast(trueStmts)) + return true; + else if (StmtList *sl = dynamic_cast(trueStmts)) + return (sl->stmts.size() == 1 && + dynamic_cast(sl->stmts[0]) != NULL); + else + return false; +} + + void IfStmt::EmitCode(FunctionEmitContext *ctx) const { // First check all of the things that might happen due to errors @@ -415,6 +437,15 @@ IfStmt::EmitCode(FunctionEmitContext *ctx) const { ctx->SetCurrentBasicBlock(bexit); ctx->EndIf(); } + else if (lCanApplyBreakOptimization(trueStmts, falseStmts)) { + // If we have a simple break statement inside the 'if' and are + // under varying control flow, just update the execution mask + // directly and don't emit code for the statements. This leads to + // better code for this case--this is surprising and should be + // root-caused further, but for now this gives us performance + // benefit in this case. + ctx->SetInternalMaskAndNot(ctx->GetInternalMask(), testValue); + } else emitVaryingIf(ctx, testValue); }