mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-26 01:38:43 +00:00
[disable-iv-rewrite] Allow WidenIV to handle NSW/NUW operations
better. Don't immediately give up when an add operation can't be trivially sign/zero-extended within a loop. If it has NSW/NUW flags, generate a new expression with sign extended (non-recurrent) operand. As before, if SCEV says that all sign extends are loop invariant, then we can widen the operation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139453 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
543376743c
commit
20151da8c3
@ -858,6 +858,8 @@ protected:
|
|||||||
|
|
||||||
const SCEVAddRecExpr *GetWideRecurrence(Instruction *NarrowUse);
|
const SCEVAddRecExpr *GetWideRecurrence(Instruction *NarrowUse);
|
||||||
|
|
||||||
|
const SCEVAddRecExpr* GetExtendedOperandRecurrence(NarrowIVDefUse DU);
|
||||||
|
|
||||||
Instruction *WidenIVUse(NarrowIVDefUse DU);
|
Instruction *WidenIVUse(NarrowIVDefUse DU);
|
||||||
|
|
||||||
void pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef);
|
void pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef);
|
||||||
@ -951,6 +953,41 @@ static bool HoistStep(Instruction *IncV, Instruction *InsertPos,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// No-wrap operations can transfer sign extension of their result to their
|
||||||
|
/// operands. Generate the SCEV value for the widened operation without
|
||||||
|
/// actually modifying the IR yet. If the expression after extending the
|
||||||
|
/// operands is an AddRec for this loop, return it.
|
||||||
|
const SCEVAddRecExpr* WidenIV::GetExtendedOperandRecurrence(NarrowIVDefUse DU) {
|
||||||
|
// Handle the common case of add<nsw/nuw>
|
||||||
|
if (DU.NarrowUse->getOpcode() != Instruction::Add)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// One operand (NarrowDef) has already been extended to WideDef. Now determine
|
||||||
|
// if extending the other will lead to a recurrence.
|
||||||
|
unsigned ExtendOperIdx = DU.NarrowUse->getOperand(0) == DU.NarrowDef ? 1 : 0;
|
||||||
|
assert(DU.NarrowUse->getOperand(1-ExtendOperIdx) == DU.NarrowDef && "bad DU");
|
||||||
|
|
||||||
|
const SCEV *ExtendOperExpr = 0;
|
||||||
|
const OverflowingBinaryOperator *OBO =
|
||||||
|
cast<OverflowingBinaryOperator>(DU.NarrowUse);
|
||||||
|
if (IsSigned && OBO->hasNoSignedWrap())
|
||||||
|
ExtendOperExpr = SE->getSignExtendExpr(
|
||||||
|
SE->getSCEV(DU.NarrowUse->getOperand(ExtendOperIdx)), WideType);
|
||||||
|
else if(!IsSigned && OBO->hasNoUnsignedWrap())
|
||||||
|
ExtendOperExpr = SE->getZeroExtendExpr(
|
||||||
|
SE->getSCEV(DU.NarrowUse->getOperand(ExtendOperIdx)), WideType);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(
|
||||||
|
SE->getAddExpr(SE->getSCEV(DU.WideDef), ExtendOperExpr,
|
||||||
|
IsSigned ? SCEV::FlagNSW : SCEV::FlagNUW));
|
||||||
|
|
||||||
|
if (!AddRec || AddRec->getLoop() != L)
|
||||||
|
return 0;
|
||||||
|
return AddRec;
|
||||||
|
}
|
||||||
|
|
||||||
/// GetWideRecurrence - Is this instruction potentially interesting from
|
/// GetWideRecurrence - Is this instruction potentially interesting from
|
||||||
/// IVUsers' perspective after widening it's type? In other words, can the
|
/// IVUsers' perspective after widening it's type? In other words, can the
|
||||||
/// extend be safely hoisted out of the loop with SCEV reducing the value to a
|
/// extend be safely hoisted out of the loop with SCEV reducing the value to a
|
||||||
@ -974,7 +1011,6 @@ const SCEVAddRecExpr *WidenIV::GetWideRecurrence(Instruction *NarrowUse) {
|
|||||||
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(WideExpr);
|
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(WideExpr);
|
||||||
if (!AddRec || AddRec->getLoop() != L)
|
if (!AddRec || AddRec->getLoop() != L)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return AddRec;
|
return AddRec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1027,6 +1063,9 @@ Instruction *WidenIV::WidenIVUse(NarrowIVDefUse DU) {
|
|||||||
|
|
||||||
// Does this user itself evaluate to a recurrence after widening?
|
// Does this user itself evaluate to a recurrence after widening?
|
||||||
const SCEVAddRecExpr *WideAddRec = GetWideRecurrence(DU.NarrowUse);
|
const SCEVAddRecExpr *WideAddRec = GetWideRecurrence(DU.NarrowUse);
|
||||||
|
if (!WideAddRec) {
|
||||||
|
WideAddRec = GetExtendedOperandRecurrence(DU);
|
||||||
|
}
|
||||||
if (!WideAddRec) {
|
if (!WideAddRec) {
|
||||||
// This user does not evaluate to a recurence after widening, so don't
|
// This user does not evaluate to a recurence after widening, so don't
|
||||||
// follow it. Instead insert a Trunc to kill off the original use,
|
// follow it. Instead insert a Trunc to kill off the original use,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user