add copysign
MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -596,6 +596,7 @@ void FpBinOp::print(ostream &os) const {
case FMin: str = "fmin "; break;
case FMaximum: str = "fmaximum "; break;
case FMinimum: str = "fminimum "; break;
+ case CopySign: str = "copysign "; break;
}
os << getName() << " = " << str << fmath << *lhs << ", " << rhs->getName()
<< ", rounding=" << rm;
@@ -806,6 +807,15 @@ StateValue FpBinOp::toSMT(State &s) const {
return fm_poison(s, a, ap, b, bp, v, fmath, false);
};
break;
+ case CopySign:
+ fn = [&](auto &a, auto &ap, auto &b, auto &bp, auto rm) -> StateValue {
+ return fm_poison(s, a, ap, b, bp,
+ [](expr &a, expr &b) {
+ return expr::mkIf(a.isFPNegative() == b.isFPNegative(),
+ a, a.fneg()); },
+ fmath, false);
+ };
+ break;
}
auto scalar = [&](auto &a, auto &ap, auto &b, auto &bp) {

MODIFY
ir/instr.h
ir/instr.h
@@ -58,7 +58,8 @@ public:
class FpBinOp final : public Instr {
public:
- enum Op { FAdd, FSub, FMul, FDiv, FRem, FMax, FMin, FMaximum, FMinimum };
+ enum Op { FAdd, FSub, FMul, FDiv, FRem, FMax, FMin, FMaximum, FMinimum,
+ CopySign };
private:
Value *lhs, *rhs;

MODIFY
llvm_util/known_fns.cpp
llvm_util/known_fns.cpp
@@ -190,6 +190,11 @@ known_call(llvm::CallInst &i, const llvm::TargetLibraryInfo &TLI,
RETURN_VAL(make_unique<FpUnaryOp>(*ty, value_name(i), *args[0],
FpUnaryOp::Trunc, parse_fmath(i)));
+ case llvm::LibFunc_copysign:
+ case llvm::LibFunc_copysignf:
+ RETURN_VAL(make_unique<FpBinOp>(*ty, value_name(i), *args[0], *args[1],
+ FpBinOp::CopySign, parse_fmath(i)));
+
case llvm::LibFunc_sqrt:
case llvm::LibFunc_sqrtf:
BB.addInstr(make_unique<Assume>(*args[0], Assume::WellDefined));

MODIFY
llvm_util/llvm2alive.cpp
llvm_util/llvm2alive.cpp
@@ -920,6 +920,7 @@ public:
make_unique<FpTernaryOp>(*ty, value_name(i), *a, *b, *c, op,
parse_fmath(i), parse_rounding(i)));
}
+ case llvm::Intrinsic::copysign:
case llvm::Intrinsic::minnum:
case llvm::Intrinsic::maxnum:
case llvm::Intrinsic::minimum:
@@ -936,6 +937,7 @@ public:
PARSE_BINOP();
FpBinOp::Op op;
switch (i.getIntrinsicID()) {
+ case llvm::Intrinsic::copysign: op = FpBinOp::CopySign; break;
case llvm::Intrinsic::minnum:
case llvm::Intrinsic::experimental_constrained_minnum: op = FpBinOp::FMin; break;
case llvm::Intrinsic::maxnum:

add copysign