Instruction *NarrowUse;
Instruction *WideDef;
- NarrowIVDefUse(): NarrowDef(nullptr), NarrowUse(nullptr), WideDef(nullptr) {}
+ // True if the narrow def is never negative. Tracking this information lets
+ // us use a sign extension instead of a zero extension or vice versa, when
+ // profitable and legal.
+ bool NeverNegative;
+
+ NarrowIVDefUse()
+ : NarrowDef(nullptr), NarrowUse(nullptr), WideDef(nullptr),
+ NeverNegative(false) {}
- NarrowIVDefUse(Instruction *ND, Instruction *NU, Instruction *WD):
- NarrowDef(ND), NarrowUse(NU), WideDef(WD) {}
+ NarrowIVDefUse(Instruction *ND, Instruction *NU, Instruction *WD,
+ bool NeverNegative)
+ : NarrowDef(ND), NarrowUse(NU), WideDef(WD),
+ NeverNegative(NeverNegative) {}
};
/// WidenIV - The goal of this transform is to remove sign and zero extends
Type *WideType;
bool IsSigned;
- // True if the narrow induction variable is never negative. Tracking this
- // information lets us use a sign extension instead of a zero extension or
- // vice versa, when profitable and legal.
- bool NeverNegative;
-
// Context
LoopInfo *LI;
Loop *L;
OrigPhi(WI.NarrowIV),
WideType(WI.WidestNativeType),
IsSigned(WI.IsSigned),
- NeverNegative(false),
LI(LInfo),
L(LI->getLoopFor(OrigPhi->getParent())),
SE(SEv),
// (A) == icmp slt i32 sext(%narrow), sext(%val)
// == icmp slt i32 zext(%narrow), sext(%val)
- if (!(NeverNegative || IsSigned == Cmp->isSigned()))
+ if (!(DU.NeverNegative || IsSigned == Cmp->isSigned()))
return false;
Value *Op = Cmp->getOperand(Cmp->getOperand(0) == DU.NarrowDef ? 1 : 0);
/// pushNarrowIVUsers - Add eligible users of NarrowDef to NarrowIVUsers.
///
void WidenIV::pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef) {
+ const SCEV *NarrowSCEV = SE->getSCEV(NarrowDef);
+ bool NeverNegative =
+ SE->isKnownPredicate(ICmpInst::ICMP_SGE, NarrowSCEV,
+ SE->getConstant(NarrowSCEV->getType(), 0));
for (User *U : NarrowDef->users()) {
Instruction *NarrowUser = cast<Instruction>(U);
if (!Widened.insert(NarrowUser).second)
continue;
- NarrowIVUsers.push_back(NarrowIVDefUse(NarrowDef, NarrowUser, WideDef));
+ NarrowIVUsers.push_back(
+ NarrowIVDefUse(NarrowDef, NarrowUser, WideDef, NeverNegative));
}
}
if (!AddRec)
return nullptr;
- NeverNegative = SE->isKnownPredicate(ICmpInst::ICMP_SGE, AddRec,
- SE->getConstant(AddRec->getType(), 0));
-
// Widen the induction variable expression.
const SCEV *WideIVExpr = IsSigned ?
SE->getSignExtendExpr(AddRec, WideType) :
leave:
ret i32 0
}
+
+declare void @consume.i64(i64)
+declare void @consume.i1(i1)
+
+define i32 @test10(i32 %v) {
+; CHECK-LABEL: @test10(
+ entry:
+; CHECK-NOT: zext
+ br label %loop
+
+ loop:
+; CHECK: loop:
+; CHECK: %indvars.iv = phi i64 [ %indvars.iv.next, %loop ], [ 0, %entry ]
+; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+; CHECK: [[MUL:%[a-z0-9]+]] = mul nsw i64 %indvars.iv, -1
+; CHECK: [[MUL_TRUNC:%[a-z0-9]+]] = trunc i64 [[MUL]] to i32
+; CHECK: [[CMP:%[a-z0-9]+]] = icmp eq i32 [[MUL_TRUNC]], %v
+; CHECK: call void @consume.i1(i1 [[CMP]])
+
+ %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
+ %i.inc = add i32 %i, 1
+ %iv = mul i32 %i, -1
+ %cmp = icmp eq i32 %iv, %v
+ call void @consume.i1(i1 %cmp)
+ %be.cond = icmp slt i32 %i.inc, 11
+ %ext = sext i32 %iv to i64
+ call void @consume.i64(i64 %ext)
+ br i1 %be.cond, label %loop, label %leave
+
+ leave:
+ ret i32 22
+}