if (!BI)
return true;
- // If already constant, nothing to do.
- if (isa<Constant>(BI->getCondition()))
- return true;
-
// Likewise, the loop latch must be dominated by the exiting BB.
if (!DT->dominates(ExitingBB, L->getLoopLatch()))
return true;
+ if (auto *CI = dyn_cast<ConstantInt>(BI->getCondition())) {
+ // If already constant, nothing to do. However, if this is an
+ // unconditional exit, we can still replace header phis with their
+ // preheader value.
+ if (!L->contains(BI->getSuccessor(CI->isNullValue())))
+ replaceLoopPHINodesWithPreheaderValues(L, DeadInsts);
+ return true;
+ }
+
return false;
});
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[PHI2:%.*]], [[LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[DEC:%.*]] = add nuw nsw i32 [[PHI1]], -1
; CHECK-NEXT: br i1 false, label [[LEFT:%.*]], label [[RIGHT:%.*]]
; CHECK: left:
-; CHECK-NEXT: br label [[LATCH]]
+; CHECK-NEXT: br label [[LATCH:%.*]]
; CHECK: right:
; CHECK-NEXT: br label [[LATCH]]
; CHECK: latch:
-; CHECK-NEXT: [[PHI2]] = phi i32 [ [[PHI1]], [[LEFT]] ], [ [[DEC]], [[RIGHT]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 -1, undef
; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: [[TMP1:%.*]] = udiv i64 60392, [[TMP0]]
; CHECK-NEXT: br label [[LOOP2:%.*]]
; CHECK: loop2:
-; CHECK-NEXT: [[INDVARS_IV1:%.*]] = phi i64 [ [[TMP1]], [[LOOP2_PREHEADER]] ], [ [[INDVARS_IV_NEXT2:%.*]], [[LOOP2]] ]
-; CHECK-NEXT: [[INDVARS_IV_NEXT2]] = add nuw nsw i64 [[INDVARS_IV1]], -1
+; CHECK-NEXT: [[INDVARS_IV_NEXT2:%.*]] = add nuw nsw i64 [[TMP1]], -1
; CHECK-NEXT: [[I4:%.*]] = load atomic i64, i64* [[P1:%.*]] unordered, align 8
; CHECK-NEXT: [[I6:%.*]] = sub i64 [[I4]], [[INDVARS_IV_NEXT2]]
; CHECK-NEXT: store atomic i64 [[I6]], i64* [[P1]] unordered, align 8
; CHECK-NEXT: [[TMP5:%.*]] = add nsw i64 [[TMP4]], 60392
; CHECK-NEXT: br label [[LOOP2:%.*]]
; CHECK: loop2:
-; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP5]], [[LOOP2_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP2]] ]
-; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = add nsw i64 [[TMP5]], -1
; CHECK-NEXT: [[I4:%.*]] = load atomic i64, i64* [[P1:%.*]] unordered, align 8
; CHECK-NEXT: [[I6:%.*]] = sub i64 [[I4]], [[INDVARS_IV_NEXT]]
; CHECK-NEXT: store atomic i64 [[I6]], i64* [[P1]] unordered, align 8
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT: store i64 [[INDVARS_IV]], i64* null, align 8
-; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT: store i64 0, i64* null, align 8
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[RETURN:%.*]]
; CHECK: return:
; CHECK-NEXT: ret void
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[BB:%.*]]
; CHECK: bb:
-; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 40, [[ENTRY:%.*]] ], [ [[DOTINT:%.*]], [[BB]] ]
-; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to double
+; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 40 to double
; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @foo(double [[INDVAR_CONV]]) #[[ATTR0]]
-; CHECK-NEXT: [[DOTINT]] = add nsw i32 [[IV_INT]], -1
; CHECK-NEXT: br i1 false, label [[BB]], label [[RETURN:%.*]]
; CHECK: return:
; CHECK-NEXT: ret void
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer.header:
+; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 0, i32 undef)
+; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[SMAX]], 1
; CHECK-NEXT: br label [[INNER_HEADER:%.*]]
; CHECK: inner.header:
; CHECK-NEXT: br i1 false, label [[INNER_LATCH:%.*]], label [[OUTER_LATCH:%.*]]
; CHECK: outer.latch:
; CHECK-NEXT: br i1 false, label [[OUTER_HEADER]], label [[EXIT_LOOPEXIT1:%.*]]
; CHECK: exit.loopexit:
+; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[TMP0]], [[INNER_LATCH]] ]
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: exit.loopexit1:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
+; CHECK-NEXT: [[EXIT_PHI:%.*]] = phi i32 [ [[INC_LCSSA]], [[EXIT_LOOPEXIT]] ], [ undef, [[EXIT_LOOPEXIT1]] ]
; CHECK-NEXT: ret void
;
entry:
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[PTR_IV:%.*]] = phi %structIF* [ [[PTR_INC:%.*]], [[LATCH:%.*]] ], [ [[BASE:%.*]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[INDVARS1:%.*]] = bitcast %structIF* [[PTR_IV]] to i32*
+; CHECK-NEXT: [[INDVARS1:%.*]] = bitcast %structIF* [[BASE:%.*]] to i32*
; CHECK-NEXT: store i32 4, i32* [[INDVARS1]], align 4
-; CHECK-NEXT: br i1 false, label [[LATCH]], label [[EXIT:%.*]]
+; CHECK-NEXT: br i1 false, label [[LATCH:%.*]], label [[EXIT:%.*]]
; CHECK: latch:
-; CHECK-NEXT: [[PTR_INC]] = getelementptr inbounds [[STRUCTIF:%.*]], %structIF* [[PTR_IV]], i64 1
; CHECK-NEXT: br label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: ret void
; CHECK: for.body.preheader:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
-; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 1, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ]
-; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32
+; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 1 to i32
; CHECK-NEXT: br i1 undef, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then:
-; CHECK-NEXT: br i1 undef, label [[IF_THEN33:%.*]], label [[FOR_INC]]
+; CHECK-NEXT: br i1 undef, label [[IF_THEN33:%.*]], label [[FOR_INC:%.*]]
; CHECK: if.then33:
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: if.else:
; CHECK-NEXT: br i1 undef, label [[IF_THEN97:%.*]], label [[FOR_INC]]
; CHECK: if.then97:
-; CHECK-NEXT: call void @use64(i64 [[INDVARS_IV]])
+; CHECK-NEXT: call void @use64(i64 1)
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: [[KMIN_1:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN33]] ], [ 0, [[IF_THEN]] ], [ [[TMP0]], [[IF_THEN97]] ], [ 0, [[IF_ELSE]] ]
; CHECK-NEXT: call void @use32(i32 [[KMIN_1]])
-; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: br i1 false, label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
; CHECK: for.end.loopexit:
; CHECK-NEXT: br label [[FOR_END]]
; CHECK-NEXT: [[A_PROMOTED13:%.*]] = load i32, i32* @a, align 4
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]]
; CHECK: for.cond1.preheader:
-; CHECK-NEXT: [[OR_LCSSA14:%.*]] = phi i32 [ [[A_PROMOTED13]], [[ENTRY:%.*]] ], [ [[OR_LCSSA:%.*]], [[FOR_END:%.*]] ]
-; CHECK-NEXT: [[D_010:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ 0, [[FOR_END]] ]
; CHECK-NEXT: br label [[FOR_BODY3:%.*]]
; CHECK: for.body3:
-; CHECK-NEXT: [[INC12:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INC:%.*]], [[FOR_BODY3]] ]
-; CHECK-NEXT: [[OR11:%.*]] = phi i32 [ [[OR_LCSSA14]], [[FOR_COND1_PREHEADER]] ], [ [[OR:%.*]], [[FOR_BODY3]] ]
-; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[INC12]], [[D_010]]
-; CHECK-NEXT: [[OR]] = or i32 [[OR11]], [[ADD]]
-; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[INC12]], 1
-; CHECK-NEXT: br i1 false, label [[FOR_BODY3]], label [[FOR_END]]
+; CHECK-NEXT: [[ADD:%.*]] = sub i32 0, 1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[A_PROMOTED13]], [[ADD]]
+; CHECK-NEXT: br i1 false, label [[FOR_BODY3]], label [[FOR_END:%.*]]
; CHECK: for.end:
-; CHECK-NEXT: [[OR_LCSSA]] = phi i32 [ [[OR]], [[FOR_BODY3]] ]
+; CHECK-NEXT: [[OR_LCSSA:%.*]] = phi i32 [ [[OR]], [[FOR_BODY3]] ]
; CHECK-NEXT: br i1 false, label [[FOR_COND1_PREHEADER]], label [[FOR_END6:%.*]]
; CHECK: for.end6:
; CHECK-NEXT: [[OR_LCSSA_LCSSA:%.*]] = phi i32 [ [[OR_LCSSA]], [[FOR_END]] ]
; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ -9, [[BB:%.*]] ], [ [[TMP6:%.*]], [[BB1:%.*]] ]
; CHECK-NEXT: br label [[BB3:%.*]]
; CHECK: bb3:
-; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ -9, [[BB2]] ], [ [[TMP6]], [[BB10:%.*]] ]
; CHECK-NEXT: br i1 false, label [[BB5:%.*]], label [[BB12:%.*]]
; CHECK: bb5:
-; CHECK-NEXT: [[TMP6]] = add nsw i32 [[TMP4]], -1
+; CHECK-NEXT: [[TMP6]] = add nsw i32 -9, -1
; CHECK-NEXT: br i1 undef, label [[BB8:%.*]], label [[BB9:%.*]]
; CHECK: bb8:
-; CHECK-NEXT: br label [[BB10]]
+; CHECK-NEXT: br label [[BB10:%.*]]
; CHECK: bb9:
; CHECK-NEXT: br label [[BB10]]
; CHECK: bb10:
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
-; CHECK-NEXT: [[POS_42:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD85:%.*]], [[FOR_INC:%.*]] ]
; CHECK-NEXT: br label [[FOR_INNER:%.*]]
; CHECK: for.inner:
; CHECK-NEXT: [[I_0_I:%.*]] = phi i32 [ 0, [[FOR_BODY]] ], [ [[INC_I:%.*]], [[FOR_INNER]] ]
; CHECK-NEXT: [[I_0_I1:%.*]] = phi i32 [ 0, [[FOR_INNER_EXIT]] ], [ [[INC_I3:%.*]], [[FOR_INNER_2]] ]
; CHECK-NEXT: [[INC_I3]] = add nuw nsw i32 [[I_0_I1]], 1
; CHECK-NEXT: [[CMP7_I4:%.*]] = icmp slt i8 [[N]], 0
-; CHECK-NEXT: br i1 [[CMP7_I4]], label [[FOR_INNER_2]], label [[FOR_INC]]
+; CHECK-NEXT: br i1 [[CMP7_I4]], label [[FOR_INNER_2]], label [[FOR_INC:%.*]]
; CHECK: for.inc:
; CHECK-NEXT: [[INC_I3_LCSSA:%.*]] = phi i32 [ [[INC_I3]], [[FOR_INNER_2]] ]
-; CHECK-NEXT: [[ADD71:%.*]] = add i32 [[POS_42]], [[INC_I_LCSSA]]
-; CHECK-NEXT: [[ADD85]] = add i32 [[ADD71]], [[INC_I3_LCSSA]]
+; CHECK-NEXT: [[ADD71:%.*]] = add i32 0, [[INC_I_LCSSA]]
+; CHECK-NEXT: [[ADD85:%.*]] = add i32 [[ADD71]], [[INC_I3_LCSSA]]
; CHECK-NEXT: br i1 false, label [[FOR_BODY]], label [[WHILE_COND_PREHEADER:%.*]]
; CHECK: while.cond.preheader:
; CHECK-NEXT: [[ADD85_LCSSA:%.*]] = phi i32 [ [[ADD85]], [[FOR_INC]] ]
; CHECK-NEXT: bb:
; CHECK-NEXT: br label [[BB4:%.*]]
; CHECK: bb1:
-; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = add i32 [[INDVARS_IV:%.*]], 1
; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[TMP1:%.*]], [[SMAX:%.*]]
; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[BB4]]
; CHECK: bb2:
; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[TMP0]], [[BB1:%.*]] ]
; CHECK-NEXT: ret void
; CHECK: bb4:
-; CHECK-NEXT: [[INDVARS_IV]] = phi i32 [ [[INDVARS_IV_NEXT]], [[BB1]] ], [ undef, [[BB:%.*]] ]
-; CHECK-NEXT: [[SMAX]] = call i32 @llvm.smax.i32(i32 [[INDVARS_IV]], i32 36)
-; CHECK-NEXT: [[TMP6:%.*]] = invoke i32 @quux() [ "deopt"(i32 0, i32 0, i32 0, i32 180, i32 0, i32 25, i32 0, i32 7, i8* null, i32 7, i8* null, i32 7, i8* null, i32 3, i32 [[INDVARS_IV]], i32 3, i32 undef, i32 7, i8* null, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 4, double undef, i32 7, i8* null, i32 4, i64 undef, i32 7, i8* null, i32 0, i8 addrspace(1)* undef, i32 3, i32 undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 7, i8* null) ]
+; CHECK-NEXT: [[SMAX]] = call i32 @llvm.smax.i32(i32 undef, i32 36)
+; CHECK-NEXT: [[TMP6:%.*]] = invoke i32 @quux() [ "deopt"(i32 0, i32 0, i32 0, i32 180, i32 0, i32 25, i32 0, i32 7, i8* null, i32 7, i8* null, i32 7, i8* null, i32 3, i32 undef, i32 3, i32 undef, i32 7, i8* null, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 4, double undef, i32 7, i8* null, i32 4, i64 undef, i32 7, i8* null, i32 0, i8 addrspace(1)* undef, i32 3, i32 undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 0, i8 addrspace(1)* undef, i32 7, i8* null) ]
; CHECK-NEXT: to label [[BB7:%.*]] unwind label [[BB15:%.*]]
; CHECK: bb7:
-; CHECK-NEXT: [[TMP1]] = add i32 [[TMP6]], [[INDVARS_IV]]
+; CHECK-NEXT: [[TMP1]] = add i32 [[TMP6]], undef
; CHECK-NEXT: br label [[BB9:%.*]]
; CHECK: bb9:
; CHECK-NEXT: br i1 true, label [[BB1]], label [[BB9]]
; CHECK-NEXT: bb:
; CHECK-NEXT: br label [[BB1:%.*]]
; CHECK: bb1:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ 11, [[BB:%.*]] ]
; CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 112, -1
-; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i32 [[TMP2]], 1
; CHECK-NEXT: [[TMP5:%.*]] = mul i32 [[TMP3]], [[TMP3]]
-; CHECK-NEXT: [[TMP6:%.*]] = mul nsw i32 [[TMP2]], -6
+; CHECK-NEXT: [[TMP6:%.*]] = mul nsw i32 11, -6
; CHECK-NEXT: [[TMP7:%.*]] = mul nsw i32 [[TMP6]], [[TMP5]]
-; CHECK-NEXT: [[TMP8:%.*]] = add nuw nsw i32 [[TMP7]], [[TMP2]]
+; CHECK-NEXT: [[TMP8:%.*]] = add nuw nsw i32 [[TMP7]], 11
; CHECK-NEXT: [[TMP9:%.*]] = and i32 undef, 1
; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP9]], 0
; CHECK-NEXT: br i1 [[TMP10]], label [[BB33_LOOPEXIT1:%.*]], label [[BB34_PREHEADER:%.*]]
; CHECK-NEXT: [[TMP2_LCSSA9:%.*]] = phi i32 [ [[TMP2_LCSSA12]], [[BB11:%.*]] ]
; CHECK-NEXT: br label [[BB33:%.*]]
; CHECK: bb33.loopexit1:
-; CHECK-NEXT: [[TMP2_LCSSA:%.*]] = phi i32 [ [[TMP2]], [[BB1]] ]
+; CHECK-NEXT: [[TMP2_LCSSA:%.*]] = phi i32 [ 11, [[BB1]] ]
; CHECK-NEXT: br label [[BB33]]
; CHECK: bb33:
; CHECK-NEXT: [[TMP210:%.*]] = phi i32 [ [[TMP2_LCSSA]], [[BB33_LOOPEXIT1]] ], [ [[TMP2_LCSSA9]], [[BB33_LOOPEXIT]] ]
; CHECK: loop2.preheader:
; CHECK-NEXT: br label [[LOOP2:%.*]]
; CHECK: loop2:
-; CHECK-NEXT: [[PTR:%.*]] = phi i64* [ [[PTR_BASE:%.*]], [[LOOP2_PREHEADER]] ], [ [[PTR_NEXT:%.*]], [[LOOP2]] ]
-; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds i64, i64* [[PTR]], i64 1
+; CHECK-NEXT: [[PTR_NEXT:%.*]] = getelementptr inbounds i64, i64* [[PTR_BASE:%.*]], i64 1
; CHECK-NEXT: br i1 true, label [[LOOP2_EXIT:%.*]], label [[LOOP2]]
; CHECK: loop2.exit:
; CHECK-NEXT: [[PTR_NEXT_LCSSA:%.*]] = phi i64* [ [[PTR_NEXT]], [[LOOP2]] ]