Index: llvm/lib/Analysis/LoopInfo.cpp =================================================================== --- llvm/lib/Analysis/LoopInfo.cpp +++ llvm/lib/Analysis/LoopInfo.cpp @@ -303,6 +303,16 @@ Instruction *LatchCmpOp0 = dyn_cast(CmpInst->getOperand(0)); Instruction *LatchCmpOp1 = dyn_cast(CmpInst->getOperand(1)); + // IndVarSimplify can introduce truncs after certain induction variable + // optimisations so that the cmp instructions looks like: + // + // cmp = Trunc(IndVar) < FinalValue + // + // Here we look through the Trunc instruction to see if we can still match + // instruction IndVar. + if (isa(LatchCmpOp0)) + LatchCmpOp0 = dyn_cast(LatchCmpOp0->getOperand(0)); + for (PHINode &IndVar : Header->phis()) { InductionDescriptor IndDesc; if (!InductionDescriptor::isInductionPHI(&IndVar, this, &SE, IndDesc)) Index: llvm/test/CodeGen/AArch64/arm64-scaled_iv.ll =================================================================== --- llvm/test/CodeGen/AArch64/arm64-scaled_iv.ll +++ llvm/test/CodeGen/AArch64/arm64-scaled_iv.ll @@ -13,27 +13,23 @@ define void @mulDouble(double* nocapture %a, double* nocapture %b, double* nocapture %c) { ; CHECK-LABEL: @mulDouble( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[B8:%.*]] = bitcast double* [[B:%.*]] to i8* ; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr double, double* [[A:%.*]], i64 1 -; CHECK-NEXT: [[SCEVGEP1:%.*]] = bitcast double* [[SCEVGEP]] to i8* -; CHECK-NEXT: [[SCEVGEP4:%.*]] = getelementptr double, double* [[C:%.*]], i64 2 -; CHECK-NEXT: [[SCEVGEP45:%.*]] = bitcast double* [[SCEVGEP4]] to i8* +; CHECK-NEXT: [[SCEVGEP3:%.*]] = getelementptr double, double* [[C:%.*]], i64 2 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[UGLYGEP9:%.*]] = getelementptr i8, i8* [[B8]], i64 [[LSR_IV]] -; CHECK-NEXT: [[UGLYGEP910:%.*]] = bitcast i8* [[UGLYGEP9]] to double* -; CHECK-NEXT: [[TMP1:%.*]] = load double, double* [[UGLYGEP910]], align 8 -; CHECK-NEXT: [[UGLYGEP6:%.*]] = getelementptr i8, i8* [[SCEVGEP45]], i64 [[LSR_IV]] -; CHECK-NEXT: [[UGLYGEP67:%.*]] = bitcast i8* [[UGLYGEP6]] to double* -; CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[UGLYGEP67]], align 8 +; CHECK-NEXT: [[LSR_IV6:%.*]] = phi double* [ [[SCEVGEP7:%.*]], [[FOR_BODY]] ], [ [[B:%.*]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[LSR_IV4:%.*]] = phi double* [ [[SCEVGEP5:%.*]], [[FOR_BODY]] ], [ [[SCEVGEP3]], [[ENTRY]] ] +; CHECK-NEXT: [[LSR_IV2:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 19, [[ENTRY]] ] +; CHECK-NEXT: [[LSR_IV:%.*]] = phi double* [ [[SCEVGEP1:%.*]], [[FOR_BODY]] ], [ [[SCEVGEP]], [[ENTRY]] ] +; CHECK-NEXT: [[TMP1:%.*]] = load double, double* [[LSR_IV6]], align 8 +; CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[LSR_IV4]], align 8 ; CHECK-NEXT: [[MUL:%.*]] = fmul double [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, i8* [[SCEVGEP1]], i64 [[LSR_IV]] -; CHECK-NEXT: [[UGLYGEP2:%.*]] = bitcast i8* [[UGLYGEP]] to double* -; CHECK-NEXT: store double [[MUL]], double* [[UGLYGEP2]], align 8 -; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i64 [[LSR_IV]], 8 -; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[LSR_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[TMP3]], 152 +; CHECK-NEXT: store double [[MUL]], double* [[LSR_IV]], align 8 +; CHECK-NEXT: [[SCEVGEP1]] = getelementptr double, double* [[LSR_IV]], i64 1 +; CHECK-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV2]], -1 +; CHECK-NEXT: [[SCEVGEP5]] = getelementptr double, double* [[LSR_IV4]], i64 1 +; CHECK-NEXT: [[SCEVGEP7]] = getelementptr double, double* [[LSR_IV6]], i64 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 0 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] ; CHECK: for.end: ; CHECK-NEXT: ret void