Skip to content

Commit 50f04c9

Browse files
committed
constrained FP ops: mismatch of rounding mode now yields poison
1 parent d954f8b commit 50f04c9

File tree

5 files changed

+53
-21
lines changed

5 files changed

+53
-21
lines changed

ir/attrs.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ smt::expr FpRoundingMode::toSMT() const {
221221
case FpRoundingMode::RTP: return expr::rtp();
222222
case FpRoundingMode::RTN: return expr::rtn();
223223
case FpRoundingMode::RTZ: return expr::rtz();
224+
case FpRoundingMode::Default: UNREACHABLE();
224225
}
225226
UNREACHABLE();
226227
}
@@ -234,6 +235,7 @@ ostream& operator<<(std::ostream &os, FpRoundingMode rounding) {
234235
case FpRoundingMode::RTP: str = "upward"; break;
235236
case FpRoundingMode::RTN: str = "downward"; break;
236237
case FpRoundingMode::RTZ: str = "towardzero"; break;
238+
case FpRoundingMode::Default: UNREACHABLE();
237239
}
238240
return os << str;
239241
}

ir/attrs.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,12 @@ struct FastMathFlags final {
9797

9898

9999
struct FpRoundingMode final {
100-
enum Mode { Dynamic, RNE, RNA, RTP, RTN, RTZ } mode;
101-
FpRoundingMode() : mode(RNE) {}
100+
enum Mode { RNE, RNA, RTP, RTN, RTZ, Dynamic, Default } mode;
101+
FpRoundingMode() : mode(Default) {}
102102
FpRoundingMode(Mode mode) : mode(mode) {}
103103
bool isDynamic() const { return mode == Dynamic; }
104+
bool isDefault() const { return mode == Default; }
105+
Mode getMode() const { return mode; }
104106
smt::expr toSMT() const;
105107
friend std::ostream& operator<<(std::ostream &os, FpRoundingMode rounding);
106108
};

ir/instr.cpp

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,9 @@ void FpBinOp::print(ostream &os) const {
598598
case FMinimum: str = "fminimum "; break;
599599
case CopySign: str = "copysign "; break;
600600
}
601-
os << getName() << " = " << str << fmath << *lhs << ", " << rhs->getName()
602-
<< ", rounding=" << rm;
601+
os << getName() << " = " << str << fmath << *lhs << ", " << rhs->getName();
602+
if (!rm.isDefault())
603+
os << ", rounding=" << rm;
603604
}
604605

605606
static expr any_fp_zero(State &s, const expr &v) {
@@ -701,25 +702,22 @@ static StateValue fm_poison(State &s, const expr &a, const expr &ap,
701702

702703
static StateValue round_value(const function<StateValue(FpRoundingMode)> &fn,
703704
const State &s, FpRoundingMode rm) {
704-
if (!rm.isDynamic())
705-
return fn(rm);
705+
if (rm.isDefault())
706+
return fn(FpRoundingMode::RNE);
706707

707708
auto &var = s.getFpRoundingMode();
709+
if (!rm.isDynamic()) {
710+
auto [v, np] = fn(rm);
711+
return { move(v), np && var == rm.getMode() };
712+
}
713+
708714
return StateValue::mkIf(var == FpRoundingMode::RNE, fn(FpRoundingMode::RNE),
709715
StateValue::mkIf(var == FpRoundingMode::RNA, fn(FpRoundingMode::RNA),
710716
StateValue::mkIf(var == FpRoundingMode::RTP, fn(FpRoundingMode::RTP),
711717
StateValue::mkIf(var == FpRoundingMode::RTN, fn(FpRoundingMode::RTN),
712718
fn(FpRoundingMode::RTZ)))));
713719
}
714720

715-
static expr get_fp_rounding(const State &s) {
716-
auto &var = s.getFpRoundingMode();
717-
return expr::mkIf(var == FpRoundingMode::RNE, expr::rne(),
718-
expr::mkIf(var == FpRoundingMode::RNA, expr::rna(),
719-
expr::mkIf(var == FpRoundingMode::RTP, expr::rtp(),
720-
expr::mkIf(var == FpRoundingMode::RTN, expr::rtn(), expr::rtz()))));
721-
}
722-
723721
StateValue FpBinOp::toSMT(State &s) const {
724722
function<StateValue(const expr&, const expr&, const expr&, const expr&,
725723
FpRoundingMode)> fn;
@@ -989,7 +987,9 @@ void FpUnaryOp::print(ostream &os) const {
989987
case Sqrt: str = "sqrt "; break;
990988
}
991989

992-
os << getName() << " = " << str << fmath << *val << ", rounding=" << rm;
990+
os << getName() << " = " << str << fmath << *val;
991+
if (!rm.isDefault())
992+
os << ", rounding=" << rm;
993993
}
994994

995995
StateValue FpUnaryOp::toSMT(State &s) const {
@@ -1260,8 +1260,9 @@ void FpTernaryOp::print(ostream &os) const {
12601260
case MulAdd: str = "fmuladd "; break;
12611261
}
12621262

1263-
os << getName() << " = " << str << fmath << *a << ", " << *b << ", " << *c
1264-
<< ", rounding=" << rm;
1263+
os << getName() << " = " << str << fmath << *a << ", " << *b << ", " << *c;
1264+
if (!rm.isDefault())
1265+
os << ", rounding=" << rm;
12651266
}
12661267

12671268
StateValue FpTernaryOp::toSMT(State &s) const {
@@ -1492,8 +1493,9 @@ void FpConversionOp::print(ostream &os) const {
14921493
case LRound: str = "lround "; break;
14931494
}
14941495

1495-
os << getName() << " = " << str << *val << print_type(getType(), " to ", "")
1496-
<< ", rounding=" << rm;
1496+
os << getName() << " = " << str << *val << print_type(getType(), " to ", "");
1497+
if (!rm.isDefault())
1498+
os << ", rounding=" << rm;
14971499
}
14981500

14991501
StateValue FpConversionOp::toSMT(State &s) const {
@@ -1516,14 +1518,14 @@ StateValue FpConversionOp::toSMT(State &s) const {
15161518
case FPToSInt:
15171519
case LRInt:
15181520
case LRound:
1519-
fn = [&](auto &val, auto &to_type, auto rm_) -> StateValue {
1521+
fn = [&](auto &val, auto &to_type, auto rm_in) -> StateValue {
15201522
expr rm;
15211523
switch (op) {
15221524
case FPToSInt:
15231525
rm = expr::rtz();
15241526
break;
15251527
case LRInt:
1526-
rm = get_fp_rounding(s);
1528+
rm = rm_in.toSMT();
15271529
break;
15281530
case LRound:
15291531
rm = expr::rna();
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
; ERROR: Target is more poisonous than source
2+
3+
define float @src(float noundef %a) {
4+
%x = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.upward", metadata !"fpexcept.strict")
5+
%y = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.upward", metadata !"fpexcept.strict")
6+
%ret = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.strict")
7+
ret float %ret
8+
}
9+
10+
define float @tgt(float noundef %a) {
11+
ret float poison
12+
}
13+
14+
declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata)

tests/alive-tv/fp/fadd3.srctgt.ll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
define float @src(float %a) {
2+
%x = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.upward", metadata !"fpexcept.strict")
3+
%y = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.downward", metadata !"fpexcept.strict")
4+
%ret = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.strict")
5+
ret float %ret
6+
}
7+
8+
define float @tgt(float %a) {
9+
ret float poison
10+
}
11+
12+
declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata)

0 commit comments

Comments
 (0)