Skip to content
This repository was archived by the owner on Apr 28, 2023. It is now read-only.

Commit e5c6778

Browse files
Add primitive CPU mapper
This commit adds a primitive CPU mapper and updates the tests. In the current form, the context is not being used to gist and conditionals on parameters of the form `if (M == 40) { ... } ` are needed. So this PR also adds the `emitIf` function to generate the proper LLVM IR and let the tests pass.
1 parent 2830c07 commit e5c6778

File tree

5 files changed

+249
-50
lines changed

5 files changed

+249
-50
lines changed

tc/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ add_library(
7676

7777
polyhedral/codegen_llvm.cc
7878
polyhedral/llvm_jit.cc
79+
polyhedral/cpu/mapped_scop.cc
7980
)
8081
target_include_directories(tc_core_cpu PUBLIC ${LLVM_INCLUDE_DIRS})
8182
target_link_libraries(

tc/core/polyhedral/codegen_llvm.cc

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,8 @@ class LLVMCodegen {
405405
} else if (auto blockNode = node.as<isl::ast_node_block>()) {
406406
return emitBlock(blockNode);
407407
} else {
408-
if (node.as<isl::ast_node_if>()) {
409-
LOG(FATAL) << "NYI if node: " << node << std::endl;
408+
if (auto cond = node.as<isl::ast_node_if>()) {
409+
return emitIf(cond);
410410
} else {
411411
LOG(FATAL) << "NYI " << node << std::endl;
412412
}
@@ -445,6 +445,38 @@ class LLVMCodegen {
445445
return arrTy->getPointerTo();
446446
}
447447

448+
llvm::BasicBlock* emitIf(isl::ast_node_if node) {
449+
auto* incoming = halide_cg.get_builder().GetInsertBlock();
450+
auto* function = incoming->getParent();
451+
452+
llvm::Value* condVal = halide_cg.codegen(node.get_cond());
453+
auto* thenBB = llvm::BasicBlock::Create(llvmCtx, "then", function);
454+
// Recursively emit "then" in a new thenBB
455+
halide_cg.get_builder().SetInsertPoint(thenBB);
456+
auto innerBB = emitAst(node.get_then());
457+
458+
// outer -> thenBB
459+
halide_cg.get_builder().SetInsertPoint(incoming);
460+
// outer ---------> if_exit
461+
// TODO: When we support "else", go to elseBB instead of exit
462+
auto* exit = llvm::BasicBlock::Create(llvmCtx, "if_exit", function);
463+
halide_cg.get_builder().CreateCondBr(condVal, thenBB, exit);
464+
465+
// then -> if_exit
466+
halide_cg.get_builder().SetInsertPoint(innerBB);
467+
halide_cg.get_builder().CreateBr(exit);
468+
469+
// Else is often empty in the absence of full tile extraction
470+
if (node.has_else()) {
471+
LOG(FATAL) << "NYI: else conditional branch";
472+
return halide_cg.get_builder().GetInsertBlock();
473+
}
474+
475+
// Set the insertion point to if_exit
476+
halide_cg.get_builder().SetInsertPoint(exit);
477+
return halide_cg.get_builder().GetInsertBlock();
478+
}
479+
448480
llvm::BasicBlock* emitFor(isl::ast_node_for node) {
449481
auto* incoming = halide_cg.get_builder().GetInsertBlock();
450482
auto* function = incoming->getParent();

tc/core/polyhedral/cpu/mapped_scop.cc

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* Copyright (c) 2017-present, Facebook, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "tc/core/polyhedral/cpu/mapped_scop.h"
17+
18+
#include <algorithm>
19+
#include <array>
20+
#include <iostream>
21+
#include <numeric>
22+
#include <sstream>
23+
#include <stdexcept>
24+
#include <unordered_set>
25+
26+
#include "tc/core/check.h"
27+
#include "tc/core/flags.h"
28+
#include "tc/core/functional.h"
29+
#include "tc/core/polyhedral/codegen_llvm.h"
30+
#include "tc/core/polyhedral/exceptions.h"
31+
#include "tc/core/polyhedral/llvm_jit.h"
32+
#include "tc/core/polyhedral/schedule_transforms.h"
33+
#include "tc/core/polyhedral/schedule_utils.h"
34+
#include "tc/core/polyhedral/scop.h"
35+
36+
#include <glog/logging.h>
37+
38+
namespace tc {
39+
namespace polyhedral {
40+
41+
std::unique_ptr<Jit> MappedScop::codegen(
42+
const std::string& specializedName) const {
43+
std::unique_ptr<Jit> jit(new Jit());
44+
jit->codegenScop(specializedName, *scop_);
45+
return jit;
46+
}
47+
48+
std::unique_ptr<MappedScop> MappedScop::makeSequential(
49+
std::unique_ptr<Scop>&& scopUPtr,
50+
const CpuMappingOptions& cpuOptions) {
51+
using namespace polyhedral::detail;
52+
53+
const auto& generic = cpuOptions.generic;
54+
auto mappedScop = std::unique_ptr<MappedScop>(
55+
new MappedScop(std::move(scopUPtr), generic.proto.unroll()));
56+
auto& scop = mappedScop->scop_;
57+
58+
// 1a. Optionally specialize before scheduling...
59+
if (generic.proto.fix_parameters_before_scheduling()) {
60+
scop->specializeToContext();
61+
}
62+
63+
// 2. Schedule
64+
scop = Scop::makeScheduled(*scop, generic.outerScheduleOptions);
65+
66+
// 3. Tile
67+
TC_CHECK_LT(0u, generic.tiling.size())
68+
<< "Must pass tile vector with >= 1 tile sizes";
69+
auto outerBand = scop->tileOuterBand(generic.tiling);
70+
71+
// 4. Optionally reschedule if point loops need a different strategy than
72+
// tile loops
73+
if (generic.outerScheduleOptions != generic.intraTileScheduleOptions) {
74+
scop->reschedule(outerBand->child({0}), generic.intraTileScheduleOptions);
75+
LOG_IF(INFO, FLAGS_debug_tc_mapper)
76+
<< "After intra-tile rescheduling:" << std::endl
77+
<< *mappedScop->schedule();
78+
}
79+
80+
// 1b. ...or after rescheduling
81+
if (!generic.proto.fix_parameters_before_scheduling()) {
82+
scop->specializeToContext();
83+
}
84+
85+
LOG_IF(INFO, FLAGS_debug_tc_mapper)
86+
<< "After sequential strategy:" << std::endl
87+
<< *mappedScop->schedule();
88+
89+
return mappedScop;
90+
}
91+
92+
} // namespace polyhedral
93+
} // namespace tc

tc/core/polyhedral/cpu/mapped_scop.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* Copyright (c) 2017-present, Facebook, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#pragma once
17+
18+
#include <map>
19+
#include <memory>
20+
#include <string>
21+
#include <unordered_map>
22+
#include <vector>
23+
24+
#include "tc/core/cpu/cpu_mapping_options.h"
25+
#include "tc/core/polyhedral/llvm_jit.h"
26+
#include "tc/core/polyhedral/scop.h"
27+
#include "tc/core/tensor.h"
28+
#include "tc/external/isl.h"
29+
30+
namespace tc {
31+
namespace polyhedral {
32+
33+
class MappedScop {
34+
private:
35+
MappedScop(std::unique_ptr<Scop>&& scop, uint64_t unroll_)
36+
: scop_(std::move(scop)), unroll(unroll_) {}
37+
38+
public:
39+
static std::unique_ptr<MappedScop> makeSequential(
40+
std::unique_ptr<Scop>&& scopUPtr,
41+
const CpuMappingOptions& mappingOptions);
42+
43+
// Fix the values of the specified parameters in the context
44+
// to the corresponding specified values.
45+
template <typename T>
46+
void fixParameters(const std::unordered_map<std::string, T>& sizes) {
47+
scop_->fixParameters(sizes);
48+
}
49+
50+
// Generate code at the current state of transformation provided a
51+
// name for the generated function.
52+
std::unique_ptr<Jit> codegen(const std::string& specializedName) const;
53+
54+
// Accessors..
55+
// Const accessor to schedule of underlying Scop.
56+
inline const detail::ScheduleTree* schedule() const {
57+
return scop_->scheduleRoot();
58+
}
59+
// Reference to underlying scop, no ownership transfer intended.
60+
inline const Scop& scop() const {
61+
return *scop_;
62+
}
63+
inline Scop& scop() {
64+
return *scop_;
65+
}
66+
67+
private:
68+
std::unique_ptr<Scop> scop_;
69+
70+
public:
71+
const uint64_t unroll;
72+
};
73+
} // namespace polyhedral
74+
} // namespace tc

0 commit comments

Comments
 (0)