}
/// Create a TargetMachine. As we lack a dedicated always available target for
-/// unittests, we go for "x86_64" which should be available in most builds.
+/// unittests, we go for "AMDGPU" to be able to test normal and subregister
+/// liveranges.
std::unique_ptr<TargetMachine> createTargetMachine() {
- Triple TargetTriple("x86_64--");
+ Triple TargetTriple("amdgcn--");
std::string Error;
const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
if (!T)
TargetOptions Options;
return std::unique_ptr<TargetMachine>(
- T->createTargetMachine("x86_64", "", "", Options, None,
+ T->createTargetMachine("AMDGPU", "", "", Options, None,
CodeModel::Default, CodeGenOpt::Aggressive));
}
LiveIntervalTest T;
};
-/**
- * Move instruction number \p From in front of instruction number \p To and
- * update affected liveness intervals with LiveIntervalAnalysis::handleMove().
- */
-static void testHandleMove(MachineFunction &MF, LiveIntervals &LIS,
- unsigned From, unsigned To, unsigned BlockNum = 0) {
+static MachineInstr &getMI(MachineFunction &MF, unsigned At,
+ unsigned BlockNum) {
MachineBasicBlock &MBB = *MF.getBlockNumbered(BlockNum);
unsigned I = 0;
- MachineInstr *FromInstr = nullptr;
- MachineInstr *ToInstr = nullptr;
for (MachineInstr &MI : MBB) {
- if (I == From)
- FromInstr = &MI;
- if (I == To)
- ToInstr = &MI;
+ if (I == At)
+ return MI;
++I;
}
- assert(FromInstr != nullptr && ToInstr != nullptr);
+ llvm_unreachable("Instruction not found");
+}
- MBB.splice(ToInstr->getIterator(), &MBB, FromInstr->getIterator());
- LIS.handleMove(*FromInstr, true);
+/**
+ * Move instruction number \p From in front of instruction number \p To and
+ * update affected liveness intervals with LiveIntervalAnalysis::handleMove().
+ */
+static void testHandleMove(MachineFunction &MF, LiveIntervals &LIS,
+ unsigned From, unsigned To, unsigned BlockNum = 0) {
+ MachineInstr &FromInstr = getMI(MF, From, BlockNum);
+ MachineInstr &ToInstr = getMI(MF, To, BlockNum);
+
+ MachineBasicBlock &MBB = *FromInstr.getParent();
+ MBB.splice(ToInstr.getIterator(), &MBB, FromInstr.getIterator());
+ LIS.handleMove(FromInstr, true);
}
static void liveIntervalTest(StringRef MIRFunc, LiveIntervalTest T) {
"...\n"
"name: func\n"
"registers:\n"
-" - { id: 0, class: gr64 }\n"
+" - { id: 0, class: sreg_64 }\n"
"body: |\n"
" bb.0:\n"
) + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
TEST(LiveIntervalTest, MoveUpDef) {
// Value defined.
liveIntervalTest(
-" NOOP\n"
-" NOOP\n"
+" S_NOP 0\n"
+" S_NOP 0\n"
" early-clobber %0 = IMPLICIT_DEF\n"
-" RETQ %0\n",
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 2, 1);
});
TEST(LiveIntervalTest, MoveUpRedef) {
liveIntervalTest(
" %0 = IMPLICIT_DEF\n"
-" NOOP\n"
+" S_NOP 0\n"
" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
-" RETQ %0\n",
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 2, 1);
});
TEST(LiveIntervalTest, MoveUpEarlyDef) {
liveIntervalTest(
-" NOOP\n"
-" NOOP\n"
+" S_NOP 0\n"
+" S_NOP 0\n"
" early-clobber %0 = IMPLICIT_DEF\n"
-" RETQ %0\n",
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 2, 1);
});
TEST(LiveIntervalTest, MoveUpEarlyRedef) {
liveIntervalTest(
" %0 = IMPLICIT_DEF\n"
-" NOOP\n"
+" S_NOP 0\n"
" early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
-" RETQ %0\n",
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 2, 1);
});
TEST(LiveIntervalTest, MoveUpKill) {
liveIntervalTest(
" %0 = IMPLICIT_DEF\n"
-" NOOP\n"
-" NOOP implicit %0\n",
+" S_NOP 0\n"
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 2, 1);
});
TEST(LiveIntervalTest, MoveUpKillFollowing) {
liveIntervalTest(
" %0 = IMPLICIT_DEF\n"
-" NOOP\n"
-" NOOP implicit %0\n"
-" RETQ %0\n",
+" S_NOP 0\n"
+" S_NOP 0, implicit %0\n"
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 2, 1);
});
TEST(LiveIntervalTest, MoveDownDef) {
// Value defined.
liveIntervalTest(
-" NOOP\n"
+" S_NOP 0\n"
" early-clobber %0 = IMPLICIT_DEF\n"
-" NOOP\n"
-" RETQ %0\n",
+" S_NOP 0\n"
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 1, 2);
});
liveIntervalTest(
" %0 = IMPLICIT_DEF\n"
" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
-" NOOP\n"
-" RETQ %0\n",
+" S_NOP 0\n"
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 1, 2);
});
TEST(LiveIntervalTest, MoveDownEarlyDef) {
liveIntervalTest(
-" NOOP\n"
+" S_NOP 0\n"
" early-clobber %0 = IMPLICIT_DEF\n"
-" NOOP\n"
-" RETQ %0\n",
+" S_NOP 0\n"
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 1, 2);
});
liveIntervalTest(
" %0 = IMPLICIT_DEF\n"
" early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
-" NOOP\n"
-" RETQ %0\n",
+" S_NOP 0\n"
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 1, 2);
});
TEST(LiveIntervalTest, MoveDownKill) {
liveIntervalTest(
" %0 = IMPLICIT_DEF\n"
-" NOOP implicit %0\n"
-" NOOP\n",
+" S_NOP 0, implicit %0\n"
+" S_NOP 0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 1, 2);
});
TEST(LiveIntervalTest, MoveDownKillFollowing) {
liveIntervalTest(
" %0 = IMPLICIT_DEF\n"
-" NOOP\n"
-" NOOP implicit %0\n"
-" RETQ %0\n",
+" S_NOP 0\n"
+" S_NOP 0, implicit %0\n"
+" S_NOP 0, implicit %0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 1, 2);
});
TEST(LiveIntervalTest, MoveUndefUse) {
liveIntervalTest(
" %0 = IMPLICIT_DEF\n"
-" NOOP implicit undef %0\n"
-" NOOP implicit %0\n"
-" NOOP\n",
+" S_NOP 0, implicit undef %0\n"
+" S_NOP 0, implicit %0\n"
+" S_NOP 0\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 1, 3);
});
liveIntervalTest(
" successors: %bb.1, %bb.2\n"
" %0 = IMPLICIT_DEF\n"
-" JG_1 %bb.2, implicit %eflags\n"
-" JMP_1 %bb.1\n"
+" S_CBRANCH_VCCNZ %bb.2, implicit undef %vcc\n"
+" S_BRANCH %bb.1\n"
" bb.2:\n"
-" NOOP implicit %0\n"
+" S_NOP 0, implicit %0\n"
" bb.1:\n"
" successors: %bb.2\n"
" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
-" JMP_1 %bb.2\n",
+" S_BRANCH %bb.2\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 2, 0, 2);
});
// findLastUseBefore() used by handleMoveUp() must ignore undef operands.
liveIntervalTest(
" %0 = IMPLICIT_DEF\n"
-" NOOP\n"
-" NOOP implicit undef %0\n"
+" S_NOP 0\n"
+" S_NOP 0, implicit undef %0\n"
" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 3, 1);
TEST(LiveIntervalTest, MoveOverUndefUse1) {
// findLastUseBefore() used by handleMoveUp() must ignore undef operands.
liveIntervalTest(
-" %rax = IMPLICIT_DEF\n"
-" NOOP\n"
-" NOOP implicit undef %rax\n"
-" %rax = IMPLICIT_DEF implicit %rax(tied-def 0)\n",
+" %sgpr0 = IMPLICIT_DEF\n"
+" S_NOP 0\n"
+" S_NOP 0, implicit undef %sgpr0\n"
+" %sgpr0 = IMPLICIT_DEF implicit %sgpr0(tied-def 0)\n",
[](MachineFunction &MF, LiveIntervals &LIS) {
testHandleMove(MF, LIS, 3, 1);
});
}
+TEST(LiveIntervalTest, SubRegMoveDown) {
+ // Subregister ranges can have holes inside a basic block. Check for a
+ // movement of the form 32->150 in a liverange [16, 32) [100,200).
+ liveIntervalTest(
+" successors: %bb.1, %bb.2\n"
+" %0 = IMPLICIT_DEF\n"
+" S_CBRANCH_VCCNZ %bb.2, implicit undef %vcc\n"
+" S_BRANCH %bb.1\n"
+" bb.2:\n"
+" successors: %bb.1\n"
+" S_NOP 0, implicit %0:sub0\n"
+" S_NOP 0, implicit %0:sub1\n"
+" S_NOP 0\n"
+" undef %0:sub0 = IMPLICIT_DEF\n"
+" %0:sub1 = IMPLICIT_DEF\n"
+" bb.1:\n"
+" S_NOP 0, implicit %0\n",
+ [](MachineFunction &MF, LiveIntervals &LIS) {
+ // Scheduler behaviour: Clear def,read-undef flag and move.
+ MachineInstr &MI = getMI(MF, 3, /*BlockNum=*/1);
+ MI.getOperand(0).setIsUndef(false);
+ testHandleMove(MF, LIS, 1, 4, /*BlockNum=*/1);
+ });
+}
+
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
initLLVM();