[Beignet] [Patch v2 4/4] move simpleBlock check and if/endif optimize after select.
Ruiling Song
ruiling.song83 at gmail.com
Tue Jan 17 04:29:33 UTC 2017
2017-01-06 22:40 GMT+08:00 <xionghu.luo at intel.com>:
> From: Luo Xionghu <xionghu.luo at intel.com>
>
> the if opt could be a independent pass like function by checking the
> instruction state changes and special instructions like I64, mixed bit
> etc. this could reduce the code complexit of structure code.
>
> v2: as the GenInstructionState flag/subFlag default value is 0.0, so
> isSimpleBlock function return false if the insn state uses 0.1 as flag.
> This rule could make function more straight forward, no need to enum
> the special instructions except SEL_OP_SEL_CMP(no predication per spec).
>
> Signed-off-by: Luo Xionghu <xionghu.luo at intel.com>
> ---
> backend/src/CMakeLists.txt | 1 +
> backend/src/backend/gen_context.cpp | 8 +-
> backend/src/backend/gen_insn_selection.hpp | 2 +
> backend/src/backend/gen_insn_selection_if_opt.cpp | 119
> ++++++++++++++++++++++
> 4 files changed, 129 insertions(+), 1 deletion(-)
> create mode 100644 backend/src/backend/gen_insn_selection_if_opt.cpp
>
> diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt
> index 6ff25e7..c98ab3d 100644
> --- a/backend/src/CMakeLists.txt
> +++ b/backend/src/CMakeLists.txt
> @@ -104,6 +104,7 @@ set (GBE_SRC
> backend/gen_insn_selection.cpp
> backend/gen_insn_selection.hpp
> backend/gen_insn_selection_optimize.cpp
> + backend/gen_insn_selection_if_opt.cpp
> backend/gen_insn_scheduling.cpp
> backend/gen_insn_scheduling.hpp
> backend/gen_insn_selection_output.cpp
> diff --git a/backend/src/backend/gen_context.cpp
> b/backend/src/backend/gen_context.cpp
> index 10e2c9e..769cd86 100644
> --- a/backend/src/backend/gen_context.cpp
> +++ b/backend/src/backend/gen_context.cpp
> @@ -3617,14 +3617,20 @@ namespace gbe
> kernel->curbeSize = ALIGN(kernel->curbeSize, GEN_REG_SIZE);
> }
>
> + BVAR(OCL_OUTPUT_BEFORE_OPT, false);
> BVAR(OCL_OUTPUT_SEL_IR, false);
> BVAR(OCL_OPTIMIZE_SEL_IR, true);
> + BVAR(OCL_OPTIMIZE_IF_IR, true);
>
I think OCL_OPTIMIZE_IF_BLOCK is more easy to understand.
> bool GenContext::emitCode(void) {
> GenKernel *genKernel = static_cast<GenKernel*>(this->kernel);
> sel->select();
> + sel->addID();
> + if (OCL_OUTPUT_BEFORE_OPT)
>
OCL_OUTPUT_BEFORE_OPT is not easy to understand, output what?
I think OCL_OUTPUT_SEL_IR_AFTER_SELECT is a little better.
> + outputSelectionIR(*this, this->sel, genKernel->getName());
> if (OCL_OPTIMIZE_SEL_IR)
> sel->optimize();
> - sel->addID();
> + if (OCL_OPTIMIZE_IF_IR)
> + sel->if_opt();
>
Hi Xiuli,
this addID is only needed by outputSelectionIR(), right?
if it is only meaningful to outputSelectionIR, I would prefer putting it
under if (OCL_OUTPUT_SEL_IR).
> if (OCL_OUTPUT_SEL_IR)
outputSelectionIR(*this, this->sel, genKernel->getName());
> schedulePreRegAllocation(*this, *this->sel);
> diff --git a/backend/src/backend/gen_insn_selection.hpp
> b/backend/src/backend/gen_insn_selection.hpp
> index f4cc948..88ae44f 100644
> --- a/backend/src/backend/gen_insn_selection.hpp
> +++ b/backend/src/backend/gen_insn_selection.hpp
> @@ -318,6 +318,8 @@ namespace gbe
> void optimize(void);
> uint32_t opt_features;
>
> + void if_opt(void);
> +
> /* Add insn ID for sel IR */
> void addID(void);
> const GenContext &getCtx();
> diff --git a/backend/src/backend/gen_insn_selection_if_opt.cpp
> b/backend/src/backend/gen_insn_selection_if_opt.cpp
> new file mode 100644
> index 0000000..026f5b9
> --- /dev/null
> +++ b/backend/src/backend/gen_insn_selection_if_opt.cpp
> @@ -0,0 +1,119 @@
> +
> +#include "backend/gen_insn_selection.hpp"
> +#include "backend/gen_context.hpp"
> +#include "ir/function.hpp"
> +#include "ir/liveness.hpp"
> +#include "ir/profile.hpp"
> +#include "sys/cvar.hpp"
> +#include "sys/vector.hpp"
> +#include <algorithm>
> +#include <climits>
> +#include <map>
> +
> +namespace gbe
> +{
> + class IfOptimizer
> + {
> + public:
> + IfOptimizer(const GenContext& ctx, SelectionBlock& selblock) :
> ctx(ctx), selBlock(selblock) {}
> + void run();
> + bool isSimpleBlock();
> + void removeSimpleIfEndif();
> + ~IfOptimizer() {}
> + protected:
> + const GenContext &ctx; //in case that we need it
> + SelectionBlock &selBlock;
> + bool optimized;
> + };
> +
> + bool IfOptimizer::isSimpleBlock() {
> +
> + if(selBlock.insnList.size() > 20)
> + return false;
> +
> + bool if_exits = false;
> + bool endif_exits = false;
> + for (auto &insn : selBlock.insnList) {
> + if (insn.opcode == SEL_OP_IF) {
> + if_exits = true;
> + continue;
> + }
> + if(if_exits) {
> + GenInstructionState curr = insn.state;
> + if (curr.execWidth == 1 || curr.predicate != GEN_PREDICATE_NONE
> || curr.flagIndex != 0 || (curr.flag == 0 && curr.subFlag == 1)) {
> + return false;
> + }
> +
> + if (insn.opcode == SEL_OP_ELSE) {
> + return false;
> + }
> +
> + if (insn.opcode == SEL_OP_SEL_CMP) {
> + return false;
> + }
> + }
> +
> + if (insn.opcode == SEL_OP_ENDIF) {
> + endif_exits = true;
> + break;
> + }
> + }
> +
> + if (!if_exits || !endif_exits)
> + return false;
> +
> + return true;
> + }
> +
> + void IfOptimizer::removeSimpleIfEndif() {
> + if(isSimpleBlock()) {
> + GenInstructionState curr;
> + bool if_find = false;
>
I think you need to re-write your code like below to make it more clean:
you need to be careful here to make the logic is the same as before.
auto iter = selBlock.insnList.begin();
while (iter != selBlock.insnList.end()) {
//remove if and endif, change instruction flags.
SelectionInstruction& insn = *iter;
if(insn.opcode == SEL_OP_IF && !if_find) {
iter = selBlock.insnList.erase(&insn);
if_find = true;
} else if (ENDIF) {
iter = selBlock.insnList.erase(&insn);
optimized = true;
} else {
if (if_find) {
insn.state.predicate = GEN_PREDICATE_NORMAL;
insn.state.flag = 0;
insn.state.subFlag = 1;
}
++iter;
}
}
+ for (auto iter = selBlock.insnList.begin(); iter !=
> selBlock.insnList.end(); iter++ ) {
> + //remove if and endif, change instruction flags.
> + SelectionInstruction& insn = *iter;
> + if(insn.opcode == SEL_OP_IF && !if_find) {
> + iter = selBlock.insnList.erase(&insn);
> + if (iter == selBlock.insnList.end()) {
> + break;
> + }
> + SelectionInstruction &next = *iter;
> + next.state.predicate = GEN_PREDICATE_NORMAL;
> + next.state.flag = 0;
> + next.state.subFlag = 1;
> + if_find = true;
> + continue;
> + }
> +
> + if(!if_find)
> + continue;
> +
> + insn.state.predicate = GEN_PREDICATE_NORMAL;
> + insn.state.flag = 0;
> + insn.state.subFlag = 1;
> + if (insn.opcode == SEL_OP_ENDIF) {
> + selBlock.insnList.erase(&insn);
> + optimized = true;
> + break;
> + }
> + }
> + }
> + }
> +
> + void IfOptimizer::run()
> + {
> + optimized = false;
> + removeSimpleIfEndif();
> + }
> +
> + void Selection::if_opt()
> + {
> + //do basic block level optimization
> + for (SelectionBlock &block : *blockList) {
> + IfOptimizer ifopt(getCtx(), block);
> + ifopt.run();
> + }
> +
> + }
> +} /* namespace gbe */
> +
> --
> 2.5.0
>
> _______________________________________________
> Beignet mailing list
> Beignet at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/beignet
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/beignet/attachments/20170117/2e30d98c/attachment.html>
More information about the Beignet
mailing list