hgt312
September 19, 2019, 3:46am
1
As title.
Firstly, I want use call_pure_extern
, but isnan
is related to platform when using LLVM (depends on libc).
Float32
Float64
Win
_isnanf
_isnan/isnan
OSX
__isnanf
__isnand/isnan
Linux
isnanf
isnan
Then I want to use x!=x
to check if a float number is NaN.
However, there are 2 problems.
An expression like a = (b != b)
will be rewrite to a = 0
.
In LLVM codegen, fcmp use one
but not une
, so that it cannot be used to check NaN.
hgt312:
one
Compared with call libc function, I prefer we use unordered
flag of LLVM. However, I can not be sure what is the performance cost it will introduce into. We should benchmark it. If there is performance downgrade, we should provide one flag and keep ordered
flag of LLVM be default.
hgt312
September 19, 2019, 6:04am
3
Is there a flag or function call to disable rewriting?
I don’t fully understand what is the meaning of disable rewriting. If you ask the flag of LLVM, for NE, should be here:
return builder_->CreateFCmpOEQ(a, b);
}
}
llvm::Value* CodeGenLLVM::VisitExpr_(const NE* op) {
llvm::Value* a = MakeValue(op->a);
llvm::Value* b = MakeValue(op->b);
if (op->a.type().is_int() || op->a.type().is_uint()) {
return builder_->CreateICmpNE(a, b);
} else {
return builder_->CreateFCmpONE(a, b);
}
}
llvm::Value* CodeGenLLVM::VisitExpr_(const And* op) {
return builder_->CreateAnd(MakeValue(op->a), MakeValue(op->b));
}
llvm::Value* CodeGenLLVM::VisitExpr_(const Or* op) {
return builder_->CreateOr(MakeValue(op->a), MakeValue(op->b));
}
You could try it and decide what to do next.
hgt312
September 19, 2019, 7:45am
5
I have tried to change this to UNE
, however, I cannot get expected result.
if (is_one(op->condition)) {
return op->then_case;
}
return res;
}
Expr Mutate_(const NE* op, const Expr& e) final {
// eager check NE for device check
Expr res = IRMutator::Mutate_(op, e);
op = res.as<NE>();
if (ir::Equal(op->a, op->b)) {
return make_const(op->type, false);
}
return res;
}
Expr Mutate_(const Variable* op, const Expr& e) final {
if (op == var_) {
return make_const(op->type, device_type_);
} else {
return e;
In the built C code, it assigns a const 0.
FrozenGene:
CreateFCmpO
You could debug why it doesn’t work.
Maybe you could print the fast math flags of builder_.
builder_->getFastMathFlags()
I suspect we set it in somewhere be NoNan or fast LLVM Language Reference Manual — LLVM 21.0.0git documentation