@@ -331,3 +331,112 @@ define void @foo(i8 %v0) {
331331 EXPECT_THAT (getPtrVec (SingleUnion), testing::ElementsAre (I0, I1, I2, Ret));
332332 }
333333}
334+
335+ TEST_F (IntervalTest, NotifyMoveInstr) {
336+ parseIR (C, R"IR(
337+ define void @foo(i8 %v0) {
338+ %I0 = add i8 %v0, %v0
339+ %I1 = add i8 %v0, %v0
340+ %I2 = add i8 %v0, %v0
341+ ret void
342+ }
343+ )IR" );
344+ Function &LLVMF = *M->getFunction (" foo" );
345+ sandboxir::Context Ctx (C);
346+ auto &F = *Ctx.createFunction (&LLVMF);
347+ auto *BB = &*F.begin ();
348+ auto It = BB->begin ();
349+ auto *I0 = &*It++;
350+ auto *I1 = &*It++;
351+ auto *I2 = &*It++;
352+ auto *Ret = &*It++;
353+ {
354+ // Assert that we don't try to move external instr to the interval.
355+ sandboxir::Interval<sandboxir::Instruction> I2Ret (I2, Ret);
356+ #ifndef NDEBUG
357+ EXPECT_DEATH (I2Ret.notifyMoveInstr (I0, Ret->getIterator ()), " .*interval.*" );
358+ #endif // NDEBUG
359+ }
360+ {
361+ // Assert that we don't move before self.
362+ sandboxir::Interval<sandboxir::Instruction> I2Ret (I2, Ret);
363+ #ifndef NDEBUG
364+ EXPECT_DEATH (I2Ret.notifyMoveInstr (Ret, Ret->getIterator ()), " .*self.*" );
365+ #endif // NDEBUG
366+ }
367+ {
368+ // Single-element interval.
369+ sandboxir::Interval<sandboxir::Instruction> I2I2 (I2, I2);
370+ I2I2.notifyMoveInstr (I2, Ret->getIterator ());
371+ EXPECT_EQ (I2I2.top (), I2);
372+ EXPECT_EQ (I2I2.bottom (), I2);
373+ }
374+ {
375+ // Two-element interval swap.
376+ sandboxir::Interval<sandboxir::Instruction> I1I2 (I1, I2);
377+ I1I2.notifyMoveInstr (I2, I1->getIterator ());
378+ I2->moveBefore (I1);
379+ EXPECT_EQ (I1I2.top (), I2);
380+ EXPECT_EQ (I1I2.bottom (), I1);
381+
382+ I2->moveAfter (I1);
383+ }
384+ {
385+ // Move to same position.
386+ sandboxir::Interval<sandboxir::Instruction> I0Ret (I0, Ret);
387+ I0Ret.notifyMoveInstr (I0, I1->getIterator ());
388+ I0->moveBefore (I1);
389+ EXPECT_EQ (I0Ret.top (), I0);
390+ EXPECT_EQ (I0Ret.bottom (), Ret);
391+ }
392+ {
393+ // Move internal to internal.
394+ sandboxir::Interval<sandboxir::Instruction> I0Ret (I0, Ret);
395+ I0Ret.notifyMoveInstr (I2, I1->getIterator ());
396+ I2->moveBefore (I1);
397+ EXPECT_EQ (I0Ret.top (), I0);
398+ EXPECT_EQ (I0Ret.bottom (), Ret);
399+
400+ I2->moveAfter (I1);
401+ }
402+ {
403+ // Move internal before top.
404+ sandboxir::Interval<sandboxir::Instruction> I0Ret (I0, Ret);
405+ I0Ret.notifyMoveInstr (I2, I0->getIterator ());
406+ I2->moveBefore (I0);
407+ EXPECT_EQ (I0Ret.top (), I2);
408+ EXPECT_EQ (I0Ret.bottom (), Ret);
409+
410+ I2->moveAfter (I1);
411+ }
412+ {
413+ // Move internal to bottom.
414+ sandboxir::Interval<sandboxir::Instruction> I0Ret (I0, Ret);
415+ I0Ret.notifyMoveInstr (I2, BB->end ());
416+ I2->moveAfter (Ret);
417+ EXPECT_EQ (I0Ret.top (), I0);
418+ EXPECT_EQ (I0Ret.bottom (), I2);
419+
420+ I2->moveAfter (I1);
421+ }
422+ {
423+ // Move bottom before internal.
424+ sandboxir::Interval<sandboxir::Instruction> I0Ret (I0, Ret);
425+ I0Ret.notifyMoveInstr (Ret, I2->getIterator ());
426+ Ret->moveBefore (I2);
427+ EXPECT_EQ (I0Ret.top (), I0);
428+ EXPECT_EQ (I0Ret.bottom (), I2);
429+
430+ Ret->moveAfter (I2);
431+ }
432+ {
433+ // Move bottom before top.
434+ sandboxir::Interval<sandboxir::Instruction> I0Ret (I0, Ret);
435+ I0Ret.notifyMoveInstr (Ret, I0->getIterator ());
436+ Ret->moveBefore (I0);
437+ EXPECT_EQ (I0Ret.top (), Ret);
438+ EXPECT_EQ (I0Ret.bottom (), I2);
439+
440+ Ret->moveAfter (I2);
441+ }
442+ }
0 commit comments