mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-11 10:25:41 +00:00
Handle floating point ivs during doInitialization().
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59466 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -96,7 +96,8 @@ namespace {
|
|||||||
void DeleteTriviallyDeadInstructions(SmallPtrSet<Instruction*, 16> &Insts);
|
void DeleteTriviallyDeadInstructions(SmallPtrSet<Instruction*, 16> &Insts);
|
||||||
|
|
||||||
void OptimizeCanonicalIVType(Loop *L);
|
void OptimizeCanonicalIVType(Loop *L);
|
||||||
void HandleFloatingPointIV(Loop *L);
|
void HandleFloatingPointIV(Loop *L, PHINode *PH,
|
||||||
|
SmallPtrSet<Instruction*, 16> &DeadInsts);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,6 +434,8 @@ bool IndVarSimplify::doInitialization(Loop *L, LPPassManager &LPM) {
|
|||||||
PHINode *PN = cast<PHINode>(I);
|
PHINode *PN = cast<PHINode>(I);
|
||||||
if (isa<PointerType>(PN->getType()))
|
if (isa<PointerType>(PN->getType()))
|
||||||
EliminatePointerRecurrence(PN, Preheader, DeadInsts);
|
EliminatePointerRecurrence(PN, Preheader, DeadInsts);
|
||||||
|
else
|
||||||
|
HandleFloatingPointIV(L, PN, DeadInsts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DeadInsts.empty())
|
if (!DeadInsts.empty())
|
||||||
@@ -468,7 +471,6 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
|
|||||||
// auxillary induction variables.
|
// auxillary induction variables.
|
||||||
std::vector<std::pair<PHINode*, SCEVHandle> > IndVars;
|
std::vector<std::pair<PHINode*, SCEVHandle> > IndVars;
|
||||||
|
|
||||||
HandleFloatingPointIV(L);
|
|
||||||
for (BasicBlock::iterator I = Header->begin(); isa<PHINode>(I); ++I) {
|
for (BasicBlock::iterator I = Header->begin(); isa<PHINode>(I); ++I) {
|
||||||
PHINode *PN = cast<PHINode>(I);
|
PHINode *PN = cast<PHINode>(I);
|
||||||
if (PN->getType()->isInteger()) { // FIXME: when we have fast-math, enable!
|
if (PN->getType()->isInteger()) { // FIXME: when we have fast-math, enable!
|
||||||
@@ -723,149 +725,133 @@ void IndVarSimplify::OptimizeCanonicalIVType(Loop *L) {
|
|||||||
|
|
||||||
/// HandleFloatingPointIV - If the loop has floating induction variable
|
/// HandleFloatingPointIV - If the loop has floating induction variable
|
||||||
/// then insert corresponding integer induction variable if possible.
|
/// then insert corresponding integer induction variable if possible.
|
||||||
void IndVarSimplify::HandleFloatingPointIV(Loop *L) {
|
/// For example,
|
||||||
BasicBlock *Header = L->getHeader();
|
/// for(double i = 0; i < 10000; ++i)
|
||||||
SmallVector <PHINode *, 4> FPHIs;
|
/// bar(i)
|
||||||
Instruction *NonPHIInsn = NULL;
|
/// is converted into
|
||||||
|
/// for(int i = 0; i < 10000; ++i)
|
||||||
|
/// bar((double)i);
|
||||||
|
///
|
||||||
|
void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH,
|
||||||
|
SmallPtrSet<Instruction*, 16> &DeadInsts) {
|
||||||
|
|
||||||
// Collect all floating point IVs first.
|
unsigned IncomingEdge = L->contains(PH->getIncomingBlock(0));
|
||||||
BasicBlock::iterator I = Header->begin();
|
unsigned BackEdge = IncomingEdge^1;
|
||||||
while(true) {
|
|
||||||
if (!isa<PHINode>(I)) {
|
// Check incoming value.
|
||||||
NonPHIInsn = I;
|
ConstantFP *CZ = dyn_cast<ConstantFP>(PH->getIncomingValue(IncomingEdge));
|
||||||
break;
|
if (!CZ) return;
|
||||||
}
|
APFloat PHInit = CZ->getValueAPF();
|
||||||
PHINode *PH = cast<PHINode>(I);
|
if (!PHInit.isPosZero()) return;
|
||||||
if (PH->getType()->isFloatingPoint())
|
|
||||||
FPHIs.push_back(PH);
|
// Check IV increment.
|
||||||
++I;
|
BinaryOperator *Incr =
|
||||||
|
dyn_cast<BinaryOperator>(PH->getIncomingValue(BackEdge));
|
||||||
|
if (!Incr) return;
|
||||||
|
if (Incr->getOpcode() != Instruction::Add) return;
|
||||||
|
ConstantFP *IncrValue = NULL;
|
||||||
|
unsigned IncrVIndex = 1;
|
||||||
|
if (Incr->getOperand(1) == PH)
|
||||||
|
IncrVIndex = 0;
|
||||||
|
IncrValue = dyn_cast<ConstantFP>(Incr->getOperand(IncrVIndex));
|
||||||
|
if (!IncrValue) return;
|
||||||
|
APFloat IVAPF = IncrValue->getValueAPF();
|
||||||
|
APFloat One = APFloat(IVAPF.getSemantics(), 1);
|
||||||
|
if (!IVAPF.bitwiseIsEqual(One)) return;
|
||||||
|
|
||||||
|
// Check Incr uses.
|
||||||
|
Value::use_iterator IncrUse = Incr->use_begin();
|
||||||
|
Instruction *U1 = cast<Instruction>(IncrUse++);
|
||||||
|
if (IncrUse == Incr->use_end()) return;
|
||||||
|
Instruction *U2 = cast<Instruction>(IncrUse++);
|
||||||
|
if (IncrUse != Incr->use_end()) return;
|
||||||
|
|
||||||
|
// Find exit condition.
|
||||||
|
FCmpInst *EC = dyn_cast<FCmpInst>(U1);
|
||||||
|
if (!EC)
|
||||||
|
EC = dyn_cast<FCmpInst>(U2);
|
||||||
|
if (!EC) return;
|
||||||
|
|
||||||
|
if (BranchInst *BI = dyn_cast<BranchInst>(EC->getParent()->getTerminator())) {
|
||||||
|
if (!BI->isConditional()) return;
|
||||||
|
if (BI->getCondition() != EC) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SmallVector<PHINode *, 4>::iterator I = FPHIs.begin(), E = FPHIs.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
PHINode *PH = *I;
|
|
||||||
unsigned IncomingEdge = L->contains(PH->getIncomingBlock(0));
|
|
||||||
unsigned BackEdge = IncomingEdge^1;
|
|
||||||
|
|
||||||
// Check incoming value.
|
// Find exit value.
|
||||||
ConstantFP *CZ = dyn_cast<ConstantFP>(PH->getIncomingValue(IncomingEdge));
|
ConstantFP *EV = NULL;
|
||||||
if (!CZ) continue;
|
unsigned EVIndex = 1;
|
||||||
APFloat PHInit = CZ->getValueAPF();
|
if (EC->getOperand(1) == Incr)
|
||||||
if (!PHInit.isPosZero()) continue;
|
EVIndex = 0;
|
||||||
|
EV = dyn_cast<ConstantFP>(EC->getOperand(EVIndex));
|
||||||
// Check IV increment.
|
if (!EV) return;
|
||||||
BinaryOperator *Incr =
|
APFloat EVAPF = EV->getValueAPF();
|
||||||
dyn_cast<BinaryOperator>(PH->getIncomingValue(BackEdge));
|
if (EVAPF.isNegative()) return;
|
||||||
if (!Incr) continue;
|
|
||||||
if (Incr->getOpcode() != Instruction::Add) continue;
|
// Find corresponding integer exit value.
|
||||||
ConstantFP *IncrValue = NULL;
|
uint64_t intEV = Type::Int32Ty->getPrimitiveSizeInBits();
|
||||||
unsigned IncrVIndex = 1;
|
bool isExact = false;
|
||||||
if (Incr->getOperand(1) == PH)
|
if (EVAPF.convertToInteger(&intEV, 32, false, APFloat::rmTowardZero, &isExact)
|
||||||
IncrVIndex = 0;
|
!= APFloat::opOK)
|
||||||
IncrValue = dyn_cast<ConstantFP>(Incr->getOperand(IncrVIndex));
|
return;
|
||||||
if (!IncrValue) continue;
|
if (!isExact) return;
|
||||||
APFloat IVAPF = IncrValue->getValueAPF();
|
|
||||||
APFloat One = APFloat(IVAPF.getSemantics(), 1);
|
// Find new predicate for integer comparison.
|
||||||
if (!IVAPF.bitwiseIsEqual(One)) continue;
|
CmpInst::Predicate NewPred = CmpInst::BAD_ICMP_PREDICATE;
|
||||||
|
switch (EC->getPredicate()) {
|
||||||
// Check Incr uses.
|
case CmpInst::FCMP_OEQ:
|
||||||
Value::use_iterator IncrUse = Incr->use_begin();
|
case CmpInst::FCMP_UEQ:
|
||||||
Instruction *U1 = cast<Instruction>(IncrUse++);
|
NewPred = CmpInst::ICMP_EQ;
|
||||||
if (IncrUse == Incr->use_end()) continue;
|
break;
|
||||||
Instruction *U2 = cast<Instruction>(IncrUse++);
|
case CmpInst::FCMP_OGT:
|
||||||
if (IncrUse != Incr->use_end()) continue;
|
case CmpInst::FCMP_UGT:
|
||||||
|
NewPred = CmpInst::ICMP_UGT;
|
||||||
// Find exict condition.
|
break;
|
||||||
FCmpInst *EC = dyn_cast<FCmpInst>(U1);
|
case CmpInst::FCMP_OGE:
|
||||||
if (!EC)
|
case CmpInst::FCMP_UGE:
|
||||||
EC = dyn_cast<FCmpInst>(U2);
|
NewPred = CmpInst::ICMP_UGE;
|
||||||
if (!EC) continue;
|
break;
|
||||||
bool skip = false;
|
case CmpInst::FCMP_OLT:
|
||||||
Instruction *Terminator = EC->getParent()->getTerminator();
|
case CmpInst::FCMP_ULT:
|
||||||
for(Value::use_iterator ECUI = EC->use_begin(), ECUE = EC->use_end();
|
NewPred = CmpInst::ICMP_ULT;
|
||||||
ECUI != ECUE; ++ECUI) {
|
break;
|
||||||
Instruction *U = cast<Instruction>(ECUI);
|
case CmpInst::FCMP_OLE:
|
||||||
if (U != Terminator) {
|
case CmpInst::FCMP_ULE:
|
||||||
skip = true;
|
NewPred = CmpInst::ICMP_ULE;
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
}
|
break;
|
||||||
if (skip) continue;
|
|
||||||
|
|
||||||
// Find exit value.
|
|
||||||
ConstantFP *EV = NULL;
|
|
||||||
unsigned EVIndex = 1;
|
|
||||||
if (EC->getOperand(1) == Incr)
|
|
||||||
EVIndex = 0;
|
|
||||||
EV = dyn_cast<ConstantFP>(EC->getOperand(EVIndex));
|
|
||||||
if (!EV) continue;
|
|
||||||
APFloat EVAPF = EV->getValueAPF();
|
|
||||||
if (EVAPF.isNegative()) continue;
|
|
||||||
|
|
||||||
// Find corresponding integer exit value.
|
|
||||||
uint64_t integerVal = Type::Int32Ty->getPrimitiveSizeInBits();
|
|
||||||
bool isExact = false;
|
|
||||||
if (EVAPF.convertToInteger(&integerVal, 32, false, APFloat::rmTowardZero, &isExact)
|
|
||||||
!= APFloat::opOK)
|
|
||||||
continue;
|
|
||||||
if (!isExact) continue;
|
|
||||||
|
|
||||||
// Find new predicate for integer comparison.
|
|
||||||
CmpInst::Predicate NewPred = CmpInst::BAD_ICMP_PREDICATE;
|
|
||||||
switch (EC->getPredicate()) {
|
|
||||||
case CmpInst::FCMP_OEQ:
|
|
||||||
case CmpInst::FCMP_UEQ:
|
|
||||||
NewPred = CmpInst::ICMP_EQ;
|
|
||||||
break;
|
|
||||||
case CmpInst::FCMP_OGT:
|
|
||||||
case CmpInst::FCMP_UGT:
|
|
||||||
NewPred = CmpInst::ICMP_UGT;
|
|
||||||
break;
|
|
||||||
case CmpInst::FCMP_OGE:
|
|
||||||
case CmpInst::FCMP_UGE:
|
|
||||||
NewPred = CmpInst::ICMP_UGE;
|
|
||||||
break;
|
|
||||||
case CmpInst::FCMP_OLT:
|
|
||||||
case CmpInst::FCMP_ULT:
|
|
||||||
NewPred = CmpInst::ICMP_ULT;
|
|
||||||
break;
|
|
||||||
case CmpInst::FCMP_OLE:
|
|
||||||
case CmpInst::FCMP_ULE:
|
|
||||||
NewPred = CmpInst::ICMP_ULE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (NewPred == CmpInst::BAD_ICMP_PREDICATE) continue;
|
|
||||||
|
|
||||||
// Insert new integer induction variable.
|
|
||||||
SCEVExpander Rewriter(*SE, *LI);
|
|
||||||
PHINode *NewIV =
|
|
||||||
cast<PHINode>(Rewriter.getOrInsertCanonicalInductionVariable(L,Type::Int32Ty));
|
|
||||||
ConstantInt *NewEV = ConstantInt::get(Type::Int32Ty, integerVal);
|
|
||||||
Value *LHS = (EVIndex == 1 ? NewIV->getIncomingValue(BackEdge) : NewEV);
|
|
||||||
Value *RHS = (EVIndex == 1 ? NewEV : NewIV->getIncomingValue(BackEdge));
|
|
||||||
ICmpInst *NewEC = new ICmpInst(NewPred, LHS, RHS, EC->getNameStart(),
|
|
||||||
EC->getParent()->getTerminator());
|
|
||||||
|
|
||||||
// Delete old, floating point, exit comparision instruction.
|
|
||||||
SE->deleteValueFromRecords(EC);
|
|
||||||
EC->replaceAllUsesWith(NewEC);
|
|
||||||
EC->eraseFromParent();
|
|
||||||
|
|
||||||
// Delete old, floating point, increment instruction.
|
|
||||||
SE->deleteValueFromRecords(Incr);
|
|
||||||
Incr->replaceAllUsesWith(UndefValue::get(Incr->getType()));
|
|
||||||
Incr->eraseFromParent();
|
|
||||||
|
|
||||||
// Replace floating induction variable.
|
|
||||||
UIToFPInst *Conv = new UIToFPInst(NewIV, PH->getType(), "indvar.conv",
|
|
||||||
NonPHIInsn);
|
|
||||||
PH->replaceAllUsesWith(Conv);
|
|
||||||
|
|
||||||
SE->deleteValueFromRecords(PH);
|
|
||||||
PH->removeIncomingValue((unsigned)0);
|
|
||||||
PH->removeIncomingValue((unsigned)0);
|
|
||||||
}
|
}
|
||||||
|
if (NewPred == CmpInst::BAD_ICMP_PREDICATE) return;
|
||||||
|
|
||||||
|
// Insert new integer induction variable.
|
||||||
|
PHINode *NewPHI = PHINode::Create(Type::Int32Ty,
|
||||||
|
PH->getName()+".int", PH);
|
||||||
|
NewPHI->addIncoming(Constant::getNullValue(NewPHI->getType()),
|
||||||
|
PH->getIncomingBlock(IncomingEdge));
|
||||||
|
|
||||||
|
Value *NewAdd = BinaryOperator::CreateAdd(NewPHI,
|
||||||
|
ConstantInt::get(Type::Int32Ty, 1),
|
||||||
|
Incr->getName()+".int", Incr);
|
||||||
|
NewPHI->addIncoming(NewAdd, PH->getIncomingBlock(BackEdge));
|
||||||
|
|
||||||
|
ConstantInt *NewEV = ConstantInt::get(Type::Int32Ty, intEV);
|
||||||
|
Value *LHS = (EVIndex == 1 ? NewPHI->getIncomingValue(BackEdge) : NewEV);
|
||||||
|
Value *RHS = (EVIndex == 1 ? NewEV : NewPHI->getIncomingValue(BackEdge));
|
||||||
|
ICmpInst *NewEC = new ICmpInst(NewPred, LHS, RHS, EC->getNameStart(),
|
||||||
|
EC->getParent()->getTerminator());
|
||||||
|
|
||||||
|
// Delete old, floating point, exit comparision instruction.
|
||||||
|
EC->replaceAllUsesWith(NewEC);
|
||||||
|
DeadInsts.insert(EC);
|
||||||
|
|
||||||
|
// Delete old, floating point, increment instruction.
|
||||||
|
Incr->replaceAllUsesWith(UndefValue::get(Incr->getType()));
|
||||||
|
DeadInsts.insert(Incr);
|
||||||
|
|
||||||
|
// Replace floating induction variable.
|
||||||
|
UIToFPInst *Conv = new UIToFPInst(NewPHI, PH->getType(), "indvar.conv",
|
||||||
|
PH->getParent()->getFirstNonPHI());
|
||||||
|
PH->replaceAllUsesWith(Conv);
|
||||||
|
DeadInsts.insert(PH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user