forked from OSchip/llvm-project
Make TwoAddressInstructionPass::rescheduleMIBelowKill subreg-aware
This fixes PR28824. Differential Revision: https://reviews.llvm.org/D23220 llvm-svn: 278370
This commit is contained in:
parent
56684d4538
commit
e36d7716c3
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/SmallSet.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/Analysis/AliasAnalysis.h"
|
#include "llvm/Analysis/AliasAnalysis.h"
|
||||||
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
||||||
|
@ -539,6 +539,16 @@ regsAreCompatible(unsigned RegA, unsigned RegB, const TargetRegisterInfo *TRI) {
|
||||||
return TRI->regsOverlap(RegA, RegB);
|
return TRI->regsOverlap(RegA, RegB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if Reg is equal or aliased to at least one register in Set.
|
||||||
|
static bool regOverlapsSet(const SmallVectorImpl<unsigned> &Set, unsigned Reg,
|
||||||
|
const TargetRegisterInfo *TRI) {
|
||||||
|
for (unsigned R : Set)
|
||||||
|
if (TRI->regsOverlap(R, Reg))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// Return true if it's potentially profitable to commute the two-address
|
/// Return true if it's potentially profitable to commute the two-address
|
||||||
/// instruction that's being processed.
|
/// instruction that's being processed.
|
||||||
bool
|
bool
|
||||||
|
@ -864,9 +874,9 @@ rescheduleMIBelowKill(MachineBasicBlock::iterator &mi,
|
||||||
// FIXME: Needs more sophisticated heuristics.
|
// FIXME: Needs more sophisticated heuristics.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SmallSet<unsigned, 2> Uses;
|
SmallVector<unsigned, 2> Uses;
|
||||||
SmallSet<unsigned, 2> Kills;
|
SmallVector<unsigned, 2> Kills;
|
||||||
SmallSet<unsigned, 2> Defs;
|
SmallVector<unsigned, 2> Defs;
|
||||||
for (const MachineOperand &MO : MI->operands()) {
|
for (const MachineOperand &MO : MI->operands()) {
|
||||||
if (!MO.isReg())
|
if (!MO.isReg())
|
||||||
continue;
|
continue;
|
||||||
|
@ -874,12 +884,12 @@ rescheduleMIBelowKill(MachineBasicBlock::iterator &mi,
|
||||||
if (!MOReg)
|
if (!MOReg)
|
||||||
continue;
|
continue;
|
||||||
if (MO.isDef())
|
if (MO.isDef())
|
||||||
Defs.insert(MOReg);
|
Defs.push_back(MOReg);
|
||||||
else {
|
else {
|
||||||
Uses.insert(MOReg);
|
Uses.push_back(MOReg);
|
||||||
if (MOReg != Reg && (MO.isKill() ||
|
if (MOReg != Reg && (MO.isKill() ||
|
||||||
(LIS && isPlainlyKilled(MI, MOReg, LIS))))
|
(LIS && isPlainlyKilled(MI, MOReg, LIS))))
|
||||||
Kills.insert(MOReg);
|
Kills.push_back(MOReg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,8 +898,9 @@ rescheduleMIBelowKill(MachineBasicBlock::iterator &mi,
|
||||||
MachineBasicBlock::iterator AfterMI = std::next(Begin);
|
MachineBasicBlock::iterator AfterMI = std::next(Begin);
|
||||||
|
|
||||||
MachineBasicBlock::iterator End = AfterMI;
|
MachineBasicBlock::iterator End = AfterMI;
|
||||||
while (End->isCopy() && Defs.count(End->getOperand(1).getReg())) {
|
while (End->isCopy() &&
|
||||||
Defs.insert(End->getOperand(0).getReg());
|
regOverlapsSet(Defs, End->getOperand(1).getReg(), TRI)) {
|
||||||
|
Defs.push_back(End->getOperand(0).getReg());
|
||||||
++End;
|
++End;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,21 +926,21 @@ rescheduleMIBelowKill(MachineBasicBlock::iterator &mi,
|
||||||
if (!MOReg)
|
if (!MOReg)
|
||||||
continue;
|
continue;
|
||||||
if (MO.isDef()) {
|
if (MO.isDef()) {
|
||||||
if (Uses.count(MOReg))
|
if (regOverlapsSet(Uses, MOReg, TRI))
|
||||||
// Physical register use would be clobbered.
|
// Physical register use would be clobbered.
|
||||||
return false;
|
return false;
|
||||||
if (!MO.isDead() && Defs.count(MOReg))
|
if (!MO.isDead() && regOverlapsSet(Defs, MOReg, TRI))
|
||||||
// May clobber a physical register def.
|
// May clobber a physical register def.
|
||||||
// FIXME: This may be too conservative. It's ok if the instruction
|
// FIXME: This may be too conservative. It's ok if the instruction
|
||||||
// is sunken completely below the use.
|
// is sunken completely below the use.
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (Defs.count(MOReg))
|
if (regOverlapsSet(Defs, MOReg, TRI))
|
||||||
return false;
|
return false;
|
||||||
bool isKill =
|
bool isKill =
|
||||||
MO.isKill() || (LIS && isPlainlyKilled(&OtherMI, MOReg, LIS));
|
MO.isKill() || (LIS && isPlainlyKilled(&OtherMI, MOReg, LIS));
|
||||||
if (MOReg != Reg &&
|
if (MOReg != Reg && ((isKill && regOverlapsSet(Uses, MOReg, TRI)) ||
|
||||||
((isKill && Uses.count(MOReg)) || Kills.count(MOReg)))
|
regOverlapsSet(Kills, MOReg, TRI)))
|
||||||
// Don't want to extend other live ranges and update kills.
|
// Don't want to extend other live ranges and update kills.
|
||||||
return false;
|
return false;
|
||||||
if (MOReg == Reg && !isKill)
|
if (MOReg == Reg && !isKill)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
; RUN: llc < %s -mtriple=i386-unknown-linux-gnu | FileCheck %s
|
||||||
|
|
||||||
|
@d = global i32 0, align 4
|
||||||
|
|
||||||
|
; Verify the sar happens before ecx is clobbered with the parameter being
|
||||||
|
; passed to fn3
|
||||||
|
; CHECK-LABEL: fn4
|
||||||
|
; CHECK: movb d, %cl
|
||||||
|
; CHECK: sarl %cl
|
||||||
|
; CHECK: movl $2, %ecx
|
||||||
|
define i32 @fn4(i32 %i) #0 {
|
||||||
|
entry:
|
||||||
|
%0 = load i32, i32* @d, align 4
|
||||||
|
%shr = ashr i32 %i, %0
|
||||||
|
tail call fastcc void @fn3(i32 2, i32 5, i32 %shr, i32 %i)
|
||||||
|
%cmp = icmp slt i32 %shr, 1
|
||||||
|
%. = zext i1 %cmp to i32
|
||||||
|
ret i32 %.
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @fn3(i32 %p1, i32 %p2, i32 %p3, i32 %p4) #0
|
||||||
|
|
||||||
|
attributes #0 = { nounwind }
|
Loading…
Reference in New Issue