llvm.org GIT mirror llvm / 728c7f3
Fold trunc casts into add-recurrence expressions, allowing the add-recurrence to be exposed. Add a new SCEV folding rule to help simplify expressions in the presence of these extra truncs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71264 91177308-0d34-0410-b5e6-96231b3b80d8 Dan Gohman 11 years ago
2 changed file(s) with 86 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
747747 if (const SCEVAddRecExpr *AddRec = dyn_cast(Op)) {
748748 std::vector Operands;
749749 for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i)
750 // FIXME: This should allow truncation of other expression types!
751 if (isa(AddRec->getOperand(i)))
752 Operands.push_back(getTruncateExpr(AddRec->getOperand(i), Ty));
753 else
754 break;
755 if (Operands.size() == AddRec->getNumOperands())
756 return getAddRecExpr(Operands, AddRec->getLoop());
750 Operands.push_back(getTruncateExpr(AddRec->getOperand(i), Ty));
751 return getAddRecExpr(Operands, AddRec->getLoop());
757752 }
758753
759754 SCEVTruncateExpr *&Result = (*SCEVTruncates)[std::make_pair(Op, Ty)];
965960 return getAddExpr(Ops);
966961 }
967962
968 // Now we know the first non-constant operand. Skip past any cast SCEVs.
963 // Check for truncates. If all the operands are truncated from the same
964 // type, see if factoring out the truncate would permit the result to be
965 // folded. eg., trunc(x) + m*trunc(n) --> trunc(x + trunc(m)*n)
966 // if the contents of the resulting outer trunc fold to something simple.
967 for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) {
968 const SCEVTruncateExpr *Trunc = cast(Ops[Idx]);
969 const Type *DstType = Trunc->getType();
970 const Type *SrcType = Trunc->getOperand()->getType();
971 std::vector LargeOps;
972 bool Ok = true;
973 // Check all the operands to see if they can be represented in the
974 // source type of the truncate.
975 for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
976 if (const SCEVTruncateExpr *T = dyn_cast(Ops[i])) {
977 if (T->getOperand()->getType() != SrcType) {
978 Ok = false;
979 break;
980 }
981 LargeOps.push_back(T->getOperand());
982 } else if (const SCEVConstant *C = dyn_cast(Ops[i])) {
983 // This could be either sign or zero extension, but sign extension
984 // is much more likely to be foldable here.
985 LargeOps.push_back(getSignExtendExpr(C, SrcType));
986 } else if (const SCEVMulExpr *M = dyn_cast(Ops[i])) {
987 std::vector LargeMulOps;
988 for (unsigned j = 0, f = M->getNumOperands(); j != f && Ok; ++j) {
989 if (const SCEVTruncateExpr *T =
990 dyn_cast(M->getOperand(j))) {
991 if (T->getOperand()->getType() != SrcType) {
992 Ok = false;
993 break;
994 }
995 LargeMulOps.push_back(T->getOperand());
996 } else if (const SCEVConstant *C =
997 dyn_cast(M->getOperand(j))) {
998 // This could be either sign or zero extension, but sign extension
999 // is much more likely to be foldable here.
1000 LargeMulOps.push_back(getSignExtendExpr(C, SrcType));
1001 } else {
1002 Ok = false;
1003 break;
1004 }
1005 }
1006 if (Ok)
1007 LargeOps.push_back(getMulExpr(LargeMulOps));
1008 } else {
1009 Ok = false;
1010 break;
1011 }
1012 }
1013 if (Ok) {
1014 // Evaluate the expression in the larger type.
1015 SCEVHandle Fold = getAddExpr(LargeOps);
1016 // If it folds to something simple, use it. Otherwise, don't.
1017 if (isa(Fold) || isa(Fold))
1018 return getTruncateExpr(Fold, DstType);
1019 }
1020 }
1021
1022 // Skip past any other cast SCEVs.
9691023 while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddExpr)
9701024 ++Idx;
9711025
0 ; RUN: llvm-as < %s | opt -analyze -scalar-evolution -disable-output \
1 ; RUN: | grep {sext.*trunc.*Exits: 11}
2
3 ; ScalarEvolution should be able to compute a loop exit value for %indvar.i8.
4
5 define void @another_count_down_signed(double* %d, i64 %n) nounwind {
6 entry:
7 br label %loop
8
9 loop: ; preds = %loop, %entry
10 %indvar = phi i64 [ %n, %entry ], [ %indvar.next, %loop ] ; [#uses=4]
11 %s0 = shl i64 %indvar, 8 ; [#uses=1]
12 %indvar.i8 = ashr i64 %s0, 8 ; [#uses=1]
13 %t0 = getelementptr double* %d, i64 %indvar.i8 ; [#uses=2]
14 %t1 = load double* %t0 ; [#uses=1]
15 %t2 = mul double %t1, 1.000000e-01 ; [#uses=1]
16 store double %t2, double* %t0
17 %indvar.next = sub i64 %indvar, 1 ; [#uses=2]
18 %exitcond = icmp eq i64 %indvar.next, 10 ; [#uses=1]
19 br i1 %exitcond, label %return, label %loop
20
21 return: ; preds = %loop
22 ret void
23 }