diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h --- a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h @@ -225,15 +225,23 @@ /// away any copies. /// /// Also walks through hints such as G_ASSERT_ZEXT. -Optional -getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); +/// +/// Optionally, an alternative set of copy opcodes can be recognized through +/// \p CopyOpcodes. +Optional getDefSrcRegIgnoringCopies( + Register Reg, const MachineRegisterInfo &MRI, + ArrayRef CopyOpcodes = {TargetOpcode::COPY}); /// Find the def instruction for \p Reg, folding away any trivial copies. May /// return nullptr if \p Reg is not a generic virtual register. /// /// Also walks through hints such as G_ASSERT_ZEXT. -MachineInstr *getDefIgnoringCopies(Register Reg, - const MachineRegisterInfo &MRI); +/// +/// Optionally, an alternative set of copy opcodes can be recognized through +/// \p CopyOpcodes. +MachineInstr *getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI, + ArrayRef CopyOpcodes = { + TargetOpcode::COPY}); /// Find the source register for \p Reg, folding away any trivial copies. It /// will be an output register of the instruction that getDefIgnoringCopies @@ -241,7 +249,12 @@ /// register. /// /// Also walks through hints such as G_ASSERT_ZEXT. -Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); +/// +/// Optionally, an alternative set of copy opcodes can be recognized through +/// \p CopyOpcodes. +Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI, + ArrayRef CopyOpcodes = { + TargetOpcode::COPY}); // Templated variant of getOpcodeDef returning a MachineInstr derived T. /// See if Reg is defined by an single def instruction of type T diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp --- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -431,14 +431,16 @@ } Optional -llvm::getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI) { +llvm::getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI, + ArrayRef CopyOpcodes) { Register DefSrcReg = Reg; auto *DefMI = MRI.getVRegDef(Reg); auto DstTy = MRI.getType(DefMI->getOperand(0).getReg()); if (!DstTy.isValid()) return None; unsigned Opc = DefMI->getOpcode(); - while (Opc == TargetOpcode::COPY || isPreISelGenericOptimizationHint(Opc)) { + while (is_contained(CopyOpcodes, Opc) || + isPreISelGenericOptimizationHint(Opc)) { Register SrcReg = DefMI->getOperand(1).getReg(); auto SrcTy = MRI.getType(SrcReg); if (!SrcTy.isValid()) @@ -451,16 +453,18 @@ } MachineInstr *llvm::getDefIgnoringCopies(Register Reg, - const MachineRegisterInfo &MRI) { + const MachineRegisterInfo &MRI, + ArrayRef CopyOpcodes) { Optional DefSrcReg = - getDefSrcRegIgnoringCopies(Reg, MRI); + getDefSrcRegIgnoringCopies(Reg, MRI, CopyOpcodes); return DefSrcReg ? DefSrcReg->MI : nullptr; } Register llvm::getSrcRegIgnoringCopies(Register Reg, - const MachineRegisterInfo &MRI) { + const MachineRegisterInfo &MRI, + ArrayRef CopyOpcodes) { Optional DefSrcReg = - getDefSrcRegIgnoringCopies(Reg, MRI); + getDefSrcRegIgnoringCopies(Reg, MRI, CopyOpcodes); return DefSrcReg ? DefSrcReg->Reg : Register(); } diff --git a/llvm/unittests/CodeGen/GlobalISel/GISelUtilsTest.cpp b/llvm/unittests/CodeGen/GlobalISel/GISelUtilsTest.cpp --- a/llvm/unittests/CodeGen/GlobalISel/GISelUtilsTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/GISelUtilsTest.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "GISelMITest.h" #include "llvm/CodeGen/GlobalISel/Utils.h" #include "gtest/gtest.h" @@ -245,4 +246,21 @@ EXPECT_EQ(V4P1, getLCMType(P1, V2S64)); } +TEST_F(AArch64GISelMITest, AltIgnoreCopies) { + setUp(); + if (!TM) + return; + + auto X = B.buildInstr(TargetOpcode::G_IMPLICIT_DEF, {S1}, {}); + auto Freeze = B.buildInstr(TargetOpcode::G_FREEZE, {S1}, {X}); + auto Copy = B.buildInstr(TargetOpcode::COPY, {S1}, {Freeze}); + + auto DefSrcReg = + getDefSrcRegIgnoringCopies(Copy->getOperand(0).getReg(), *MRI, + {TargetOpcode::COPY, TargetOpcode::G_FREEZE}); + + EXPECT_EQ(DefSrcReg->MI, X); + EXPECT_EQ(DefSrcReg->Reg, X->getOperand(0).getReg()); } + +} // namespace