llvm-reduce: Don't remove strictfp
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Tue, 3 Jan 2023 13:00:03 +0000 (08:00 -0500)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Tue, 3 Jan 2023 20:57:58 +0000 (15:57 -0500)
The verifier should fail if constrained intrinsics are used in
functions with strictfp, but that patch hasn't been pushed yet.

Ideally we would be able to analyze the function body to see if any
constrained intrinsics were used, but we seem to be missing a utility
function to check for any constrained ops.

llvm/test/tools/llvm-reduce/remove-attributes-strictfp.ll [new file with mode: 0644]
llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp

diff --git a/llvm/test/tools/llvm-reduce/remove-attributes-strictfp.ll b/llvm/test/tools/llvm-reduce/remove-attributes-strictfp.ll
new file mode 100644 (file)
index 0000000..8607aae
--- /dev/null
@@ -0,0 +1,48 @@
+; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=attributes --test FileCheck --test-arg %s --test-arg --input-file %s -o %t
+; RUN: FileCheck --check-prefixes=CHECK,RESULT %s < %t
+
+; Test that invalid reductions aren't produced on strictfp functions.
+
+; CHECK-LABEL: define float @strictfp_intrinsic(float %x, float %y)
+; RESULT-SAME: [[STRICTFP_ONLY:#[0-9]+]] {
+define float @strictfp_intrinsic(float %x, float %y) #0 {
+  %val = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict")
+  ret float %val
+}
+
+; CHECK-LABEL: define float @strictfp_callsite(float %x, float %y)
+; RESULT-SAME: [[STRICTFP_ONLY]] {
+; RESULT: call float @extern.func(float %x, float %y) [[STRICTFP_ONLY]]
+define float @strictfp_callsite(float %x, float %y) #0 {
+  %val = call float @extern.func(float %x, float %y) #0
+  ret float %val
+}
+
+; CHECK-LABEL: define float @strictfp_declaration(float %x, float %y)
+; RESULT-SAME: [[STRICTFP_ONLY]] {
+define float @strictfp_declaration(float %x, float %y) #0 {
+  %val = call float @strict.extern.func(float %x, float %y)
+  ret float %val
+}
+
+; CHECK-LABEL: define float @strictfp_no_constrained_ops(float %x, float %y)
+; RESULT-SAME: [[STRICTFP_ONLY]] {
+define float @strictfp_no_constrained_ops(float %x, float %y) #0 {
+  %val = call float @llvm.copysign.f32(float %x, float %y)
+  ret float %val
+}
+
+; CHECK-LABEL: declare float @strict.extern.func(float, float)
+; RESULT-SAME: [[STRICTFP_ONLY]]{{$}}
+declare float @strict.extern.func(float, float) #0
+
+declare float @extern.func(float, float)
+
+declare float @llvm.copysign.f32(float, float) #1
+declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) #2
+
+; RESULT: attributes [[STRICTFP_ONLY]] = { strictfp }
+
+attributes #0 = { nounwind strictfp }
+attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) }
index 5650367..0bd16ff 100644 (file)
@@ -119,6 +119,13 @@ public:
 
         if (RemoveNoInline && Kind == Attribute::OptimizeNone)
           continue;
+
+        // TODO: Could only remove this if there are no constrained calls in the
+        // function.
+        if (Kind == Attribute::StrictFP) {
+          AttrsToPreserve.emplace_back(A);
+          continue;
+        }
       }
 
       if (O.shouldKeep())