[llvm] [SandboxVec][Interval] Implement Interval::notifyMoveInstr() (PR #119471)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 10 15:31:19 PST 2024
https://github.com/vporpo created https://github.com/llvm/llvm-project/pull/119471
This patch implements the notifier for Instruction intervals. It updates the interval's top/bottom.
>From da371d3c1b0310fe16629d030a6ccb62f1ef468a Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Wed, 13 Nov 2024 12:10:00 -0800
Subject: [PATCH] [SandboxVec][Interval] Implement Interval::notifyMoveInstr()
This patch implements the notifier for Instruction intervals.
It updates the interval's top/bottom.
---
.../Vectorize/SandboxVectorizer/Interval.h | 24 ++++
.../SandboxVectorizer/IntervalTest.cpp | 109 ++++++++++++++++++
2 files changed, 133 insertions(+)
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h
index e2d0b82489ddc7..922dd2c3a1f893 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h
@@ -21,8 +21,10 @@
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/SandboxIR/Instruction.h"
#include "llvm/Support/raw_ostream.h"
#include <iterator>
+#include <type_traits>
namespace llvm::sandboxir {
@@ -207,6 +209,28 @@ template <typename T> class Interval {
return {NewTop, NewBottom};
}
+ /// Update the interval when \p I is about to be moved before \p Before.
+ // SFINAE disables this for non-Instructions.
+ template <typename HelperT = T>
+ std::enable_if_t<std::is_same<HelperT, Instruction>::value, void>
+ notifyMoveInstr(HelperT *I, decltype(I->getIterator()) BeforeIt) {
+ assert(contains(I) && "Expect `I` in interval!");
+ assert(I->getIterator() != BeforeIt && "Can't move `I` before itself!");
+
+ // Nothing to do if the instruction won't move.
+ if (std::next(I->getIterator()) == BeforeIt)
+ return;
+
+ T *NewTop = Top->getIterator() == BeforeIt ? I
+ : I == Top ? Top->getNextNode()
+ : Top;
+ T *NewBottom = std::next(Bottom->getIterator()) == BeforeIt ? I
+ : I == Bottom ? Bottom->getPrevNode()
+ : Bottom;
+ Top = NewTop;
+ Bottom = NewBottom;
+ }
+
#ifndef NDEBUG
void print(raw_ostream &OS) const {
auto *Top = top();
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/IntervalTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/IntervalTest.cpp
index b04e4fc7cffcae..32521ed79a314b 100644
--- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/IntervalTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/IntervalTest.cpp
@@ -331,3 +331,112 @@ define void @foo(i8 %v0) {
EXPECT_THAT(getPtrVec(SingleUnion), testing::ElementsAre(I0, I1, I2, Ret));
}
}
+
+TEST_F(IntervalTest, NotifyMoveInstr) {
+ parseIR(C, R"IR(
+define void @foo(i8 %v0) {
+ %I0 = add i8 %v0, %v0
+ %I1 = add i8 %v0, %v0
+ %I2 = 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++;
+ {
+ // Assert that we don't try to move external instr to the interval.
+ sandboxir::Interval<sandboxir::Instruction> I2Ret(I2, Ret);
+#ifndef NDEBUG
+ EXPECT_DEATH(I2Ret.notifyMoveInstr(I0, Ret->getIterator()), ".*interval.*");
+#endif // NDEBUG
+ }
+ {
+ // Assert that we don't move before self.
+ sandboxir::Interval<sandboxir::Instruction> I2Ret(I2, Ret);
+#ifndef NDEBUG
+ EXPECT_DEATH(I2Ret.notifyMoveInstr(Ret, Ret->getIterator()), ".*self.*");
+#endif // NDEBUG
+ }
+ {
+ // Single-element interval.
+ sandboxir::Interval<sandboxir::Instruction> I2I2(I2, I2);
+ I2I2.notifyMoveInstr(I2, Ret->getIterator());
+ EXPECT_EQ(I2I2.top(), I2);
+ EXPECT_EQ(I2I2.bottom(), I2);
+ }
+ {
+ // Two-element interval swap.
+ sandboxir::Interval<sandboxir::Instruction> I1I2(I1, I2);
+ I1I2.notifyMoveInstr(I2, I1->getIterator());
+ I2->moveBefore(I1);
+ EXPECT_EQ(I1I2.top(), I2);
+ EXPECT_EQ(I1I2.bottom(), I1);
+
+ I2->moveAfter(I1);
+ }
+ {
+ // Move to same position.
+ sandboxir::Interval<sandboxir::Instruction> I0Ret(I0, Ret);
+ I0Ret.notifyMoveInstr(I0, I1->getIterator());
+ I0->moveBefore(I1);
+ EXPECT_EQ(I0Ret.top(), I0);
+ EXPECT_EQ(I0Ret.bottom(), Ret);
+ }
+ {
+ // Move internal to internal.
+ sandboxir::Interval<sandboxir::Instruction> I0Ret(I0, Ret);
+ I0Ret.notifyMoveInstr(I2, I1->getIterator());
+ I2->moveBefore(I1);
+ EXPECT_EQ(I0Ret.top(), I0);
+ EXPECT_EQ(I0Ret.bottom(), Ret);
+
+ I2->moveAfter(I1);
+ }
+ {
+ // Move internal before top.
+ sandboxir::Interval<sandboxir::Instruction> I0Ret(I0, Ret);
+ I0Ret.notifyMoveInstr(I2, I0->getIterator());
+ I2->moveBefore(I0);
+ EXPECT_EQ(I0Ret.top(), I2);
+ EXPECT_EQ(I0Ret.bottom(), Ret);
+
+ I2->moveAfter(I1);
+ }
+ {
+ // Move internal to bottom.
+ sandboxir::Interval<sandboxir::Instruction> I0Ret(I0, Ret);
+ I0Ret.notifyMoveInstr(I2, BB->end());
+ I2->moveAfter(Ret);
+ EXPECT_EQ(I0Ret.top(), I0);
+ EXPECT_EQ(I0Ret.bottom(), I2);
+
+ I2->moveAfter(I1);
+ }
+ {
+ // Move bottom before internal.
+ sandboxir::Interval<sandboxir::Instruction> I0Ret(I0, Ret);
+ I0Ret.notifyMoveInstr(Ret, I2->getIterator());
+ Ret->moveBefore(I2);
+ EXPECT_EQ(I0Ret.top(), I0);
+ EXPECT_EQ(I0Ret.bottom(), I2);
+
+ Ret->moveAfter(I2);
+ }
+ {
+ // Move bottom before top.
+ sandboxir::Interval<sandboxir::Instruction> I0Ret(I0, Ret);
+ I0Ret.notifyMoveInstr(Ret, I0->getIterator());
+ Ret->moveBefore(I0);
+ EXPECT_EQ(I0Ret.top(), Ret);
+ EXPECT_EQ(I0Ret.bottom(), I2);
+
+ Ret->moveAfter(I2);
+ }
+}
More information about the llvm-commits
mailing list