Skip to content

[SandboxVec] Simple Instruction Interval class #108882

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 20, 2024
Merged

Conversation

vporpo
Copy link
Contributor

@vporpo vporpo commented Sep 16, 2024

An InstrInterval is a range of instructions in a block. The class will eventually have an API for set operations, like union, intersection etc.

@llvmbot
Copy link
Member

llvmbot commented Sep 16, 2024

@llvm/pr-subscribers-llvm-transforms

Author: vporpo (vporpo)

Changes

An InstrInterval is a range of instructions in a block. The class will eventually have an API for set operations, like union, intersection etc.


Full diff: https://github.com/llvm/llvm-project/pull/108882.diff

4 Files Affected:

  • (added) llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h (+103)
  • (modified) llvm/unittests/Transforms/Vectorize/CMakeLists.txt (+2)
  • (added) llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt (+12)
  • (added) llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp (+68)
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h
new file mode 100644
index 00000000000000..9ba451aebe3f7f
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h
@@ -0,0 +1,103 @@
+//===- InstrInterval.h ------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
+#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
+
+#include "llvm/SandboxIR/SandboxIR.h"
+#include <iterator>
+
+namespace llvm::sandboxir {
+
+/// A simple iterator for iterating the interval.
+template <typename DerefType, typename InstrIntervalType>
+class InstrIntervalIterator {
+  sandboxir::Instruction *I;
+  InstrIntervalType &R;
+
+public:
+  using difference_type = std::ptrdiff_t;
+  using value_type = sandboxir::Instruction;
+  using pointer = value_type *;
+  using reference = sandboxir::Instruction &;
+  using iterator_category = std::bidirectional_iterator_tag;
+
+  InstrIntervalIterator(sandboxir::Instruction *I, InstrIntervalType &R)
+      : I(I), R(R) {}
+  bool operator==(const InstrIntervalIterator &Other) const {
+    assert(&R == &Other.R && "Iterators belong to different regions!");
+    return Other.I == I;
+  }
+  bool operator!=(const InstrIntervalIterator &Other) const {
+    return !(*this == Other);
+  }
+  InstrIntervalIterator &operator++() {
+    assert(I != nullptr && "already at end()!");
+    I = I->getNextNode();
+    return *this;
+  }
+  InstrIntervalIterator operator++(int) {
+    auto ItCopy = *this;
+    ++*this;
+    return ItCopy;
+  }
+  InstrIntervalIterator &operator--() {
+    // `I` is nullptr for end() when ToI is the BB terminator.
+    I = I != nullptr ? I->getPrevNode() : R.ToI;
+    return *this;
+  }
+  InstrIntervalIterator operator--(int) {
+    auto ItCopy = *this;
+    --*this;
+    return ItCopy;
+  }
+  template <typename T =
+                std::enable_if<std::is_same<DerefType, Instruction *&>::value>>
+  sandboxir::Instruction &operator*() {
+    return *I;
+  }
+  DerefType operator*() const { return *I; }
+};
+
+class InstrInterval {
+  Instruction *FromI;
+  Instruction *ToI;
+
+public:
+  InstrInterval() : FromI(nullptr), ToI(nullptr) {}
+  InstrInterval(Instruction *FromI, Instruction *ToI)
+      : FromI(FromI), ToI(ToI) {}
+  bool empty() const {
+    assert(((FromI == nullptr && ToI == nullptr) ||
+            (FromI != nullptr && ToI != nullptr)) &&
+           "Either none or both should be null");
+    return FromI == nullptr;
+  }
+  bool contains(Instruction *I) const {
+    if (empty())
+      return false;
+    return (FromI == I || FromI->comesBefore(I)) &&
+           (I == ToI || I->comesBefore(ToI));
+  }
+
+  using iterator =
+      InstrIntervalIterator<sandboxir::Instruction &, InstrInterval>;
+  using const_iterator = InstrIntervalIterator<const sandboxir::Instruction &,
+                                               const InstrInterval>;
+  iterator begin() { return iterator(FromI, *this); }
+  iterator end() {
+    return iterator(ToI != nullptr ? ToI->getNextNode() : nullptr, *this);
+  }
+  const_iterator begin() const { return const_iterator(FromI, *this); }
+  const_iterator end() const {
+    return const_iterator(ToI != nullptr ? ToI->getNextNode() : nullptr, *this);
+  }
+};
+} // namespace llvm::sandboxir
+
+#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
diff --git a/llvm/unittests/Transforms/Vectorize/CMakeLists.txt b/llvm/unittests/Transforms/Vectorize/CMakeLists.txt
index 1354558a94f0d5..0df39c41a90414 100644
--- a/llvm/unittests/Transforms/Vectorize/CMakeLists.txt
+++ b/llvm/unittests/Transforms/Vectorize/CMakeLists.txt
@@ -1,3 +1,5 @@
+add_subdirectory(SandboxVectorizer)
+
 set(LLVM_LINK_COMPONENTS
   Analysis
   Core
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
new file mode 100644
index 00000000000000..22ac8eb793d195
--- /dev/null
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_LINK_COMPONENTS
+  Analysis
+  Core
+  Vectorize
+  AsmParser
+  TargetParser
+  SandboxIR
+  )
+
+add_llvm_unittest(SandboxVectorizerTests
+  InstrIntervalTest.cpp
+  )
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp
new file mode 100644
index 00000000000000..b8b8e4e982be56
--- /dev/null
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp
@@ -0,0 +1,68 @@
+//===- InstrIntervalTest.cpp ----------------------------------------------===//
+//
+// 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/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gmock/gmock-matchers.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+struct InstrIntervalTest : public testing::Test {
+  LLVMContext C;
+  std::unique_ptr<Module> M;
+
+  void parseIR(LLVMContext &C, const char *IR) {
+    SMDiagnostic Err;
+    M = parseAssemblyString(IR, Err, C);
+    if (!M)
+      Err.print("InstrIntervalTest", errs());
+  }
+};
+
+TEST_F(InstrIntervalTest, Basic) {
+  parseIR(C, R"IR(
+define void @foo(i8 %v0) {
+  %add0 = add i8 %v0, %v0
+  %add1 = add i8 %v0, %v0
+  %add2 = add i8 %v0, %v0
+  ret void
+}
+)IR");
+  Function &LLVMF = *M->getFunction("foo");
+  sandboxir::Context Ctx(C);
+  auto &F = *Ctx.createFunction(&LLVMF);
+  auto *BB = &*F.begin();
+  auto It = BB->begin();
+  auto *I0 = &*It++;
+  auto *I1 = &*It++;
+  auto *I2 = &*It++;
+  auto *Ret = &*It++;
+
+  sandboxir::InstrInterval Interval(I0, Ret);
+  // Check empty().
+  EXPECT_FALSE(Interval.empty());
+  sandboxir::InstrInterval Empty;
+  EXPECT_TRUE(Empty.empty());
+  sandboxir::InstrInterval One(I0, I0);
+  EXPECT_FALSE(One.empty());
+  // Check contains().
+  for (auto &I : *BB) {
+    EXPECT_TRUE(Interval.contains(&I));
+    EXPECT_FALSE(Empty.contains(&I));
+  }
+  EXPECT_FALSE(One.contains(I1));
+  EXPECT_FALSE(One.contains(I2));
+  EXPECT_FALSE(One.contains(Ret));
+  // Check iterator.
+  auto BBIt = BB->begin();
+  for (auto &I : Interval)
+    EXPECT_EQ(&I, &*BBIt++);
+}

@tschuett
Copy link

Same comments as for the dependency graph:

@vporpo
Copy link
Contributor Author

vporpo commented Sep 16, 2024

could use some doxygen

Do you mean like adding more comments?

to me it reads like an analysis and could be placed in https://github.com/llvm/llvm-project/tree/main/llvm/include/llvm/SandboxIR

I think of it more like a helper class for the vectorizer, rather than an analysis. It's not specific to the vectorizer, so it would make sense to move it into SandboxIR, but I think that there won't be any other users for it outside the vectorizer. If that changes we can move it then.

Regarding the Dependency Graph, that class is specific to the vectorizer. It's not going to be a generic Dependency Graph that others could use.

@tschuett
Copy link

could use some doxygen
Do you mean like adding more comments?

Yep. At the top of the file.

@tschuett
Copy link

Like an overview. Especially the dependency graph could benefit from an introduction/overview.

@vporpo vporpo force-pushed the Interval branch 2 times, most recently from a96c9f7 to 3f7a8e6 Compare September 18, 2024 15:28
public:
InstrInterval() : FromI(nullptr), ToI(nullptr) {}
InstrInterval(Instruction *FromI, Instruction *ToI)
: FromI(FromI), ToI(ToI) {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert(FromI->comesBefore(ToI))?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can also contain a single instruction so it's assert(FromI == ToI || FromI->comesBefore(ToI)).

An InstrInterval is a range of instructions in a block.
The class will eventually have an API for set operations, like union,
intersection etc.
@vporpo
Copy link
Contributor Author

vporpo commented Sep 19, 2024

ping

@vporpo vporpo merged commit 7688393 into llvm:main Sep 20, 2024
8 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 20, 2024

LLVM Buildbot has detected a new failure on builder bolt-x86_64-ubuntu-dylib running on bolt-worker while building llvm at step 6 "test-build-bolt-check-bolt".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/119/builds/2237

Here is the relevant piece of the build log for the reference
Step 6 (test-build-bolt-check-bolt) failure: test (failure)
******************** TEST 'BOLT :: perf2bolt/perf_test.test' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 5: /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/clang /home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/Inputs/perf_test.c -fuse-ld=lld -Wl,--script=/home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/Inputs/perf_test.lds -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp
+ /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/clang /home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/Inputs/perf_test.c -fuse-ld=lld -Wl,--script=/home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/Inputs/perf_test.lds -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp
RUN: at line 6: perf record -e cycles:u -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp2 -- /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp
+ perf record -e cycles:u -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp2 -- /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp
Lowering default frequency rate from 4000 to 2000.
Please consider tweaking /proc/sys/kernel/perf_event_max_sample_rate.
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.003 MB /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp2 (21 samples) ]
RUN: at line 7: /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/perf2bolt /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp -p=/home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp2 -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp3 -nl -ignore-build-id 2>&1 | /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/FileCheck /home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/perf_test.test
+ /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/perf2bolt /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp -p=/home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp2 -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp3 -nl -ignore-build-id
+ /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/FileCheck /home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/perf_test.test
RUN: at line 12: /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/clang /home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/Inputs/perf_test.c -no-pie -fuse-ld=lld -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp4
+ /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/clang /home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/Inputs/perf_test.c -no-pie -fuse-ld=lld -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp4
RUN: at line 13: perf record -e cycles:u -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp5 -- /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp4
+ perf record -e cycles:u -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp5 -- /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp4
Lowering default frequency rate from 4000 to 2000.
Please consider tweaking /proc/sys/kernel/perf_event_max_sample_rate.
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.002 MB /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp5 (9 samples) ]
RUN: at line 14: /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/perf2bolt /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp4 -p=/home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp5 -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp6 -nl -ignore-build-id 2>&1 | /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/FileCheck /home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/perf_test.test --check-prefix=CHECK-NO-PIE
+ /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/FileCheck /home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/perf_test.test --check-prefix=CHECK-NO-PIE
+ /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/bin/perf2bolt /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp4 -p=/home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp5 -o /home/worker/bolt-worker2/bolt-x86_64-ubuntu-dylib/build/tools/bolt/test/perf2bolt/Output/perf_test.test.tmp6 -nl -ignore-build-id
/home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/perf_test.test:17:19: error: CHECK-NO-PIE-NOT: excluded string found in input
CHECK-NO-PIE-NOT: !! WARNING !! This high mismatch ratio indicates the input binary is probably not the same binary used during profiling collection.
                  ^
<stdin>:26:2: note: found here
 !! WARNING !! This high mismatch ratio indicates the input binary is probably not the same binary used during profiling collection. The generated data may be ineffective for improving performance.
 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Input file: <stdin>
Check file: /home/worker/bolt-worker2/llvm-project/bolt/test/perf2bolt/perf_test.test

-dump-input=help explains the following input dump.

Input was:
<<<<<<
        .
        .
        .
       21: BOLT-WARNING: Running parallel work of 0 estimated cost, will switch to trivial scheduling. 
       22: PERF2BOLT: processing basic events (without LBR)... 
       23: PERF2BOLT: read 9 samples 
       24: PERF2BOLT: out of range samples recorded in unknown regions: 9 (100.0%) 
       25:  
       26:  !! WARNING !! This high mismatch ratio indicates the input binary is probably not the same binary used during profiling collection. The generated data may be ineffective for improving performance. 
...

@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 20, 2024

LLVM Buildbot has detected a new failure on builder lld-x86_64-win running on as-worker-93 while building llvm at step 7 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/146/builds/1198

Here is the relevant piece of the build log for the reference
Step 7 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM-Unit :: Support/./SupportTests.exe/36/87' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe-LLVM-Unit-22376-36-87.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=87 GTEST_SHARD_INDEX=36 C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe
--

Script:
--
C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe --gtest_filter=ProgramEnvTest.CreateProcessLongPath
--
C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(160): error: Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(163): error: fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied



C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:160
Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:163
fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied




********************


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants