mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
If all IV uses are extending integer IV then change the type of IV itself, if possible.
llvm-svn: 55674
This commit is contained in:
parent
cda9086d29
commit
a1e2066b1d
@ -46,6 +46,7 @@ STATISTIC(NumInserted, "Number of PHIs inserted");
|
||||
STATISTIC(NumVariable, "Number of PHIs with variable strides");
|
||||
STATISTIC(NumEliminated, "Number of strides eliminated");
|
||||
STATISTIC(NumShadow, "Number of Shadow IVs optimized");
|
||||
STATISTIC(NumIVType, "Number of IV types optimized");
|
||||
|
||||
namespace {
|
||||
|
||||
@ -184,6 +185,10 @@ private:
|
||||
/// inside the loop then try to eliminate the cast opeation.
|
||||
void OptimizeShadowIV(Loop *L);
|
||||
|
||||
/// OptimizeIVType - If IV is always sext'ed or zext'ed then
|
||||
/// change the type of IV, if possible.
|
||||
void OptimizeIVType(Loop *L);
|
||||
|
||||
bool FindIVUserForCond(ICmpInst *Cond, IVStrideUse *&CondUse,
|
||||
const SCEVHandle *&CondStride);
|
||||
bool RequiresTypeConversion(const Type *Ty, const Type *NewTy);
|
||||
@ -1808,6 +1813,200 @@ void LoopStrengthReduce::OptimizeShadowIV(Loop *L) {
|
||||
}
|
||||
}
|
||||
|
||||
/// suitableExtInstruction - Helper function used by OptimizeIVType.
|
||||
/// If I is a suitable SEXT or ZEXT instruction then return type
|
||||
/// to which I is extended to. Otherwise return NULL.
|
||||
const Type *suitableExtInstruction(Instruction *I, bool isSigned,
|
||||
const Type *ExtType) {
|
||||
|
||||
const Type *DestType = NULL;
|
||||
if (ZExtInst *ZI = dyn_cast<ZExtInst>(I))
|
||||
DestType = ZI->getDestTy();
|
||||
else if (SExtInst *SI = dyn_cast<SExtInst>(I)) {
|
||||
// If the inital value is signed then this is not suitable for
|
||||
// OptimizeIVType transformation.
|
||||
if (isSigned)
|
||||
return NULL;
|
||||
DestType = SI->getDestTy();
|
||||
}
|
||||
|
||||
if (!DestType) return NULL;
|
||||
|
||||
if (!ExtType)
|
||||
return DestType;
|
||||
|
||||
// If another use of IV extended to some other type then the IV is not
|
||||
// suitable for OptimizeIVType transformation.
|
||||
if (ExtType != DestType)
|
||||
return NULL;
|
||||
|
||||
return DestType;
|
||||
}
|
||||
|
||||
/// suitableIVIncr - Helper function used by OptimizeIVType. If I is
|
||||
/// a suitable binary operator whose all uses are either SEXT or ZEXT
|
||||
/// then return the type to which all uses are extended to. Otherwise
|
||||
/// return NULL.
|
||||
const Type *suitableIVIncr(Instruction *I,
|
||||
Instruction *PHI, bool isSigned,
|
||||
const Type *ExtType) {
|
||||
|
||||
BinaryOperator *Incr = dyn_cast<BinaryOperator>(I);
|
||||
if (!Incr) return NULL;
|
||||
|
||||
if (Incr->getOpcode() != Instruction::Add)
|
||||
return NULL;
|
||||
|
||||
ConstantInt *C = NULL;
|
||||
if (Incr->getOperand(0) == PHI)
|
||||
C = dyn_cast<ConstantInt>(Incr->getOperand(1));
|
||||
else if (Incr->getOperand(1) == PHI)
|
||||
C = dyn_cast<ConstantInt>(Incr->getOperand(0));
|
||||
|
||||
if (!C) return NULL;
|
||||
|
||||
const Type *RExtType = NULL;
|
||||
for (Value::use_iterator IncUI = Incr->use_begin(),
|
||||
IncUE = Incr->use_end(); IncUI != IncUE; ++IncUI) {
|
||||
|
||||
Instruction *U2 = dyn_cast<Instruction>(*IncUI);
|
||||
if (U2 == PHI)
|
||||
continue;
|
||||
const Type *DestType = suitableExtInstruction(U2, isSigned, ExtType);
|
||||
if (!DestType)
|
||||
return NULL;
|
||||
|
||||
if (!RExtType)
|
||||
RExtType = DestType;
|
||||
|
||||
if (DestType != RExtType)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return RExtType;
|
||||
|
||||
}
|
||||
|
||||
/// getNewPHIIncrement - Create a new increment instruction for newPHI
|
||||
/// using type Ty based on increment instruction Incr.
|
||||
/// Helper function used by OptimizeIVType.
|
||||
BinaryOperator *getNewPHIIncrement(BinaryOperator *Incr, PHINode *PHI,
|
||||
PHINode *NewPHI, const Type *Ty) {
|
||||
ConstantInt *C = NULL;
|
||||
if (Incr->getOperand(0) == PHI)
|
||||
C = dyn_cast<ConstantInt>(Incr->getOperand(1));
|
||||
else if (Incr->getOperand(1) == PHI)
|
||||
C = dyn_cast<ConstantInt>(Incr->getOperand(0));
|
||||
|
||||
assert (C && "Unexpected Incr operand!");
|
||||
return BinaryOperator::Create(Incr->getOpcode(), NewPHI,
|
||||
ConstantInt::get(Ty, C->getZExtValue()),
|
||||
"IV.next", Incr);
|
||||
}
|
||||
|
||||
/// OptimizeIVType - If IV is always sext'ed or zext'ed then
|
||||
/// change the type of IV, if possible.
|
||||
void LoopStrengthReduce::OptimizeIVType(Loop *L) {
|
||||
|
||||
BasicBlock *LPH = L->getLoopPreheader();
|
||||
SmallVector<PHINode *, 4> PHIs;
|
||||
for (BasicBlock::iterator BI = L->getHeader()->begin(),
|
||||
BE = L->getHeader()->end(); BI != BE; ++BI) {
|
||||
if (PHINode *PHI = dyn_cast<PHINode>(BI))
|
||||
PHIs.push_back(PHI);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
while(!PHIs.empty()) {
|
||||
PHINode *PHI = PHIs.back(); PHIs.pop_back();
|
||||
if (PHI->getNumIncomingValues() != 2) continue;
|
||||
|
||||
unsigned Entry = 0, Latch = 1;
|
||||
if (PHI->getIncomingBlock(0) != LPH) {
|
||||
Entry = 1;
|
||||
Latch = 0;
|
||||
}
|
||||
|
||||
ConstantInt *CInit = dyn_cast<ConstantInt>(PHI->getIncomingValue(Entry));
|
||||
if (!CInit) return;
|
||||
|
||||
bool signedInit = CInit->getValue().isNegative();
|
||||
|
||||
bool TransformPhi = true;
|
||||
const Type *ExtType = NULL;
|
||||
BinaryOperator *Incr = NULL;
|
||||
SmallVector<Instruction *, 4> PHIUses;
|
||||
|
||||
// Collect all IV uses.
|
||||
for (Value::use_iterator UI = PHI->use_begin(),
|
||||
UE = PHI->use_end(); UI != UE; ++UI) {
|
||||
Instruction *Use = dyn_cast<Instruction>(*UI);
|
||||
if (!Use) {
|
||||
TransformPhi = false;
|
||||
break;
|
||||
}
|
||||
|
||||
ExtType = suitableIVIncr(Use, PHI, signedInit, ExtType);
|
||||
if (ExtType) {
|
||||
Incr = cast<BinaryOperator>(Use);
|
||||
continue;
|
||||
}
|
||||
ExtType = suitableExtInstruction(Use, signedInit, ExtType);
|
||||
if (ExtType) {
|
||||
PHIUses.push_back(Use);
|
||||
continue;
|
||||
}
|
||||
|
||||
TransformPhi = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!TransformPhi || Incr == false || PHIUses.empty())
|
||||
continue;
|
||||
|
||||
// Apply transformation. Extend IV type and eliminate SEXT or ZEXT
|
||||
// instructions.
|
||||
NumIVType++;
|
||||
|
||||
PHINode *NewPH = PHINode::Create(ExtType, "IV", PHI);
|
||||
ConstantInt *NewCInit = ConstantInt::get(ExtType, CInit->getZExtValue());
|
||||
BinaryOperator *NewIncr = getNewPHIIncrement(Incr, PHI, NewPH, ExtType);
|
||||
|
||||
NewPH->addIncoming(NewCInit, PHI->getIncomingBlock(Entry));
|
||||
NewPH->addIncoming(NewIncr, PHI->getIncomingBlock(Latch));
|
||||
|
||||
// Replace all SEXT or ZEXT uses with new IV directly.
|
||||
while (!PHIUses.empty()) {
|
||||
Instruction *Use = PHIUses.back(); PHIUses.pop_back();
|
||||
SE->deleteValueFromRecords(Use);
|
||||
Use->replaceAllUsesWith(NewPH);
|
||||
Use->eraseFromParent();
|
||||
}
|
||||
|
||||
// Replace all uses of IV increment with new increment.
|
||||
SmallVector<Instruction *, 2> IncrUses;
|
||||
for (Value::use_iterator UI2 = Incr->use_begin(),
|
||||
UE2 = Incr->use_end(); UI2 != UE2; ++UI2)
|
||||
IncrUses.push_back(cast<Instruction>(*UI2));
|
||||
|
||||
while (!IncrUses.empty()) {
|
||||
Instruction *Use = IncrUses.back(); IncrUses.pop_back();
|
||||
if (Use == PHI) continue;
|
||||
SE->deleteValueFromRecords(Use);
|
||||
Use->replaceAllUsesWith(NewIncr);
|
||||
Use->eraseFromParent();
|
||||
}
|
||||
|
||||
// Remove old PHI and increment instruction.
|
||||
SE->deleteValueFromRecords(PHI);
|
||||
PHI->removeIncomingValue(Entry);
|
||||
PHI->removeIncomingValue(Latch);
|
||||
SE->deleteValueFromRecords(Incr);
|
||||
Incr->eraseFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
// OptimizeIndvars - Now that IVUsesByStride is set up with all of the indvar
|
||||
// uses in the loop, look to see if we can eliminate some, in favor of using
|
||||
// common indvars for the different uses.
|
||||
@ -1877,6 +2076,8 @@ bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
UIntPtrTy = TD->getIntPtrType();
|
||||
Changed = false;
|
||||
|
||||
OptimizeIVType(L);
|
||||
|
||||
// Find all uses of induction variables in this loop, and catagorize
|
||||
// them by stride. Start by finding all of the PHI nodes in the header for
|
||||
// this loop. If they are induction variables, inspect their uses.
|
||||
|
57
test/Transforms/LoopStrengthReduce/2008-09-02-IVType.ll
Normal file
57
test/Transforms/LoopStrengthReduce/2008-09-02-IVType.ll
Normal file
@ -0,0 +1,57 @@
|
||||
; RUN: llvm-as < %s | opt -loop-reduce | llvm-dis | grep sext | count 1
|
||||
; ModuleID = '<stdin>'
|
||||
%struct.App1Marker = type <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 }>
|
||||
%struct.ComponentInstanceRecord = type <{ [1 x i32] }>
|
||||
%struct.DCPredictors = type { [5 x i16] }
|
||||
%struct.DecodeTable = type { i16, i16, i16, i16, i8**, i8** }
|
||||
%struct.ICMDataProcRecord = type <{ i16 (i8**, i32, i32)*, i32 }>
|
||||
%struct.JPEGBitStream = type { i8*, i32, i32, i32, i32, i32, %struct.App1Marker*, i8*, i32, i16, i16, i32 }
|
||||
%struct.JPEGGlobals = type { [2048 x i8], %struct.JPEGBitStream, i8*, i32, i32, %struct.ComponentInstanceRecord*, %struct.ComponentInstanceRecord*, i32, %struct.OpaqueQTMLMutex*, %struct.Rect, i32, i32, %struct.SharedGlobals, %struct.DCPredictors, i8, i8, void (i8*, i16**, i32, %struct.YUVGeneralParams*)*, %struct.YUVGeneralParams, i16, i16, i32, [5 x i16*], [5 x %struct.DecodeTable*], [5 x %struct.DecodeTable*], [5 x i8], [5 x i8], [4 x [65 x i16]], [4 x %struct.DecodeTable], [4 x %struct.DecodeTable], [4 x i8*], [4 x i8*], i16, i16, i32, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, [18 x i8], [18 x i8], [18 x i8], [18 x i8], i32, i32, i8**, i8**, i8, i8, i8, i8, i16, i16, %struct.App1Marker*, i8, i8, i8, i8, i32**, i8*, i16*, i8*, i16*, i8, [3 x i8], i32, [3 x i32], [3 x i32], [3 x i32], [3 x i32], [3 x i32], [3 x i16*], [3 x i16*], [3 x i8**], [3 x %struct.DecodeTable*], [3 x %struct.DecodeTable*], [3 x i32], i32, [3 x i16*], i32, i32, i32, [3 x i32], i8, i8, i8, i8, %struct.ICMDataProcRecord*, i32, i32, i8**, i8**, i8**, i8**, i32, i32, i8*, i32, i32, i16*, i16*, i8*, i32, i32, i32, i32, i32, i32, i32, [16 x <2 x i64>], [1280 x i8], i8 }
|
||||
%struct.OpaqueQTMLMutex = type opaque
|
||||
%struct.Rect = type { i16, i16, i16, i16 }
|
||||
%struct.SharedDGlobals = type { %struct.DecodeTable, %struct.DecodeTable, %struct.DecodeTable, %struct.DecodeTable }
|
||||
%struct.SharedEGlobals = type { i8**, i8**, i8**, i8** }
|
||||
%struct.SharedGlobals = type { %struct.SharedEGlobals*, %struct.SharedDGlobals* }
|
||||
%struct.YUVGeneralParams = type { i16*, i8*, i8*, i8*, i8*, i8*, void (i8*, i16**, i32, %struct.YUVGeneralParams*)*, i16, i16, i16, [6 x i8], void (i8*, i16**, i32, %struct.YUVGeneralParams*)*, i16, i16 }
|
||||
@llvm.used = appending global [1 x i8*] [ i8* bitcast (i16 (%struct.JPEGGlobals*)* @ExtractBufferedBlocksIgnored to i8*) ], section "llvm.metadata" ; <[1 x i8*]*> [#uses=0]
|
||||
|
||||
define i16 @ExtractBufferedBlocksIgnored(%struct.JPEGGlobals* %globp) signext nounwind {
|
||||
entry:
|
||||
%tmp4311 = getelementptr %struct.JPEGGlobals* %globp, i32 0, i32 70 ; <i32*> [#uses=1]
|
||||
%tmp4412 = load i32* %tmp4311, align 16 ; <i32> [#uses=2]
|
||||
%tmp4613 = icmp sgt i32 %tmp4412, 0 ; <i1> [#uses=1]
|
||||
br i1 %tmp4613, label %bb, label %bb49
|
||||
|
||||
bb: ; preds = %bb28, %entry
|
||||
%component.09 = phi i16 [ 0, %entry ], [ %tmp37, %bb28 ] ; <i16> [#uses=2]
|
||||
%tmp12 = sext i16 %component.09 to i32 ; <i32> [#uses=2]
|
||||
%tmp6 = getelementptr %struct.JPEGGlobals* %globp, i32 0, i32 77, i32 %tmp12 ; <i16**> [#uses=2]
|
||||
%tmp7 = load i16** %tmp6, align 4 ; <i16*> [#uses=2]
|
||||
%tmp235 = getelementptr %struct.JPEGGlobals* %globp, i32 0, i32 71, i32 %tmp12 ; <i32*> [#uses=1]
|
||||
%tmp246 = load i32* %tmp235, align 4 ; <i32> [#uses=2]
|
||||
%tmp267 = icmp sgt i32 %tmp246, 0 ; <i1> [#uses=1]
|
||||
br i1 %tmp267, label %bb8, label %bb28
|
||||
|
||||
bb8: ; preds = %bb8, %bb
|
||||
%indvar = phi i32 [ 0, %bb ], [ %indvar.next2, %bb8 ] ; <i32> [#uses=3]
|
||||
%theDCTBufferIter.01.rec = shl i32 %indvar, 6 ; <i32> [#uses=1]
|
||||
%tmp10.rec = add i32 %theDCTBufferIter.01.rec, 64 ; <i32> [#uses=1]
|
||||
%tmp10 = getelementptr i16* %tmp7, i32 %tmp10.rec ; <i16*> [#uses=1]
|
||||
%i.02 = trunc i32 %indvar to i16 ; <i16> [#uses=1]
|
||||
%tmp13 = add i16 %i.02, 1 ; <i16> [#uses=1]
|
||||
%phitmp = sext i16 %tmp13 to i32 ; <i32> [#uses=1]
|
||||
%tmp26 = icmp slt i32 %phitmp, %tmp246 ; <i1> [#uses=1]
|
||||
%indvar.next2 = add i32 %indvar, 1 ; <i32> [#uses=1]
|
||||
br i1 %tmp26, label %bb8, label %bb28
|
||||
|
||||
bb28: ; preds = %bb8, %bb
|
||||
%theDCTBufferIter.0.lcssa = phi i16* [ %tmp7, %bb ], [ %tmp10, %bb8 ] ; <i16*> [#uses=1]
|
||||
store i16* %theDCTBufferIter.0.lcssa, i16** %tmp6, align 4
|
||||
%tmp37 = add i16 %component.09, 1 ; <i16> [#uses=2]
|
||||
%phitmp15 = sext i16 %tmp37 to i32 ; <i32> [#uses=1]
|
||||
%tmp46 = icmp slt i32 %phitmp15, %tmp4412 ; <i1> [#uses=1]
|
||||
br i1 %tmp46, label %bb, label %bb49
|
||||
|
||||
bb49: ; preds = %bb28, %entry
|
||||
ret i16 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user