diff --git a/llvm_util/llvm2alive.cpp b/llvm_util/llvm2alive.cpp index 549a2e73a..6e6ef42b1 100644 --- a/llvm_util/llvm2alive.cpp +++ b/llvm_util/llvm2alive.cpp @@ -1739,24 +1739,26 @@ class llvm2alive_ : public llvm::InstVisitor> { } } - static FPDenormalAttrs::Type parse_fp_denormal_str(string_view str) { - if (str == "dynamic") return FPDenormalAttrs::Dynamic; - if (str == "ieee") return FPDenormalAttrs::IEEE; - if (str == "preserve-sign") return FPDenormalAttrs::PreserveSign; - if (str == "positive-zero") return FPDenormalAttrs::PositiveZero; - UNREACHABLE(); + static FPDenormalAttrs::Type parse_fp_denormal(llvm::DenormalMode::DenormalModeKind mode) { + switch (mode) { + case llvm::DenormalMode::IEEE: + return FPDenormalAttrs::IEEE; + case llvm::DenormalMode::PositiveZero: + return FPDenormalAttrs::PositiveZero; + case llvm::DenormalMode::PreserveSign: + return FPDenormalAttrs::PreserveSign; + case llvm::DenormalMode::Dynamic: + return FPDenormalAttrs::Dynamic; + default: + UNREACHABLE(); + } } - static FPDenormalAttrs parse_fp_denormal(string_view str) { - FPDenormalAttrs attr; - auto comma = str.find(','); - if (comma == string_view::npos) { - attr.input = attr.output = parse_fp_denormal_str(str); - } else { - attr.output = parse_fp_denormal_str(string_view(str.data(), comma)); - attr.input = parse_fp_denormal_str(str.data() + comma + 1); - } - return attr; + static FPDenormalAttrs parse_fp_denormal(llvm::DenormalMode mode) { + return { + .input = parse_fp_denormal(mode.Input), + .output = parse_fp_denormal(mode.Output), + }; } static void handleFnAttrs(const llvm::AttributeSet &aset, FnAttrs &attrs) { @@ -1764,11 +1766,7 @@ class llvm2alive_ : public llvm::InstVisitor> { if (llvmattr.isStringAttribute()) { auto str = llvmattr.getKindAsString(); auto val = llvmattr.getValueAsString(); - if (str == "denormal-fp-math") { - attrs.setFPDenormal(parse_fp_denormal(val)); - } else if (str == "denormal-fp-math-f32") { - attrs.setFPDenormal(parse_fp_denormal(val), 32); - } else if (str == "alloc-family") { + if (str == "alloc-family") { attrs.allocfamily = val; } } @@ -1790,6 +1788,13 @@ class llvm2alive_ : public llvm::InstVisitor> { attrs.allocsize_1 = *args.second; break; } + case llvm::Attribute::DenormalFPEnv: { + auto fp_env = llvmattr.getDenormalFPEnv(); + attrs.setFPDenormal(parse_fp_denormal(fp_env.DefaultMode)); + if (fp_env.F32Mode != fp_env.DefaultMode) + attrs.setFPDenormal(parse_fp_denormal(fp_env.F32Mode), 32); + break; + } case llvm::Attribute::AllocKind: { auto kind = llvmattr.getAllocKind(); if ((kind & llvm::AllocFnKind::Alloc) != llvm::AllocFnKind::Unknown) diff --git a/tests/alive-tv/fp/denormal-attrs-mismatch.srctgt.ll b/tests/alive-tv/fp/denormal-attrs-mismatch.srctgt.ll new file mode 100644 index 000000000..34e1a9ec5 --- /dev/null +++ b/tests/alive-tv/fp/denormal-attrs-mismatch.srctgt.ll @@ -0,0 +1,9 @@ +; ERROR: Function attributes not refined + +define float @src(float %x) denormal_fpenv(positivezero) { + ret float %x +} + +define float @tgt(float %x) { + ret float %x +} diff --git a/tests/alive-tv/fp/denormal-ieee-default.srctgt.ll b/tests/alive-tv/fp/denormal-ieee-default.srctgt.ll new file mode 100644 index 000000000..1bf247737 --- /dev/null +++ b/tests/alive-tv/fp/denormal-ieee-default.srctgt.ll @@ -0,0 +1,9 @@ +; this transformation is OK since ieee is the default + +define float @src(float %x) denormal_fpenv(ieee) { + ret float %x +} + +define float @tgt(float %x) { + ret float %x +} diff --git a/tests/alive-tv/fp/fadd-denormal.srctgt.ll b/tests/alive-tv/fp/fadd-denormal.srctgt.ll index acc6f4a0a..cca8137ed 100644 --- a/tests/alive-tv/fp/fadd-denormal.srctgt.ll +++ b/tests/alive-tv/fp/fadd-denormal.srctgt.ll @@ -1,8 +1,8 @@ -define double @src() "denormal-fp-math"="positive-zero" { +define double @src() denormal_fpenv(positivezero) { %result = fadd double 0x8000000000000, 0.0 ret double %result } -define double @tgt() "denormal-fp-math"="positive-zero" { +define double @tgt() denormal_fpenv(positivezero) { ret double 0.0 } diff --git a/tests/alive-tv/fp/fdiv-denormal-f32-fold.srctgt.ll b/tests/alive-tv/fp/fdiv-denormal-f32-fold.srctgt.ll new file mode 100644 index 000000000..b9fb32ec0 --- /dev/null +++ b/tests/alive-tv/fp/fdiv-denormal-f32-fold.srctgt.ll @@ -0,0 +1,8 @@ +define float @src() denormal_fpenv(float: positivezero) { + %result = fdiv float 0x3810000000000000, 2.000000e+00 + ret float %result +} + +define float @tgt() denormal_fpenv(float: positivezero) { + ret float 0.0 +} diff --git a/tests/alive-tv/fp/fdiv-denormal-f32-no-fold-1.srctgt.ll b/tests/alive-tv/fp/fdiv-denormal-f32-no-fold-1.srctgt.ll new file mode 100644 index 000000000..f96e736bc --- /dev/null +++ b/tests/alive-tv/fp/fdiv-denormal-f32-no-fold-1.srctgt.ll @@ -0,0 +1,12 @@ +; ERROR: Value mismatch + +; the "float: ieee" here overrides the positivezero for the float type + +define float @src() denormal_fpenv(positivezero, float: ieee) { + %result = fdiv float 0x3810000000000000, 2.000000e+00 + ret float %result +} + +define float @tgt() denormal_fpenv(positivezero, float: ieee) { + ret float 0.0 +} diff --git a/tests/alive-tv/fp/fdiv-denormal-f32-no-fold-2.srctgt.ll b/tests/alive-tv/fp/fdiv-denormal-f32-no-fold-2.srctgt.ll new file mode 100644 index 000000000..902ada1db --- /dev/null +++ b/tests/alive-tv/fp/fdiv-denormal-f32-no-fold-2.srctgt.ll @@ -0,0 +1,12 @@ +; ERROR: Value mismatch + +; the float attribute should not apply to doubles + +define double @src() denormal_fpenv(float: positivezero) { + %result = fdiv double 0x3810000000000000, 2.000000e+00 + ret double %result +} + +define double @tgt() denormal_fpenv(float: positivezero) { + ret double 0.0 +} diff --git a/tests/alive-tv/fp/fdiv-denormal-fpenv.srctgt.ll b/tests/alive-tv/fp/fdiv-denormal-fpenv.srctgt.ll new file mode 100644 index 000000000..19f5ee663 --- /dev/null +++ b/tests/alive-tv/fp/fdiv-denormal-fpenv.srctgt.ll @@ -0,0 +1,8 @@ +define float @src() denormal_fpenv(positivezero|ieee) { + %result = fdiv float 0x3810000000000000, -2.000000e+00 + ret float %result +} + +define float @tgt() denormal_fpenv(positivezero|ieee) { + ret float 0.0 +} diff --git a/tests/alive-tv/fp/fneg-denormal.srctgt.ll b/tests/alive-tv/fp/fneg-denormal.srctgt.ll index d44f3f332..7584b109f 100644 --- a/tests/alive-tv/fp/fneg-denormal.srctgt.ll +++ b/tests/alive-tv/fp/fneg-denormal.srctgt.ll @@ -1,8 +1,8 @@ -define double @src() "denormal-fp-math"="positive-zero" { +define double @src() denormal_fpenv(positivezero) { %result = fneg double 0x8000000000000 ret double %result } -define double @tgt() "denormal-fp-math"="positive-zero" { +define double @tgt() denormal_fpenv(positivezero) { ret double 0x8008000000000000 } diff --git a/tests/alive-tv/params/fn-refinement.srctgt.ll b/tests/alive-tv/params/fn-refinement.srctgt.ll index 64066ab90..fe131ff3c 100644 --- a/tests/alive-tv/params/fn-refinement.srctgt.ll +++ b/tests/alive-tv/params/fn-refinement.srctgt.ll @@ -1,10 +1,10 @@ -define double @src() "denormal-fp-math"="positive-zero" { +; ERROR: Function attributes not refined + +define double @src() denormal_fpenv(positivezero) { %result = fadd double 0x8000000000000, 0.0 ret double %result } -define double @tgt() "denormal-fp-math"="ieee" { +define double @tgt() denormal_fpenv(ieee) { ret double 0.0 } - -; ERROR: Function attributes not refined