Skip to content

Commit

Permalink
Merge branch 'master' into metal_codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
Photos Test 1 committed Aug 22, 2015
1 parent c0dc704 commit 145e9c6
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 18 deletions.
2 changes: 1 addition & 1 deletion llvm
Submodule llvm updated from 440cf8 to 327cfd
26 changes: 26 additions & 0 deletions src/CodeGen_X86.cpp
Expand Up @@ -382,6 +382,32 @@ void CodeGen_X86::visit(const Cast *op) {
}
}


#if LLVM_VERSION >= 38
// Workaround for https://llvm.org/bugs/show_bug.cgi?id=24512
// LLVM uses a numerically unstable method for vector
// uint32->float conversion before AVX.
if (op->value.type().element_of() == UInt(32) &&
op->type.is_float() &&
op->type.is_vector() &&
!target.has_feature(Target::AVX)) {
Type signed_type = Int(32, op->type.width);

// Convert the top 31 bits to float using the signed version
Expr top_bits = cast(signed_type, op->value / 2);
top_bits = cast(op->type, top_bits);

// Convert the bottom bit
Expr bottom_bit = cast(signed_type, op->value % 2);
bottom_bit = cast(op->type, bottom_bit);

// Recombine as floats
codegen(top_bits + top_bits + bottom_bit);
return;
}
#endif


CodeGen_Posix::visit(op);
}

Expand Down
113 changes: 101 additions & 12 deletions src/ScheduleFunctions.cpp
Expand Up @@ -818,23 +818,112 @@ string schedule_to_source(Function f,
if (compute_at.is_inline()) {
ss << ".compute_inline()";
} else {
string store_var_name = store_at.var;
string compute_var_name = compute_at.var;
if (store_var_name == Var::outermost().name()) {
store_var_name = "Var::outermost()";
}
if (compute_var_name == Var::outermost().name()) {
compute_var_name = "Var::outermost()";
}
if (!store_at.match(compute_at)) {
if (store_at.is_root()) {
ss << ".store_root()";
} else {
ss << ".store_at(" << store_at.func << ", " << store_at.var << ")";
ss << ".store_at(" << store_at.func << ", " << store_var_name << ")";
}
}
if (compute_at.is_root()) {
ss << ".compute_root()";
} else {
ss << ".compute_at(" << compute_at.func << ", " << compute_at.var << ")";
ss << ".compute_at(" << compute_at.func << ", " << compute_var_name << ")";
}
}
ss << ";";
return ss.str();
}

class StmtUsesFunc : public IRVisitor {
using IRVisitor::visit;
string func;
void visit(const Call *op) {
if (op->name == func) {
result = true;
}
IRVisitor::visit(op);
}
public:
bool result = false;
StmtUsesFunc(string f) : func(f) {}
};

class PrintUsesOfFunc : public IRVisitor {
using IRVisitor::visit;

int indent = 1;
string func, caller;
bool last_print_was_ellipsis = false;
std::ostream &stream;

void do_indent() {
for (int i = 0; i < indent; i++) {
stream << " ";
}
}

void visit(const For *op) {
if (ends_with(op->name, Var::outermost().name()) ||
ends_with(op->name, LoopLevel::root().var)) {
IRVisitor::visit(op);
} else {

int old_indent = indent;

StmtUsesFunc uses(func);
op->body.accept(&uses);
if (!uses.result) {
if (!last_print_was_ellipsis) {
do_indent();
stream << "...\n";
last_print_was_ellipsis = true;
}
} else {
do_indent();
stream << "for " << op->name << ":\n";
last_print_was_ellipsis = false;
indent++;
}

IRVisitor::visit(op);
indent = old_indent;
}
}

void visit(const ProducerConsumer *op) {
string old_caller = caller;
caller = op->name;
op->produce.accept(this);
if (op->update.defined()) {
op->update.accept(this);
}
caller = old_caller;
op->consume.accept(this);
}

void visit(const Call *op) {
if (op->name == func) {
do_indent();
stream << caller << " uses " << func << "\n";
last_print_was_ellipsis = false;
} else {
IRVisitor::visit(op);
}
}

public:
PrintUsesOfFunc(string f, std::ostream &s) : func(f), stream(s) {}
};

void validate_schedule(Function f, Stmt s, bool is_output) {

// If f is extern, check that none of its inputs are scheduled inline.
Expand All @@ -844,7 +933,7 @@ void validate_schedule(Function f, Stmt s, bool is_output) {
Function g(arg.func);
if (g.schedule().compute_level().is_inline()) {
user_error
<< "Function " << g.name() << " cannot be scheduled to be computed inline, "
<< "Func " << g.name() << " cannot be scheduled to be computed inline, "
<< "because it is used in the externally-computed function " << f.name() << "\n";
}
}
Expand Down Expand Up @@ -880,7 +969,7 @@ void validate_schedule(Function f, Stmt s, bool is_output) {
if (store_at.is_root() && compute_at.is_root()) {
return;
} else {
user_error << "Function " << f.name() << " is the output, so must"
user_error << "Func " << f.name() << " is the output, so must"
<< " be scheduled compute_root (which is the default).\n";
}
}
Expand Down Expand Up @@ -914,7 +1003,7 @@ void validate_schedule(Function f, Stmt s, bool is_output) {
if (store_at_ok && compute_at_ok) {
for (size_t i = store_idx + 1; i <= compute_idx; i++) {
if (sites[i].is_parallel) {
err << "Function \"" << f.name()
err << "Func \"" << f.name()
<< "\" is stored outside the parallel loop over "
<< sites[i].loop_level.func << "." << sites[i].loop_level.var
<< " but computed within it. This is a potential race condition.\n";
Expand All @@ -924,16 +1013,16 @@ void validate_schedule(Function f, Stmt s, bool is_output) {
}

if (!store_at_ok || !compute_at_ok) {
err << "Function \"" << f.name() << "\" is computed and stored in the following invalid location:\n"
<< schedule_to_source(f, store_at, compute_at) << "\n"
err << "Func \"" << f.name() << "\" is computed at the following invalid location:\n"
<< " " << schedule_to_source(f, store_at, compute_at) << "\n"
<< "Legal locations for this function are:\n";
for (size_t i = 0; i < sites.size(); i++) {
for (size_t j = i; j < sites.size(); j++) {
if (j > i && sites[j].is_parallel) break;
err << schedule_to_source(f, sites[i].loop_level, sites[j].loop_level) << "\n";

}
err << " " << schedule_to_source(f, sites[i].loop_level, sites[i].loop_level) << "\n";
}
err << "\"" << f.name() << "\" is used in the following places:\n";
PrintUsesOfFunc printer(f.name(), err);
s.accept(&printer);

user_error << err.str();
}
}
Expand Down
14 changes: 11 additions & 3 deletions test/error/bad_compute_at.cpp
Expand Up @@ -4,16 +4,24 @@
using namespace Halide;

int main(int argc, char **argv) {
Func f("f"), g("g"), h("h");
Func f("f"), g("g"), h("h"), junk1, junk2, junk3;
Var x("x"), y("y");

f(x) = x;
g(x) = f(x);
h(x, y) = g(x);
junk1(x) = 3;
junk2(x) = 3;
junk3(x, y) = 3;
h(x, y) = g(x) + f(x) + junk1(x) + junk2(x) + junk3(x, y);

g.compute_at(h, y);

// This makes no sense, because f is only used by g, which is computed at (h, y), which is outside of (h, x).
// Add some other junk functions to complicate the error message
junk1.compute_at(h, y);
junk2.compute_at(h, x);
junk3.compute_root();

// This makes no sense, because f is also used by g, which is computed at (h, y), which is outside of (h, x).
f.compute_at(h, x);

h.realize(10);
Expand Down
2 changes: 0 additions & 2 deletions test/error/float16_t_overflow_int_conv.cpp
Expand Up @@ -19,8 +19,6 @@ int main() {
// down to the largest representable value in half(65504). but should be
// representable in single precision
const int32_t largeNum = 65536;
h_assert(!std::isnan(largeNum), "largeNum should not be NaN");
h_assert(!std::isinf(largeNum), "largeNum should not be inf");

// This should fail as it triggers overflow
float16_t fail = float16_t::make_from_signed_int(largeNum, RoundingMode::ToNearestTiesToEven);
Expand Down

0 comments on commit 145e9c6

Please sign in to comment.