#include "X86InstrInfo.h"
#include "X86Subtarget.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/CodeGen/LiveVariables.h"
+#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
/// \brief Loop over all of the instructions in the basic block
/// replacing applicable byte or word instructions with better
/// 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
/// of the original destination register of the MachineInstr
/// Machine loop info used for guiding some heruistics.
MachineLoopInfo *MLI;
+
+ /// Register Liveness information after the current instruction.
+ LivePhysRegs LiveRegs;
};
char FixupBWInstPass::ID = 0;
}
TII = MF.getSubtarget<X86Subtarget>().getInstrInfo();
OptForSize = MF.getFunction()->optForSize();
MLI = &getAnalysis<MachineLoopInfo>();
+ LiveRegs.init(&TII->getRegisterInfo());
DEBUG(dbgs() << "Start X86FixupBWInsts\n";);
if (getX86SubSuperRegister(SuperDestReg, OrigDestSize) != OrigDestReg)
return false;
- MachineBasicBlock::LivenessQueryResult LQR =
- OrigMI->getParent()->computeRegisterLiveness(&TII->getRegisterInfo(),
- SuperDestReg, OrigMI);
-
- if (LQR != MachineBasicBlock::LQR_Dead)
+ if (LiveRegs.contains(SuperDestReg))
return false;
if (OrigDestSize == 8) {
// whether the super-register is dead.
unsigned UpperByteReg = getX86SubSuperRegister(SuperDestReg, 8, true);
- LQR = OrigMI->getParent()->computeRegisterLiveness(&TII->getRegisterInfo(),
- UpperByteReg, OrigMI);
- if (LQR != MachineBasicBlock::LQR_Dead)
+ if (LiveRegs.contains(UpperByteReg))
return false;
}
}
void FixupBWInstPass::processBasicBlock(MachineFunction &MF,
- MachineBasicBlock &MBB) const {
+ MachineBasicBlock &MBB) {
// This algorithm doesn't delete the instructions it is replacing
// right away. By leaving the existing instructions in place, the
// from making it seem as if the larger register might be live.
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 *MI = I;
+ MachineInstr *MI = &*I;
// See if this is an instruction of the type we are currently looking for.
switch (MI->getOpcode()) {
if (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()) {
; 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 -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.B = type { i32, i32, i32, i32, i32, i32, i32, i32 }
; BWON: movzbl
; BWOFF: movb
; CHECK: movb
-; CHECK: movb
+; BWON: movzbl
+; BWOFF: movb
; CHECK: movb
; CHECK: ret
define void @no_merge_loads(i32 %count, %struct.A* noalias nocapture %q, %struct.A* noalias nocapture %p) nounwind uwtable noinline ssp {
; Make sure that we merge the consecutive load/store sequence below and use a
; word (16 bit) instead of a byte copy.
; CHECK-LABEL: MergeLoadStoreBaseIndexOffset:
-; CHECK: movw (%{{.*}},%{{.*}}), [[REG:%[a-z]+]]
-; CHECK: movw [[REG]], (%{{.*}})
+; BWON: movzwl (%{{.*}},%{{.*}}), %e[[REG:[a-z]+]]
+; BWOFF: movw (%{{.*}},%{{.*}}), %[[REG:[a-z]+]]
+; CHECK: movw %[[REG]], (%{{.*}})
define void @MergeLoadStoreBaseIndexOffset(i64* %a, i8* %b, i8* %c, i32 %n) {
br label %1
; word (16 bit) instead of a byte copy even if there are intermediate sign
; extensions.
; CHECK-LABEL: MergeLoadStoreBaseIndexOffsetSext:
-; CHECK: movw (%{{.*}},%{{.*}}), [[REG:%[a-z]+]]
-; CHECK: movw [[REG]], (%{{.*}})
+; BWON: movzwl (%{{.*}},%{{.*}}), %e[[REG:[a-z]+]]
+; BWOFF: movw (%{{.*}},%{{.*}}), %[[REG:[a-z]+]]
+; CHECK: movw %[[REG]], (%{{.*}})
define void @MergeLoadStoreBaseIndexOffsetSext(i8* %a, i8* %b, i8* %c, i32 %n) {
br label %1
; This has byte loads interspersed with byte stores, in a single
; basic-block loop. The upper portion should be dead, so the movb loads
; 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
; load:
; BWON: movzbl
; store:
; CHECK: movb
; load:
-; CHECK: movb
+; BWON: movzbl
+; BWOFF: movb
; store:
; CHECK: movb
; CHECK: ret
; This has word loads interspersed with word stores.
; The upper portion should be dead, so the movw loads should have
; 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
; load:
; BWON: movzwl
; store:
; CHECK: movw
; load:
-; CHECK: movw
+; BWON: movzwl
+; BWOFF: movw
; store:
; CHECK: movw
; CHECK: ret
; RUN: FileCheck -check-prefix=CHECK -check-prefix=BWOFF %s
; RUN: llc < %s -mtriple=i686-unknown-linux-gnu -fixup-byte-word-insts=1 | \
; 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
; Except on Darwin, for legay reasons.
; DARWIN-LABEL: unsigned_i16:
-; DARWIN: movw
+; DARWIN-BWOFF: movw
+; DARWIN-BWON: movzwl
; DARWIN-NEXT: addw
; DARWIN-NEXT: movzwl
; DARWIN-NEXT: ret