diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2468,10 +2468,19 @@ // Fence instruction simplification Instruction *InstCombinerImpl::visitFenceInst(FenceInst &FI) { - // Remove identical consecutive fences. Instruction *Next = FI.getNextNonDebugInstruction(); - if (auto *NFI = dyn_cast(Next)) - if (FI.isIdenticalTo(NFI)) + if (auto *NFI = dyn_cast(Next)) { + // Remove identical consecutive fences. + // When we have a weaker-ordering fence consecutively followed by a + // stronger-ordering fence, we can remove the weaker one. + if (FI.isIdenticalTo(NFI) || isStrongerThan(NFI->getOrdering(), FI.getOrdering())) + return eraseInstFromFunction(FI); + } + + // Remove weaker fence if it is preceeded immediately by a stronger ordering + // fence. + if (auto *PFI = dyn_cast_or_null(FI.getPrevNonDebugInstruction())) + if (isStrongerThan(PFI->getOrdering(), FI.getOrdering())) return eraseInstFromFunction(FI); return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/consecutive-fences.ll b/llvm/test/Transforms/InstCombine/consecutive-fences.ll --- a/llvm/test/Transforms/InstCombine/consecutive-fences.ll +++ b/llvm/test/Transforms/InstCombine/consecutive-fences.ll @@ -4,7 +4,6 @@ ; CHECK-LABEL: define void @tinkywinky ; CHECK-NEXT: fence seq_cst -; CHECK-NEXT: fence syncscope("singlethread") acquire ; CHECK-NEXT: ret void ; CHECK-NEXT: } @@ -31,9 +30,6 @@ } ; CHECK-LABEL: define void @patatino -; CHECK-NEXT: fence acquire -; CHECK-NEXT: fence seq_cst -; CHECK-NEXT: fence acquire ; CHECK-NEXT: fence seq_cst ; CHECK-NEXT: ret void ; CHECK-NEXT: } @@ -46,6 +42,27 @@ ret void } +; CHECK-LABEL: define void @weaker_fence_1 +; CHECK-NEXT: fence seq_cst +; CHECK-NEXT: ret void +define void @weaker_fence_1() { + fence seq_cst + fence release + fence seq_cst + ret void +} + +; CHECK-LABEL: define void @weaker_fence_2 +; CHECK-NEXT: fence seq_cst +; CHECK-NEXT: ret void +define void @weaker_fence_2() { + fence seq_cst + fence release + fence seq_cst + fence acquire + ret void +} + ; CHECK-LABEL: define void @debug ; CHECK-NOT: fence ; CHECK: call void @llvm.dbg.value