diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -908,6 +908,14 @@ if (replaceIVUserWithLoopInvariant(UseInst)) continue; + // Go further for the bitcast ''prtoint ptr to i64' + if (isa(UseInst)) + for (Use &U : UseInst->uses()) { + Instruction *User = cast(U.getUser()); + if (replaceIVUserWithLoopInvariant(User)) + break; // done replacing + } + Instruction *IVOperand = UseOper.second; for (unsigned N = 0; IVOperand; ++N) { assert(N <= Simplified.size() && "runaway iteration"); diff --git a/llvm/test/Transforms/IndVarSimplify/pr59633.ll b/llvm/test/Transforms/IndVarSimplify/pr59633.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/pr59633.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=indvars -S | FileCheck %s + +declare void @foo(i64 noundef) + +; Function Attrs: mustprogress noreturn uwtable +define void @pr59633(ptr noundef %ptr) { +; CHECK-LABEL: @pr59633( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR1:%.*]] = ptrtoint ptr [[PTR:%.*]] to i64 +; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[PTR1]] to i4 +; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[TMP0]] to i64 +; CHECK-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK: while.body: +; CHECK-NEXT: tail call void @foo(i64 noundef [[TMP1]]) +; CHECK-NEXT: br label [[WHILE_BODY]] +; +entry: + br label %while.body + +while.body: ; preds = %entry, %while.body + %ptr.addr.0 = phi ptr [ %ptr, %entry ], [ %add.ptr, %while.body ] + %0 = ptrtoint ptr %ptr.addr.0 to i64 + %and = and i64 %0, 15 ; loop invariant + tail call void @foo(i64 noundef %and) + %add.ptr = getelementptr inbounds i8, ptr %ptr.addr.0, i64 16 + br label %while.body +} +