Index: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp +++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -521,20 +521,19 @@ if (isa(U) && !DT->isReachableFromEntry(cast(U)->getParent())) continue; - if (ICmpInst *ICI = dyn_cast(U)) { - if (ICI->getOperand(0) == TI && L->isLoopInvariant(ICI->getOperand(1))) { - assert(L->contains(ICI->getParent()) && "LCSSA form broken?"); - // If we cannot get rid of trunc, bail. - if (ICI->isSigned() && !DoesSExtCollapse) - return false; - if (ICI->isUnsigned() && !DoesZExtCollapse) - return false; - // For equality, either signed or unsigned works. - ICmpUsers.push_back(ICI); - } else - return false; - } else + ICmpInst *ICI = dyn_cast(U); + if (!ICI) return false; + assert(L->contains(ICI->getParent()) && "LCSSA form broken?"); + if (!(ICI->getOperand(0) == TI && L->isLoopInvariant(ICI->getOperand(1))) && + !(ICI->getOperand(1) == TI && L->isLoopInvariant(ICI->getOperand(0)))) return false; + // If we cannot get rid of trunc, bail. + if (ICI->isSigned() && !DoesSExtCollapse) + return false; + if (ICI->isUnsigned() && !DoesZExtCollapse) + return false; + // For equality, either signed or unsigned works. + ICmpUsers.push_back(ICI); } auto CanUseZExt = [&](ICmpInst *ICI) { @@ -557,7 +556,8 @@ }; // Replace all comparisons against trunc with comparisons against IV. for (auto *ICI : ICmpUsers) { - auto *Op1 = ICI->getOperand(1); + bool IsSwapped = L->isLoopInvariant(ICI->getOperand(0)); + auto *Op1 = IsSwapped ? ICI->getOperand(0) : ICI->getOperand(1); Instruction *Ext = nullptr; // For signed/unsigned predicate, replace the old comparison with comparison // of immediate IV against sext/zext of the invariant argument. If we can @@ -566,6 +566,7 @@ // TODO: If we see a signed comparison which can be turned into unsigned, // we can do it here for canonicalization purposes. ICmpInst::Predicate Pred = ICI->getPredicate(); + if (IsSwapped) Pred = ICmpInst::getSwappedPredicate(Pred); if (CanUseZExt(ICI)) { assert(DoesZExtCollapse && "Unprofitable zext?"); Ext = new ZExtInst(Op1, IVTy, "zext", ICI); Index: llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll =================================================================== --- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll +++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll @@ -561,4 +561,108 @@ ret void } +define void @test_13a(i32 %n) { +; +; CHECK-LABEL: @test_13a( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 to i64 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]] +; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %iv.next = add nsw nuw i64 %iv, 2 + %narrow.iv = trunc i64 %iv to i32 + %cmp = icmp ne i32 1024, %narrow.iv + br i1 %cmp, label %loop, label %exit +exit: + ret void +} + +define void @test_13b(i32 %n) { +; +; CHECK-LABEL: @test_13b( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 to i64 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]] +; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %iv.next = add nsw nuw i64 %iv, 2 + %narrow.iv = trunc i64 %iv to i32 + %cmp = icmp ugt i32 1024, %narrow.iv + br i1 %cmp, label %loop, label %exit +exit: + ret void +} + +define void @test_13c(i32 %n) { +; +; CHECK-LABEL: @test_13c( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 to i64 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]] +; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %iv.next = add nsw nuw i64 %iv, 2 + %narrow.iv = trunc i64 %iv to i32 + %cmp = icmp sgt i32 1024, %narrow.iv + br i1 %cmp, label %loop, label %exit +exit: + ret void +} + +define void @test_13d(i32 %n) { +; +; CHECK-LABEL: @test_13d( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SEXT:%.*]] = sext i32 1024 to i64 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -20, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]] +; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop +loop: + %iv = phi i64 [ -20, %entry ], [ %iv.next, %loop ] + %iv.next = add nsw i64 %iv, 2 + %narrow.iv = trunc i64 %iv to i32 + %cmp = icmp sgt i32 1024, %narrow.iv + br i1 %cmp, label %loop, label %exit +exit: + ret void +} + !0 = !{i32 0, i32 1000}