stub support for FP exceptions (WIP)
MODIFY
ir/attrs.cpp
ir/attrs.cpp
@@ -240,4 +240,14 @@ ostream& operator<<(std::ostream &os, FpRoundingMode rounding) {
return os << str;
}
+ostream& operator<<(std::ostream &os, FpExceptionMode ex) {
+ const char *str;
+ switch (ex.mode) {
+ case FpExceptionMode::Ignore: str = "ignore"; break;
+ case FpExceptionMode::MayTrap: str = "maytrap"; break;
+ case FpExceptionMode::Strict: str = "strict"; break;
+ }
+ return os << str;
+}
+
}

MODIFY
ir/attrs.h
ir/attrs.h
@@ -107,4 +107,13 @@ struct FpRoundingMode final {
friend std::ostream& operator<<(std::ostream &os, FpRoundingMode rounding);
};
+
+struct FpExceptionMode final {
+ enum Mode { Ignore, MayTrap, Strict } mode;
+ FpExceptionMode() : mode(Ignore) {}
+ FpExceptionMode(Mode mode) : mode(mode) {}
+ Mode getMode() const { return mode; }
+ friend std::ostream& operator<<(std::ostream &os, FpExceptionMode ex);
+};
+
}

MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -601,6 +601,7 @@ void FpBinOp::print(ostream &os) const {
os << getName() << " = " << str << fmath << *lhs << ", " << rhs->getName();
if (!rm.isDefault())
os << ", rounding=" << rm;
+ os << ", exceptions=" << ex;
}
static expr any_fp_zero(State &s, const expr &v) {
@@ -990,6 +991,7 @@ void FpUnaryOp::print(ostream &os) const {
os << getName() << " = " << str << fmath << *val;
if (!rm.isDefault())
os << ", rounding=" << rm;
+ os << ", exceptions=" << ex;
}
StateValue FpUnaryOp::toSMT(State &s) const {
@@ -1263,6 +1265,7 @@ void FpTernaryOp::print(ostream &os) const {
os << getName() << " = " << str << fmath << *a << ", " << *b << ", " << *c;
if (!rm.isDefault())
os << ", rounding=" << rm;
+ os << ", exceptions=" << ex;
}
StateValue FpTernaryOp::toSMT(State &s) const {
@@ -1496,6 +1499,7 @@ void FpConversionOp::print(ostream &os) const {
os << getName() << " = " << str << *val << print_type(getType(), " to ", "");
if (!rm.isDefault())
os << ", rounding=" << rm;
+ os << ", exceptions=" << ex;
}
StateValue FpConversionOp::toSMT(State &s) const {

MODIFY
ir/instr.h
ir/instr.h
@@ -66,12 +66,13 @@ private:
Op op;
FastMathFlags fmath;
FpRoundingMode rm;
+ FpExceptionMode ex;
public:
FpBinOp(Type &type, std::string &&name, Value &lhs, Value &rhs, Op op,
- FastMathFlags fmath, FpRoundingMode rm = {})
+ FastMathFlags fmath, FpRoundingMode rm = {}, FpExceptionMode ex = {})
: Instr(type, std::move(name)), lhs(&lhs), rhs(&rhs), op(op), fmath(fmath),
- rm(rm) {}
+ rm(rm), ex(ex) {}
std::vector<Value*> operands() const override;
bool propagatesPoison() const override;
@@ -120,11 +121,14 @@ private:
Op op;
FastMathFlags fmath;
FpRoundingMode rm;
+ FpExceptionMode ex;
public:
FpUnaryOp(Type &type, std::string &&name, Value &val, Op op,
- FastMathFlags fmath, FpRoundingMode rm = {})
- : Instr(type, std::move(name)), val(&val), op(op), fmath(fmath), rm(rm) {}
+ FastMathFlags fmath, FpRoundingMode rm = {},
+ FpExceptionMode ex = {})
+ : Instr(type, std::move(name)), val(&val), op(op), fmath(fmath), rm(rm),
+ ex(ex) {}
std::vector<Value*> operands() const override;
bool propagatesPoison() const override;
@@ -193,12 +197,14 @@ private:
Op op;
FastMathFlags fmath;
FpRoundingMode rm;
+ FpExceptionMode ex;
public:
FpTernaryOp(Type &type, std::string &&name, Value &a, Value &b, Value &c,
- Op op, FastMathFlags fmath, FpRoundingMode rm = {})
+ Op op, FastMathFlags fmath, FpRoundingMode rm = {},
+ FpExceptionMode ex = {})
: Instr(type, std::move(name)), a(&a), b(&b), c(&c), op(op), fmath(fmath),
- rm(rm) {}
+ rm(rm), ex(ex) {}
std::vector<Value*> operands() const override;
bool propagatesPoison() const override;
@@ -243,11 +249,12 @@ private:
Value *val;
Op op;
FpRoundingMode rm;
+ FpExceptionMode ex;
public:
FpConversionOp(Type &type, std::string &&name, Value &val, Op op,
- FpRoundingMode rm = {})
- : Instr(type, std::move(name)), val(&val), op(op), rm(rm) {}
+ FpRoundingMode rm = {}, FpExceptionMode ex = {})
+ : Instr(type, std::move(name)), val(&val), op(op), rm(rm), ex(ex) {}
std::vector<Value*> operands() const override;
bool propagatesPoison() const override;

MODIFY
llvm_util/llvm2alive.cpp
llvm_util/llvm2alive.cpp
@@ -43,6 +43,18 @@ FpRoundingMode parse_rounding(llvm::Instruction &i) {
}
}
+FpExceptionMode parse_exceptions(llvm::Instruction &i) {
+ auto *fp = dyn_cast<llvm::ConstrainedFPIntrinsic>(&i);
+ if (!fp || !fp->getExceptionBehavior().hasValue())
+ return {};
+ switch (fp->getExceptionBehavior().getValue()) {
+ case llvm::fp::ebIgnore: return FpExceptionMode::Ignore;
+ case llvm::fp::ebMayTrap: return FpExceptionMode::MayTrap;
+ case llvm::fp::ebStrict: return FpExceptionMode::Strict;
+ default: UNREACHABLE();
+ }
+}
+
unsigned constexpr_idx;
unsigned copy_idx;
unsigned alignopbundle_idx;
@@ -918,7 +930,8 @@ public:
}
RETURN_IDENTIFIER(
make_unique<FpTernaryOp>(*ty, value_name(i), *a, *b, *c, op,
- parse_fmath(i), parse_rounding(i)));
+ parse_fmath(i), parse_rounding(i),
+ parse_exceptions(i)));
}
case llvm::Intrinsic::copysign:
case llvm::Intrinsic::minnum:
@@ -952,10 +965,9 @@ public:
case llvm::Intrinsic::experimental_constrained_fdiv: op = FpBinOp::FDiv; break;
default: UNREACHABLE();
}
- // TODO: missing support for exceptions
RETURN_IDENTIFIER(
make_unique<FpBinOp>(*ty, value_name(i), *a, *b, op, parse_fmath(i),
- parse_rounding(i)));
+ parse_rounding(i), parse_exceptions(i)));
}
case llvm::Intrinsic::fabs:
case llvm::Intrinsic::ceil:
@@ -997,10 +1009,9 @@ public:
case llvm::Intrinsic::experimental_constrained_trunc: op = FpUnaryOp::Trunc; break;
default: UNREACHABLE();
}
- // TODO: missing support for exceptions
RETURN_IDENTIFIER(
make_unique<FpUnaryOp>(*ty, value_name(i), *val, op, parse_fmath(i),
- parse_rounding(i)));
+ parse_rounding(i), parse_exceptions(i)));
}
case llvm::Intrinsic::experimental_constrained_sitofp:
case llvm::Intrinsic::experimental_constrained_uitofp:
@@ -1037,9 +1048,9 @@ public:
default:
return error(i);
}
- // TODO: missing support for exceptions
RETURN_IDENTIFIER(make_unique<FpConversionOp>(*ty, value_name(i), *val,
- op, parse_rounding(i)));
+ op, parse_rounding(i),
+ parse_exceptions(i)));
}
case llvm::Intrinsic::lifetime_start:
case llvm::Intrinsic::lifetime_end:

MODIFY
tests/alive-tv/fp/fadd3-fail.srctgt.ll
tests/alive-tv/fp/fadd3-fail.srctgt.ll
; ERROR: Target is more poisonous than source
define float @src(float noundef %a) {
- %x = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.upward", metadata !"fpexcept.strict")
- %y = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.upward", metadata !"fpexcept.strict")
- %ret = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ %x = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.upward", metadata !"fpexcept.ignore")
+ %y = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.upward", metadata !"fpexcept.ignore")
+ %ret = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore")
ret float %ret
}

MODIFY
tests/alive-tv/fp/fadd3.srctgt.ll
tests/alive-tv/fp/fadd3.srctgt.ll
define float @src(float %a) {
- %x = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.upward", metadata !"fpexcept.strict")
- %y = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.downward", metadata !"fpexcept.strict")
- %ret = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ %x = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.upward", metadata !"fpexcept.ignore")
+ %y = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.downward", metadata !"fpexcept.ignore")
+ %ret = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore")
ret float %ret
}

stub support for FP exceptions (WIP)