diff --git a/llvm/lib/Transforms/Scalar/GVNHoist.cpp b/llvm/lib/Transforms/Scalar/GVNHoist.cpp --- a/llvm/lib/Transforms/Scalar/GVNHoist.cpp +++ b/llvm/lib/Transforms/Scalar/GVNHoist.cpp @@ -808,15 +808,19 @@ void GVNHoist::checkSafety(CHIArgs C, BasicBlock *BB, GVNHoist::InsKind K, SmallVectorImpl &Safe) { int NumBBsOnAllPaths = MaxNumberOfBBSInPath; + const Instruction *T = BB->getTerminator(); + const bool IsCallBrTerminated = isa(T); for (auto CHI : C) { Instruction *Insn = CHI.I; if (!Insn) // No instruction was inserted in this CHI. continue; + if (IsCallBrTerminated && + std::find(T->user_begin(), T->user_end(), Insn) != T->user_end()) + continue; if (K == InsKind::Scalar) { if (safeToHoistScalar(BB, Insn->getParent(), NumBBsOnAllPaths)) Safe.push_back(CHI); } else { - auto *T = BB->getTerminator(); if (MemoryUseOrDef *UD = MSSA->getMemoryAccess(Insn)) if (safeToHoistLdSt(T, Insn, UD, K, NumBBsOnAllPaths)) Safe.push_back(CHI); diff --git a/llvm/test/Transforms/GVNHoist/hoist-call.ll b/llvm/test/Transforms/GVNHoist/hoist-call.ll --- a/llvm/test/Transforms/GVNHoist/hoist-call.ll +++ b/llvm/test/Transforms/GVNHoist/hoist-call.ll @@ -1,13 +1,20 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -passes=gvn-hoist < %s | FileCheck %s ; Check that the call and fcmp are hoisted. -; CHECK-LABEL: define void @fun( -; CHECK: call float -; CHECK: fcmp oeq -; CHECK-NOT: call float -; CHECK-NOT: fcmp oeq - define void @fun(float %__b) minsize { +; CHECK-LABEL: @fun( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.fabs.f32(float [[__B:%.*]]) +; CHECK-NEXT: [[CMPINF7:%.*]] = fcmp oeq float [[TMP0]], 0x7FF0000000000000 +; CHECK-NEXT: br i1 undef, label [[IF_THEN8:%.*]], label [[LOR_LHS_FALSE:%.*]] +; CHECK: lor.lhs.false: +; CHECK-NEXT: unreachable +; CHECK: if.then8: +; CHECK-NEXT: ret void +; entry: br label %if.then @@ -26,3 +33,63 @@ } declare float @llvm.fabs.f32(float) + +; Check that extractvalues are not hoisted into entry, but that non-dependent +; adds are. +define i32 @foo(i32 %x) { +; CHECK-LABEL: @foo( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 1 +; CHECK-NEXT: [[TMP0:%.*]] = callbr { i32, i32 } asm sideeffect "somestuff", "=r,=r,!i"() +; CHECK-NEXT: to label [[ASM_FALLTHROUGH:%.*]] [label %err.split] +; CHECK: asm.fallthrough: +; CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0 +; CHECK-NEXT: ret i32 [[ADD]] +; CHECK: err.split: +; CHECK-NEXT: [[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0 +; CHECK-NEXT: ret i32 [[ADD]] +; +entry: + %0 = callbr { i32, i32 } asm sideeffect "somestuff", "=r,=r,!i"() + to label %asm.fallthrough [label %err.split] + +asm.fallthrough: ; preds = %entry + %asmresult = extractvalue { i32, i32 } %0, 0 + %add = add nsw i32 %x, 1 + ret i32 %add + +err.split: ; preds = %entry + %asmresult2 = extractvalue { i32, i32 } %0, 0 + %add2 = add nsw i32 %x, 1 + ret i32 %add2 +} + +; Check that extractvalues and dependent adds are not hoisted into entry. +define i32 @foo2() { +; CHECK-LABEL: @foo2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = callbr { i32, i32 } asm sideeffect "somestuff", "=r,=r,!i"() +; CHECK-NEXT: to label [[ASM_FALLTHROUGH:%.*]] [label %err.split] +; CHECK: asm.fallthrough: +; CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[ASMRESULT]], 1 +; CHECK-NEXT: ret i32 [[ADD]] +; CHECK: err.split: +; CHECK-NEXT: [[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0 +; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[ASMRESULT2]], 1 +; CHECK-NEXT: ret i32 [[ADD2]] +; +entry: + %0 = callbr { i32, i32 } asm sideeffect "somestuff", "=r,=r,!i"() + to label %asm.fallthrough [label %err.split] + +asm.fallthrough: ; preds = %entry + %asmresult = extractvalue { i32, i32 } %0, 0 + %add = add nsw i32 %asmresult, 1 + ret i32 %add + +err.split: ; preds = %entry + %asmresult2 = extractvalue { i32, i32 } %0, 0 + %add2 = add nsw i32 %asmresult2, 1 + ret i32 %add2 +}