aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/MI
diff options
context:
space:
mode:
authorValery Pykhtin <valery.pykhtin@gmail.com>2023-08-17 11:47:46 +0200
committerValery Pykhtin <valery.pykhtin@gmail.com>2023-09-12 10:59:43 +0200
commitaf2dcc3052a8e2c88d7d919ee19f811e806c5e9b (patch)
treec702d430587cda8a86a40f0a58b3f861b43900be /llvm/unittests/MI
parenta1e38e0b8e3e9d02304cf1a578f02a80fdb02bce (diff)
downloadllvm-af2dcc3052a8e2c88d7d919ee19f811e806c5e9b.zip
llvm-af2dcc3052a8e2c88d7d919ee19f811e806c5e9b.tar.gz
llvm-af2dcc3052a8e2c88d7d919ee19f811e806c5e9b.tar.bz2
[AMDGPU] Handle inUndef flag in LiveVariables::recomputeForSingleDefVirtReg
A register's use with isUndef flags shouldn't be considered as a point where the register is live. LiveVariables::runOnInstr ignores such uses. This was found when I tried to replace calls to SIOptimizeVGPRLiveRange::updateLiveRangeInThenRegion SIOptimizeVGPRLiveRange::updateLiveRangeInElseRegion with LiveVariables::recomputeForSingleDefVirtReg. In the testcase below %2 use is undef in the last REG_SEQUENCE. CodeGen/AMDGPU/si-opt-vgpr-liverange-bug-deadlanes.mir failed: Function Live Ins: $vgpr0 in %0 bb.0: successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%), %bb.2(50.00%) liveins: $vgpr0 %0:vgpr_32 = COPY killed $vgpr0 %1:vgpr_32 = V_MOV_B32_e32 0, implicit $exec %2:vgpr_32 = BUFFER_LOAD_DWORD_OFFEN killed %0:vgpr_32, undef %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable invariant load (s32)) %3:sreg_64 = V_CMP_NE_U32_e64 0, %2:vgpr_32, implicit $exec %7:sreg_64 = SI_IF killed %3:sreg_64, %bb.2, implicit-def dead $exec, implicit-def dead $scc, implicit $exec S_BRANCH %bb.1 bb.1: ; predecessors: %bb.0 successors: %bb.2(0x80000000); %bb.2(100.00%) %8:vreg_128 = REG_SEQUENCE killed %1:vgpr_32, %subreg.sub0, %1:vgpr_32, %subreg.sub1, %1:vgpr_32, %subreg.sub2, undef %4.sub3:vreg_128, %subreg.sub3 bb.2: ; predecessors: %bb.0, %bb.1 successors: %bb.3(0x40000000), %bb.4(0x40000000); %bb.3(50.00%), %bb.4(50.00%) %9:vreg_128 = PHI undef %10:vreg_128, %bb.0, %8:vreg_128, %bb.1 %14:vgpr_32 = PHI %2:vgpr_32, %bb.0, undef %15:vgpr_32, %bb.1 %11:sreg_64 = SI_ELSE killed %7:sreg_64, %bb.4, implicit-def dead $exec, implicit-def dead $scc, implicit $exec S_BRANCH %bb.3 bb.3: ; predecessors: %bb.2 successors: %bb.4(0x80000000); %bb.4(100.00%) %12:vreg_128 = REG_SEQUENCE killed %14:vgpr_32, %subreg.sub0, %14:vgpr_32, %subreg.sub1, %14:vgpr_32, %subreg.sub2, undef %6:vgpr_32, %subreg.sub3 bb.4: ; predecessors: %bb.2, %bb.3 %13:vreg_128 = PHI %9:vreg_128, %bb.2, %12:vreg_128, %bb.3 SI_END_CF killed %11:sreg_64, implicit-def dead $exec, implicit-def dead $scc, implicit $exec dead %4:vreg_128 = REG_SEQUENCE killed %13.sub2:vreg_128, %subreg.sub0, %13.sub2:vreg_128, %subreg.sub1, %13.sub2:vreg_128, %subreg.sub2, **undef %2:vgpr_32**, %subreg.sub3 S_ENDPGM 0 *** Bad machine code: LiveVariables: Block should not be in AliveBlocks *** - function: _amdgpu_ps_main - basic block: %bb.1 (0x55e17ebd7100) Virtual register %2 is not needed live through the block. *** Bad machine code: LiveVariables: Block should not be in AliveBlocks *** - function: _amdgpu_ps_main - basic block: %bb.2 (0x55e17ebd7200) Virtual register %2 is not needed live through the block. *** Bad machine code: LiveVariables: Block should not be in AliveBlocks *** - function: _amdgpu_ps_main - basic block: %bb.3 (0x55e17ebd7300) Virtual register %2 is not needed live through the block. Differential Revision: https://reviews.llvm.org/D158167
Diffstat (limited to 'llvm/unittests/MI')
-rw-r--r--llvm/unittests/MI/LiveIntervalTest.cpp107
1 files changed, 89 insertions, 18 deletions
diff --git a/llvm/unittests/MI/LiveIntervalTest.cpp b/llvm/unittests/MI/LiveIntervalTest.cpp
index 0957891..e3b07c9 100644
--- a/llvm/unittests/MI/LiveIntervalTest.cpp
+++ b/llvm/unittests/MI/LiveIntervalTest.cpp
@@ -1,5 +1,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/LiveIntervals.h"
+#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
@@ -75,22 +76,28 @@ std::unique_ptr<Module> parseMIR(LLVMContext &Context,
return M;
}
-typedef std::function<void(MachineFunction&,LiveIntervals&)> LiveIntervalTest;
-
struct TestPass : public MachineFunctionPass {
static char ID;
- TestPass() : MachineFunctionPass(ID) {
+ TestPass() : MachineFunctionPass(ID) {}
+};
+
+template <typename AnalysisType>
+struct TestPassT : public TestPass {
+
+ typedef std::function<void(MachineFunction&,AnalysisType&)> TestFx;
+
+ TestPassT() {
// We should never call this but always use PM.add(new TestPass(...))
abort();
}
- TestPass(LiveIntervalTest T, bool ShouldPass)
- : MachineFunctionPass(ID), T(T), ShouldPass(ShouldPass) {
+ TestPassT(TestFx T, bool ShouldPass)
+ : T(T), ShouldPass(ShouldPass) {
initializeTestPassPass(*PassRegistry::getPassRegistry());
}
bool runOnMachineFunction(MachineFunction &MF) override {
- LiveIntervals &LIS = getAnalysis<LiveIntervals>();
- T(MF, LIS);
+ AnalysisType &A = getAnalysis<AnalysisType>();
+ T(MF, A);
EXPECT_EQ(MF.verify(this, /* Banner */ nullptr, /* AbortOnError */ false),
ShouldPass);
return true;
@@ -98,12 +105,12 @@ struct TestPass : public MachineFunctionPass {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
- AU.addRequired<LiveIntervals>();
- AU.addPreserved<LiveIntervals>();
+ AU.addRequired<AnalysisType>();
+ AU.addPreserved<AnalysisType>();
MachineFunctionPass::getAnalysisUsage(AU);
}
private:
- LiveIntervalTest T;
+ TestFx T;
bool ShouldPass;
};
@@ -188,8 +195,10 @@ static bool checkRegUnitInterference(LiveIntervals &LIS,
return false;
}
-static void liveIntervalTest(StringRef MIRFunc, LiveIntervalTest T,
- bool ShouldPass = true) {
+template <typename AnalysisType>
+static void doTest(StringRef MIRFunc,
+ typename TestPassT<AnalysisType>::TestFx T,
+ bool ShouldPass = true) {
LLVMContext Context;
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
// This test is designed for the X86 backend; stop if it is not available.
@@ -197,7 +206,18 @@ static void liveIntervalTest(StringRef MIRFunc, LiveIntervalTest T,
return;
legacy::PassManager PM;
+ std::unique_ptr<MIRParser> MIR;
+ std::unique_ptr<Module> M = parseMIR(Context, PM, MIR, *TM, MIRFunc, "func");
+ ASSERT_TRUE(M);
+
+ PM.add(new TestPassT<AnalysisType>(T, ShouldPass));
+
+ PM.run(*M);
+}
+static void liveIntervalTest(StringRef MIRFunc,
+ TestPassT<LiveIntervals>::TestFx T,
+ bool ShouldPass = true) {
SmallString<160> S;
StringRef MIRString = (Twine(R"MIR(
---
@@ -208,14 +228,25 @@ registers:
body: |
bb.0:
)MIR") + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
- std::unique_ptr<MIRParser> MIR;
- std::unique_ptr<Module> M = parseMIR(Context, PM, MIR, *TM, MIRString,
- "func");
- ASSERT_TRUE(M);
- PM.add(new TestPass(T, ShouldPass));
+ doTest<LiveIntervals>(MIRString, T, ShouldPass);
+}
- PM.run(*M);
+static void liveVariablesTest(StringRef MIRFunc,
+ TestPassT<LiveVariables>::TestFx T,
+ bool ShouldPass = true) {
+ SmallString<160> S;
+ StringRef MIRString = (Twine(R"MIR(
+---
+...
+name: func
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: sreg_64 }
+body: |
+ bb.0:
+)MIR") + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
+ doTest<LiveVariables>(MIRString, T, ShouldPass);
}
} // End of anonymous namespace.
@@ -778,6 +809,46 @@ TEST(LiveIntervalTest, LiveThroughSegments) {
false);
}
+TEST(LiveVariablesTest, recomputeForSingleDefVirtReg_handle_undef1) {
+ liveVariablesTest(R"MIR(
+ %0 = IMPLICIT_DEF
+ S_NOP 0, implicit %0
+ S_NOP 0, implicit undef %0
+)MIR", [](MachineFunction &MF, LiveVariables &LV) {
+ auto &FirstNop = getMI(MF, 1, 0);
+ auto &SecondNop = getMI(MF, 2, 0);
+ EXPECT_TRUE(FirstNop.getOperand(1).isKill());
+ EXPECT_FALSE(SecondNop.getOperand(1).isKill());
+
+ Register R = Register::index2VirtReg(0);
+ LV.recomputeForSingleDefVirtReg(R);
+
+ EXPECT_TRUE(FirstNop.getOperand(1).isKill());
+ EXPECT_FALSE(SecondNop.getOperand(1).isKill());
+ });
+}
+
+TEST(LiveVariablesTest, recomputeForSingleDefVirtReg_handle_undef2) {
+ liveVariablesTest(R"MIR(
+ %0 = IMPLICIT_DEF
+ S_NOP 0, implicit %0
+ S_NOP 0, implicit undef %0, implicit %0
+)MIR", [](MachineFunction &MF, LiveVariables &LV) {
+ auto &FirstNop = getMI(MF, 1, 0);
+ auto &SecondNop = getMI(MF, 2, 0);
+ EXPECT_FALSE(FirstNop.getOperand(1).isKill());
+ EXPECT_FALSE(SecondNop.getOperand(1).isKill());
+ EXPECT_TRUE(SecondNop.getOperand(2).isKill());
+
+ Register R = Register::index2VirtReg(0);
+ LV.recomputeForSingleDefVirtReg(R);
+
+ EXPECT_FALSE(FirstNop.getOperand(1).isKill());
+ EXPECT_FALSE(SecondNop.getOperand(1).isKill());
+ EXPECT_TRUE(SecondNop.getOperand(2).isKill());
+ });
+}
+
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
initLLVM();