mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-27 16:17:17 +00:00
While handling floating point IVs lift restrictions on initial value and increment value.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59471 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -446,7 +446,6 @@ bool IndVarSimplify::doInitialization(Loop *L, LPPassManager &LPM) {
|
|||||||
|
|
||||||
bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
|
bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||||
|
|
||||||
|
|
||||||
LI = &getAnalysis<LoopInfo>();
|
LI = &getAnalysis<LoopInfo>();
|
||||||
SE = &getAnalysis<ScalarEvolution>();
|
SE = &getAnalysis<ScalarEvolution>();
|
||||||
|
|
||||||
@@ -723,6 +722,19 @@ void IndVarSimplify::OptimizeCanonicalIVType(Loop *L) {
|
|||||||
Incr->eraseFromParent();
|
Incr->eraseFromParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool convertToInt(const APFloat &APF, uint64_t *intVal) {
|
||||||
|
|
||||||
|
bool isExact = false;
|
||||||
|
if (APF.convertToInteger(intVal, 32, APF.isNegative(),
|
||||||
|
APFloat::rmTowardZero, &isExact)
|
||||||
|
!= APFloat::opOK)
|
||||||
|
return false;
|
||||||
|
if (!isExact)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
/// For example,
|
/// For example,
|
||||||
@@ -739,12 +751,14 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH,
|
|||||||
unsigned BackEdge = IncomingEdge^1;
|
unsigned BackEdge = IncomingEdge^1;
|
||||||
|
|
||||||
// Check incoming value.
|
// Check incoming value.
|
||||||
ConstantFP *CZ = dyn_cast<ConstantFP>(PH->getIncomingValue(IncomingEdge));
|
ConstantFP *InitValue = dyn_cast<ConstantFP>(PH->getIncomingValue(IncomingEdge));
|
||||||
if (!CZ) return;
|
if (!InitValue) return;
|
||||||
APFloat PHInit = CZ->getValueAPF();
|
uint64_t newInitValue = Type::Int32Ty->getPrimitiveSizeInBits();
|
||||||
if (!PHInit.isPosZero()) return;
|
if (!convertToInt(InitValue->getValueAPF(), &newInitValue))
|
||||||
|
return;
|
||||||
// Check IV increment.
|
|
||||||
|
// Check IV increment. Reject this PH if increement operation is not
|
||||||
|
// an add or increment value can not be represented by an integer.
|
||||||
BinaryOperator *Incr =
|
BinaryOperator *Incr =
|
||||||
dyn_cast<BinaryOperator>(PH->getIncomingValue(BackEdge));
|
dyn_cast<BinaryOperator>(PH->getIncomingValue(BackEdge));
|
||||||
if (!Incr) return;
|
if (!Incr) return;
|
||||||
@@ -755,11 +769,12 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH,
|
|||||||
IncrVIndex = 0;
|
IncrVIndex = 0;
|
||||||
IncrValue = dyn_cast<ConstantFP>(Incr->getOperand(IncrVIndex));
|
IncrValue = dyn_cast<ConstantFP>(Incr->getOperand(IncrVIndex));
|
||||||
if (!IncrValue) return;
|
if (!IncrValue) return;
|
||||||
APFloat IVAPF = IncrValue->getValueAPF();
|
uint64_t newIncrValue = Type::Int32Ty->getPrimitiveSizeInBits();
|
||||||
APFloat One = APFloat(IVAPF.getSemantics(), 1);
|
if (!convertToInt(IncrValue->getValueAPF(), &newIncrValue))
|
||||||
if (!IVAPF.bitwiseIsEqual(One)) return;
|
return;
|
||||||
|
|
||||||
// Check Incr uses.
|
// Check Incr uses. One user is PH and the other users is exit condition used
|
||||||
|
// by the conditional terminator.
|
||||||
Value::use_iterator IncrUse = Incr->use_begin();
|
Value::use_iterator IncrUse = Incr->use_begin();
|
||||||
Instruction *U1 = cast<Instruction>(IncrUse++);
|
Instruction *U1 = cast<Instruction>(IncrUse++);
|
||||||
if (IncrUse == Incr->use_end()) return;
|
if (IncrUse == Incr->use_end()) return;
|
||||||
@@ -777,23 +792,17 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH,
|
|||||||
if (BI->getCondition() != EC) return;
|
if (BI->getCondition() != EC) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find exit value.
|
// Find exit value. If exit value can not be represented as an interger then
|
||||||
|
// do not handle this floating point PH.
|
||||||
ConstantFP *EV = NULL;
|
ConstantFP *EV = NULL;
|
||||||
unsigned EVIndex = 1;
|
unsigned EVIndex = 1;
|
||||||
if (EC->getOperand(1) == Incr)
|
if (EC->getOperand(1) == Incr)
|
||||||
EVIndex = 0;
|
EVIndex = 0;
|
||||||
EV = dyn_cast<ConstantFP>(EC->getOperand(EVIndex));
|
EV = dyn_cast<ConstantFP>(EC->getOperand(EVIndex));
|
||||||
if (!EV) return;
|
if (!EV) return;
|
||||||
APFloat EVAPF = EV->getValueAPF();
|
|
||||||
if (EVAPF.isNegative()) return;
|
|
||||||
|
|
||||||
// Find corresponding integer exit value.
|
|
||||||
uint64_t intEV = Type::Int32Ty->getPrimitiveSizeInBits();
|
uint64_t intEV = Type::Int32Ty->getPrimitiveSizeInBits();
|
||||||
bool isExact = false;
|
if (!convertToInt(EV->getValueAPF(), &intEV))
|
||||||
if (EVAPF.convertToInteger(&intEV, 32, false, APFloat::rmTowardZero, &isExact)
|
|
||||||
!= APFloat::opOK)
|
|
||||||
return;
|
return;
|
||||||
if (!isExact) return;
|
|
||||||
|
|
||||||
// Find new predicate for integer comparison.
|
// Find new predicate for integer comparison.
|
||||||
CmpInst::Predicate NewPred = CmpInst::BAD_ICMP_PREDICATE;
|
CmpInst::Predicate NewPred = CmpInst::BAD_ICMP_PREDICATE;
|
||||||
@@ -826,11 +835,12 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH,
|
|||||||
// Insert new integer induction variable.
|
// Insert new integer induction variable.
|
||||||
PHINode *NewPHI = PHINode::Create(Type::Int32Ty,
|
PHINode *NewPHI = PHINode::Create(Type::Int32Ty,
|
||||||
PH->getName()+".int", PH);
|
PH->getName()+".int", PH);
|
||||||
NewPHI->addIncoming(Constant::getNullValue(NewPHI->getType()),
|
NewPHI->addIncoming(ConstantInt::get(Type::Int32Ty, newInitValue),
|
||||||
PH->getIncomingBlock(IncomingEdge));
|
PH->getIncomingBlock(IncomingEdge));
|
||||||
|
|
||||||
Value *NewAdd = BinaryOperator::CreateAdd(NewPHI,
|
Value *NewAdd = BinaryOperator::CreateAdd(NewPHI,
|
||||||
ConstantInt::get(Type::Int32Ty, 1),
|
ConstantInt::get(Type::Int32Ty,
|
||||||
|
newIncrValue),
|
||||||
Incr->getName()+".int", Incr);
|
Incr->getName()+".int", Incr);
|
||||||
NewPHI->addIncoming(NewAdd, PH->getIncomingBlock(BackEdge));
|
NewPHI->addIncoming(NewAdd, PH->getIncomingBlock(BackEdge));
|
||||||
|
|
||||||
@@ -849,9 +859,16 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH,
|
|||||||
DeadInsts.insert(Incr);
|
DeadInsts.insert(Incr);
|
||||||
|
|
||||||
// Replace floating induction variable.
|
// Replace floating induction variable.
|
||||||
UIToFPInst *Conv = new UIToFPInst(NewPHI, PH->getType(), "indvar.conv",
|
if (EV->getValueAPF().isNegative()
|
||||||
PH->getParent()->getFirstNonPHI());
|
|| InitValue->getValueAPF().isNegative()) {
|
||||||
PH->replaceAllUsesWith(Conv);
|
SIToFPInst *Conv = new SIToFPInst(NewPHI, PH->getType(), "indvar.conv",
|
||||||
|
PH->getParent()->getFirstNonPHI());
|
||||||
|
PH->replaceAllUsesWith(Conv);
|
||||||
|
} else {
|
||||||
|
UIToFPInst *Conv = new UIToFPInst(NewPHI, PH->getType(), "indvar.conv",
|
||||||
|
PH->getParent()->getFirstNonPHI());
|
||||||
|
PH->replaceAllUsesWith(Conv);
|
||||||
|
}
|
||||||
DeadInsts.insert(PH);
|
DeadInsts.insert(PH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
; RUN: llvm-as < %s | opt -indvars | llvm-dis | grep icmp | count 1
|
; RUN: llvm-as < %s | opt -indvars | llvm-dis | grep icmp | count 4
|
||||||
define void @bar() nounwind {
|
define void @bar() nounwind {
|
||||||
entry:
|
entry:
|
||||||
br label %bb
|
br label %bb
|
||||||
@@ -15,3 +15,51 @@ return: ; preds = %bb
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare i32 @foo(double)
|
declare i32 @foo(double)
|
||||||
|
|
||||||
|
define void @bar2() nounwind {
|
||||||
|
entry:
|
||||||
|
br label %bb
|
||||||
|
|
||||||
|
bb: ; preds = %bb, %entry
|
||||||
|
%x.0.reg2mem.0 = phi double [ -10.000000e+00, %entry ], [ %1, %bb ] ; <double> [#uses=2]
|
||||||
|
%0 = tail call i32 @foo(double %x.0.reg2mem.0) nounwind ; <i32> [#uses=0]
|
||||||
|
%1 = add double %x.0.reg2mem.0, 2.000000e+00 ; <double> [#uses=2]
|
||||||
|
%2 = fcmp olt double %1, -1.000000e+00 ; <i1> [#uses=1]
|
||||||
|
br i1 %2, label %bb, label %return
|
||||||
|
|
||||||
|
return: ; preds = %bb
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
define void @bar3() nounwind {
|
||||||
|
entry:
|
||||||
|
br label %bb
|
||||||
|
|
||||||
|
bb: ; preds = %bb, %entry
|
||||||
|
%x.0.reg2mem.0 = phi double [ 0.000000e+00, %entry ], [ %1, %bb ] ; <double> [#uses=2]
|
||||||
|
%0 = tail call i32 @foo(double %x.0.reg2mem.0) nounwind ; <i32> [#uses=0]
|
||||||
|
%1 = add double %x.0.reg2mem.0, 1.000000e+00 ; <double> [#uses=2]
|
||||||
|
%2 = fcmp olt double %1, -1.000000e+00 ; <i1> [#uses=1]
|
||||||
|
br i1 %2, label %bb, label %return
|
||||||
|
|
||||||
|
return: ; preds = %bb
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @bar4() nounwind {
|
||||||
|
entry:
|
||||||
|
br label %bb
|
||||||
|
|
||||||
|
bb: ; preds = %bb, %entry
|
||||||
|
%x.0.reg2mem.0 = phi double [ 40.000000e+00, %entry ], [ %1, %bb ] ; <double> [#uses=2]
|
||||||
|
%0 = tail call i32 @foo(double %x.0.reg2mem.0) nounwind ; <i32> [#uses=0]
|
||||||
|
%1 = add double %x.0.reg2mem.0, -1.000000e+00 ; <double> [#uses=2]
|
||||||
|
%2 = fcmp olt double %1, 1.000000e+00 ; <i1> [#uses=1]
|
||||||
|
br i1 %2, label %bb, label %return
|
||||||
|
|
||||||
|
return: ; preds = %bb
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user