Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -3268,6 +3268,16 @@ return visitCallSite(II); } +// Fence instruction simplification +Instruction *InstCombiner::visitFenceInst(FenceInst &FI) { + // Remove identical consecutive fences. + if (auto *NFI = dyn_cast(FI.getNextNode())) + if (NFI->getSynchScope() == FI.getSynchScope() && + NFI->getOrdering() == FI.getOrdering()) + return eraseInstFromFunction(FI); + return nullptr; +} + // InvokeInst simplification // Instruction *InstCombiner::visitInvokeInst(InvokeInst &II) { Index: lib/Transforms/InstCombine/InstCombineInternal.h =================================================================== --- lib/Transforms/InstCombine/InstCombineInternal.h +++ lib/Transforms/InstCombine/InstCombineInternal.h @@ -289,6 +289,7 @@ Instruction *visitLoadInst(LoadInst &LI); Instruction *visitStoreInst(StoreInst &SI); Instruction *visitBranchInst(BranchInst &BI); + Instruction *visitFenceInst(FenceInst &FI); Instruction *visitSwitchInst(SwitchInst &SI); Instruction *visitReturnInst(ReturnInst &RI); Instruction *visitInsertValueInst(InsertValueInst &IV); Index: test/Transforms/InstCombine/consecutive-fences.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/consecutive-fences.ll @@ -0,0 +1,47 @@ +; RUN: opt -instcombine -S %s | FileCheck %s + +; Make sure we collapse the fences in this case + +; CHECK-LABEL: define void @tinkywinky +; CHECK-NEXT: fence seq_cst +; CHECK-NEXT: fence singlethread acquire +; CHECK-NEXT: ret void +; CHECK-NEXT: } + +define void @tinkywinky() { + fence seq_cst + fence seq_cst + fence seq_cst + fence singlethread acquire + fence singlethread acquire + fence singlethread acquire + ret void +} + +; CHECK-LABEL: define void @dipsy +; CHECK-NEXT: fence seq_cst +; CHECK-NEXT: fence singlethread seq_cst +; CHECK-NEXT: ret void +; CHECK-NEXT: } + +define void @dipsy() { + fence seq_cst + fence singlethread seq_cst + ret void +} + +; 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: } + +define void @patatino() { + fence acquire + fence seq_cst + fence acquire + fence seq_cst + ret void +}