diff --git a/llvm/lib/Analysis/CodeMetrics.cpp b/llvm/lib/Analysis/CodeMetrics.cpp --- a/llvm/lib/Analysis/CodeMetrics.cpp +++ b/llvm/lib/Analysis/CodeMetrics.cpp @@ -34,8 +34,9 @@ for (const Value *Operand : U->operands()) if (Visited.insert(Operand).second) - if (isSafeToSpeculativelyExecute(Operand)) - Worklist.push_back(Operand); + if (const auto *I = dyn_cast(Operand)) + if (!I->mayHaveSideEffects() && !I->isTerminator()) + Worklist.push_back(I); } static void completeEphemeralValues(SmallPtrSetImpl &Visited, diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -494,7 +494,9 @@ if (V == E) return true; - if (V == I || isSafeToSpeculativelyExecute(V)) { + if (V == I || (isa(V) && + !cast(V)->mayHaveSideEffects() && + !cast(V)->isTerminator())) { EphValues.insert(V); if (const User *U = dyn_cast(V)) append_range(WorkSet, U->operands()); diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2577,11 +2577,11 @@ int Size = 0; SmallPtrSet EphValues; - auto IsEphemeral = [&](const Value *V) { - if (isa(V)) + auto IsEphemeral = [&](const Instruction *I) { + if (isa(I)) return true; - return isSafeToSpeculativelyExecute(V) && - all_of(V->users(), + return !I->mayHaveSideEffects() && !I->isTerminator() && + all_of(I->users(), [&](const User *U) { return EphValues.count(U); }); }; diff --git a/llvm/test/Transforms/Inline/ephemeral.ll b/llvm/test/Transforms/Inline/ephemeral.ll --- a/llvm/test/Transforms/Inline/ephemeral.ll +++ b/llvm/test/Transforms/Inline/ephemeral.ll @@ -26,10 +26,10 @@ ret i32 %a1 } -; TODO: The load should be considered ephemeral here, even though it is not -; speculatable. +; Only the ret should be included in the instruction count, the load and icmp +; are both ephemeral. ; CHECK: Analyzing call of inner2... -; CHECK: NumInstructions: 2 +; CHECK: NumInstructions: 1 define void @inner2(i8* %y) { %v = load i8, i8* %y %c = icmp eq i8 %v, 42 diff --git a/llvm/test/Transforms/SimplifyCFG/unprofitable-pr.ll b/llvm/test/Transforms/SimplifyCFG/unprofitable-pr.ll --- a/llvm/test/Transforms/SimplifyCFG/unprofitable-pr.ll +++ b/llvm/test/Transforms/SimplifyCFG/unprofitable-pr.ll @@ -233,32 +233,37 @@ ret void } -; TODO: The load should be considered ephemeral here, even though it is not -; speculatable. +; The load, icmp and assume should not count towards the limit, they are +; ephemeral. define void @test_non_speculatable(i1 %c, i64* align 1 %ptr, i8* %ptr2) local_unnamed_addr #0 { ; CHECK-LABEL: @test_non_speculatable( -; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE1:%.*]], label [[FALSE1:%.*]] -; CHECK: true1: +; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE2_CRITEDGE:%.*]], label [[FALSE1:%.*]] +; CHECK: false1: +; CHECK-NEXT: store volatile i64 1, i64* [[PTR:%.*]], align 4 ; CHECK-NEXT: [[V:%.*]] = load i8, i8* [[PTR2:%.*]], align 1 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 42 ; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) -; CHECK-NEXT: store volatile i64 0, i64* [[PTR:%.*]], align 8 +; CHECK-NEXT: store volatile i64 0, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 -; CHECK-NEXT: br i1 [[C]], label [[TRUE2:%.*]], label [[FALSE2:%.*]] -; CHECK: false1: -; CHECK-NEXT: store volatile i64 1, i64* [[PTR]], align 4 -; CHECK-NEXT: br label [[TRUE1]] +; CHECK-NEXT: store volatile i64 3, i64* [[PTR]], align 8 +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: common.ret: ; CHECK-NEXT: ret void -; CHECK: true2: +; CHECK: true2.critedge: +; CHECK-NEXT: [[V_C:%.*]] = load i8, i8* [[PTR2]], align 1 +; CHECK-NEXT: [[C2_C:%.*]] = icmp eq i8 [[V_C]], 42 +; CHECK-NEXT: call void @llvm.assume(i1 [[C2_C]]) +; CHECK-NEXT: store volatile i64 0, i64* [[PTR]], align 8 +; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 +; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 +; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 +; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 +; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 2, i64* [[PTR]], align 8 -; CHECK-NEXT: br label [[COMMON_RET:%.*]] -; CHECK: false2: -; CHECK-NEXT: store volatile i64 3, i64* [[PTR]], align 8 ; CHECK-NEXT: br label [[COMMON_RET]] ; br i1 %c, label %true1, label %false1