mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:40:38 +00:00
[X86] Use LivePhysRegs in X86FixupBWInsts.
Kill-flags, which computeRegisterLiveness uses, are not reliable. LivePhysRegs is. Differential Revision: http://reviews.llvm.org/D19472 llvm-svn: 267495
This commit is contained in:
parent
504105c02c
commit
b6c12fe106
@ -49,7 +49,7 @@
|
|||||||
#include "X86InstrInfo.h"
|
#include "X86InstrInfo.h"
|
||||||
#include "X86Subtarget.h"
|
#include "X86Subtarget.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/CodeGen/LiveVariables.h"
|
#include "llvm/CodeGen/LivePhysRegs.h"
|
||||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||||
@ -81,7 +81,7 @@ class FixupBWInstPass : public MachineFunctionPass {
|
|||||||
/// \brief Loop over all of the instructions in the basic block
|
/// \brief Loop over all of the instructions in the basic block
|
||||||
/// replacing applicable byte or word instructions with better
|
/// replacing applicable byte or word instructions with better
|
||||||
/// alternatives.
|
/// alternatives.
|
||||||
void processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
void processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
|
||||||
|
|
||||||
/// \brief This sets the \p SuperDestReg to the 32 bit super reg
|
/// \brief This sets the \p SuperDestReg to the 32 bit super reg
|
||||||
/// of the original destination register of the MachineInstr
|
/// of the original destination register of the MachineInstr
|
||||||
@ -128,6 +128,9 @@ private:
|
|||||||
|
|
||||||
/// Machine loop info used for guiding some heruistics.
|
/// Machine loop info used for guiding some heruistics.
|
||||||
MachineLoopInfo *MLI;
|
MachineLoopInfo *MLI;
|
||||||
|
|
||||||
|
/// Register Liveness information after the current instruction.
|
||||||
|
LivePhysRegs LiveRegs;
|
||||||
};
|
};
|
||||||
char FixupBWInstPass::ID = 0;
|
char FixupBWInstPass::ID = 0;
|
||||||
}
|
}
|
||||||
@ -142,6 +145,7 @@ bool FixupBWInstPass::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
TII = MF.getSubtarget<X86Subtarget>().getInstrInfo();
|
TII = MF.getSubtarget<X86Subtarget>().getInstrInfo();
|
||||||
OptForSize = MF.getFunction()->optForSize();
|
OptForSize = MF.getFunction()->optForSize();
|
||||||
MLI = &getAnalysis<MachineLoopInfo>();
|
MLI = &getAnalysis<MachineLoopInfo>();
|
||||||
|
LiveRegs.init(&TII->getRegisterInfo());
|
||||||
|
|
||||||
DEBUG(dbgs() << "Start X86FixupBWInsts\n";);
|
DEBUG(dbgs() << "Start X86FixupBWInsts\n";);
|
||||||
|
|
||||||
@ -181,11 +185,7 @@ bool FixupBWInstPass::getSuperRegDestIfDead(MachineInstr *OrigMI,
|
|||||||
if (getX86SubSuperRegister(SuperDestReg, OrigDestSize) != OrigDestReg)
|
if (getX86SubSuperRegister(SuperDestReg, OrigDestSize) != OrigDestReg)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MachineBasicBlock::LivenessQueryResult LQR =
|
if (LiveRegs.contains(SuperDestReg))
|
||||||
OrigMI->getParent()->computeRegisterLiveness(&TII->getRegisterInfo(),
|
|
||||||
SuperDestReg, OrigMI);
|
|
||||||
|
|
||||||
if (LQR != MachineBasicBlock::LQR_Dead)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (OrigDestSize == 8) {
|
if (OrigDestSize == 8) {
|
||||||
@ -194,9 +194,7 @@ bool FixupBWInstPass::getSuperRegDestIfDead(MachineInstr *OrigMI,
|
|||||||
// whether the super-register is dead.
|
// whether the super-register is dead.
|
||||||
unsigned UpperByteReg = getX86SubSuperRegister(SuperDestReg, 8, true);
|
unsigned UpperByteReg = getX86SubSuperRegister(SuperDestReg, 8, true);
|
||||||
|
|
||||||
LQR = OrigMI->getParent()->computeRegisterLiveness(&TII->getRegisterInfo(),
|
if (LiveRegs.contains(UpperByteReg))
|
||||||
UpperByteReg, OrigMI);
|
|
||||||
if (LQR != MachineBasicBlock::LQR_Dead)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +227,7 @@ MachineInstr *FixupBWInstPass::tryReplaceLoad(unsigned New32BitOpcode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FixupBWInstPass::processBasicBlock(MachineFunction &MF,
|
void FixupBWInstPass::processBasicBlock(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) {
|
||||||
|
|
||||||
// This algorithm doesn't delete the instructions it is replacing
|
// This algorithm doesn't delete the instructions it is replacing
|
||||||
// right away. By leaving the existing instructions in place, the
|
// right away. By leaving the existing instructions in place, the
|
||||||
@ -243,9 +241,14 @@ void FixupBWInstPass::processBasicBlock(MachineFunction &MF,
|
|||||||
// from making it seem as if the larger register might be live.
|
// from making it seem as if the larger register might be live.
|
||||||
SmallVector<std::pair<MachineInstr *, MachineInstr *>, 8> MIReplacements;
|
SmallVector<std::pair<MachineInstr *, MachineInstr *>, 8> MIReplacements;
|
||||||
|
|
||||||
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
|
// Start computing liveness for this block. We iterate from the end to be able
|
||||||
|
// to update this for each instruction.
|
||||||
|
LiveRegs.clear();
|
||||||
|
LiveRegs.addLiveOuts(&MBB);
|
||||||
|
|
||||||
|
for (auto I = MBB.rbegin(); I != MBB.rend(); ++I) {
|
||||||
MachineInstr *NewMI = nullptr;
|
MachineInstr *NewMI = nullptr;
|
||||||
MachineInstr *MI = I;
|
MachineInstr *MI = &*I;
|
||||||
|
|
||||||
// See if this is an instruction of the type we are currently looking for.
|
// See if this is an instruction of the type we are currently looking for.
|
||||||
switch (MI->getOpcode()) {
|
switch (MI->getOpcode()) {
|
||||||
@ -275,6 +278,9 @@ void FixupBWInstPass::processBasicBlock(MachineFunction &MF,
|
|||||||
|
|
||||||
if (NewMI)
|
if (NewMI)
|
||||||
MIReplacements.push_back(std::make_pair(MI, NewMI));
|
MIReplacements.push_back(std::make_pair(MI, NewMI));
|
||||||
|
|
||||||
|
// We're done with this instruction, update liveness for the next one.
|
||||||
|
LiveRegs.stepBackward(*MI);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!MIReplacements.empty()) {
|
while (!MIReplacements.empty()) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+avx -fixup-byte-word-insts=1 < %s | FileCheck -check-prefix=CHECK -check-prefix=BWON %s
|
; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+avx -fixup-byte-word-insts=1 < %s | FileCheck -check-prefix=CHECK -check-prefix=BWON %s
|
||||||
; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+avx -fixup-byte-word-insts=0 < %s | FileCheck -check-prefix=CHECK -check-prefix=BWOFF %s
|
; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+avx -fixup-byte-word-insts=0 < %s | FileCheck -check-prefix=CHECK -check-prefix=BWOFF %s
|
||||||
; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+avx -addr-sink-using-gep=1 < %s | FileCheck %s
|
; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+avx -addr-sink-using-gep=1 < %s | FileCheck -check-prefix=CHECK -check-prefix=BWON %s
|
||||||
|
|
||||||
%struct.A = type { i8, i8, i8, i8, i8, i8, i8, i8 }
|
%struct.A = type { i8, i8, i8, i8, i8, i8, i8, i8 }
|
||||||
%struct.B = type { i32, i32, i32, i32, i32, i32, i32, i32 }
|
%struct.B = type { i32, i32, i32, i32, i32, i32, i32, i32 }
|
||||||
@ -185,7 +185,8 @@ define void @merge_loads_i16(i32 %count, %struct.A* noalias nocapture %q, %struc
|
|||||||
; BWON: movzbl
|
; BWON: movzbl
|
||||||
; BWOFF: movb
|
; BWOFF: movb
|
||||||
; CHECK: movb
|
; CHECK: movb
|
||||||
; CHECK: movb
|
; BWON: movzbl
|
||||||
|
; BWOFF: movb
|
||||||
; CHECK: movb
|
; CHECK: movb
|
||||||
; CHECK: ret
|
; CHECK: ret
|
||||||
define void @no_merge_loads(i32 %count, %struct.A* noalias nocapture %q, %struct.A* noalias nocapture %p) nounwind uwtable noinline ssp {
|
define void @no_merge_loads(i32 %count, %struct.A* noalias nocapture %q, %struct.A* noalias nocapture %p) nounwind uwtable noinline ssp {
|
||||||
@ -340,8 +341,9 @@ block4: ; preds = %4, %.lr.ph
|
|||||||
; Make sure that we merge the consecutive load/store sequence below and use a
|
; Make sure that we merge the consecutive load/store sequence below and use a
|
||||||
; word (16 bit) instead of a byte copy.
|
; word (16 bit) instead of a byte copy.
|
||||||
; CHECK-LABEL: MergeLoadStoreBaseIndexOffset:
|
; CHECK-LABEL: MergeLoadStoreBaseIndexOffset:
|
||||||
; CHECK: movw (%{{.*}},%{{.*}}), [[REG:%[a-z]+]]
|
; BWON: movzwl (%{{.*}},%{{.*}}), %e[[REG:[a-z]+]]
|
||||||
; CHECK: movw [[REG]], (%{{.*}})
|
; BWOFF: movw (%{{.*}},%{{.*}}), %[[REG:[a-z]+]]
|
||||||
|
; CHECK: movw %[[REG]], (%{{.*}})
|
||||||
define void @MergeLoadStoreBaseIndexOffset(i64* %a, i8* %b, i8* %c, i32 %n) {
|
define void @MergeLoadStoreBaseIndexOffset(i64* %a, i8* %b, i8* %c, i32 %n) {
|
||||||
br label %1
|
br label %1
|
||||||
|
|
||||||
@ -372,8 +374,9 @@ define void @MergeLoadStoreBaseIndexOffset(i64* %a, i8* %b, i8* %c, i32 %n) {
|
|||||||
; word (16 bit) instead of a byte copy even if there are intermediate sign
|
; word (16 bit) instead of a byte copy even if there are intermediate sign
|
||||||
; extensions.
|
; extensions.
|
||||||
; CHECK-LABEL: MergeLoadStoreBaseIndexOffsetSext:
|
; CHECK-LABEL: MergeLoadStoreBaseIndexOffsetSext:
|
||||||
; CHECK: movw (%{{.*}},%{{.*}}), [[REG:%[a-z]+]]
|
; BWON: movzwl (%{{.*}},%{{.*}}), %e[[REG:[a-z]+]]
|
||||||
; CHECK: movw [[REG]], (%{{.*}})
|
; BWOFF: movw (%{{.*}},%{{.*}}), %[[REG:[a-z]+]]
|
||||||
|
; CHECK: movw %[[REG]], (%{{.*}})
|
||||||
define void @MergeLoadStoreBaseIndexOffsetSext(i8* %a, i8* %b, i8* %c, i32 %n) {
|
define void @MergeLoadStoreBaseIndexOffsetSext(i8* %a, i8* %b, i8* %c, i32 %n) {
|
||||||
br label %1
|
br label %1
|
||||||
|
|
||||||
|
@ -11,8 +11,6 @@ target triple = "x86_64-apple-macosx10.8.0"
|
|||||||
; This has byte loads interspersed with byte stores, in a single
|
; This has byte loads interspersed with byte stores, in a single
|
||||||
; basic-block loop. The upper portion should be dead, so the movb loads
|
; basic-block loop. The upper portion should be dead, so the movb loads
|
||||||
; should have been changed into movzbl instead.
|
; should have been changed into movzbl instead.
|
||||||
; TODO: The second movb load doesn't get fixed due to register liveness
|
|
||||||
; not being accurate enough.
|
|
||||||
; CHECK-LABEL: foo1
|
; CHECK-LABEL: foo1
|
||||||
; load:
|
; load:
|
||||||
; BWON: movzbl
|
; BWON: movzbl
|
||||||
@ -20,7 +18,8 @@ target triple = "x86_64-apple-macosx10.8.0"
|
|||||||
; store:
|
; store:
|
||||||
; CHECK: movb
|
; CHECK: movb
|
||||||
; load:
|
; load:
|
||||||
; CHECK: movb
|
; BWON: movzbl
|
||||||
|
; BWOFF: movb
|
||||||
; store:
|
; store:
|
||||||
; CHECK: movb
|
; CHECK: movb
|
||||||
; CHECK: ret
|
; CHECK: ret
|
||||||
@ -59,8 +58,6 @@ a4: ; preds = %4, %.lr.ph
|
|||||||
; This has word loads interspersed with word stores.
|
; This has word loads interspersed with word stores.
|
||||||
; The upper portion should be dead, so the movw loads should have
|
; The upper portion should be dead, so the movw loads should have
|
||||||
; been changed into movzwl instead.
|
; been changed into movzwl instead.
|
||||||
; TODO: The second movw load doesn't get fixed due to register liveness
|
|
||||||
; not being accurate enough.
|
|
||||||
; CHECK-LABEL: foo2
|
; CHECK-LABEL: foo2
|
||||||
; load:
|
; load:
|
||||||
; BWON: movzwl
|
; BWON: movzwl
|
||||||
@ -68,7 +65,8 @@ a4: ; preds = %4, %.lr.ph
|
|||||||
; store:
|
; store:
|
||||||
; CHECK: movw
|
; CHECK: movw
|
||||||
; load:
|
; load:
|
||||||
; CHECK: movw
|
; BWON: movzwl
|
||||||
|
; BWOFF: movw
|
||||||
; store:
|
; store:
|
||||||
; CHECK: movw
|
; CHECK: movw
|
||||||
; CHECK: ret
|
; CHECK: ret
|
||||||
|
@ -6,7 +6,10 @@
|
|||||||
; RUN: FileCheck -check-prefix=CHECK -check-prefix=BWOFF %s
|
; RUN: FileCheck -check-prefix=CHECK -check-prefix=BWOFF %s
|
||||||
; RUN: llc < %s -mtriple=i686-unknown-linux-gnu -fixup-byte-word-insts=1 | \
|
; RUN: llc < %s -mtriple=i686-unknown-linux-gnu -fixup-byte-word-insts=1 | \
|
||||||
; RUN: FileCheck -check-prefix=CHECK -check-prefix=BWON %s
|
; RUN: FileCheck -check-prefix=CHECK -check-prefix=BWON %s
|
||||||
; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck -check-prefix=DARWIN %s
|
; RUN: llc < %s -mtriple=x86_64-apple-darwin -fixup-byte-word-insts=0 | \
|
||||||
|
; RUN: FileCheck -check-prefix=DARWIN -check-prefix=DARWIN-BWOFF %s
|
||||||
|
; RUN: llc < %s -mtriple=x86_64-apple-darwin -fixup-byte-word-insts=1 | \
|
||||||
|
; RUN: FileCheck -check-prefix=DARWIN -check-prefix=DARWIN-BWON %s
|
||||||
|
|
||||||
|
|
||||||
@x = common global i32 0, align 4
|
@x = common global i32 0, align 4
|
||||||
@ -84,7 +87,8 @@ entry:
|
|||||||
|
|
||||||
; Except on Darwin, for legay reasons.
|
; Except on Darwin, for legay reasons.
|
||||||
; DARWIN-LABEL: unsigned_i16:
|
; DARWIN-LABEL: unsigned_i16:
|
||||||
; DARWIN: movw
|
; DARWIN-BWOFF: movw
|
||||||
|
; DARWIN-BWON: movzwl
|
||||||
; DARWIN-NEXT: addw
|
; DARWIN-NEXT: addw
|
||||||
; DARWIN-NEXT: movzwl
|
; DARWIN-NEXT: movzwl
|
||||||
; DARWIN-NEXT: ret
|
; DARWIN-NEXT: ret
|
||||||
|
Loading…
Reference in New Issue
Block a user