mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
Merge information about the number of zero, one, and sign bits of live-out
registers at phis. This enables us to eliminate a lot of pointless zexts during the DAGCombine phase. This fixes <rdar://problem/8760114>. llvm-svn: 126380
This commit is contained in:
parent
af4779907f
commit
724eb8706a
@ -159,6 +159,13 @@ public:
|
||||
return LOI;
|
||||
}
|
||||
|
||||
/// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the
|
||||
/// register is a PHI destination and the PHI's LiveOutInfo is not valid. If
|
||||
/// the register's LiveOutInfo is for a smaller bit width, it is extended to
|
||||
/// the larger bit width by zero extension. The bit width must be no smaller
|
||||
/// than the LiveOutInfo's existing bit width.
|
||||
const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth);
|
||||
|
||||
/// AddLiveOutRegInfo - Adds LiveOutInfo for a register.
|
||||
void AddLiveOutRegInfo(unsigned Reg, unsigned NumSignBits,
|
||||
const APInt &KnownZero, const APInt &KnownOne) {
|
||||
@ -173,6 +180,10 @@ public:
|
||||
LOI.KnownZero = KnownZero;
|
||||
}
|
||||
|
||||
/// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination
|
||||
/// register based on the LiveOutInfo of its operands.
|
||||
void ComputePHILiveOutRegInfo(const PHINode*);
|
||||
|
||||
/// InvalidatePHILiveOutRegInfo - Invalidates a PHI's LiveOutInfo, to be
|
||||
/// called when a block is visited before all of its predecessors.
|
||||
void InvalidatePHILiveOutRegInfo(const PHINode *PN) {
|
||||
|
@ -255,6 +255,122 @@ unsigned FunctionLoweringInfo::CreateRegs(const Type *Ty) {
|
||||
return FirstReg;
|
||||
}
|
||||
|
||||
/// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the
|
||||
/// register is a PHI destination and the PHI's LiveOutInfo is not valid. If
|
||||
/// the register's LiveOutInfo is for a smaller bit width, it is extended to
|
||||
/// the larger bit width by zero extension. The bit width must be no smaller
|
||||
/// than the LiveOutInfo's existing bit width.
|
||||
const FunctionLoweringInfo::LiveOutInfo *
|
||||
FunctionLoweringInfo::GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth) {
|
||||
if (!LiveOutRegInfo.inBounds(Reg))
|
||||
return NULL;
|
||||
|
||||
LiveOutInfo *LOI = &LiveOutRegInfo[Reg];
|
||||
if (!LOI->IsValid)
|
||||
return NULL;
|
||||
|
||||
if (BitWidth >= LOI->KnownZero.getBitWidth()) {
|
||||
LOI->KnownZero = LOI->KnownZero.zextOrTrunc(BitWidth);
|
||||
LOI->KnownOne = LOI->KnownOne.zextOrTrunc(BitWidth);
|
||||
}
|
||||
|
||||
return LOI;
|
||||
}
|
||||
|
||||
/// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination
|
||||
/// register based on the LiveOutInfo of its operands.
|
||||
void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) {
|
||||
const Type *Ty = PN->getType();
|
||||
if (!Ty->isIntegerTy() || Ty->isVectorTy())
|
||||
return;
|
||||
|
||||
SmallVector<EVT, 1> ValueVTs;
|
||||
ComputeValueVTs(TLI, Ty, ValueVTs);
|
||||
assert(ValueVTs.size() == 1 &&
|
||||
"PHIs with non-vector integer types should have a single VT.");
|
||||
EVT IntVT = ValueVTs[0];
|
||||
|
||||
if (TLI.getNumRegisters(PN->getContext(), IntVT) != 1)
|
||||
return;
|
||||
IntVT = TLI.getTypeToTransformTo(PN->getContext(), IntVT);
|
||||
unsigned BitWidth = IntVT.getSizeInBits();
|
||||
|
||||
unsigned DestReg = ValueMap[PN];
|
||||
if (!TargetRegisterInfo::isVirtualRegister(DestReg))
|
||||
return;
|
||||
LiveOutRegInfo.grow(DestReg);
|
||||
LiveOutInfo &DestLOI = LiveOutRegInfo[DestReg];
|
||||
|
||||
Value *V = PN->getIncomingValue(0);
|
||||
if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
|
||||
DestLOI.NumSignBits = 1;
|
||||
APInt Zero(BitWidth, 0);
|
||||
DestLOI.KnownZero = Zero;
|
||||
DestLOI.KnownOne = Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
||||
APInt Val = CI->getValue().zextOrTrunc(BitWidth);
|
||||
DestLOI.NumSignBits = Val.getNumSignBits();
|
||||
DestLOI.KnownZero = ~Val;
|
||||
DestLOI.KnownOne = Val;
|
||||
} else {
|
||||
assert(ValueMap.count(V) && "V should have been placed in ValueMap when its"
|
||||
"CopyToReg node was created.");
|
||||
unsigned SrcReg = ValueMap[V];
|
||||
if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) {
|
||||
DestLOI.IsValid = false;
|
||||
return;
|
||||
}
|
||||
const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth);
|
||||
if (!SrcLOI) {
|
||||
DestLOI.IsValid = false;
|
||||
return;
|
||||
}
|
||||
DestLOI = *SrcLOI;
|
||||
}
|
||||
|
||||
assert(DestLOI.KnownZero.getBitWidth() == BitWidth &&
|
||||
DestLOI.KnownOne.getBitWidth() == BitWidth &&
|
||||
"Masks should have the same bit width as the type.");
|
||||
|
||||
for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) {
|
||||
Value *V = PN->getIncomingValue(i);
|
||||
if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
|
||||
DestLOI.NumSignBits = 1;
|
||||
APInt Zero(BitWidth, 0);
|
||||
DestLOI.KnownZero = Zero;
|
||||
DestLOI.KnownOne = Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
||||
APInt Val = CI->getValue().zextOrTrunc(BitWidth);
|
||||
DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, Val.getNumSignBits());
|
||||
DestLOI.KnownZero &= ~Val;
|
||||
DestLOI.KnownOne &= Val;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(ValueMap.count(V) && "V should have been placed in ValueMap when "
|
||||
"its CopyToReg node was created.");
|
||||
unsigned SrcReg = ValueMap[V];
|
||||
if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) {
|
||||
DestLOI.IsValid = false;
|
||||
return;
|
||||
}
|
||||
const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth);
|
||||
if (!SrcLOI) {
|
||||
DestLOI.IsValid = false;
|
||||
return;
|
||||
}
|
||||
DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, SrcLOI->NumSignBits);
|
||||
DestLOI.KnownZero &= SrcLOI->KnownZero;
|
||||
DestLOI.KnownOne &= SrcLOI->KnownOne;
|
||||
}
|
||||
}
|
||||
|
||||
/// setByValArgumentFrameIndex - Record frame index for the byval
|
||||
/// argument. This overrides previous frame index entry for this argument,
|
||||
/// if any.
|
||||
|
@ -842,7 +842,12 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!AllPredsVisited) {
|
||||
if (AllPredsVisited) {
|
||||
for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end();
|
||||
I != E && isa<PHINode>(I); ++I) {
|
||||
FuncInfo->ComputePHILiveOutRegInfo(cast<PHINode>(I));
|
||||
}
|
||||
} else {
|
||||
for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end();
|
||||
I != E && isa<PHINode>(I); ++I) {
|
||||
FuncInfo->InvalidatePHILiveOutRegInfo(cast<PHINode>(I));
|
||||
|
35
test/CodeGen/X86/phi-constants.ll
Normal file
35
test/CodeGen/X86/phi-constants.ll
Normal file
@ -0,0 +1,35 @@
|
||||
; RUN: llc < %s -march=x86-64 | FileCheck %s
|
||||
|
||||
%"class.std::bitset" = type { [8 x i8] }
|
||||
|
||||
define zeroext i1 @_Z3fooPjmS_mRSt6bitsetILm32EE(i32* nocapture %a, i64 %asize, i32* nocapture %b, i64 %bsize, %"class.std::bitset"* %bits) nounwind readonly ssp noredzone {
|
||||
entry:
|
||||
%tmp.i.i.i.i = bitcast %"class.std::bitset"* %bits to i64*
|
||||
br label %for.cond
|
||||
|
||||
for.cond: ; preds = %for.inc, %entry
|
||||
%0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
|
||||
%conv = zext i32 %0 to i64
|
||||
%cmp = icmp eq i64 %conv, %bsize
|
||||
br i1 %cmp, label %return, label %for.body
|
||||
|
||||
for.body: ; preds = %for.cond
|
||||
%arrayidx = getelementptr inbounds i32* %b, i64 %conv
|
||||
%tmp5 = load i32* %arrayidx, align 4
|
||||
%conv6 = zext i32 %tmp5 to i64
|
||||
%rem.i.i.i.i = and i64 %conv6, 63
|
||||
%tmp3.i = load i64* %tmp.i.i.i.i, align 8
|
||||
%shl.i.i = shl i64 1, %rem.i.i.i.i
|
||||
%and.i = and i64 %shl.i.i, %tmp3.i
|
||||
%cmp.i = icmp eq i64 %and.i, 0
|
||||
br i1 %cmp.i, label %for.inc, label %return
|
||||
|
||||
for.inc: ; preds = %for.body
|
||||
%inc = add i32 %0, 1
|
||||
br label %for.cond
|
||||
|
||||
return: ; preds = %for.body, %for.cond
|
||||
; CHECK-NOT: and
|
||||
%retval.0 = phi i1 [ true, %for.body ], [ false, %for.cond ]
|
||||
ret i1 %retval.0
|
||||
}
|
Loading…
Reference in New Issue
Block a user