From d6e69c437d0f1f5377d9074af3b42bc2502d2ea0 Mon Sep 17 00:00:00 2001 From: John Regehr Date: Tue, 21 Apr 2026 20:14:45 -0600 Subject: [PATCH 1/2] support new first-class denormal attributes --- llvm_util/llvm2alive.cpp | 29 +++++++++++++++++++ .../fp/denormal-attrs-mismatch.srctgt.ll | 9 ++++++ .../fp/denormal-ieee-default.srctgt.ll | 9 ++++++ .../fp/fadd-denormal-old-attr.srctgt.ll | 8 +++++ tests/alive-tv/fp/fadd-denormal.srctgt.ll | 4 +-- .../fp/fdiv-denormal-f32-fold.srctgt.ll | 8 +++++ .../fp/fdiv-denormal-f32-no-fold-1.srctgt.ll | 12 ++++++++ .../fp/fdiv-denormal-f32-no-fold-2.srctgt.ll | 12 ++++++++ .../alive-tv/fp/fdiv-denormal-fpenv.srctgt.ll | 8 +++++ .../fp/fneg-denormal-old-attr.srctgt.ll | 8 +++++ tests/alive-tv/fp/fneg-denormal.srctgt.ll | 4 +-- .../params/fn-refinement-old-attr.srctgt.ll | 10 +++++++ tests/alive-tv/params/fn-refinement.srctgt.ll | 8 ++--- 13 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 tests/alive-tv/fp/denormal-attrs-mismatch.srctgt.ll create mode 100644 tests/alive-tv/fp/denormal-ieee-default.srctgt.ll create mode 100644 tests/alive-tv/fp/fadd-denormal-old-attr.srctgt.ll create mode 100644 tests/alive-tv/fp/fdiv-denormal-f32-fold.srctgt.ll create mode 100644 tests/alive-tv/fp/fdiv-denormal-f32-no-fold-1.srctgt.ll create mode 100644 tests/alive-tv/fp/fdiv-denormal-f32-no-fold-2.srctgt.ll create mode 100644 tests/alive-tv/fp/fdiv-denormal-fpenv.srctgt.ll create mode 100644 tests/alive-tv/fp/fneg-denormal-old-attr.srctgt.ll create mode 100644 tests/alive-tv/params/fn-refinement-old-attr.srctgt.ll diff --git a/llvm_util/llvm2alive.cpp b/llvm_util/llvm2alive.cpp index 549a2e73a..ec89c99da 100644 --- a/llvm_util/llvm2alive.cpp +++ b/llvm_util/llvm2alive.cpp @@ -1759,6 +1759,28 @@ class llvm2alive_ : public llvm::InstVisitor> { return attr; } + 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(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) { for (const llvm::Attribute &llvmattr : aset) { if (llvmattr.isStringAttribute()) { @@ -1790,6 +1812,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-old-attr.srctgt.ll b/tests/alive-tv/fp/fadd-denormal-old-attr.srctgt.ll new file mode 100644 index 000000000..acc6f4a0a --- /dev/null +++ b/tests/alive-tv/fp/fadd-denormal-old-attr.srctgt.ll @@ -0,0 +1,8 @@ +define double @src() "denormal-fp-math"="positive-zero" { + %result = fadd double 0x8000000000000, 0.0 + ret double %result +} + +define double @tgt() "denormal-fp-math"="positive-zero" { + ret double 0.0 +} 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-old-attr.srctgt.ll b/tests/alive-tv/fp/fneg-denormal-old-attr.srctgt.ll new file mode 100644 index 000000000..d44f3f332 --- /dev/null +++ b/tests/alive-tv/fp/fneg-denormal-old-attr.srctgt.ll @@ -0,0 +1,8 @@ +define double @src() "denormal-fp-math"="positive-zero" { + %result = fneg double 0x8000000000000 + ret double %result +} + +define double @tgt() "denormal-fp-math"="positive-zero" { + ret double 0x8008000000000000 +} 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-old-attr.srctgt.ll b/tests/alive-tv/params/fn-refinement-old-attr.srctgt.ll new file mode 100644 index 000000000..64066ab90 --- /dev/null +++ b/tests/alive-tv/params/fn-refinement-old-attr.srctgt.ll @@ -0,0 +1,10 @@ +define double @src() "denormal-fp-math"="positive-zero" { + %result = fadd double 0x8000000000000, 0.0 + ret double %result +} + +define double @tgt() "denormal-fp-math"="ieee" { + ret double 0.0 +} + +; ERROR: Function attributes not refined 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 From cec4d3a10a45fa509ed9ae22129300ab942316f0 Mon Sep 17 00:00:00 2001 From: John Regehr Date: Fri, 24 Apr 2026 08:25:59 -0600 Subject: [PATCH 2/2] remove code for parsing denormal attributes as string --- llvm_util/llvm2alive.cpp | 26 +------------------ .../fp/fadd-denormal-old-attr.srctgt.ll | 8 ------ .../fp/fneg-denormal-old-attr.srctgt.ll | 8 ------ .../params/fn-refinement-old-attr.srctgt.ll | 10 ------- 4 files changed, 1 insertion(+), 51 deletions(-) delete mode 100644 tests/alive-tv/fp/fadd-denormal-old-attr.srctgt.ll delete mode 100644 tests/alive-tv/fp/fneg-denormal-old-attr.srctgt.ll delete mode 100644 tests/alive-tv/params/fn-refinement-old-attr.srctgt.ll diff --git a/llvm_util/llvm2alive.cpp b/llvm_util/llvm2alive.cpp index ec89c99da..6e6ef42b1 100644 --- a/llvm_util/llvm2alive.cpp +++ b/llvm_util/llvm2alive.cpp @@ -1739,26 +1739,6 @@ 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 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::Type parse_fp_denormal(llvm::DenormalMode::DenormalModeKind mode) { switch (mode) { case llvm::DenormalMode::IEEE: @@ -1786,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; } } diff --git a/tests/alive-tv/fp/fadd-denormal-old-attr.srctgt.ll b/tests/alive-tv/fp/fadd-denormal-old-attr.srctgt.ll deleted file mode 100644 index acc6f4a0a..000000000 --- a/tests/alive-tv/fp/fadd-denormal-old-attr.srctgt.ll +++ /dev/null @@ -1,8 +0,0 @@ -define double @src() "denormal-fp-math"="positive-zero" { - %result = fadd double 0x8000000000000, 0.0 - ret double %result -} - -define double @tgt() "denormal-fp-math"="positive-zero" { - ret double 0.0 -} diff --git a/tests/alive-tv/fp/fneg-denormal-old-attr.srctgt.ll b/tests/alive-tv/fp/fneg-denormal-old-attr.srctgt.ll deleted file mode 100644 index d44f3f332..000000000 --- a/tests/alive-tv/fp/fneg-denormal-old-attr.srctgt.ll +++ /dev/null @@ -1,8 +0,0 @@ -define double @src() "denormal-fp-math"="positive-zero" { - %result = fneg double 0x8000000000000 - ret double %result -} - -define double @tgt() "denormal-fp-math"="positive-zero" { - ret double 0x8008000000000000 -} diff --git a/tests/alive-tv/params/fn-refinement-old-attr.srctgt.ll b/tests/alive-tv/params/fn-refinement-old-attr.srctgt.ll deleted file mode 100644 index 64066ab90..000000000 --- a/tests/alive-tv/params/fn-refinement-old-attr.srctgt.ll +++ /dev/null @@ -1,10 +0,0 @@ -define double @src() "denormal-fp-math"="positive-zero" { - %result = fadd double 0x8000000000000, 0.0 - ret double %result -} - -define double @tgt() "denormal-fp-math"="ieee" { - ret double 0.0 -} - -; ERROR: Function attributes not refined