From b45424e277831af9b88331dce2e0e261133c3be8 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Mon, 11 May 2020 17:13:23 -0400 Subject: [PATCH 01/19] [skip ci] Convert loop_var into LoopIndexStmt (stage 1) --- taichi/analysis/verify.cpp | 30 ++++----- taichi/ir/ir.h | 1 + taichi/ir/statements.h | 7 ++- taichi/transforms/compile_to_offloads.cpp | 4 ++ taichi/transforms/convert_into_loop_index.cpp | 62 +++++++++++++++++++ taichi/transforms/ir_printer.cpp | 7 ++- taichi/transforms/offload.cpp | 44 ++++++------- taichi/transforms/variable_optimization.cpp | 3 +- 8 files changed, 115 insertions(+), 43 deletions(-) create mode 100644 taichi/transforms/convert_into_loop_index.cpp diff --git a/taichi/analysis/verify.cpp b/taichi/analysis/verify.cpp index 0805090378358..cdd1d2225732c 100644 --- a/taichi/analysis/verify.cpp +++ b/taichi/analysis/verify.cpp @@ -73,26 +73,28 @@ class IRVerifier : public BasicStmtVisitor { void visit(RangeForStmt *for_stmt) override { basic_verify(for_stmt); - TI_ASSERT(for_stmt->loop_var->is()); - TI_ASSERT_INFO(irpass::analysis::gather_statements( - for_stmt->loop_var->parent, - [&](Stmt *s) { - if (auto store = s->cast()) - return store->ptr == for_stmt->loop_var; - else if (auto atomic = s->cast()) { - return atomic->dest == for_stmt->loop_var; - } else { - return false; - } - }) - .empty(), - "loop_var of {} modified", for_stmt->id); + if (for_stmt->loop_var) { + TI_ASSERT(for_stmt->loop_var->is()); + TI_ASSERT_INFO(irpass::analysis::gather_statements( + for_stmt->loop_var->parent, + [&](Stmt *s) { + if (auto store = s->cast()) + return store->ptr == for_stmt->loop_var; + else if (auto atomic = s->cast()) { + return atomic->dest == for_stmt->loop_var; + } else { + return false; + } + }).empty(), "loop_var of {} modified", for_stmt->id); + } for_stmt->body->accept(this); } void visit(StructForStmt *for_stmt) override { basic_verify(for_stmt); for (auto &loop_var : for_stmt->loop_vars) { + if (!loop_var) + continue; TI_ASSERT(loop_var->is()); TI_ASSERT_INFO(irpass::analysis::gather_statements( loop_var->parent, diff --git a/taichi/ir/ir.h b/taichi/ir/ir.h index 85916350ba82b..a9d650e8573e8 100644 --- a/taichi/ir/ir.h +++ b/taichi/ir/ir.h @@ -97,6 +97,7 @@ void full_simplify(IRNode *root, Kernel *kernel = nullptr); void print(IRNode *root, std::string *output = nullptr); void lower(IRNode *root); +void convert_into_loop_index(IRNode *root); void typecheck(IRNode *root, Kernel *kernel = nullptr); void loop_vectorize(IRNode *root); void slp_vectorize(IRNode *root); diff --git a/taichi/ir/statements.h b/taichi/ir/statements.h index a49e438efd04c..dc536bac1f82b 100644 --- a/taichi/ir/statements.h +++ b/taichi/ir/statements.h @@ -217,11 +217,12 @@ class OffloadedStmt : public Stmt { class LoopIndexStmt : public Stmt { public: + Stmt *loop; int index; bool is_struct_for; - LoopIndexStmt(int index, bool is_struct_for) - : index(index), is_struct_for(is_struct_for) { + LoopIndexStmt(Stmt *loop, int index, bool is_struct_for) + : loop(loop), index(index), is_struct_for(is_struct_for) { TI_STMT_REG_FIELDS; } @@ -229,7 +230,7 @@ class LoopIndexStmt : public Stmt { return false; } - TI_STMT_DEF_FIELDS(ret_type, index, is_struct_for); + TI_STMT_DEF_FIELDS(ret_type, loop, index, is_struct_for); DEFINE_ACCEPT }; diff --git a/taichi/transforms/compile_to_offloads.cpp b/taichi/transforms/compile_to_offloads.cpp index dacbd44b4db15..5fa0c45288ffa 100644 --- a/taichi/transforms/compile_to_offloads.cpp +++ b/taichi/transforms/compile_to_offloads.cpp @@ -67,6 +67,10 @@ void compile_to_offloads(IRNode *ir, irpass::analysis::verify(ir); } + irpass::convert_into_loop_index(ir); + print("Converted into loop index"); + irpass::analysis::verify(ir); + if (config.check_out_of_bound) { irpass::check_out_of_bound(ir); print("Bound checked"); diff --git a/taichi/transforms/convert_into_loop_index.cpp b/taichi/transforms/convert_into_loop_index.cpp new file mode 100644 index 0000000000000..c21f5606bf375 --- /dev/null +++ b/taichi/transforms/convert_into_loop_index.cpp @@ -0,0 +1,62 @@ +#include "taichi/ir/ir.h" + +TLANG_NAMESPACE_BEGIN + +class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { + public: + using BasicStmtVisitor::visit; + + static void convert(Stmt *loop, + Stmt *loop_var, + int index, + bool is_struct_for) { + if (!loop_var) + return; + irpass::replace_statements_with( + loop, + [&](Stmt *load) { + if (auto local_load = load->cast()) { + return local_load->width() == 1 && + local_load->ptr[0].var == loop_var && + local_load->ptr[0].offset == 0; + } + return false; + }, + [&]() { return Stmt::make(loop, index, is_struct_for); }); + } + + void preprocess_container_stmt(Stmt *stmt) override { + if (auto range_for = stmt->cast()) { + convert(range_for, range_for->loop_var, 0, false); + range_for->loop_var = nullptr; + } else if (auto struct_for = stmt->cast()) { + for (int i = 0; i < (int)struct_for->loop_vars.size(); i++) { + convert(struct_for, struct_for->loop_vars[i], i, true); + struct_for->loop_vars[i] = nullptr; + } + } + } + + static void run(IRNode *node) { + ConvertIntoLoopIndexStmt converter; + while (true) { + bool modified = false; + try { + node->accept(&converter); + } catch (IRModified) { + modified = true; + } + if (!modified) + break; + } + } +}; + +namespace irpass { +void convert_into_loop_index(IRNode *root) { + ConvertIntoLoopIndexStmt::run(root); + typecheck(root); +} +} // namespace irpass + +TLANG_NAMESPACE_END diff --git a/taichi/transforms/ir_printer.cpp b/taichi/transforms/ir_printer.cpp index 617ce6ddb7f97..2a5dbec2b50c0 100644 --- a/taichi/transforms/ir_printer.cpp +++ b/taichi/transforms/ir_printer.cpp @@ -258,7 +258,8 @@ class IRPrinter : public IRVisitor { void visit(RangeForStmt *for_stmt) override { print("{} : {}for {} in range({}, {}, step {}) {{", for_stmt->name(), - for_stmt->reversed ? "reversed " : "", for_stmt->loop_var->name(), + for_stmt->reversed ? "reversed " : "", for_stmt->loop_var ? + for_stmt->loop_var->name() : "nullptr", for_stmt->begin->name(), for_stmt->end->name(), for_stmt->vectorize); for_stmt->body->accept(this); print("}}"); @@ -267,7 +268,7 @@ class IRPrinter : public IRVisitor { void visit(StructForStmt *for_stmt) override { auto loop_vars = make_list( for_stmt->loop_vars, - [](Stmt *const &stmt) -> std::string { return stmt->name(); }); + [](Stmt *const &stmt) -> std::string { return stmt ? stmt->name() : "nullptr"; }); print("{} : for {} where {} active, step {} {{", for_stmt->name(), loop_vars, for_stmt->snode->get_node_type_name_hinted(), for_stmt->vectorize); @@ -457,7 +458,7 @@ class IRPrinter : public IRVisitor { } void visit(LoopIndexStmt *stmt) override { - print("{}{} = loop index {}", stmt->type_hint(), stmt->name(), stmt->index); + print("{}{} = loop {} index {}", stmt->type_hint(), stmt->name(), stmt->loop->name(), stmt->index); } void visit(GlobalTemporaryStmt *stmt) override { diff --git a/taichi/transforms/offload.cpp b/taichi/transforms/offload.cpp index fbd40bdc8e885..ec1895dd7d9d2 100644 --- a/taichi/transforms/offload.cpp +++ b/taichi/transforms/offload.cpp @@ -24,22 +24,22 @@ class Offloader { run(root); } - void fix_loop_index_load(Stmt *s, - Stmt *loop_var, - int index, - bool is_struct_for) { - replace_statements_with( - s, - [&](Stmt *load) { - if (auto local_load = load->cast()) { - return local_load->width() == 1 && - local_load->ptr[0].var == loop_var && - local_load->ptr[0].offset == 0; - } - return false; - }, - [&]() { return Stmt::make(index, is_struct_for); }); - } +// void fix_loop_index_load(Stmt *s, +// Stmt *loop_var, +// int index, +// bool is_struct_for) { +// replace_statements_with( +// s, +// [&](Stmt *load) { +// if (auto local_load = load->cast()) { +// return local_load->width() == 1 && +// local_load->ptr[0].var == loop_var && +// local_load->ptr[0].offset == 0; +// } +// return false; +// }, +// [&]() { return Stmt::make(index, is_struct_for); }); +// } void run(IRNode *root) { auto root_block = dynamic_cast(root); @@ -78,7 +78,7 @@ class Offloader { } offloaded->block_dim = s->block_dim; offloaded->num_cpu_threads = s->parallelize; - fix_loop_index_load(s, s->loop_var, 0, /*is_struct_for=*/false); +// fix_loop_index_load(s, s->loop_var, 0, /*is_struct_for=*/false); for (int j = 0; j < (int)s->body->statements.size(); j++) { offloaded->body->insert(std::move(s->body->statements[j])); } @@ -120,11 +120,11 @@ class Offloader { auto offloaded_struct_for = Stmt::make_typed(OffloadedStmt::TaskType::struct_for); - for (int i = 0; i < for_stmt->loop_vars.size(); i++) { - fix_loop_index_load(for_stmt, for_stmt->loop_vars[i], - leaf->physical_index_position[i], - /*is_struct_for=*/true); - } +// for (int i = 0; i < for_stmt->loop_vars.size(); i++) { +// fix_loop_index_load(for_stmt, for_stmt->loop_vars[i], +// leaf->physical_index_position[i], +// /*is_struct_for=*/true); +// } for (int i = 0; i < (int)for_stmt->body->statements.size(); i++) { offloaded_struct_for->body->insert( diff --git a/taichi/transforms/variable_optimization.cpp b/taichi/transforms/variable_optimization.cpp index 85e2cfc1def55..db130f3c4c3e4 100644 --- a/taichi/transforms/variable_optimization.cpp +++ b/taichi/transforms/variable_optimization.cpp @@ -176,7 +176,8 @@ class AllocaOptimize : public VariableOptimize { } for (auto &loop_var : loop_vars) { - get_state_machine(loop_var).mark_as_loop_var(); + if (loop_var) + get_state_machine(loop_var).mark_as_loop_var(); } auto origin = state_machines; modify_all_state_machines(&StateMachine::begin_if_or_loop); From 17dfe8d3027e63824a74be84cba3a16a727ac249 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Tue, 12 May 2020 17:35:40 -0400 Subject: [PATCH 02/19] [skip ci] Fix irpass::offload --- taichi/ir/transforms.h | 1 + taichi/transforms/convert_into_loop_index.cpp | 6 +++- taichi/transforms/offload.cpp | 33 ++++++------------- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/taichi/ir/transforms.h b/taichi/ir/transforms.h index ffbf15d115bb1..ac315cd7f45a4 100644 --- a/taichi/ir/transforms.h +++ b/taichi/ir/transforms.h @@ -30,6 +30,7 @@ void full_simplify(IRNode *root, Kernel *kernel = nullptr); void print(IRNode *root, std::string *output = nullptr); void lower(IRNode *root); +void convert_into_loop_index(IRNode *root); void typecheck(IRNode *root, Kernel *kernel = nullptr); void loop_vectorize(IRNode *root); void slp_vectorize(IRNode *root); diff --git a/taichi/transforms/convert_into_loop_index.cpp b/taichi/transforms/convert_into_loop_index.cpp index c21f5606bf375..142534bd29ffc 100644 --- a/taichi/transforms/convert_into_loop_index.cpp +++ b/taichi/transforms/convert_into_loop_index.cpp @@ -1,4 +1,6 @@ #include "taichi/ir/ir.h" +#include "taichi/ir/transforms.h" +#include "taichi/ir/visitors.h" TLANG_NAMESPACE_BEGIN @@ -30,8 +32,10 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { convert(range_for, range_for->loop_var, 0, false); range_for->loop_var = nullptr; } else if (auto struct_for = stmt->cast()) { + auto leaf = struct_for->snode; for (int i = 0; i < (int)struct_for->loop_vars.size(); i++) { - convert(struct_for, struct_for->loop_vars[i], i, true); + convert(struct_for, struct_for->loop_vars[i], + leaf->physical_index_position[i], true); struct_for->loop_vars[i] = nullptr; } } diff --git a/taichi/transforms/offload.cpp b/taichi/transforms/offload.cpp index e9a2773866437..9d6e5324814d0 100644 --- a/taichi/transforms/offload.cpp +++ b/taichi/transforms/offload.cpp @@ -26,23 +26,6 @@ class Offloader { run(root); } -// void fix_loop_index_load(Stmt *s, -// Stmt *loop_var, -// int index, -// bool is_struct_for) { -// replace_statements_with( -// s, -// [&](Stmt *load) { -// if (auto local_load = load->cast()) { -// return local_load->width() == 1 && -// local_load->ptr[0].var == loop_var && -// local_load->ptr[0].offset == 0; -// } -// return false; -// }, -// [&]() { return Stmt::make(index, is_struct_for); }); -// } - void run(IRNode *root) { auto root_block = dynamic_cast(root); auto root_statements = std::move(root_block->statements); @@ -80,7 +63,7 @@ class Offloader { } offloaded->block_dim = s->block_dim; offloaded->num_cpu_threads = s->parallelize; -// fix_loop_index_load(s, s->loop_var, 0, /*is_struct_for=*/false); + replace_all_usages_with(s, s, offloaded.get()); for (int j = 0; j < (int)s->body->statements.size(); j++) { offloaded->body->insert(std::move(s->body->statements[j])); } @@ -122,11 +105,7 @@ class Offloader { auto offloaded_struct_for = Stmt::make_typed(OffloadedStmt::TaskType::struct_for); -// for (int i = 0; i < for_stmt->loop_vars.size(); i++) { -// fix_loop_index_load(for_stmt, for_stmt->loop_vars[i], -// leaf->physical_index_position[i], -// /*is_struct_for=*/true); -// } + replace_all_usages_with(for_stmt, for_stmt, offloaded_struct_for.get()); for (int i = 0; i < (int)for_stmt->body->statements.size(); i++) { offloaded_struct_for->body->insert( @@ -153,6 +132,7 @@ class StmtToOffloaded : public BasicStmtVisitor { public: void visit(OffloadedStmt *stmt) override { current_offloaded = stmt; + stmt_to_offloaded[stmt] = current_offloaded; if (stmt->body) stmt->body->accept(this); current_offloaded = nullptr; @@ -165,6 +145,13 @@ class StmtToOffloaded : public BasicStmtVisitor { } } + void preprocess_container_stmt(Stmt *stmt) override { + if (current_offloaded != nullptr) { + // inside a offloaded stmt, record its belonging offloaded_stmt + stmt_to_offloaded[stmt] = current_offloaded; + } + } + public: static std::unordered_map run(IRNode *ir) { StmtToOffloaded pass; From eaf692c0f110401585cbebde8cb5b3ecff1a184e Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Tue, 12 May 2020 17:49:44 -0400 Subject: [PATCH 03/19] Should work on CPU now --- taichi/backends/cpu/codegen_cpu.cpp | 2 +- taichi/codegen/codegen_llvm.cpp | 23 ++++++++++++++--------- taichi/codegen/codegen_llvm.h | 3 +-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/taichi/backends/cpu/codegen_cpu.cpp b/taichi/backends/cpu/codegen_cpu.cpp index 4840f6c897398..980f9e57fd094 100644 --- a/taichi/backends/cpu/codegen_cpu.cpp +++ b/taichi/backends/cpu/codegen_cpu.cpp @@ -32,7 +32,7 @@ class CodeGenLLVMCPU : public CodeGenLLVM { tlctx->get_data_type()}); auto loop_var = create_entry_block_alloca(DataType::i32); - offloaded_loop_vars_llvm[stmt].push_back(loop_var); + loop_vars_llvm[stmt].push_back(loop_var); builder->CreateStore(get_arg(1), loop_var); stmt->body->accept(this); diff --git a/taichi/codegen/codegen_llvm.cpp b/taichi/codegen/codegen_llvm.cpp index 5e7b43419a78b..991132c847e36 100644 --- a/taichi/codegen/codegen_llvm.cpp +++ b/taichi/codegen/codegen_llvm.cpp @@ -790,13 +790,16 @@ void CodeGenLLVM::create_naive_range_for(RangeForStmt *for_stmt) { BasicBlock *after_loop = BasicBlock::Create(*llvm_context, "after_for", func); BasicBlock *loop_test = BasicBlock::Create(*llvm_context, "for_loop_test", func); + + auto loop_var = create_entry_block_alloca(DataType::i32); + loop_vars_llvm[for_stmt].push_back(loop_var); + if (!for_stmt->reversed) { - builder->CreateStore(llvm_val[for_stmt->begin], - llvm_val[for_stmt->loop_var]); + builder->CreateStore(llvm_val[for_stmt->begin], loop_var); } else { builder->CreateStore( builder->CreateSub(llvm_val[for_stmt->end], tlctx->get_constant(1)), - llvm_val[for_stmt->loop_var]); + loop_var); } builder->CreateBr(loop_test); @@ -807,12 +810,12 @@ void CodeGenLLVM::create_naive_range_for(RangeForStmt *for_stmt) { if (!for_stmt->reversed) { cond = builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SLT, - builder->CreateLoad(llvm_val[for_stmt->loop_var]), + builder->CreateLoad(loop_var), llvm_val[for_stmt->end]); } else { cond = builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SGE, - builder->CreateLoad(llvm_val[for_stmt->loop_var]), + builder->CreateLoad(loop_var), llvm_val[for_stmt->begin]); } builder->CreateCondBr(cond, body, after_loop); @@ -833,9 +836,9 @@ void CodeGenLLVM::create_naive_range_for(RangeForStmt *for_stmt) { builder->SetInsertPoint(loop_inc); if (!for_stmt->reversed) { - create_increment(llvm_val[for_stmt->loop_var], tlctx->get_constant(1)); + create_increment(loop_var, tlctx->get_constant(1)); } else { - create_increment(llvm_val[for_stmt->loop_var], tlctx->get_constant(-1)); + create_increment(loop_var, tlctx->get_constant(-1)); } builder->CreateBr(loop_test); } @@ -1408,13 +1411,15 @@ void CodeGenLLVM::create_offload_struct_for(OffloadedStmt *stmt, bool spmd) { void CodeGenLLVM::visit(LoopIndexStmt *stmt) { TI_ASSERT(&module->getContext() == tlctx->get_this_thread_context()); - if (stmt->is_struct_for) { + if (stmt->loop->is() && + stmt->loop->as()->task_type == + OffloadedStmt::TaskType::struct_for) { llvm_val[stmt] = builder->CreateLoad(builder->CreateGEP( current_coordinates, {tlctx->get_constant(0), tlctx->get_constant(0), tlctx->get_constant(stmt->index)})); } else { llvm_val[stmt] = builder->CreateLoad( - offloaded_loop_vars_llvm[current_offloaded_stmt][stmt->index]); + loop_vars_llvm[stmt->loop][stmt->index]); } } diff --git a/taichi/codegen/codegen_llvm.h b/taichi/codegen/codegen_llvm.h index a1a3fa471e28d..ba10fd7a325c8 100644 --- a/taichi/codegen/codegen_llvm.h +++ b/taichi/codegen/codegen_llvm.h @@ -72,8 +72,7 @@ class CodeGenLLVM : public IRVisitor, public LLVMModuleBuilder { std::vector offloaded_tasks; BasicBlock *func_body_bb; - std::unordered_map> - offloaded_loop_vars_llvm; + std::unordered_map> loop_vars_llvm; using IRVisitor::visit; using LLVMModuleBuilder::call; From 7263e02ebe6769e10a34ca14e2e500636fa6c3f9 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Tue, 12 May 2020 22:52:01 -0400 Subject: [PATCH 04/19] Move convert_into_loop_index to right after lower_ast --- taichi/ir/ir.cpp | 11 +++++- taichi/ir/ir.h | 3 +- taichi/ir/transforms.h | 5 ++- taichi/transforms/compile_to_offloads.cpp | 8 ++-- .../transforms/demote_dense_struct_fors.cpp | 38 ++++++++++++++----- taichi/transforms/make_adjoint.cpp | 4 ++ taichi/transforms/statement_replace.cpp | 30 ++++++++++----- 7 files changed, 71 insertions(+), 28 deletions(-) diff --git a/taichi/ir/ir.cpp b/taichi/ir/ir.cpp index 6f3e0b0cb26d1..f2bb7e5438c2f 100644 --- a/taichi/ir/ir.cpp +++ b/taichi/ir/ir.cpp @@ -655,10 +655,11 @@ void Block::replace_statements_in_range(int start, } void Block::replace_with(Stmt *old_statement, - std::unique_ptr &&new_statement) { + std::unique_ptr &&new_statement, + bool replace_usages) { VecStatement vec; vec.push_back(std::move(new_statement)); - replace_with(old_statement, std::move(vec)); + replace_with(old_statement, std::move(vec), replace_usages); } Stmt *Block::lookup_var(const Identifier &ident) const { @@ -719,6 +720,12 @@ void Block::replace_with(Stmt *old_statement, if (replace_usages) old_statement->replace_with(new_statements.back().get()); trash_bin.push_back(std::move(statements[location])); + if (new_statements.size() == 1) { + // Keep all std::vector::iterator valid in this case. + statements[location] = std::move(new_statements[0]); + statements[location]->parent = this; + return; + } statements.erase(statements.begin() + location); for (int i = (int)new_statements.size() - 1; i >= 0; i--) { insert(std::move(new_statements[i]), location); diff --git a/taichi/ir/ir.h b/taichi/ir/ir.h index 117bd559448d6..76006210da23b 100644 --- a/taichi/ir/ir.h +++ b/taichi/ir/ir.h @@ -835,7 +835,8 @@ class Block : public IRNode { void insert(VecStatement &&stmt, int location = -1); void replace_statements_in_range(int start, int end, VecStatement &&stmts); void set_statements(VecStatement &&stmts); - void replace_with(Stmt *old_statement, std::unique_ptr &&new_statement); + void replace_with(Stmt *old_statement, std::unique_ptr &&new_statement, + bool replace_usages = true); void insert_before(Stmt *old_statement, VecStatement &&new_statements); void replace_with(Stmt *old_statement, VecStatement &&new_statements, diff --git a/taichi/ir/transforms.h b/taichi/ir/transforms.h index ac315cd7f45a4..4b897fc53152c 100644 --- a/taichi/ir/transforms.h +++ b/taichi/ir/transforms.h @@ -42,9 +42,10 @@ void make_adjoint(IRNode *root, bool use_stack = false); void constant_fold(IRNode *root); OffloadedResult offload(IRNode *root); void fix_block_parents(IRNode *root); -void replace_statements_with(IRNode *root, +bool replace_statements_with(IRNode *root, std::function filter, - std::function()> generator); + std::function()> generator, + bool throw_ir_modified = true); void demote_dense_struct_fors(IRNode *root); void demote_atomics(IRNode *root); void reverse_segments(IRNode *root); // for autograd diff --git a/taichi/transforms/compile_to_offloads.cpp b/taichi/transforms/compile_to_offloads.cpp index 7852717710be4..8afbb99ebc068 100644 --- a/taichi/transforms/compile_to_offloads.cpp +++ b/taichi/transforms/compile_to_offloads.cpp @@ -34,6 +34,10 @@ void compile_to_offloads(IRNode *ir, irpass::lower(ir); print("Lowered"); + irpass::convert_into_loop_index(ir); + print("Converted into loop index"); + irpass::analysis::verify(ir); + irpass::typecheck(ir); print("Typechecked"); irpass::analysis::verify(ir); @@ -70,10 +74,6 @@ void compile_to_offloads(IRNode *ir, irpass::analysis::verify(ir); } - irpass::convert_into_loop_index(ir); - print("Converted into loop index"); - irpass::analysis::verify(ir); - if (config.check_out_of_bound) { irpass::check_out_of_bound(ir); print("Bound checked"); diff --git a/taichi/transforms/demote_dense_struct_fors.cpp b/taichi/transforms/demote_dense_struct_fors.cpp index 721e8f4af0f92..0a5ad67b4e753 100644 --- a/taichi/transforms/demote_dense_struct_fors.cpp +++ b/taichi/transforms/demote_dense_struct_fors.cpp @@ -5,6 +5,7 @@ TLANG_NAMESPACE_BEGIN VecStatement convert_to_range_for(StructForStmt *struct_for) { +// std::cout << "start convert " << struct_for->id << std::endl; VecStatement ret; auto loop_var = ret.push_back(DataType::i32); auto lower = ret.push_back(TypedConstant(0)); @@ -17,27 +18,28 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { snode = snode->parent; } std::reverse(snodes.begin(), snodes.end()); - TI_ASSERT(total_bits <= 31); + TI_ASSERT(total_bits <= 30); auto upper_bound = 1 << total_bits; auto upper = ret.push_back(TypedConstant(upper_bound)); auto body = std::move(struct_for->body); - auto old_loop_vars = struct_for->loop_vars; +// auto old_loop_vars = struct_for->loop_vars; + auto num_loop_vars = struct_for->loop_vars.size(); std::vector new_loop_vars; VecStatement body_header; std::vector physical_indices; - TI_ASSERT(snodes.back()->num_active_indices == (int)old_loop_vars.size()); - for (int i = 0; i < (int)old_loop_vars.size(); i++) { + TI_ASSERT(snodes.back()->num_active_indices == (int)num_loop_vars); + for (int i = 0; i < (int)num_loop_vars; i++) { new_loop_vars.push_back(body_header.push_back(TypedConstant(0))); physical_indices.push_back(snodes.back()->physical_index_position[i]); } - auto main_loop_var = - body_header.push_back(LocalAddress(loop_var, 0)); + auto main_loop_var = body_header.push_back(nullptr, 0, false); +// body_header.push_back(LocalAddress(loop_var, 0)); int offset = total_bits; Stmt *test = body_header.push_back(TypedConstant(-1)); @@ -78,14 +80,27 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { } } - for (int i = 0; i < (int)old_loop_vars.size(); i++) { +// std::cout << "a\n"; + for (int i = 0; i < (int)num_loop_vars; i++) { auto alloca = body_header.push_back(DataType::i32); body_header.push_back(alloca, new_loop_vars[i]); - irpass::replace_all_usages_with(body.get(), old_loop_vars[i], alloca); + irpass::replace_statements_with( + body.get(), + [&](Stmt *s) { + if (auto loop_index = s->cast()) { + return loop_index->loop == struct_for && + loop_index->index == i; + } + return false; + }, + [&]() { return Stmt::make(LocalAddress(alloca, 0)); }, + false); +// irpass::replace_all_usages_with(body.get(), old_loop_vars[i], alloca); } +// std::cout << "b\n"; if (has_test) { - // Createa an If statement + // Create an If statement auto if_stmt = Stmt::make_typed(test); if_stmt->true_statements = std::move(body); body = std::make_unique(); @@ -93,11 +108,14 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { } body->insert(std::move(body_header), 0); +// std::cout << "a\n"; auto range_for = Stmt::make( - loop_var, lower, upper, std::move(body), struct_for->vectorize, + nullptr, lower, upper, std::move(body), struct_for->vectorize, struct_for->parallelize, struct_for->block_dim, false); + main_loop_var->loop = range_for.get(); ret.push_back(std::move(range_for)); +// std::cout << "end convert " << struct_for->id << std::endl; // TODO: safe guard range return ret; } diff --git a/taichi/transforms/make_adjoint.cpp b/taichi/transforms/make_adjoint.cpp index c2c76ed60927a..df827cb5a08bd 100644 --- a/taichi/transforms/make_adjoint.cpp +++ b/taichi/transforms/make_adjoint.cpp @@ -211,6 +211,10 @@ class MakeAdjoint : public IRVisitor { // do nothing. } + void visit(LoopIndexStmt *stmt) override { + // do nothing. + } + void visit(UnaryOpStmt *stmt) override { if (stmt->op_type == UnaryOpType::floor) { // do nothing diff --git a/taichi/transforms/statement_replace.cpp b/taichi/transforms/statement_replace.cpp index e8a00b7dd6ff4..adecc1f7af600 100644 --- a/taichi/transforms/statement_replace.cpp +++ b/taichi/transforms/statement_replace.cpp @@ -10,22 +10,32 @@ class StatementReplace : public IRVisitor { IRNode *node; std::function filter; std::function()> generator; + bool throw_ir_modified; + bool modified; StatementReplace(IRNode *node, std::function filter, - std::function()> generator) - : node(node), filter(filter), generator(generator) { + std::function()> generator, + bool throw_ir_modified) + : node(node), filter(filter), generator(generator), + throw_ir_modified(throw_ir_modified) { allow_undefined_visitor = true; invoke_default_visitor = true; + modified = false; } void replace_if_necessary(Stmt *stmt) { if (filter(stmt)) { +// std::cout << "begin replace\n"; auto block = stmt->parent; auto new_stmt = generator(); irpass::replace_all_usages_with(node, stmt, new_stmt.get()); - block->replace_with(stmt, std::move(new_stmt)); - throw IRModified(); + block->replace_with(stmt, std::move(new_stmt), false); + if (throw_ir_modified) + throw IRModified(); + else + modified = true; +// std::cout << "end replace\n"; } } @@ -63,7 +73,7 @@ class StatementReplace : public IRVisitor { replace_if_necessary(stmt); } - void run() { + bool run() { while (true) { try { node->accept(this); @@ -72,16 +82,18 @@ class StatementReplace : public IRVisitor { } break; } + return modified; } }; namespace irpass { -void replace_statements_with(IRNode *root, +bool replace_statements_with(IRNode *root, std::function filter, - std::function()> generator) { - StatementReplace transformer(root, filter, generator); - transformer.run(); + std::function()> generator, + bool throw_ir_modified) { + StatementReplace transformer(root, filter, generator, throw_ir_modified); + return transformer.run(); } } // namespace irpass From 8c7898aa7994b0300325bb6159633f91d23f036b Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 15:51:22 -0400 Subject: [PATCH 05/19] Merge master --- taichi/ir/transforms.h | 5 ++--- taichi/transforms/demote_dense_struct_fors.cpp | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/taichi/ir/transforms.h b/taichi/ir/transforms.h index b5db7c431c66a..a29cd59f9b1bf 100644 --- a/taichi/ir/transforms.h +++ b/taichi/ir/transforms.h @@ -42,10 +42,9 @@ void make_adjoint(IRNode *root, bool use_stack = false); void constant_fold(IRNode *root); OffloadedResult offload(IRNode *root); void fix_block_parents(IRNode *root); -bool replace_statements_with(IRNode *root, +void replace_statements_with(IRNode *root, std::function filter, - std::function()> generator, - bool throw_ir_modified = true); + std::function()> generator); void demote_dense_struct_fors(IRNode *root); void demote_atomics(IRNode *root); void reverse_segments(IRNode *root); // for autograd diff --git a/taichi/transforms/demote_dense_struct_fors.cpp b/taichi/transforms/demote_dense_struct_fors.cpp index 0a5ad67b4e753..c9cc0bf3e1c6f 100644 --- a/taichi/transforms/demote_dense_struct_fors.cpp +++ b/taichi/transforms/demote_dense_struct_fors.cpp @@ -93,8 +93,7 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { } return false; }, - [&]() { return Stmt::make(LocalAddress(alloca, 0)); }, - false); + [&]() { return Stmt::make(LocalAddress(alloca, 0)); }); // irpass::replace_all_usages_with(body.get(), old_loop_vars[i], alloca); } From cf3b420192e6c05375c8b6aa38b4df03ba02270d Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 17:07:45 -0400 Subject: [PATCH 06/19] Fix tests --- taichi/analysis/verify.cpp | 14 ++++++++++++++ taichi/transforms/demote_dense_struct_fors.cpp | 5 +---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/taichi/analysis/verify.cpp b/taichi/analysis/verify.cpp index 8144cb30c7066..be02ed1e4f18f 100644 --- a/taichi/analysis/verify.cpp +++ b/taichi/analysis/verify.cpp @@ -73,6 +73,20 @@ class IRVerifier : public BasicStmtVisitor { TI_ASSERT(stmt->ptr->is()); } + void visit(LoopIndexStmt *stmt) override { + basic_verify(stmt); + TI_ASSERT(stmt->loop); + if (stmt->loop->is()) { + TI_ASSERT(stmt->loop->as()->task_type == + OffloadedStmt::TaskType::struct_for || + stmt->loop->as()->task_type == + OffloadedStmt::TaskType::range_for); + } else { + TI_ASSERT(stmt->loop->is() || + stmt->loop->is()); + } + } + void visit(RangeForStmt *for_stmt) override { basic_verify(for_stmt); if (for_stmt->loop_var) { diff --git a/taichi/transforms/demote_dense_struct_fors.cpp b/taichi/transforms/demote_dense_struct_fors.cpp index c9cc0bf3e1c6f..77a0ede8f9e61 100644 --- a/taichi/transforms/demote_dense_struct_fors.cpp +++ b/taichi/transforms/demote_dense_struct_fors.cpp @@ -80,7 +80,6 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { } } -// std::cout << "a\n"; for (int i = 0; i < (int)num_loop_vars; i++) { auto alloca = body_header.push_back(DataType::i32); body_header.push_back(alloca, new_loop_vars[i]); @@ -89,7 +88,7 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { [&](Stmt *s) { if (auto loop_index = s->cast()) { return loop_index->loop == struct_for && - loop_index->index == i; + loop_index->index == snodes.back()->physical_index_position[i]; } return false; }, @@ -97,7 +96,6 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { // irpass::replace_all_usages_with(body.get(), old_loop_vars[i], alloca); } -// std::cout << "b\n"; if (has_test) { // Create an If statement auto if_stmt = Stmt::make_typed(test); @@ -107,7 +105,6 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { } body->insert(std::move(body_header), 0); -// std::cout << "a\n"; auto range_for = Stmt::make( nullptr, lower, upper, std::move(body), struct_for->vectorize, struct_for->parallelize, struct_for->block_dim, false); From e0da2cd05b80433217458163f4fc7b4c70ecac0a Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 18:23:57 -0400 Subject: [PATCH 07/19] Fix CUDA compilation --- taichi/backends/cuda/codegen_cuda.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taichi/backends/cuda/codegen_cuda.cpp b/taichi/backends/cuda/codegen_cuda.cpp index 69bd4d261689f..9fa97afa4e9d1 100644 --- a/taichi/backends/cuda/codegen_cuda.cpp +++ b/taichi/backends/cuda/codegen_cuda.cpp @@ -346,7 +346,7 @@ class CodeGenLLVMCUDA : public CodeGenLLVM { tlctx->get_data_type()}); auto loop_var = create_entry_block_alloca(DataType::i32); - offloaded_loop_vars_llvm[stmt].push_back(loop_var); + loop_vars_llvm[stmt].push_back(loop_var); builder->CreateStore(get_arg(1), loop_var); stmt->body->accept(this); From 35ca9737624f4a239d0c7cda4af6925ed5680a68 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 18:28:19 -0400 Subject: [PATCH 08/19] [skip ci] Remove comments --- taichi/transforms/demote_dense_struct_fors.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/taichi/transforms/demote_dense_struct_fors.cpp b/taichi/transforms/demote_dense_struct_fors.cpp index 77a0ede8f9e61..ea459b8907bdb 100644 --- a/taichi/transforms/demote_dense_struct_fors.cpp +++ b/taichi/transforms/demote_dense_struct_fors.cpp @@ -5,9 +5,7 @@ TLANG_NAMESPACE_BEGIN VecStatement convert_to_range_for(StructForStmt *struct_for) { -// std::cout << "start convert " << struct_for->id << std::endl; VecStatement ret; - auto loop_var = ret.push_back(DataType::i32); auto lower = ret.push_back(TypedConstant(0)); std::vector snodes; auto snode = struct_for->snode; @@ -24,7 +22,6 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { auto upper = ret.push_back(TypedConstant(upper_bound)); auto body = std::move(struct_for->body); -// auto old_loop_vars = struct_for->loop_vars; auto num_loop_vars = struct_for->loop_vars.size(); std::vector new_loop_vars; @@ -39,7 +36,6 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { } auto main_loop_var = body_header.push_back(nullptr, 0, false); -// body_header.push_back(LocalAddress(loop_var, 0)); int offset = total_bits; Stmt *test = body_header.push_back(TypedConstant(-1)); @@ -93,7 +89,6 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { return false; }, [&]() { return Stmt::make(LocalAddress(alloca, 0)); }); -// irpass::replace_all_usages_with(body.get(), old_loop_vars[i], alloca); } if (has_test) { @@ -111,7 +106,6 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { main_loop_var->loop = range_for.get(); ret.push_back(std::move(range_for)); -// std::cout << "end convert " << struct_for->id << std::endl; // TODO: safe guard range return ret; } From e26a9091d3f317e7e55b90e620496703b032757c Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 19:53:56 -0400 Subject: [PATCH 09/19] Metal backend --- taichi/backends/metal/codegen_metal.cpp | 59 +++++++++++-------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/taichi/backends/metal/codegen_metal.cpp b/taichi/backends/metal/codegen_metal.cpp index 829e8a2c84587..d67f567d3a104 100644 --- a/taichi/backends/metal/codegen_metal.cpp +++ b/taichi/backends/metal/codegen_metal.cpp @@ -309,17 +309,21 @@ class KernelCodegen : public IRVisitor { } void visit(LoopIndexStmt *stmt) override { - using TaskType = OffloadedStmt::TaskType; - const auto type = current_kernel_attribs_->task_type; const auto stmt_name = stmt->raw_name(); - if (type == TaskType::range_for) { - TI_ASSERT(stmt->index == 0); - emit("const int {} = {};", stmt_name, kLinearLoopIndexName); - } else if (type == TaskType::struct_for) { - emit("const int {} = {}.coords[{}];", stmt_name, kListgenElemVarName, - stmt->index); - } else { - TI_NOT_IMPLEMENTED; + if (stmt->loop->is()) { + using TaskType = OffloadedStmt::TaskType; + const auto type = current_kernel_attribs_->task_type; + if (type == TaskType::range_for) { + TI_ASSERT(stmt->index == 0); + emit("const int {} = {};", stmt_name, kLinearLoopIndexName); + } else if (type == TaskType::struct_for) { + emit("const int {} = {}.coords[{}];", stmt_name, kListgenElemVarName, + stmt->index); + } else { + TI_NOT_IMPLEMENTED; + } + } else if (stmt->loop->is()) { + emit("const int {} = {};", stmt_name, stmt->loop->raw_name()); } } @@ -445,29 +449,20 @@ class KernelCodegen : public IRVisitor { void visit(RangeForStmt *for_stmt) override { TI_ASSERT(for_stmt->width() == 1); - auto *loop_var = for_stmt->loop_var; - if (loop_var->ret_type.data_type == DataType::i32) { - if (!for_stmt->reversed) { - emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", - loop_var->raw_name(), for_stmt->begin->raw_name(), - loop_var->raw_name(), for_stmt->end->raw_name(), - loop_var->raw_name(), loop_var->raw_name(), 1); - emit(" int {} = {}_;", loop_var->raw_name(), loop_var->raw_name()); - } else { - // reversed for loop - emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", - loop_var->raw_name(), for_stmt->end->raw_name(), - loop_var->raw_name(), for_stmt->begin->raw_name(), - loop_var->raw_name(), loop_var->raw_name(), 1); - emit(" int {} = {}_;", loop_var->raw_name(), loop_var->raw_name()); - } + auto loop_var_name = for_stmt->raw_name(); + if (!for_stmt->reversed) { + emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", + loop_var_name, for_stmt->begin->raw_name(), + loop_var_name, for_stmt->end->raw_name(), + loop_var_name, loop_var_name, 1); + emit(" int {} = {}_;", loop_var_name, loop_var_name); } else { - TI_ASSERT(!for_stmt->reversed); - const auto type_name = metal_data_type_name(loop_var->element_type()); - emit("for ({} {} = {}; {} < {}; {} = {} + ({})1) {{", type_name, - loop_var->raw_name(), for_stmt->begin->raw_name(), - loop_var->raw_name(), for_stmt->end->raw_name(), - loop_var->raw_name(), loop_var->raw_name(), type_name); + // reversed for loop + emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", + loop_var_name, for_stmt->end->raw_name(), + loop_var_name, for_stmt->begin->raw_name(), + loop_var_name, loop_var_name, 1); + emit(" int {} = {}_;", loop_var_name, loop_var_name); } for_stmt->body->accept(this); emit("}}"); From 2f1e86bcdabcd7e65f6d718120f198b04961d46c Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 19:55:19 -0400 Subject: [PATCH 10/19] [skip ci] Metal backend (continued) --- taichi/backends/metal/codegen_metal.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/taichi/backends/metal/codegen_metal.cpp b/taichi/backends/metal/codegen_metal.cpp index d67f567d3a104..e928264ab04c6 100644 --- a/taichi/backends/metal/codegen_metal.cpp +++ b/taichi/backends/metal/codegen_metal.cpp @@ -312,7 +312,7 @@ class KernelCodegen : public IRVisitor { const auto stmt_name = stmt->raw_name(); if (stmt->loop->is()) { using TaskType = OffloadedStmt::TaskType; - const auto type = current_kernel_attribs_->task_type; + const auto type = stmt->loop->as()->task_type; if (type == TaskType::range_for) { TI_ASSERT(stmt->index == 0); emit("const int {} = {};", stmt_name, kLinearLoopIndexName); @@ -323,7 +323,10 @@ class KernelCodegen : public IRVisitor { TI_NOT_IMPLEMENTED; } } else if (stmt->loop->is()) { + TI_ASSERT(stmt->index == 0); emit("const int {} = {};", stmt_name, stmt->loop->raw_name()); + } else { + TI_NOT_IMPLEMENTED; } } From 3d7424bf7314e63e88e1c4689b2985faa3aecd62 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 19:58:40 -0400 Subject: [PATCH 11/19] opengl backend --- taichi/backends/opengl/codegen_opengl.cpp | 42 +++++++++-------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/taichi/backends/opengl/codegen_opengl.cpp b/taichi/backends/opengl/codegen_opengl.cpp index a9c872b0c060a..3530be00464d3 100644 --- a/taichi/backends/opengl/codegen_opengl.cpp +++ b/taichi/backends/opengl/codegen_opengl.cpp @@ -602,38 +602,30 @@ class KernelGen : public IRVisitor { } void visit(LoopIndexStmt *stmt) override { - TI_ASSERT(!stmt->is_struct_for); + TI_ASSERT(stmt->loop->is() || + (stmt->loop->is() && + stmt->loop->as()->task_type == + OffloadedStmt::TaskType::range_for)); TI_ASSERT(stmt->index == 0); // TODO: multiple indices emit("int {} = _itv;", stmt->short_name()); } void visit(RangeForStmt *for_stmt) override { TI_ASSERT(for_stmt->width() == 1); - auto *loop_var = for_stmt->loop_var; - if (loop_var->ret_type.data_type == DataType::i32) { - if (!for_stmt->reversed) { - emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", - loop_var->short_name(), for_stmt->begin->short_name(), - loop_var->short_name(), for_stmt->end->short_name(), - loop_var->short_name(), loop_var->short_name(), 1); - // variable named `loop_var->short_name()` is already allocated by - // alloca - emit(" {} = {}_;", loop_var->short_name(), loop_var->short_name()); - } else { - // reversed for loop - emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", - loop_var->short_name(), for_stmt->end->short_name(), - loop_var->short_name(), for_stmt->begin->short_name(), - loop_var->short_name(), loop_var->short_name(), 1); - emit(" {} = {}_;", loop_var->short_name(), loop_var->short_name()); - } + auto loop_var_name = for_stmt->raw_name(); + if (!for_stmt->reversed) { + emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", + loop_var_name, for_stmt->begin->raw_name(), + loop_var_name, for_stmt->end->raw_name(), + loop_var_name, loop_var_name, 1); + emit(" int {} = {}_;", loop_var_name, loop_var_name); } else { - TI_ASSERT(!for_stmt->reversed); - const auto type_name = opengl_data_type_name(loop_var->element_type()); - emit("for ({} {} = {}; {} < {}; {} = {} + 1) {{", type_name, - loop_var->short_name(), for_stmt->begin->short_name(), - loop_var->short_name(), for_stmt->end->short_name(), - loop_var->short_name(), loop_var->short_name()); + // reversed for loop + emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", + loop_var_name, for_stmt->end->raw_name(), + loop_var_name, for_stmt->begin->raw_name(), + loop_var_name, loop_var_name, 1); + emit(" int {} = {}_;", loop_var_name, loop_var_name); } for_stmt->body->accept(this); emit("}}"); From f28468831edcfb3f3a86404fac8ad89ac365a41d Mon Sep 17 00:00:00 2001 From: Taichi Gardener Date: Wed, 13 May 2020 19:59:13 -0400 Subject: [PATCH 12/19] [skip ci] enforce code format --- docs/hello.rst | 6 +-- docs/utilities.rst | 2 +- python/taichi/main.py | 14 +++--- taichi/analysis/verify.cpp | 30 +++++++------ taichi/backends/metal/codegen_metal.cpp | 12 +++--- taichi/backends/metal/shaders/helpers.metal.h | 5 ++- taichi/backends/opengl/codegen_opengl.cpp | 43 +++++++++---------- taichi/codegen/codegen_llvm.cpp | 20 ++++----- taichi/ir/ir.h | 3 +- taichi/ir/transforms.h | 15 +++---- taichi/transforms/compile_to_offloads.cpp | 15 +++---- taichi/transforms/convert_into_loop_index.cpp | 10 +++-- .../transforms/demote_dense_struct_fors.cpp | 3 +- taichi/transforms/ir_printer.cpp | 14 +++--- 14 files changed, 98 insertions(+), 94 deletions(-) diff --git a/docs/hello.rst b/docs/hello.rst index c463e3faaeccc..54a98a59d8522 100644 --- a/docs/hello.rst +++ b/docs/hello.rst @@ -55,9 +55,9 @@ Let's dive into this simple Taichi program. import taichi as ti ------------------- -Taichi is a domain-specific language (DSL) embedded in Python. To make Taichi as easy to use as a Python package, -we have done heavy engineering with this goal in mind - letting every Python programmer write Taichi codes with -minimal learning effort. You can even use your favorite Python package management system, Python IDEs and other +Taichi is a domain-specific language (DSL) embedded in Python. To make Taichi as easy to use as a Python package, +we have done heavy engineering with this goal in mind - letting every Python programmer write Taichi codes with +minimal learning effort. You can even use your favorite Python package management system, Python IDEs and other Python packages in conjunction with Taichi. Portability diff --git a/docs/utilities.rst b/docs/utilities.rst index 69bf8692e82f6..84c1fd98057cc 100644 --- a/docs/utilities.rst +++ b/docs/utilities.rst @@ -58,7 +58,7 @@ For example, this is part of the output by ``ti regression`` after enabling cons The suggested workflow for **the PR author** to run the regression tests is: * When a performance related PR is ready, checkout that PR locally. - + * Run ``ti benchmark && ti regression`` to obtain the result. * Decide wheater to approve or request change, depends on the result. diff --git a/python/taichi/main.py b/python/taichi/main.py index 4e18d3b8235d1..22111b7ba6558 100644 --- a/python/taichi/main.py +++ b/python/taichi/main.py @@ -85,8 +85,10 @@ def display_benchmark_regression(xd, yd): def parse_dat(file): dict = {} for line in open(file).readlines(): - try: a, b = line.strip().split(':') - except: continue + try: + a, b = line.strip().split(':') + except: + continue dict[a.strip()] = int(float(b)) return dict @@ -267,7 +269,9 @@ def main(debug=False): os.chdir(baseline_dir) print('[benchmark] pushing baseline data...') os.system('git add .') - os.system(f"git commit -m 'update baseline for taichi@{ti.core.get_commit_hash()}'") + os.system( + f"git commit -m 'update baseline for taichi@{ti.core.get_commit_hash()}'" + ) os.system('git push') os.chdir(old_cwd) print('[benchmark] baseline data uploaded') @@ -279,9 +283,7 @@ def main(debug=False): print('[benchmark] fetching latest baseline...') os.system('git pull') os.chdir(old_cwd) - display_benchmark_regression( - baseline_dir, - output_dir) + display_benchmark_regression(baseline_dir, output_dir) elif mode == "build": ti.core.build() elif mode == "format": diff --git a/taichi/analysis/verify.cpp b/taichi/analysis/verify.cpp index be02ed1e4f18f..3e56285b03bd8 100644 --- a/taichi/analysis/verify.cpp +++ b/taichi/analysis/verify.cpp @@ -78,12 +78,12 @@ class IRVerifier : public BasicStmtVisitor { TI_ASSERT(stmt->loop); if (stmt->loop->is()) { TI_ASSERT(stmt->loop->as()->task_type == - OffloadedStmt::TaskType::struct_for || - stmt->loop->as()->task_type == - OffloadedStmt::TaskType::range_for); + OffloadedStmt::TaskType::struct_for || + stmt->loop->as()->task_type == + OffloadedStmt::TaskType::range_for); } else { TI_ASSERT(stmt->loop->is() || - stmt->loop->is()); + stmt->loop->is()); } } @@ -92,16 +92,18 @@ class IRVerifier : public BasicStmtVisitor { if (for_stmt->loop_var) { TI_ASSERT(for_stmt->loop_var->is()); TI_ASSERT_INFO(irpass::analysis::gather_statements( - for_stmt->loop_var->parent, - [&](Stmt *s) { - if (auto store = s->cast()) - return store->ptr == for_stmt->loop_var; - else if (auto atomic = s->cast()) { - return atomic->dest == for_stmt->loop_var; - } else { - return false; - } - }).empty(), "loop_var of {} modified", for_stmt->id); + for_stmt->loop_var->parent, + [&](Stmt *s) { + if (auto store = s->cast()) + return store->ptr == for_stmt->loop_var; + else if (auto atomic = s->cast()) { + return atomic->dest == for_stmt->loop_var; + } else { + return false; + } + }) + .empty(), + "loop_var of {} modified", for_stmt->id); } for_stmt->body->accept(this); } diff --git a/taichi/backends/metal/codegen_metal.cpp b/taichi/backends/metal/codegen_metal.cpp index e928264ab04c6..924050d647519 100644 --- a/taichi/backends/metal/codegen_metal.cpp +++ b/taichi/backends/metal/codegen_metal.cpp @@ -454,17 +454,15 @@ class KernelCodegen : public IRVisitor { TI_ASSERT(for_stmt->width() == 1); auto loop_var_name = for_stmt->raw_name(); if (!for_stmt->reversed) { - emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", - loop_var_name, for_stmt->begin->raw_name(), - loop_var_name, for_stmt->end->raw_name(), - loop_var_name, loop_var_name, 1); + emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", loop_var_name, + for_stmt->begin->raw_name(), loop_var_name, + for_stmt->end->raw_name(), loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } else { // reversed for loop emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", - loop_var_name, for_stmt->end->raw_name(), - loop_var_name, for_stmt->begin->raw_name(), - loop_var_name, loop_var_name, 1); + loop_var_name, for_stmt->end->raw_name(), loop_var_name, + for_stmt->begin->raw_name(), loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } for_stmt->body->accept(this); diff --git a/taichi/backends/metal/shaders/helpers.metal.h b/taichi/backends/metal/shaders/helpers.metal.h index 41cf774576e7f..d897cf12008f1 100644 --- a/taichi/backends/metal/shaders/helpers.metal.h +++ b/taichi/backends/metal/shaders/helpers.metal.h @@ -33,8 +33,9 @@ STR( inline int ifloordiv(int lhs, int rhs) { const int intm = (lhs / rhs); - return (((lhs < 0) != (rhs < 0) && lhs && - (rhs * intm != lhs)) ? (intm - 1) : intm); + return (((lhs < 0) != (rhs < 0) && lhs && (rhs * intm != lhs)) + ? (intm - 1) + : intm); } int32_t pow_i32(int32_t x, int32_t n) { diff --git a/taichi/backends/opengl/codegen_opengl.cpp b/taichi/backends/opengl/codegen_opengl.cpp index 3530be00464d3..b709b7968af3e 100644 --- a/taichi/backends/opengl/codegen_opengl.cpp +++ b/taichi/backends/opengl/codegen_opengl.cpp @@ -414,14 +414,13 @@ class KernelGen : public IRVisitor { emit("{} {} = atan({}, {});", dt_name, bin_name, lhs_name, rhs_name); } return; - } else if (bin->op_type == BinaryOpType::pow - && is_integral(bin->rhs->element_type())) { - // The GLSL `pow` is not so percise for `int`... e.g.: `pow(5, 3)` obtains 124 - // So that we have to use some hack to make it percise. - // Discussion: https://github.com/taichi-dev/taichi/pull/943#issuecomment-626354902 + } else if (bin->op_type == BinaryOpType::pow && + is_integral(bin->rhs->element_type())) { + // The GLSL `pow` is not so percise for `int`... e.g.: `pow(5, 3)` obtains + // 124 So that we have to use some hack to make it percise. Discussion: + // https://github.com/taichi-dev/taichi/pull/943#issuecomment-626354902 emit("{} {} = {}(fast_pow_{}({}, {}));", dt_name, bin_name, dt_name, - data_type_short_name(bin->lhs->element_type()), - lhs_name, rhs_name); + data_type_short_name(bin->lhs->element_type()), lhs_name, rhs_name); used.fast_pow = true; return; } @@ -603,9 +602,9 @@ class KernelGen : public IRVisitor { void visit(LoopIndexStmt *stmt) override { TI_ASSERT(stmt->loop->is() || - (stmt->loop->is() && - stmt->loop->as()->task_type == - OffloadedStmt::TaskType::range_for)); + (stmt->loop->is() && + stmt->loop->as()->task_type == + OffloadedStmt::TaskType::range_for)); TI_ASSERT(stmt->index == 0); // TODO: multiple indices emit("int {} = _itv;", stmt->short_name()); } @@ -614,17 +613,15 @@ class KernelGen : public IRVisitor { TI_ASSERT(for_stmt->width() == 1); auto loop_var_name = for_stmt->raw_name(); if (!for_stmt->reversed) { - emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", - loop_var_name, for_stmt->begin->raw_name(), - loop_var_name, for_stmt->end->raw_name(), - loop_var_name, loop_var_name, 1); + emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", loop_var_name, + for_stmt->begin->raw_name(), loop_var_name, + for_stmt->end->raw_name(), loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } else { // reversed for loop emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", - loop_var_name, for_stmt->end->raw_name(), - loop_var_name, for_stmt->begin->raw_name(), - loop_var_name, loop_var_name, 1); + loop_var_name, for_stmt->end->raw_name(), loop_var_name, + for_stmt->begin->raw_name(), loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } for_stmt->body->accept(this); @@ -722,12 +719,14 @@ void OpenglCodeGen::lower() { auto ir = kernel_->ir; auto &config = kernel_->program.config; config.demote_dense_struct_fors = true; - auto res = irpass::compile_to_offloads(ir, config, - /*vectorize=*/false, kernel_->grad, - /*ad_use_stack=*/false, config.print_ir, - /*lower_global_access*/true); + auto res = + irpass::compile_to_offloads(ir, config, + /*vectorize=*/false, kernel_->grad, + /*ad_use_stack=*/false, config.print_ir, + /*lower_global_access*/ true); global_tmps_buffer_size_ = res.total_size; - TI_TRACE("[glsl] Global temporary buffer size {} B", global_tmps_buffer_size_); + TI_TRACE("[glsl] Global temporary buffer size {} B", + global_tmps_buffer_size_); #ifdef _GLSL_DEBUG irpass::print(ir); #endif diff --git a/taichi/codegen/codegen_llvm.cpp b/taichi/codegen/codegen_llvm.cpp index 991132c847e36..af4ca90a287ee 100644 --- a/taichi/codegen/codegen_llvm.cpp +++ b/taichi/codegen/codegen_llvm.cpp @@ -808,15 +808,13 @@ void CodeGenLLVM::create_naive_range_for(RangeForStmt *for_stmt) { builder->SetInsertPoint(loop_test); llvm::Value *cond; if (!for_stmt->reversed) { - cond = - builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SLT, - builder->CreateLoad(loop_var), - llvm_val[for_stmt->end]); + cond = builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SLT, + builder->CreateLoad(loop_var), + llvm_val[for_stmt->end]); } else { - cond = - builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SGE, - builder->CreateLoad(loop_var), - llvm_val[for_stmt->begin]); + cond = builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SGE, + builder->CreateLoad(loop_var), + llvm_val[for_stmt->begin]); } builder->CreateCondBr(cond, body, after_loop); } @@ -1413,13 +1411,13 @@ void CodeGenLLVM::visit(LoopIndexStmt *stmt) { TI_ASSERT(&module->getContext() == tlctx->get_this_thread_context()); if (stmt->loop->is() && stmt->loop->as()->task_type == - OffloadedStmt::TaskType::struct_for) { + OffloadedStmt::TaskType::struct_for) { llvm_val[stmt] = builder->CreateLoad(builder->CreateGEP( current_coordinates, {tlctx->get_constant(0), tlctx->get_constant(0), tlctx->get_constant(stmt->index)})); } else { - llvm_val[stmt] = builder->CreateLoad( - loop_vars_llvm[stmt->loop][stmt->index]); + llvm_val[stmt] = + builder->CreateLoad(loop_vars_llvm[stmt->loop][stmt->index]); } } diff --git a/taichi/ir/ir.h b/taichi/ir/ir.h index 76006210da23b..4810b1de1de87 100644 --- a/taichi/ir/ir.h +++ b/taichi/ir/ir.h @@ -835,7 +835,8 @@ class Block : public IRNode { void insert(VecStatement &&stmt, int location = -1); void replace_statements_in_range(int start, int end, VecStatement &&stmts); void set_statements(VecStatement &&stmts); - void replace_with(Stmt *old_statement, std::unique_ptr &&new_statement, + void replace_with(Stmt *old_statement, + std::unique_ptr &&new_statement, bool replace_usages = true); void insert_before(Stmt *old_statement, VecStatement &&new_statements); void replace_with(Stmt *old_statement, diff --git a/taichi/ir/transforms.h b/taichi/ir/transforms.h index a29cd59f9b1bf..50fcd3862a7e9 100644 --- a/taichi/ir/transforms.h +++ b/taichi/ir/transforms.h @@ -49,14 +49,13 @@ void demote_dense_struct_fors(IRNode *root); void demote_atomics(IRNode *root); void reverse_segments(IRNode *root); // for autograd std::unique_ptr initialize_scratch_pad(StructForStmt *root); -OffloadedResult compile_to_offloads( - IRNode *ir, - const CompileConfig &config, - bool vectorize, - bool grad, - bool ad_use_stack, - bool verbose, - bool lower_global_access = true); +OffloadedResult compile_to_offloads(IRNode *ir, + const CompileConfig &config, + bool vectorize, + bool grad, + bool ad_use_stack, + bool verbose, + bool lower_global_access = true); } // namespace irpass diff --git a/taichi/transforms/compile_to_offloads.cpp b/taichi/transforms/compile_to_offloads.cpp index 263a631d31a34..5339b06646ed2 100644 --- a/taichi/transforms/compile_to_offloads.cpp +++ b/taichi/transforms/compile_to_offloads.cpp @@ -7,14 +7,13 @@ TLANG_NAMESPACE_BEGIN namespace irpass { -OffloadedResult compile_to_offloads( - IRNode *ir, - const CompileConfig &config, - bool vectorize, - bool grad, - bool ad_use_stack, - bool verbose, - bool lower_global_access) { +OffloadedResult compile_to_offloads(IRNode *ir, + const CompileConfig &config, + bool vectorize, + bool grad, + bool ad_use_stack, + bool verbose, + bool lower_global_access) { TI_AUTO_PROF; auto print = [&](const std::string &name) { diff --git a/taichi/transforms/convert_into_loop_index.cpp b/taichi/transforms/convert_into_loop_index.cpp index 142534bd29ffc..ce2a60a51823e 100644 --- a/taichi/transforms/convert_into_loop_index.cpp +++ b/taichi/transforms/convert_into_loop_index.cpp @@ -19,12 +19,14 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { [&](Stmt *load) { if (auto local_load = load->cast()) { return local_load->width() == 1 && - local_load->ptr[0].var == loop_var && - local_load->ptr[0].offset == 0; + local_load->ptr[0].var == loop_var && + local_load->ptr[0].offset == 0; } return false; }, - [&]() { return Stmt::make(loop, index, is_struct_for); }); + [&]() { + return Stmt::make(loop, index, is_struct_for); + }); } void preprocess_container_stmt(Stmt *stmt) override { @@ -35,7 +37,7 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { auto leaf = struct_for->snode; for (int i = 0; i < (int)struct_for->loop_vars.size(); i++) { convert(struct_for, struct_for->loop_vars[i], - leaf->physical_index_position[i], true); + leaf->physical_index_position[i], true); struct_for->loop_vars[i] = nullptr; } } diff --git a/taichi/transforms/demote_dense_struct_fors.cpp b/taichi/transforms/demote_dense_struct_fors.cpp index ea459b8907bdb..50c5a70f8c4ca 100644 --- a/taichi/transforms/demote_dense_struct_fors.cpp +++ b/taichi/transforms/demote_dense_struct_fors.cpp @@ -84,7 +84,8 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { [&](Stmt *s) { if (auto loop_index = s->cast()) { return loop_index->loop == struct_for && - loop_index->index == snodes.back()->physical_index_position[i]; + loop_index->index == + snodes.back()->physical_index_position[i]; } return false; }, diff --git a/taichi/transforms/ir_printer.cpp b/taichi/transforms/ir_printer.cpp index a84076cb0586f..79533f9f8635f 100644 --- a/taichi/transforms/ir_printer.cpp +++ b/taichi/transforms/ir_printer.cpp @@ -259,17 +259,18 @@ class IRPrinter : public IRVisitor { void visit(RangeForStmt *for_stmt) override { print("{} : {}for {} in range({}, {}, step {}) {{", for_stmt->name(), - for_stmt->reversed ? "reversed " : "", for_stmt->loop_var ? - for_stmt->loop_var->name() : "nullptr", + for_stmt->reversed ? "reversed " : "", + for_stmt->loop_var ? for_stmt->loop_var->name() : "nullptr", for_stmt->begin->name(), for_stmt->end->name(), for_stmt->vectorize); for_stmt->body->accept(this); print("}}"); } void visit(StructForStmt *for_stmt) override { - auto loop_vars = make_list( - for_stmt->loop_vars, - [](Stmt *const &stmt) -> std::string { return stmt ? stmt->name() : "nullptr"; }); + auto loop_vars = make_list(for_stmt->loop_vars, + [](Stmt *const &stmt) -> std::string { + return stmt ? stmt->name() : "nullptr"; + }); print("{} : for {} where {} active, step {} {{", for_stmt->name(), loop_vars, for_stmt->snode->get_node_type_name_hinted(), for_stmt->vectorize); @@ -459,7 +460,8 @@ class IRPrinter : public IRVisitor { } void visit(LoopIndexStmt *stmt) override { - print("{}{} = loop {} index {}", stmt->type_hint(), stmt->name(), stmt->loop->name(), stmt->index); + print("{}{} = loop {} index {}", stmt->type_hint(), stmt->name(), + stmt->loop->name(), stmt->index); } void visit(GlobalTemporaryStmt *stmt) override { From 7b0fa75774455cdf8ef6e9b40720b21d226f3cd6 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 20:01:26 -0400 Subject: [PATCH 13/19] Revert "[skip ci] enforce code format" This reverts commit f28468831edcfb3f3a86404fac8ad89ac365a41d. --- docs/hello.rst | 6 +-- docs/utilities.rst | 2 +- python/taichi/main.py | 14 +++--- taichi/analysis/verify.cpp | 30 ++++++------- taichi/backends/metal/codegen_metal.cpp | 12 +++--- taichi/backends/metal/shaders/helpers.metal.h | 5 +-- taichi/backends/opengl/codegen_opengl.cpp | 43 ++++++++++--------- taichi/codegen/codegen_llvm.cpp | 20 +++++---- taichi/ir/ir.h | 3 +- taichi/ir/transforms.h | 15 ++++--- taichi/transforms/compile_to_offloads.cpp | 15 ++++--- taichi/transforms/convert_into_loop_index.cpp | 10 ++--- .../transforms/demote_dense_struct_fors.cpp | 3 +- taichi/transforms/ir_printer.cpp | 14 +++--- 14 files changed, 94 insertions(+), 98 deletions(-) diff --git a/docs/hello.rst b/docs/hello.rst index 54a98a59d8522..c463e3faaeccc 100644 --- a/docs/hello.rst +++ b/docs/hello.rst @@ -55,9 +55,9 @@ Let's dive into this simple Taichi program. import taichi as ti ------------------- -Taichi is a domain-specific language (DSL) embedded in Python. To make Taichi as easy to use as a Python package, -we have done heavy engineering with this goal in mind - letting every Python programmer write Taichi codes with -minimal learning effort. You can even use your favorite Python package management system, Python IDEs and other +Taichi is a domain-specific language (DSL) embedded in Python. To make Taichi as easy to use as a Python package, +we have done heavy engineering with this goal in mind - letting every Python programmer write Taichi codes with +minimal learning effort. You can even use your favorite Python package management system, Python IDEs and other Python packages in conjunction with Taichi. Portability diff --git a/docs/utilities.rst b/docs/utilities.rst index 84c1fd98057cc..69bf8692e82f6 100644 --- a/docs/utilities.rst +++ b/docs/utilities.rst @@ -58,7 +58,7 @@ For example, this is part of the output by ``ti regression`` after enabling cons The suggested workflow for **the PR author** to run the regression tests is: * When a performance related PR is ready, checkout that PR locally. - + * Run ``ti benchmark && ti regression`` to obtain the result. * Decide wheater to approve or request change, depends on the result. diff --git a/python/taichi/main.py b/python/taichi/main.py index 22111b7ba6558..4e18d3b8235d1 100644 --- a/python/taichi/main.py +++ b/python/taichi/main.py @@ -85,10 +85,8 @@ def display_benchmark_regression(xd, yd): def parse_dat(file): dict = {} for line in open(file).readlines(): - try: - a, b = line.strip().split(':') - except: - continue + try: a, b = line.strip().split(':') + except: continue dict[a.strip()] = int(float(b)) return dict @@ -269,9 +267,7 @@ def main(debug=False): os.chdir(baseline_dir) print('[benchmark] pushing baseline data...') os.system('git add .') - os.system( - f"git commit -m 'update baseline for taichi@{ti.core.get_commit_hash()}'" - ) + os.system(f"git commit -m 'update baseline for taichi@{ti.core.get_commit_hash()}'") os.system('git push') os.chdir(old_cwd) print('[benchmark] baseline data uploaded') @@ -283,7 +279,9 @@ def main(debug=False): print('[benchmark] fetching latest baseline...') os.system('git pull') os.chdir(old_cwd) - display_benchmark_regression(baseline_dir, output_dir) + display_benchmark_regression( + baseline_dir, + output_dir) elif mode == "build": ti.core.build() elif mode == "format": diff --git a/taichi/analysis/verify.cpp b/taichi/analysis/verify.cpp index 3e56285b03bd8..be02ed1e4f18f 100644 --- a/taichi/analysis/verify.cpp +++ b/taichi/analysis/verify.cpp @@ -78,12 +78,12 @@ class IRVerifier : public BasicStmtVisitor { TI_ASSERT(stmt->loop); if (stmt->loop->is()) { TI_ASSERT(stmt->loop->as()->task_type == - OffloadedStmt::TaskType::struct_for || - stmt->loop->as()->task_type == - OffloadedStmt::TaskType::range_for); + OffloadedStmt::TaskType::struct_for || + stmt->loop->as()->task_type == + OffloadedStmt::TaskType::range_for); } else { TI_ASSERT(stmt->loop->is() || - stmt->loop->is()); + stmt->loop->is()); } } @@ -92,18 +92,16 @@ class IRVerifier : public BasicStmtVisitor { if (for_stmt->loop_var) { TI_ASSERT(for_stmt->loop_var->is()); TI_ASSERT_INFO(irpass::analysis::gather_statements( - for_stmt->loop_var->parent, - [&](Stmt *s) { - if (auto store = s->cast()) - return store->ptr == for_stmt->loop_var; - else if (auto atomic = s->cast()) { - return atomic->dest == for_stmt->loop_var; - } else { - return false; - } - }) - .empty(), - "loop_var of {} modified", for_stmt->id); + for_stmt->loop_var->parent, + [&](Stmt *s) { + if (auto store = s->cast()) + return store->ptr == for_stmt->loop_var; + else if (auto atomic = s->cast()) { + return atomic->dest == for_stmt->loop_var; + } else { + return false; + } + }).empty(), "loop_var of {} modified", for_stmt->id); } for_stmt->body->accept(this); } diff --git a/taichi/backends/metal/codegen_metal.cpp b/taichi/backends/metal/codegen_metal.cpp index 924050d647519..e928264ab04c6 100644 --- a/taichi/backends/metal/codegen_metal.cpp +++ b/taichi/backends/metal/codegen_metal.cpp @@ -454,15 +454,17 @@ class KernelCodegen : public IRVisitor { TI_ASSERT(for_stmt->width() == 1); auto loop_var_name = for_stmt->raw_name(); if (!for_stmt->reversed) { - emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", loop_var_name, - for_stmt->begin->raw_name(), loop_var_name, - for_stmt->end->raw_name(), loop_var_name, loop_var_name, 1); + emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", + loop_var_name, for_stmt->begin->raw_name(), + loop_var_name, for_stmt->end->raw_name(), + loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } else { // reversed for loop emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", - loop_var_name, for_stmt->end->raw_name(), loop_var_name, - for_stmt->begin->raw_name(), loop_var_name, loop_var_name, 1); + loop_var_name, for_stmt->end->raw_name(), + loop_var_name, for_stmt->begin->raw_name(), + loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } for_stmt->body->accept(this); diff --git a/taichi/backends/metal/shaders/helpers.metal.h b/taichi/backends/metal/shaders/helpers.metal.h index d897cf12008f1..41cf774576e7f 100644 --- a/taichi/backends/metal/shaders/helpers.metal.h +++ b/taichi/backends/metal/shaders/helpers.metal.h @@ -33,9 +33,8 @@ STR( inline int ifloordiv(int lhs, int rhs) { const int intm = (lhs / rhs); - return (((lhs < 0) != (rhs < 0) && lhs && (rhs * intm != lhs)) - ? (intm - 1) - : intm); + return (((lhs < 0) != (rhs < 0) && lhs && + (rhs * intm != lhs)) ? (intm - 1) : intm); } int32_t pow_i32(int32_t x, int32_t n) { diff --git a/taichi/backends/opengl/codegen_opengl.cpp b/taichi/backends/opengl/codegen_opengl.cpp index b709b7968af3e..3530be00464d3 100644 --- a/taichi/backends/opengl/codegen_opengl.cpp +++ b/taichi/backends/opengl/codegen_opengl.cpp @@ -414,13 +414,14 @@ class KernelGen : public IRVisitor { emit("{} {} = atan({}, {});", dt_name, bin_name, lhs_name, rhs_name); } return; - } else if (bin->op_type == BinaryOpType::pow && - is_integral(bin->rhs->element_type())) { - // The GLSL `pow` is not so percise for `int`... e.g.: `pow(5, 3)` obtains - // 124 So that we have to use some hack to make it percise. Discussion: - // https://github.com/taichi-dev/taichi/pull/943#issuecomment-626354902 + } else if (bin->op_type == BinaryOpType::pow + && is_integral(bin->rhs->element_type())) { + // The GLSL `pow` is not so percise for `int`... e.g.: `pow(5, 3)` obtains 124 + // So that we have to use some hack to make it percise. + // Discussion: https://github.com/taichi-dev/taichi/pull/943#issuecomment-626354902 emit("{} {} = {}(fast_pow_{}({}, {}));", dt_name, bin_name, dt_name, - data_type_short_name(bin->lhs->element_type()), lhs_name, rhs_name); + data_type_short_name(bin->lhs->element_type()), + lhs_name, rhs_name); used.fast_pow = true; return; } @@ -602,9 +603,9 @@ class KernelGen : public IRVisitor { void visit(LoopIndexStmt *stmt) override { TI_ASSERT(stmt->loop->is() || - (stmt->loop->is() && - stmt->loop->as()->task_type == - OffloadedStmt::TaskType::range_for)); + (stmt->loop->is() && + stmt->loop->as()->task_type == + OffloadedStmt::TaskType::range_for)); TI_ASSERT(stmt->index == 0); // TODO: multiple indices emit("int {} = _itv;", stmt->short_name()); } @@ -613,15 +614,17 @@ class KernelGen : public IRVisitor { TI_ASSERT(for_stmt->width() == 1); auto loop_var_name = for_stmt->raw_name(); if (!for_stmt->reversed) { - emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", loop_var_name, - for_stmt->begin->raw_name(), loop_var_name, - for_stmt->end->raw_name(), loop_var_name, loop_var_name, 1); + emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", + loop_var_name, for_stmt->begin->raw_name(), + loop_var_name, for_stmt->end->raw_name(), + loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } else { // reversed for loop emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", - loop_var_name, for_stmt->end->raw_name(), loop_var_name, - for_stmt->begin->raw_name(), loop_var_name, loop_var_name, 1); + loop_var_name, for_stmt->end->raw_name(), + loop_var_name, for_stmt->begin->raw_name(), + loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } for_stmt->body->accept(this); @@ -719,14 +722,12 @@ void OpenglCodeGen::lower() { auto ir = kernel_->ir; auto &config = kernel_->program.config; config.demote_dense_struct_fors = true; - auto res = - irpass::compile_to_offloads(ir, config, - /*vectorize=*/false, kernel_->grad, - /*ad_use_stack=*/false, config.print_ir, - /*lower_global_access*/ true); + auto res = irpass::compile_to_offloads(ir, config, + /*vectorize=*/false, kernel_->grad, + /*ad_use_stack=*/false, config.print_ir, + /*lower_global_access*/true); global_tmps_buffer_size_ = res.total_size; - TI_TRACE("[glsl] Global temporary buffer size {} B", - global_tmps_buffer_size_); + TI_TRACE("[glsl] Global temporary buffer size {} B", global_tmps_buffer_size_); #ifdef _GLSL_DEBUG irpass::print(ir); #endif diff --git a/taichi/codegen/codegen_llvm.cpp b/taichi/codegen/codegen_llvm.cpp index af4ca90a287ee..991132c847e36 100644 --- a/taichi/codegen/codegen_llvm.cpp +++ b/taichi/codegen/codegen_llvm.cpp @@ -808,13 +808,15 @@ void CodeGenLLVM::create_naive_range_for(RangeForStmt *for_stmt) { builder->SetInsertPoint(loop_test); llvm::Value *cond; if (!for_stmt->reversed) { - cond = builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SLT, - builder->CreateLoad(loop_var), - llvm_val[for_stmt->end]); + cond = + builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SLT, + builder->CreateLoad(loop_var), + llvm_val[for_stmt->end]); } else { - cond = builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SGE, - builder->CreateLoad(loop_var), - llvm_val[for_stmt->begin]); + cond = + builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SGE, + builder->CreateLoad(loop_var), + llvm_val[for_stmt->begin]); } builder->CreateCondBr(cond, body, after_loop); } @@ -1411,13 +1413,13 @@ void CodeGenLLVM::visit(LoopIndexStmt *stmt) { TI_ASSERT(&module->getContext() == tlctx->get_this_thread_context()); if (stmt->loop->is() && stmt->loop->as()->task_type == - OffloadedStmt::TaskType::struct_for) { + OffloadedStmt::TaskType::struct_for) { llvm_val[stmt] = builder->CreateLoad(builder->CreateGEP( current_coordinates, {tlctx->get_constant(0), tlctx->get_constant(0), tlctx->get_constant(stmt->index)})); } else { - llvm_val[stmt] = - builder->CreateLoad(loop_vars_llvm[stmt->loop][stmt->index]); + llvm_val[stmt] = builder->CreateLoad( + loop_vars_llvm[stmt->loop][stmt->index]); } } diff --git a/taichi/ir/ir.h b/taichi/ir/ir.h index 4810b1de1de87..76006210da23b 100644 --- a/taichi/ir/ir.h +++ b/taichi/ir/ir.h @@ -835,8 +835,7 @@ class Block : public IRNode { void insert(VecStatement &&stmt, int location = -1); void replace_statements_in_range(int start, int end, VecStatement &&stmts); void set_statements(VecStatement &&stmts); - void replace_with(Stmt *old_statement, - std::unique_ptr &&new_statement, + void replace_with(Stmt *old_statement, std::unique_ptr &&new_statement, bool replace_usages = true); void insert_before(Stmt *old_statement, VecStatement &&new_statements); void replace_with(Stmt *old_statement, diff --git a/taichi/ir/transforms.h b/taichi/ir/transforms.h index 50fcd3862a7e9..a29cd59f9b1bf 100644 --- a/taichi/ir/transforms.h +++ b/taichi/ir/transforms.h @@ -49,13 +49,14 @@ void demote_dense_struct_fors(IRNode *root); void demote_atomics(IRNode *root); void reverse_segments(IRNode *root); // for autograd std::unique_ptr initialize_scratch_pad(StructForStmt *root); -OffloadedResult compile_to_offloads(IRNode *ir, - const CompileConfig &config, - bool vectorize, - bool grad, - bool ad_use_stack, - bool verbose, - bool lower_global_access = true); +OffloadedResult compile_to_offloads( + IRNode *ir, + const CompileConfig &config, + bool vectorize, + bool grad, + bool ad_use_stack, + bool verbose, + bool lower_global_access = true); } // namespace irpass diff --git a/taichi/transforms/compile_to_offloads.cpp b/taichi/transforms/compile_to_offloads.cpp index 5339b06646ed2..263a631d31a34 100644 --- a/taichi/transforms/compile_to_offloads.cpp +++ b/taichi/transforms/compile_to_offloads.cpp @@ -7,13 +7,14 @@ TLANG_NAMESPACE_BEGIN namespace irpass { -OffloadedResult compile_to_offloads(IRNode *ir, - const CompileConfig &config, - bool vectorize, - bool grad, - bool ad_use_stack, - bool verbose, - bool lower_global_access) { +OffloadedResult compile_to_offloads( + IRNode *ir, + const CompileConfig &config, + bool vectorize, + bool grad, + bool ad_use_stack, + bool verbose, + bool lower_global_access) { TI_AUTO_PROF; auto print = [&](const std::string &name) { diff --git a/taichi/transforms/convert_into_loop_index.cpp b/taichi/transforms/convert_into_loop_index.cpp index ce2a60a51823e..142534bd29ffc 100644 --- a/taichi/transforms/convert_into_loop_index.cpp +++ b/taichi/transforms/convert_into_loop_index.cpp @@ -19,14 +19,12 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { [&](Stmt *load) { if (auto local_load = load->cast()) { return local_load->width() == 1 && - local_load->ptr[0].var == loop_var && - local_load->ptr[0].offset == 0; + local_load->ptr[0].var == loop_var && + local_load->ptr[0].offset == 0; } return false; }, - [&]() { - return Stmt::make(loop, index, is_struct_for); - }); + [&]() { return Stmt::make(loop, index, is_struct_for); }); } void preprocess_container_stmt(Stmt *stmt) override { @@ -37,7 +35,7 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { auto leaf = struct_for->snode; for (int i = 0; i < (int)struct_for->loop_vars.size(); i++) { convert(struct_for, struct_for->loop_vars[i], - leaf->physical_index_position[i], true); + leaf->physical_index_position[i], true); struct_for->loop_vars[i] = nullptr; } } diff --git a/taichi/transforms/demote_dense_struct_fors.cpp b/taichi/transforms/demote_dense_struct_fors.cpp index 50c5a70f8c4ca..ea459b8907bdb 100644 --- a/taichi/transforms/demote_dense_struct_fors.cpp +++ b/taichi/transforms/demote_dense_struct_fors.cpp @@ -84,8 +84,7 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { [&](Stmt *s) { if (auto loop_index = s->cast()) { return loop_index->loop == struct_for && - loop_index->index == - snodes.back()->physical_index_position[i]; + loop_index->index == snodes.back()->physical_index_position[i]; } return false; }, diff --git a/taichi/transforms/ir_printer.cpp b/taichi/transforms/ir_printer.cpp index 79533f9f8635f..a84076cb0586f 100644 --- a/taichi/transforms/ir_printer.cpp +++ b/taichi/transforms/ir_printer.cpp @@ -259,18 +259,17 @@ class IRPrinter : public IRVisitor { void visit(RangeForStmt *for_stmt) override { print("{} : {}for {} in range({}, {}, step {}) {{", for_stmt->name(), - for_stmt->reversed ? "reversed " : "", - for_stmt->loop_var ? for_stmt->loop_var->name() : "nullptr", + for_stmt->reversed ? "reversed " : "", for_stmt->loop_var ? + for_stmt->loop_var->name() : "nullptr", for_stmt->begin->name(), for_stmt->end->name(), for_stmt->vectorize); for_stmt->body->accept(this); print("}}"); } void visit(StructForStmt *for_stmt) override { - auto loop_vars = make_list(for_stmt->loop_vars, - [](Stmt *const &stmt) -> std::string { - return stmt ? stmt->name() : "nullptr"; - }); + auto loop_vars = make_list( + for_stmt->loop_vars, + [](Stmt *const &stmt) -> std::string { return stmt ? stmt->name() : "nullptr"; }); print("{} : for {} where {} active, step {} {{", for_stmt->name(), loop_vars, for_stmt->snode->get_node_type_name_hinted(), for_stmt->vectorize); @@ -460,8 +459,7 @@ class IRPrinter : public IRVisitor { } void visit(LoopIndexStmt *stmt) override { - print("{}{} = loop {} index {}", stmt->type_hint(), stmt->name(), - stmt->loop->name(), stmt->index); + print("{}{} = loop {} index {}", stmt->type_hint(), stmt->name(), stmt->loop->name(), stmt->index); } void visit(GlobalTemporaryStmt *stmt) override { From dbde2fbd6330702ed2fde5c9e3b060bc35b03b88 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 20:08:16 -0400 Subject: [PATCH 14/19] [skip ci] Remove LoopIndexStmt::is_struct_for --- taichi/ir/statements.h | 7 +++---- taichi/transforms/convert_into_loop_index.cpp | 9 ++++----- taichi/transforms/demote_dense_struct_fors.cpp | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/taichi/ir/statements.h b/taichi/ir/statements.h index dc536bac1f82b..ec659f0a0f12a 100644 --- a/taichi/ir/statements.h +++ b/taichi/ir/statements.h @@ -219,10 +219,9 @@ class LoopIndexStmt : public Stmt { public: Stmt *loop; int index; - bool is_struct_for; - LoopIndexStmt(Stmt *loop, int index, bool is_struct_for) - : loop(loop), index(index), is_struct_for(is_struct_for) { + LoopIndexStmt(Stmt *loop, int index) + : loop(loop), index(index) { TI_STMT_REG_FIELDS; } @@ -230,7 +229,7 @@ class LoopIndexStmt : public Stmt { return false; } - TI_STMT_DEF_FIELDS(ret_type, loop, index, is_struct_for); + TI_STMT_DEF_FIELDS(ret_type, loop, index); DEFINE_ACCEPT }; diff --git a/taichi/transforms/convert_into_loop_index.cpp b/taichi/transforms/convert_into_loop_index.cpp index 142534bd29ffc..642818daa08f8 100644 --- a/taichi/transforms/convert_into_loop_index.cpp +++ b/taichi/transforms/convert_into_loop_index.cpp @@ -10,8 +10,7 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { static void convert(Stmt *loop, Stmt *loop_var, - int index, - bool is_struct_for) { + int index) { if (!loop_var) return; irpass::replace_statements_with( @@ -24,18 +23,18 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { } return false; }, - [&]() { return Stmt::make(loop, index, is_struct_for); }); + [&]() { return Stmt::make(loop, index); }); } void preprocess_container_stmt(Stmt *stmt) override { if (auto range_for = stmt->cast()) { - convert(range_for, range_for->loop_var, 0, false); + convert(range_for, range_for->loop_var, 0); range_for->loop_var = nullptr; } else if (auto struct_for = stmt->cast()) { auto leaf = struct_for->snode; for (int i = 0; i < (int)struct_for->loop_vars.size(); i++) { convert(struct_for, struct_for->loop_vars[i], - leaf->physical_index_position[i], true); + leaf->physical_index_position[i]); struct_for->loop_vars[i] = nullptr; } } diff --git a/taichi/transforms/demote_dense_struct_fors.cpp b/taichi/transforms/demote_dense_struct_fors.cpp index ea459b8907bdb..318bb76d77fb6 100644 --- a/taichi/transforms/demote_dense_struct_fors.cpp +++ b/taichi/transforms/demote_dense_struct_fors.cpp @@ -35,7 +35,7 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { physical_indices.push_back(snodes.back()->physical_index_position[i]); } - auto main_loop_var = body_header.push_back(nullptr, 0, false); + auto main_loop_var = body_header.push_back(nullptr, 0); int offset = total_bits; Stmt *test = body_header.push_back(TypedConstant(-1)); From c1e91dd2d3aa37bc18d8c3033741ba17a9e97797 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 20:12:56 -0400 Subject: [PATCH 15/19] Finally move the pass into `lower` --- taichi/transforms/compile_to_offloads.cpp | 4 ---- taichi/transforms/convert_into_loop_index.cpp | 1 - taichi/transforms/lower_ast.cpp | 1 + 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/taichi/transforms/compile_to_offloads.cpp b/taichi/transforms/compile_to_offloads.cpp index 263a631d31a34..f3c8021a62125 100644 --- a/taichi/transforms/compile_to_offloads.cpp +++ b/taichi/transforms/compile_to_offloads.cpp @@ -35,10 +35,6 @@ OffloadedResult compile_to_offloads( irpass::lower(ir); print("Lowered"); - irpass::convert_into_loop_index(ir); - print("Converted into loop index"); - irpass::analysis::verify(ir); - irpass::typecheck(ir); print("Typechecked"); irpass::analysis::verify(ir); diff --git a/taichi/transforms/convert_into_loop_index.cpp b/taichi/transforms/convert_into_loop_index.cpp index 642818daa08f8..c8ca558836a15 100644 --- a/taichi/transforms/convert_into_loop_index.cpp +++ b/taichi/transforms/convert_into_loop_index.cpp @@ -58,7 +58,6 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { namespace irpass { void convert_into_loop_index(IRNode *root) { ConvertIntoLoopIndexStmt::run(root); - typecheck(root); } } // namespace irpass diff --git a/taichi/transforms/lower_ast.cpp b/taichi/transforms/lower_ast.cpp index 3bec42df78101..560c48e72c723 100644 --- a/taichi/transforms/lower_ast.cpp +++ b/taichi/transforms/lower_ast.cpp @@ -448,6 +448,7 @@ namespace irpass { void lower(IRNode *root) { auto offsets = LowerAST::run(root); FixStructForOffsets::run(root, offsets); + convert_into_loop_index(root); } } // namespace irpass From f0276bd0e80708cec00d0700b7a08b7b257775ea Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 20:16:32 -0400 Subject: [PATCH 16/19] [skip ci] add comment --- taichi/transforms/demote_dense_struct_fors.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/taichi/transforms/demote_dense_struct_fors.cpp b/taichi/transforms/demote_dense_struct_fors.cpp index 318bb76d77fb6..682e1e09e85fd 100644 --- a/taichi/transforms/demote_dense_struct_fors.cpp +++ b/taichi/transforms/demote_dense_struct_fors.cpp @@ -36,6 +36,7 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { } auto main_loop_var = body_header.push_back(nullptr, 0); + // We will set main_loop_var->loop later. int offset = total_bits; Stmt *test = body_header.push_back(TypedConstant(-1)); From 3a73b77c52c7a4ecc420abfe143e9b195688729a Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 13 May 2020 23:05:43 -0400 Subject: [PATCH 17/19] Fix opengl backend --- taichi/backends/opengl/codegen_opengl.cpp | 24 +++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/taichi/backends/opengl/codegen_opengl.cpp b/taichi/backends/opengl/codegen_opengl.cpp index 3530be00464d3..f7e4715a537b3 100644 --- a/taichi/backends/opengl/codegen_opengl.cpp +++ b/taichi/backends/opengl/codegen_opengl.cpp @@ -602,28 +602,32 @@ class KernelGen : public IRVisitor { } void visit(LoopIndexStmt *stmt) override { - TI_ASSERT(stmt->loop->is() || - (stmt->loop->is() && - stmt->loop->as()->task_type == - OffloadedStmt::TaskType::range_for)); TI_ASSERT(stmt->index == 0); // TODO: multiple indices - emit("int {} = _itv;", stmt->short_name()); + if (stmt->loop->is()) { + TI_ASSERT(stmt->loop->as()->task_type == + OffloadedStmt::TaskType::range_for); + emit("int {} = _itv;", stmt->short_name()); + } else if (stmt->loop->is()) { + emit("int {} = {};", stmt->short_name(), stmt->loop->short_name()); + } else { + TI_NOT_IMPLEMENTED + } } void visit(RangeForStmt *for_stmt) override { TI_ASSERT(for_stmt->width() == 1); - auto loop_var_name = for_stmt->raw_name(); + auto loop_var_name = for_stmt->short_name(); if (!for_stmt->reversed) { emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", - loop_var_name, for_stmt->begin->raw_name(), - loop_var_name, for_stmt->end->raw_name(), + loop_var_name, for_stmt->begin->short_name(), + loop_var_name, for_stmt->end->short_name(), loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } else { // reversed for loop emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", - loop_var_name, for_stmt->end->raw_name(), - loop_var_name, for_stmt->begin->raw_name(), + loop_var_name, for_stmt->end->short_name(), + loop_var_name, for_stmt->begin->short_name(), loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } From ac03804290c057b6e6fb49cfa4c5ab1b8627823c Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Thu, 14 May 2020 14:25:21 -0400 Subject: [PATCH 18/19] Use const Stmt* --- taichi/codegen/codegen_llvm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taichi/codegen/codegen_llvm.h b/taichi/codegen/codegen_llvm.h index ba10fd7a325c8..67f7980fb1407 100644 --- a/taichi/codegen/codegen_llvm.h +++ b/taichi/codegen/codegen_llvm.h @@ -72,7 +72,7 @@ class CodeGenLLVM : public IRVisitor, public LLVMModuleBuilder { std::vector offloaded_tasks; BasicBlock *func_body_bb; - std::unordered_map> loop_vars_llvm; + std::unordered_map> loop_vars_llvm; using IRVisitor::visit; using LLVMModuleBuilder::call; From 404b6e45670b78ce96d7c960dcfbccb9f9d4a29a Mon Sep 17 00:00:00 2001 From: Taichi Gardener Date: Thu, 14 May 2020 14:46:09 -0400 Subject: [PATCH 19/19] [skip ci] enforce code format --- docs/hello.rst | 6 +-- taichi/analysis/verify.cpp | 30 +++++++------- taichi/backends/metal/codegen_metal.cpp | 12 +++--- taichi/backends/metal/shaders/helpers.metal.h | 5 ++- taichi/backends/opengl/codegen_opengl.cpp | 39 +++++++++---------- taichi/codegen/codegen_llvm.cpp | 20 +++++----- taichi/ir/ir.h | 3 +- taichi/ir/statements.h | 3 +- taichi/ir/transforms.h | 15 ++++--- taichi/transforms/convert_into_loop_index.cpp | 10 ++--- .../transforms/demote_dense_struct_fors.cpp | 3 +- taichi/transforms/ir_printer.cpp | 14 ++++--- 12 files changed, 79 insertions(+), 81 deletions(-) diff --git a/docs/hello.rst b/docs/hello.rst index c463e3faaeccc..54a98a59d8522 100644 --- a/docs/hello.rst +++ b/docs/hello.rst @@ -55,9 +55,9 @@ Let's dive into this simple Taichi program. import taichi as ti ------------------- -Taichi is a domain-specific language (DSL) embedded in Python. To make Taichi as easy to use as a Python package, -we have done heavy engineering with this goal in mind - letting every Python programmer write Taichi codes with -minimal learning effort. You can even use your favorite Python package management system, Python IDEs and other +Taichi is a domain-specific language (DSL) embedded in Python. To make Taichi as easy to use as a Python package, +we have done heavy engineering with this goal in mind - letting every Python programmer write Taichi codes with +minimal learning effort. You can even use your favorite Python package management system, Python IDEs and other Python packages in conjunction with Taichi. Portability diff --git a/taichi/analysis/verify.cpp b/taichi/analysis/verify.cpp index be02ed1e4f18f..3e56285b03bd8 100644 --- a/taichi/analysis/verify.cpp +++ b/taichi/analysis/verify.cpp @@ -78,12 +78,12 @@ class IRVerifier : public BasicStmtVisitor { TI_ASSERT(stmt->loop); if (stmt->loop->is()) { TI_ASSERT(stmt->loop->as()->task_type == - OffloadedStmt::TaskType::struct_for || - stmt->loop->as()->task_type == - OffloadedStmt::TaskType::range_for); + OffloadedStmt::TaskType::struct_for || + stmt->loop->as()->task_type == + OffloadedStmt::TaskType::range_for); } else { TI_ASSERT(stmt->loop->is() || - stmt->loop->is()); + stmt->loop->is()); } } @@ -92,16 +92,18 @@ class IRVerifier : public BasicStmtVisitor { if (for_stmt->loop_var) { TI_ASSERT(for_stmt->loop_var->is()); TI_ASSERT_INFO(irpass::analysis::gather_statements( - for_stmt->loop_var->parent, - [&](Stmt *s) { - if (auto store = s->cast()) - return store->ptr == for_stmt->loop_var; - else if (auto atomic = s->cast()) { - return atomic->dest == for_stmt->loop_var; - } else { - return false; - } - }).empty(), "loop_var of {} modified", for_stmt->id); + for_stmt->loop_var->parent, + [&](Stmt *s) { + if (auto store = s->cast()) + return store->ptr == for_stmt->loop_var; + else if (auto atomic = s->cast()) { + return atomic->dest == for_stmt->loop_var; + } else { + return false; + } + }) + .empty(), + "loop_var of {} modified", for_stmt->id); } for_stmt->body->accept(this); } diff --git a/taichi/backends/metal/codegen_metal.cpp b/taichi/backends/metal/codegen_metal.cpp index e928264ab04c6..924050d647519 100644 --- a/taichi/backends/metal/codegen_metal.cpp +++ b/taichi/backends/metal/codegen_metal.cpp @@ -454,17 +454,15 @@ class KernelCodegen : public IRVisitor { TI_ASSERT(for_stmt->width() == 1); auto loop_var_name = for_stmt->raw_name(); if (!for_stmt->reversed) { - emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", - loop_var_name, for_stmt->begin->raw_name(), - loop_var_name, for_stmt->end->raw_name(), - loop_var_name, loop_var_name, 1); + emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", loop_var_name, + for_stmt->begin->raw_name(), loop_var_name, + for_stmt->end->raw_name(), loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } else { // reversed for loop emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", - loop_var_name, for_stmt->end->raw_name(), - loop_var_name, for_stmt->begin->raw_name(), - loop_var_name, loop_var_name, 1); + loop_var_name, for_stmt->end->raw_name(), loop_var_name, + for_stmt->begin->raw_name(), loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } for_stmt->body->accept(this); diff --git a/taichi/backends/metal/shaders/helpers.metal.h b/taichi/backends/metal/shaders/helpers.metal.h index 41cf774576e7f..d897cf12008f1 100644 --- a/taichi/backends/metal/shaders/helpers.metal.h +++ b/taichi/backends/metal/shaders/helpers.metal.h @@ -33,8 +33,9 @@ STR( inline int ifloordiv(int lhs, int rhs) { const int intm = (lhs / rhs); - return (((lhs < 0) != (rhs < 0) && lhs && - (rhs * intm != lhs)) ? (intm - 1) : intm); + return (((lhs < 0) != (rhs < 0) && lhs && (rhs * intm != lhs)) + ? (intm - 1) + : intm); } int32_t pow_i32(int32_t x, int32_t n) { diff --git a/taichi/backends/opengl/codegen_opengl.cpp b/taichi/backends/opengl/codegen_opengl.cpp index f7e4715a537b3..5ed1755932287 100644 --- a/taichi/backends/opengl/codegen_opengl.cpp +++ b/taichi/backends/opengl/codegen_opengl.cpp @@ -414,14 +414,13 @@ class KernelGen : public IRVisitor { emit("{} {} = atan({}, {});", dt_name, bin_name, lhs_name, rhs_name); } return; - } else if (bin->op_type == BinaryOpType::pow - && is_integral(bin->rhs->element_type())) { - // The GLSL `pow` is not so percise for `int`... e.g.: `pow(5, 3)` obtains 124 - // So that we have to use some hack to make it percise. - // Discussion: https://github.com/taichi-dev/taichi/pull/943#issuecomment-626354902 + } else if (bin->op_type == BinaryOpType::pow && + is_integral(bin->rhs->element_type())) { + // The GLSL `pow` is not so percise for `int`... e.g.: `pow(5, 3)` obtains + // 124 So that we have to use some hack to make it percise. Discussion: + // https://github.com/taichi-dev/taichi/pull/943#issuecomment-626354902 emit("{} {} = {}(fast_pow_{}({}, {}));", dt_name, bin_name, dt_name, - data_type_short_name(bin->lhs->element_type()), - lhs_name, rhs_name); + data_type_short_name(bin->lhs->element_type()), lhs_name, rhs_name); used.fast_pow = true; return; } @@ -605,7 +604,7 @@ class KernelGen : public IRVisitor { TI_ASSERT(stmt->index == 0); // TODO: multiple indices if (stmt->loop->is()) { TI_ASSERT(stmt->loop->as()->task_type == - OffloadedStmt::TaskType::range_for); + OffloadedStmt::TaskType::range_for); emit("int {} = _itv;", stmt->short_name()); } else if (stmt->loop->is()) { emit("int {} = {};", stmt->short_name(), stmt->loop->short_name()); @@ -618,17 +617,15 @@ class KernelGen : public IRVisitor { TI_ASSERT(for_stmt->width() == 1); auto loop_var_name = for_stmt->short_name(); if (!for_stmt->reversed) { - emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", - loop_var_name, for_stmt->begin->short_name(), - loop_var_name, for_stmt->end->short_name(), - loop_var_name, loop_var_name, 1); + emit("for (int {}_ = {}; {}_ < {}; {}_ = {}_ + {}) {{", loop_var_name, + for_stmt->begin->short_name(), loop_var_name, + for_stmt->end->short_name(), loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } else { // reversed for loop emit("for (int {}_ = {} - 1; {}_ >= {}; {}_ = {}_ - {}) {{", - loop_var_name, for_stmt->end->short_name(), - loop_var_name, for_stmt->begin->short_name(), - loop_var_name, loop_var_name, 1); + loop_var_name, for_stmt->end->short_name(), loop_var_name, + for_stmt->begin->short_name(), loop_var_name, loop_var_name, 1); emit(" int {} = {}_;", loop_var_name, loop_var_name); } for_stmt->body->accept(this); @@ -726,12 +723,14 @@ void OpenglCodeGen::lower() { auto ir = kernel_->ir; auto &config = kernel_->program.config; config.demote_dense_struct_fors = true; - auto res = irpass::compile_to_offloads(ir, config, - /*vectorize=*/false, kernel_->grad, - /*ad_use_stack=*/false, config.print_ir, - /*lower_global_access*/true); + auto res = + irpass::compile_to_offloads(ir, config, + /*vectorize=*/false, kernel_->grad, + /*ad_use_stack=*/false, config.print_ir, + /*lower_global_access*/ true); global_tmps_buffer_size_ = res.total_size; - TI_TRACE("[glsl] Global temporary buffer size {} B", global_tmps_buffer_size_); + TI_TRACE("[glsl] Global temporary buffer size {} B", + global_tmps_buffer_size_); #ifdef _GLSL_DEBUG irpass::print(ir); #endif diff --git a/taichi/codegen/codegen_llvm.cpp b/taichi/codegen/codegen_llvm.cpp index 991132c847e36..af4ca90a287ee 100644 --- a/taichi/codegen/codegen_llvm.cpp +++ b/taichi/codegen/codegen_llvm.cpp @@ -808,15 +808,13 @@ void CodeGenLLVM::create_naive_range_for(RangeForStmt *for_stmt) { builder->SetInsertPoint(loop_test); llvm::Value *cond; if (!for_stmt->reversed) { - cond = - builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SLT, - builder->CreateLoad(loop_var), - llvm_val[for_stmt->end]); + cond = builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SLT, + builder->CreateLoad(loop_var), + llvm_val[for_stmt->end]); } else { - cond = - builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SGE, - builder->CreateLoad(loop_var), - llvm_val[for_stmt->begin]); + cond = builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SGE, + builder->CreateLoad(loop_var), + llvm_val[for_stmt->begin]); } builder->CreateCondBr(cond, body, after_loop); } @@ -1413,13 +1411,13 @@ void CodeGenLLVM::visit(LoopIndexStmt *stmt) { TI_ASSERT(&module->getContext() == tlctx->get_this_thread_context()); if (stmt->loop->is() && stmt->loop->as()->task_type == - OffloadedStmt::TaskType::struct_for) { + OffloadedStmt::TaskType::struct_for) { llvm_val[stmt] = builder->CreateLoad(builder->CreateGEP( current_coordinates, {tlctx->get_constant(0), tlctx->get_constant(0), tlctx->get_constant(stmt->index)})); } else { - llvm_val[stmt] = builder->CreateLoad( - loop_vars_llvm[stmt->loop][stmt->index]); + llvm_val[stmt] = + builder->CreateLoad(loop_vars_llvm[stmt->loop][stmt->index]); } } diff --git a/taichi/ir/ir.h b/taichi/ir/ir.h index 76006210da23b..4810b1de1de87 100644 --- a/taichi/ir/ir.h +++ b/taichi/ir/ir.h @@ -835,7 +835,8 @@ class Block : public IRNode { void insert(VecStatement &&stmt, int location = -1); void replace_statements_in_range(int start, int end, VecStatement &&stmts); void set_statements(VecStatement &&stmts); - void replace_with(Stmt *old_statement, std::unique_ptr &&new_statement, + void replace_with(Stmt *old_statement, + std::unique_ptr &&new_statement, bool replace_usages = true); void insert_before(Stmt *old_statement, VecStatement &&new_statements); void replace_with(Stmt *old_statement, diff --git a/taichi/ir/statements.h b/taichi/ir/statements.h index ec659f0a0f12a..639b1ff6b318d 100644 --- a/taichi/ir/statements.h +++ b/taichi/ir/statements.h @@ -220,8 +220,7 @@ class LoopIndexStmt : public Stmt { Stmt *loop; int index; - LoopIndexStmt(Stmt *loop, int index) - : loop(loop), index(index) { + LoopIndexStmt(Stmt *loop, int index) : loop(loop), index(index) { TI_STMT_REG_FIELDS; } diff --git a/taichi/ir/transforms.h b/taichi/ir/transforms.h index a29cd59f9b1bf..50fcd3862a7e9 100644 --- a/taichi/ir/transforms.h +++ b/taichi/ir/transforms.h @@ -49,14 +49,13 @@ void demote_dense_struct_fors(IRNode *root); void demote_atomics(IRNode *root); void reverse_segments(IRNode *root); // for autograd std::unique_ptr initialize_scratch_pad(StructForStmt *root); -OffloadedResult compile_to_offloads( - IRNode *ir, - const CompileConfig &config, - bool vectorize, - bool grad, - bool ad_use_stack, - bool verbose, - bool lower_global_access = true); +OffloadedResult compile_to_offloads(IRNode *ir, + const CompileConfig &config, + bool vectorize, + bool grad, + bool ad_use_stack, + bool verbose, + bool lower_global_access = true); } // namespace irpass diff --git a/taichi/transforms/convert_into_loop_index.cpp b/taichi/transforms/convert_into_loop_index.cpp index c8ca558836a15..5d9500d617ad9 100644 --- a/taichi/transforms/convert_into_loop_index.cpp +++ b/taichi/transforms/convert_into_loop_index.cpp @@ -8,9 +8,7 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { public: using BasicStmtVisitor::visit; - static void convert(Stmt *loop, - Stmt *loop_var, - int index) { + static void convert(Stmt *loop, Stmt *loop_var, int index) { if (!loop_var) return; irpass::replace_statements_with( @@ -18,8 +16,8 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { [&](Stmt *load) { if (auto local_load = load->cast()) { return local_load->width() == 1 && - local_load->ptr[0].var == loop_var && - local_load->ptr[0].offset == 0; + local_load->ptr[0].var == loop_var && + local_load->ptr[0].offset == 0; } return false; }, @@ -34,7 +32,7 @@ class ConvertIntoLoopIndexStmt : public BasicStmtVisitor { auto leaf = struct_for->snode; for (int i = 0; i < (int)struct_for->loop_vars.size(); i++) { convert(struct_for, struct_for->loop_vars[i], - leaf->physical_index_position[i]); + leaf->physical_index_position[i]); struct_for->loop_vars[i] = nullptr; } } diff --git a/taichi/transforms/demote_dense_struct_fors.cpp b/taichi/transforms/demote_dense_struct_fors.cpp index 682e1e09e85fd..0ac446c12d38e 100644 --- a/taichi/transforms/demote_dense_struct_fors.cpp +++ b/taichi/transforms/demote_dense_struct_fors.cpp @@ -85,7 +85,8 @@ VecStatement convert_to_range_for(StructForStmt *struct_for) { [&](Stmt *s) { if (auto loop_index = s->cast()) { return loop_index->loop == struct_for && - loop_index->index == snodes.back()->physical_index_position[i]; + loop_index->index == + snodes.back()->physical_index_position[i]; } return false; }, diff --git a/taichi/transforms/ir_printer.cpp b/taichi/transforms/ir_printer.cpp index a84076cb0586f..79533f9f8635f 100644 --- a/taichi/transforms/ir_printer.cpp +++ b/taichi/transforms/ir_printer.cpp @@ -259,17 +259,18 @@ class IRPrinter : public IRVisitor { void visit(RangeForStmt *for_stmt) override { print("{} : {}for {} in range({}, {}, step {}) {{", for_stmt->name(), - for_stmt->reversed ? "reversed " : "", for_stmt->loop_var ? - for_stmt->loop_var->name() : "nullptr", + for_stmt->reversed ? "reversed " : "", + for_stmt->loop_var ? for_stmt->loop_var->name() : "nullptr", for_stmt->begin->name(), for_stmt->end->name(), for_stmt->vectorize); for_stmt->body->accept(this); print("}}"); } void visit(StructForStmt *for_stmt) override { - auto loop_vars = make_list( - for_stmt->loop_vars, - [](Stmt *const &stmt) -> std::string { return stmt ? stmt->name() : "nullptr"; }); + auto loop_vars = make_list(for_stmt->loop_vars, + [](Stmt *const &stmt) -> std::string { + return stmt ? stmt->name() : "nullptr"; + }); print("{} : for {} where {} active, step {} {{", for_stmt->name(), loop_vars, for_stmt->snode->get_node_type_name_hinted(), for_stmt->vectorize); @@ -459,7 +460,8 @@ class IRPrinter : public IRVisitor { } void visit(LoopIndexStmt *stmt) override { - print("{}{} = loop {} index {}", stmt->type_hint(), stmt->name(), stmt->loop->name(), stmt->index); + print("{}{} = loop {} index {}", stmt->type_hint(), stmt->name(), + stmt->loop->name(), stmt->index); } void visit(GlobalTemporaryStmt *stmt) override {