Always emit error for wrong interfaces to scalable vectors, unless cmdline flag is...
authorSander de Smalen <sander.desmalen@arm.com>
Wed, 17 Mar 2021 21:35:09 +0000 (21:35 +0000)
committerSander de Smalen <sander.desmalen@arm.com>
Fri, 2 Apr 2021 09:55:22 +0000 (10:55 +0100)
In order to bring up scalable vector support in LLVM incrementally,
we introduced behaviour to emit a warning, instead of an error, when
asking the wrong question of a scalable vector, like asking for the
fixed number of elements.

This patch puts that behaviour under a flag. The default behaviour is
that the compiler will always error, which means that all LLVM unit
tests and regression tests will now fail when a code-path is taken that
still uses the wrong interface.

The behaviour to demote an error to a warning can be individually enabled
for tools that want to support experimental use of scalable vectors.
This patch enables that behaviour when driving compilation from Clang.
This means that for users who want to try out scalable-vector support,
fixed-width codegen support, or build user-code with scalable vector
intrinsics, Clang will not crash and burn when the compiler encounters
such a case.

This allows us to do away with the following pattern in many of the SVE tests:
  RUN: .... 2>%t
  RUN: cat %t | FileCheck --check-prefix=WARN
  WARN-NOT: warning: ...

The behaviour to emit warnings is only temporary and we expect this flag
to be removed in the future when scalable vector support is more stable.

This patch also has fixes the following tests:
 unittests:
   ScalableVectorMVTsTest.SizeQueries
   SelectionDAGAddressAnalysisTest.unknownSizeFrameObjects
   AArch64SelectionDAGTest.computeKnownBitsSVE_ZERO_EXTEND_VECTOR_INREG

 regression tests:
   Transforms/InstCombine/vscale_gep.ll

Reviewed By: paulwalker-arm, ctetreau

Differential Revision: https://reviews.llvm.org/D98856

clang/lib/Driver/ToolChains/Clang.cpp
llvm/include/llvm/CodeGen/ValueTypes.h
llvm/include/llvm/Support/TypeSize.h
llvm/lib/Analysis/InstructionSimplify.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
llvm/lib/Support/CMakeLists.txt
llvm/lib/Support/TypeSize.cpp [new file with mode: 0644]
llvm/unittests/CodeGen/ScalableVectorMVTsTest.cpp

index 30a0b09..3d5cdb3 100644 (file)
@@ -5051,6 +5051,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   RenderTargetOptions(Triple, Args, KernelOrKext, CmdArgs);
 
+  // FIXME: For now we want to demote any errors to warnings, when they have
+  // been raised for asking the wrong question of scalable vectors, such as
+  // asking for the fixed number of elements. This may happen because code that
+  // is not yet ported to work for scalable vectors uses the wrong interfaces,
+  // whereas the behaviour is actually correct. Emitting a warning helps bring
+  // up scalable vector support in an incremental way. When scalable vector
+  // support is stable enough, all uses of wrong interfaces should be considered
+  // as errors, but until then, we can live with a warning being emitted by the
+  // compiler. This way, Clang can be used to compile code with scalable vectors
+  // and identify possible issues.
+  if (isa<BackendJobAction>(JA)) {
+    CmdArgs.push_back("-mllvm");
+    CmdArgs.push_back("-treat-scalable-fixed-error-as-warning");
+  }
+
   // These two are potentially updated by AddClangCLArgs.
   codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;
   bool EmitCodeView = false;
index ccdaab5..e7346f7 100644 (file)
@@ -299,19 +299,16 @@ namespace llvm {
 
     /// Given a vector type, return the number of elements it contains.
     unsigned getVectorNumElements() const {
-#ifdef STRICT_FIXED_SIZE_VECTORS
-      assert(isFixedLengthVector() && "Invalid vector type!");
-#else
       assert(isVector() && "Invalid vector type!");
+
       if (isScalableVector())
-        WithColor::warning()
-            << "Possible incorrect use of EVT::getVectorNumElements() for "
-               "scalable vector. Scalable flag may be dropped, use "
-               "EVT::getVectorElementCount() instead\n";
-#endif
-      if (isSimple())
-        return V.getVectorNumElements();
-      return getExtendedVectorNumElements();
+        llvm::reportInvalidSizeRequest(
+            "Possible incorrect use of EVT::getVectorNumElements() for "
+            "scalable vector. Scalable flag may be dropped, use "
+            "EVT::getVectorElementCount() instead");
+
+      return isSimple() ? V.getVectorNumElements()
+                        : getExtendedVectorNumElements();
     }
 
     // Given a (possibly scalable) vector type, return the ElementCount
index 7258969..30bbbd7 100644 (file)
 
 namespace llvm {
 
+/// Reports a diagnostic message to indicate an invalid size request has been
+/// done on a scalable vector. This function may not return.
+void reportInvalidSizeRequest(const char *Msg);
+
 template <typename LeafTy> struct LinearPolyBaseTypeTraits {};
 
 //===----------------------------------------------------------------------===//
@@ -446,17 +450,7 @@ public:
   //     else
   //       bail out early for scalable vectors and use getFixedValue()
   //   }
-  operator ScalarTy() const {
-#ifdef STRICT_FIXED_SIZE_VECTORS
-    return getFixedValue();
-#else
-    if (isScalable())
-      WithColor::warning() << "Compiler has made implicit assumption that "
-                              "TypeSize is not scalable. This may or may not "
-                              "lead to broken code.\n";
-    return getKnownMinValue();
-#endif
-  }
+  operator ScalarTy() const;
 
   // Additional operators needed to avoid ambiguous parses
   // because of the implicit conversion hack.
index 80c2a63..23bb5e6 100644 (file)
@@ -4332,7 +4332,10 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
   if (Q.isUndefValue(Ops[0]))
     return UndefValue::get(GEPTy);
 
-  bool IsScalableVec = isa<ScalableVectorType>(SrcTy);
+  bool IsScalableVec =
+      isa<ScalableVectorType>(SrcTy) || any_of(Ops, [](const Value *V) {
+        return isa<ScalableVectorType>(V->getType());
+      });
 
   if (Ops.size() == 2) {
     // getelementptr P, 0 -> P.
index a60610d..943e06e 100644 (file)
@@ -4847,8 +4847,8 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     assert(VT.isVector() && "This DAG node is restricted to vector types.");
     assert(Operand.getValueType().bitsLE(VT) &&
            "The input must be the same size or smaller than the result.");
-    assert(VT.getVectorNumElements() <
-             Operand.getValueType().getVectorNumElements() &&
+    assert(VT.getVectorMinNumElements() <
+               Operand.getValueType().getVectorMinNumElements() &&
            "The destination vector type must have fewer lanes than the input.");
     break;
   case ISD::ABS:
index 33caf58..ddacb4f 100644 (file)
@@ -185,6 +185,7 @@ add_llvm_component_library(LLVMSupport
   TrigramIndex.cpp
   Triple.cpp
   Twine.cpp
+  TypeSize.cpp
   Unicode.cpp
   UnicodeCaseFold.cpp
   VersionTuple.cpp
diff --git a/llvm/lib/Support/TypeSize.cpp b/llvm/lib/Support/TypeSize.cpp
new file mode 100644 (file)
index 0000000..83d40d9
--- /dev/null
@@ -0,0 +1,41 @@
+//===- TypeSize.cpp - Wrapper around type sizes------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/TypeSize.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+
+/// The ScalableErrorAsWarning is a temporary measure to suppress errors from
+/// using the wrong interface on a scalable vector.
+cl::opt<bool> ScalableErrorAsWarning(
+    "treat-scalable-fixed-error-as-warning", cl::Hidden, cl::init(false),
+    cl::desc("Treat issues where a fixed-width property is requested from a "
+             "scalable type as a warning, instead of an error."),
+    cl::ZeroOrMore);
+
+void llvm::reportInvalidSizeRequest(const char *Msg) {
+#ifndef STRICT_FIXED_SIZE_VECTORS
+  if (ScalableErrorAsWarning) {
+    WithColor::warning() << "Invalid size request on a scalable vector; " << Msg
+                         << "\n";
+    return;
+  }
+#endif
+  report_fatal_error("Invalid size request on a scalable vector.");
+}
+
+TypeSize::operator TypeSize::ScalarTy() const {
+  if (isScalable()) {
+    reportInvalidSizeRequest(
+        "Cannot implicitly convert a scalable size to a fixed-width size in "
+        "`TypeSize::operator ScalarTy()`");
+    return getKnownMinValue();
+  }
+  return getFixedValue();
+}
index 566b2e7..e38d104 100644 (file)
@@ -180,7 +180,8 @@ TEST(ScalableVectorMVTsTest, SizeQueries) {
   // Check convenience size scaling methods.
   EXPECT_EQ(v2i32.getSizeInBits() * 2, v4i32.getSizeInBits());
   EXPECT_EQ(2 * nxv2i32.getSizeInBits(), nxv4i32.getSizeInBits());
-  EXPECT_EQ(nxv2f64.getSizeInBits() / 2, nxv2i32.getSizeInBits());
+  EXPECT_EQ(nxv2f64.getSizeInBits().divideCoefficientBy(2),
+            nxv2i32.getSizeInBits());
 }
 
 } // end anonymous namespace