Index: llvm/lib/Transforms/Scalar/LICM.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LICM.cpp +++ llvm/lib/Transforms/Scalar/LICM.cpp @@ -1237,6 +1237,19 @@ // Assumes don't actually alias anything or throw return true; + if (match(CI, m_Intrinsic())) { + // Hoist widenable condition when it's the only non-invariant operand of + // its user + for (const Use &U : CI->uses()) + if (const Instruction *UI = dyn_cast(U.getUser())) + for (const Use &Op : UI->operands()) { + const Instruction *OpI = dyn_cast(Op.get()); + if (OpI && OpI != &I && !CurLoop->isLoopInvariant(OpI)) + return false; + } + return true; + } + // Handle simple cases by querying alias analysis. MemoryEffects Behavior = AA->getMemoryEffects(CI); if (Behavior.doesNotAccessMemory()) Index: llvm/test/Transforms/LICM/explicit_guards.ll =================================================================== --- llvm/test/Transforms/LICM/explicit_guards.ll +++ llvm/test/Transforms/LICM/explicit_guards.ll @@ -133,14 +133,14 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LOAD:%.*]] = load atomic i32, ptr [[P:%.*]] unordered, align 8 ; CHECK-NEXT: [[ICMP7:%.*]] = icmp ult i32 0, [[LOAD]] +; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() +; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[ICMP7]], [[WIDENABLE_COND]] ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: [[ICMP:%.*]] = icmp ult i32 [[IV]], [[X:%.*]] ; CHECK-NEXT: br i1 [[ICMP]], label [[LOOP_BODY:%.*]], label [[EXIT:%.*]] ; CHECK: loop.body: -; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[ICMP7]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED1:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid(i32 13) [ "deopt"() ]