summaryrefslogtreecommitdiff
path: root/lib/Target/X86/X86FixupBWInsts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/X86/X86FixupBWInsts.cpp')
-rw-r--r--lib/Target/X86/X86FixupBWInsts.cpp153
1 files changed, 71 insertions, 82 deletions
diff --git a/lib/Target/X86/X86FixupBWInsts.cpp b/lib/Target/X86/X86FixupBWInsts.cpp
index 01d10fe4cae4..855ea683a8af 100644
--- a/lib/Target/X86/X86FixupBWInsts.cpp
+++ b/lib/Target/X86/X86FixupBWInsts.cpp
@@ -166,49 +166,75 @@ bool FixupBWInstPass::runOnMachineFunction(MachineFunction &MF) {
return true;
}
-/// Check if register \p Reg is live after the \p MI.
-///
-/// \p LiveRegs should be in a state describing liveness information in
-/// that exact place as this function tries to precise analysis made
-/// by \p LiveRegs by exploiting the information about particular
-/// instruction \p MI. \p MI is expected to be one of the MOVs handled
-/// by the x86FixupBWInsts pass.
-/// Note: similar to LivePhysRegs::contains this would state that
-/// super-register is not used if only some part of it is used.
-///
-/// X86 backend does not have subregister liveness tracking enabled,
-/// so liveness information might be overly conservative. However, for
-/// some specific instructions (this pass only cares about MOVs) we can
-/// produce more precise results by analysing that MOV's operands.
-///
-/// Indeed, if super-register is not live before the mov it means that it
-/// was originally <read-undef> and so we are free to modify these
-/// undef upper bits. That may happen in case where the use is in another MBB
-/// and the vreg/physreg corresponding to the move has higher width than
-/// necessary (e.g. due to register coalescing with a "truncate" copy).
-/// So, it handles pattern like this:
-///
-/// %bb.2: derived from LLVM BB %if.then
-/// Live Ins: %rdi
-/// Predecessors according to CFG: %bb.0
-/// %ax = MOV16rm killed %rdi, 1, %noreg, 0, %noreg, implicit-def %eax;
-/// mem:LD2[%p]
-/// No implicit %eax
-/// Successors according to CFG: %bb.3(?%)
+/// \brief Check if after \p OrigMI the only portion of super register
+/// of the destination register of \p OrigMI that is alive is that
+/// destination register.
///
-/// %bb.3: derived from LLVM BB %if.end
-/// Live Ins: %eax Only %ax is actually live
-/// Predecessors according to CFG: %bb.2 %bb.1
-/// %ax = KILL %ax, implicit killed %eax
-/// RET 0, %ax
-static bool isLive(const MachineInstr &MI,
- const LivePhysRegs &LiveRegs,
- const TargetRegisterInfo *TRI,
- unsigned Reg) {
- if (!LiveRegs.contains(Reg))
+/// If so, return that super register in \p SuperDestReg.
+bool FixupBWInstPass::getSuperRegDestIfDead(MachineInstr *OrigMI,
+ unsigned &SuperDestReg) const {
+ auto *TRI = &TII->getRegisterInfo();
+
+ unsigned OrigDestReg = OrigMI->getOperand(0).getReg();
+ SuperDestReg = getX86SubSuperRegister(OrigDestReg, 32);
+
+ const auto SubRegIdx = TRI->getSubRegIndex(SuperDestReg, OrigDestReg);
+
+ // Make sure that the sub-register that this instruction has as its
+ // destination is the lowest order sub-register of the super-register.
+ // If it isn't, then the register isn't really dead even if the
+ // super-register is considered dead.
+ if (SubRegIdx == X86::sub_8bit_hi)
return false;
- unsigned Opc = MI.getOpcode(); (void)Opc;
+ // If neither the destination-super register nor any applicable subregisters
+ // are live after this instruction, then the super register is safe to use.
+ if (!LiveRegs.contains(SuperDestReg)) {
+ // If the original destination register was not the low 8-bit subregister
+ // then the super register check is sufficient.
+ if (SubRegIdx != X86::sub_8bit)
+ return true;
+ // If the original destination register was the low 8-bit subregister and
+ // we also need to check the 16-bit subregister and the high 8-bit
+ // subregister.
+ if (!LiveRegs.contains(getX86SubSuperRegister(OrigDestReg, 16)) &&
+ !LiveRegs.contains(getX86SubSuperRegister(SuperDestReg, 8,
+ /*High=*/true)))
+ return true;
+ // Otherwise, we have a little more checking to do.
+ }
+
+ // If we get here, the super-register destination (or some part of it) is
+ // marked as live after the original instruction.
+ //
+ // The X86 backend does not have subregister liveness tracking enabled,
+ // so liveness information might be overly conservative. Specifically, the
+ // super register might be marked as live because it is implicitly defined
+ // by the instruction we are examining.
+ //
+ // However, for some specific instructions (this pass only cares about MOVs)
+ // we can produce more precise results by analysing that MOV's operands.
+ //
+ // Indeed, if super-register is not live before the mov it means that it
+ // was originally <read-undef> and so we are free to modify these
+ // undef upper bits. That may happen in case where the use is in another MBB
+ // and the vreg/physreg corresponding to the move has higher width than
+ // necessary (e.g. due to register coalescing with a "truncate" copy).
+ // So, we would like to handle patterns like this:
+ //
+ // %bb.2: derived from LLVM BB %if.then
+ // Live Ins: %rdi
+ // Predecessors according to CFG: %bb.0
+ // %ax<def> = MOV16rm killed %rdi, 1, %noreg, 0, %noreg, implicit-def %eax
+ // ; No implicit %eax
+ // Successors according to CFG: %bb.3(?%)
+ //
+ // %bb.3: derived from LLVM BB %if.end
+ // Live Ins: %eax Only %ax is actually live
+ // Predecessors according to CFG: %bb.2 %bb.1
+ // %ax = KILL %ax, implicit killed %eax
+ // RET 0, %ax
+ unsigned Opc = OrigMI->getOpcode(); (void)Opc;
// These are the opcodes currently handled by the pass, if something
// else will be added we need to ensure that new opcode has the same
// properties.
@@ -217,65 +243,28 @@ static bool isLive(const MachineInstr &MI,
"Unexpected opcode.");
bool IsDefined = false;
- for (auto &MO: MI.implicit_operands()) {
+ for (auto &MO: OrigMI->implicit_operands()) {
if (!MO.isReg())
continue;
assert((MO.isDef() || MO.isUse()) && "Expected Def or Use only!");
- for (MCSuperRegIterator Supers(Reg, TRI, true); Supers.isValid(); ++Supers) {
+ for (MCSuperRegIterator Supers(OrigDestReg, TRI, true); Supers.isValid();
+ ++Supers) {
if (*Supers == MO.getReg()) {
if (MO.isDef())
IsDefined = true;
else
- return true; // SuperReg Imp-used' -> live before the MI
+ return false; // SuperReg Imp-used' -> live before the MI
}
}
}
// Reg is not Imp-def'ed -> it's live both before/after the instruction.
if (!IsDefined)
- return true;
+ return false;
// Otherwise, the Reg is not live before the MI and the MOV can't
// make it really live, so it's in fact dead even after the MI.
- return false;
-}
-
-/// \brief Check if after \p OrigMI the only portion of super register
-/// of the destination register of \p OrigMI that is alive is that
-/// destination register.
-///
-/// If so, return that super register in \p SuperDestReg.
-bool FixupBWInstPass::getSuperRegDestIfDead(MachineInstr *OrigMI,
- unsigned &SuperDestReg) const {
- auto *TRI = &TII->getRegisterInfo();
-
- unsigned OrigDestReg = OrigMI->getOperand(0).getReg();
- SuperDestReg = getX86SubSuperRegister(OrigDestReg, 32);
-
- const auto SubRegIdx = TRI->getSubRegIndex(SuperDestReg, OrigDestReg);
-
- // Make sure that the sub-register that this instruction has as its
- // destination is the lowest order sub-register of the super-register.
- // If it isn't, then the register isn't really dead even if the
- // super-register is considered dead.
- if (SubRegIdx == X86::sub_8bit_hi)
- return false;
-
- if (isLive(*OrigMI, LiveRegs, TRI, SuperDestReg))
- return false;
-
- if (SubRegIdx == X86::sub_8bit) {
- // In the case of byte registers, we also have to check that the upper
- // byte register is also dead. That is considered to be independent of
- // whether the super-register is dead.
- unsigned UpperByteReg =
- getX86SubSuperRegister(SuperDestReg, 8, /*High=*/true);
-
- if (isLive(*OrigMI, LiveRegs, TRI, UpperByteReg))
- return false;
- }
-
return true;
}