mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-10-26 18:20:39 +00:00
This transform only handles two-operand AddRec's. Prevent it from trying to
handle anything more complex. Fixes PR10383 again! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139186 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1974,7 +1974,8 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
|
|||||||
// multiplied together. If so, we can fold them.
|
// multiplied together. If so, we can fold them.
|
||||||
for (unsigned OtherIdx = Idx+1;
|
for (unsigned OtherIdx = Idx+1;
|
||||||
OtherIdx < Ops.size() && isa<SCEVAddRecExpr>(Ops[OtherIdx]);
|
OtherIdx < Ops.size() && isa<SCEVAddRecExpr>(Ops[OtherIdx]);
|
||||||
++OtherIdx)
|
++OtherIdx) {
|
||||||
|
bool Retry = false;
|
||||||
if (AddRecLoop == cast<SCEVAddRecExpr>(Ops[OtherIdx])->getLoop()) {
|
if (AddRecLoop == cast<SCEVAddRecExpr>(Ops[OtherIdx])->getLoop()) {
|
||||||
// {A,+,B}<L> * {C,+,D}<L> --> {A*C,+,A*D + B*C + B*D,+,2*B*D}<L>
|
// {A,+,B}<L> * {C,+,D}<L> --> {A*C,+,A*D + B*C + B*D,+,2*B*D}<L>
|
||||||
//
|
//
|
||||||
@@ -1985,7 +1986,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
|
|||||||
// Rearranging, X = x, Y = y+z, Z = 2z.
|
// Rearranging, X = x, Y = y+z, Z = 2z.
|
||||||
//
|
//
|
||||||
// x = A*C, y = (A*D + B*C), z = B*D.
|
// x = A*C, y = (A*D + B*C), z = B*D.
|
||||||
// Therefore X = A*C, Y = (A*D + B*C) + B*D and Z = 2*B*D.
|
// Therefore X = A*C, Y = A*D + B*C + B*D and Z = 2*B*D.
|
||||||
for (; OtherIdx != Ops.size() && isa<SCEVAddRecExpr>(Ops[OtherIdx]);
|
for (; OtherIdx != Ops.size() && isa<SCEVAddRecExpr>(Ops[OtherIdx]);
|
||||||
++OtherIdx)
|
++OtherIdx)
|
||||||
if (const SCEVAddRecExpr *OtherAddRec =
|
if (const SCEVAddRecExpr *OtherAddRec =
|
||||||
@@ -2002,19 +2003,28 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
|
|||||||
const SCEV *NewSecondOrderStep =
|
const SCEV *NewSecondOrderStep =
|
||||||
getMulExpr(BD, getConstant(BD->getType(), 2));
|
getMulExpr(BD, getConstant(BD->getType(), 2));
|
||||||
|
|
||||||
SmallVector<const SCEV *, 3> AddRecOps;
|
// This can happen when AddRec or OtherAddRec have >3 operands.
|
||||||
AddRecOps.push_back(NewStart);
|
// TODO: support these add-recs.
|
||||||
AddRecOps.push_back(NewStep);
|
if (isLoopInvariant(NewStart, AddRecLoop) &&
|
||||||
AddRecOps.push_back(NewSecondOrderStep);
|
isLoopInvariant(NewStep, AddRecLoop) &&
|
||||||
const SCEV *NewAddRec = getAddRecExpr(AddRecOps,
|
isLoopInvariant(NewSecondOrderStep, AddRecLoop)) {
|
||||||
AddRec->getLoop(),
|
SmallVector<const SCEV *, 3> AddRecOps;
|
||||||
SCEV::FlagAnyWrap);
|
AddRecOps.push_back(NewStart);
|
||||||
if (Ops.size() == 2) return NewAddRec;
|
AddRecOps.push_back(NewStep);
|
||||||
Ops[Idx] = AddRec = cast<SCEVAddRecExpr>(NewAddRec);
|
AddRecOps.push_back(NewSecondOrderStep);
|
||||||
Ops.erase(Ops.begin() + OtherIdx); --OtherIdx;
|
const SCEV *NewAddRec = getAddRecExpr(AddRecOps,
|
||||||
|
AddRec->getLoop(),
|
||||||
|
SCEV::FlagAnyWrap);
|
||||||
|
if (Ops.size() == 2) return NewAddRec;
|
||||||
|
Ops[Idx] = AddRec = cast<SCEVAddRecExpr>(NewAddRec);
|
||||||
|
Ops.erase(Ops.begin() + OtherIdx); --OtherIdx;
|
||||||
|
Retry = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return getMulExpr(Ops);
|
if (Retry)
|
||||||
|
return getMulExpr(Ops);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise couldn't fold anything into this recurrence. Move onto the
|
// Otherwise couldn't fold anything into this recurrence. Move onto the
|
||||||
// next one.
|
// next one.
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ return: ; preds = %bb5
|
|||||||
|
|
||||||
|
|
||||||
; PR10383
|
; PR10383
|
||||||
; This used to crash.
|
; These next two used to crash.
|
||||||
|
|
||||||
define void @test2(i1 %cmp, i64 %n) {
|
define void @test2(i1 %cmp, i64 %n) {
|
||||||
entry:
|
entry:
|
||||||
@@ -61,3 +61,22 @@ end:
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
; CHECK: Determining loop execution counts for: @test2
|
; CHECK: Determining loop execution counts for: @test2
|
||||||
|
|
||||||
|
define i32 @test3() {
|
||||||
|
if.then466:
|
||||||
|
br i1 undef, label %for.cond539.preheader, label %for.inc479
|
||||||
|
|
||||||
|
for.inc479:
|
||||||
|
%a2.07 = phi i32 [ %add495, %for.inc479 ], [ 0, %if.then466 ]
|
||||||
|
%j.36 = phi i32 [ %inc497, %for.inc479 ], [ undef, %if.then466 ]
|
||||||
|
%mul484 = mul nsw i32 %j.36, %j.36
|
||||||
|
%mul491 = mul i32 %j.36, %j.36
|
||||||
|
%mul493 = mul i32 %mul491, %mul484
|
||||||
|
%add495 = add nsw i32 %mul493, %a2.07
|
||||||
|
%inc497 = add nsw i32 %j.36, 1
|
||||||
|
br i1 undef, label %for.cond539.preheader, label %for.inc479
|
||||||
|
|
||||||
|
for.cond539.preheader:
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
; CHECK: Determining loop execution counts for: @test3
|
||||||
|
|||||||
Reference in New Issue
Block a user