diff options
author | Simon Wallis <simon.wallis2@arm.com> | 2020-07-29 16:17:47 +0100 |
---|---|---|
committer | Simon Wallis <simon.wallis2@arm.com> | 2020-07-29 16:21:01 +0100 |
commit | 6a05c6bfc8d363a6d3d6cd7015d0e6fc01a91ce2 (patch) | |
tree | e2df73c3f457c65f96c0db58d303370139da4411 /llvm/lib/CodeGen/MachineCopyPropagation.cpp | |
parent | 62beb7c6f4f2288793751740f06edc0dc25d01f6 (diff) | |
download | llvm-6a05c6bfc8d363a6d3d6cd7015d0e6fc01a91ce2.zip llvm-6a05c6bfc8d363a6d3d6cd7015d0e6fc01a91ce2.tar.gz llvm-6a05c6bfc8d363a6d3d6cd7015d0e6fc01a91ce2.tar.bz2 |
[MachineCopyPropagation] BackwardPropagatableCopy: add check for hasOverlappingMultipleDef
In MachineCopyPropagation::BackwardPropagatableCopy(),
a check is added for multiple destination registers.
The copy propagation is avoided if the copied destination register
is the same register as another destination on the same instruction.
A new test is added. This used to fail on ARM like this:
error: unpredictable instruction, RdHi and RdLo must be different
umull r9, r9, lr, r0
Reviewed By: lkail
Differential Revision: https://reviews.llvm.org/D82638
Diffstat (limited to 'llvm/lib/CodeGen/MachineCopyPropagation.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MachineCopyPropagation.cpp | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp index 70d6dcc..67d1512 100644 --- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp +++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp @@ -288,6 +288,8 @@ private: const MachineInstr &UseI, unsigned UseIdx); bool hasImplicitOverlap(const MachineInstr &MI, const MachineOperand &Use); + bool hasOverlappingMultipleDef(const MachineInstr &MI, + const MachineOperand &MODef, Register Def); /// Candidates for deletion. SmallSetVector<MachineInstr *, 8> MaybeDeadCopies; @@ -461,6 +463,21 @@ bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI, return false; } +/// For an MI that has multiple definitions, check whether \p MI has +/// a definition that overlaps with another of its definitions. +/// For example, on ARM: umull r9, r9, lr, r0 +/// The umull instruction is unpredictable unless RdHi and RdLo are different. +bool MachineCopyPropagation::hasOverlappingMultipleDef( + const MachineInstr &MI, const MachineOperand &MODef, Register Def) { + for (const MachineOperand &MIDef : MI.defs()) { + if ((&MIDef != &MODef) && MIDef.isReg() && + TRI->regsOverlap(Def, MIDef.getReg())) + return true; + } + + return false; +} + /// Look for available copies whose destination register is used by \p MI and /// replace the use in \p MI with the copy's source register. void MachineCopyPropagation::forwardUses(MachineInstr &MI) { @@ -786,6 +803,9 @@ void MachineCopyPropagation::propagateDefs(MachineInstr &MI) { if (hasImplicitOverlap(MI, MODef)) continue; + if (hasOverlappingMultipleDef(MI, MODef, Def)) + continue; + LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MODef.getReg(), TRI) << "\n with " << printReg(Def, TRI) << "\n in " << MI << " from " << *Copy); |