diff options
author | Quentin Colombet <quentin.colombet@gmail.com> | 2019-02-07 21:27:23 +0000 |
---|---|---|
committer | Quentin Colombet <quentin.colombet@gmail.com> | 2019-02-07 21:27:23 +0000 |
commit | 96f54de8ff5d357fadcf474823f70288561923bf (patch) | |
tree | 5f458880c0e8823862215080eafd91f82ce0447e /llvm/lib | |
parent | 82bf8e82c96b79fcafea5d0026feab24a270e9af (diff) | |
download | bcm5719-llvm-96f54de8ff5d357fadcf474823f70288561923bf.tar.gz bcm5719-llvm-96f54de8ff5d357fadcf474823f70288561923bf.zip |
[InstCombine] Optimize `atomicrmw <op>, 0` into `load atomic` when possible
This commit teaches InstCombine how to replace an atomicrmw operation
into a simple load atomic.
For a given `atomicrmw <op>`, this is possible when:
1. The ordering of that operation is compatible with a load (i.e.,
anything that doesn't have a release semantic).
2. <op> does not modify the value being stored
Differential Revision: https://reviews.llvm.org/D57854
llvm-svn: 353471
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp | 48 | ||||
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineInternal.h | 1 |
3 files changed, 50 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/CMakeLists.txt b/llvm/lib/Transforms/InstCombine/CMakeLists.txt index 8a3a58e9ecc..bba399bba35 100644 --- a/llvm/lib/Transforms/InstCombine/CMakeLists.txt +++ b/llvm/lib/Transforms/InstCombine/CMakeLists.txt @@ -5,6 +5,7 @@ add_public_tablegen_target(InstCombineTableGen) add_llvm_library(LLVMInstCombine InstructionCombining.cpp InstCombineAddSub.cpp + InstCombineAtomicRMW.cpp InstCombineAndOrXor.cpp InstCombineCalls.cpp InstCombineCasts.cpp diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp new file mode 100644 index 00000000000..86bbfb15986 --- /dev/null +++ b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp @@ -0,0 +1,48 @@ +//===- InstCombineAtomicRMW.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the visit functions for atomic rmw instructions. +// +//===----------------------------------------------------------------------===// +#include "InstCombineInternal.h" +#include "llvm/IR/Instructions.h" + +using namespace llvm; + +Instruction *InstCombiner::visitAtomicRMWInst(AtomicRMWInst &RMWI) { + switch (RMWI.getOperation()) { + default: + break; + case AtomicRMWInst::Add: + case AtomicRMWInst::Sub: + case AtomicRMWInst::Or: + // Replace atomicrmw <op> addr, 0 => load atomic addr. + + // Volatile RMWs perform a load and a store, we cannot replace + // this by just a load. + if (RMWI.isVolatile()) + break; + + auto *CI = dyn_cast<ConstantInt>(RMWI.getValOperand()); + if (!CI || !CI->isZero()) + break; + // Check if the required ordering is compatible with an + // atomic load. + AtomicOrdering Ordering = RMWI.getOrdering(); + assert(Ordering != AtomicOrdering::NotAtomic && + Ordering != AtomicOrdering::Unordered && + "AtomicRMWs don't make sense with Unordered or NotAtomic"); + if (Ordering != AtomicOrdering::Acquire && + Ordering != AtomicOrdering::Monotonic) + break; + LoadInst *Load = new LoadInst(RMWI.getType(), RMWI.getPointerOperand()); + Load->setAtomic(Ordering, RMWI.getSyncScopeID()); + return Load; + } + return nullptr; +} diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index 11993a46323..951e0e72e9e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -401,6 +401,7 @@ public: Instruction *visitFree(CallInst &FI); Instruction *visitLoadInst(LoadInst &LI); Instruction *visitStoreInst(StoreInst &SI); + Instruction *visitAtomicRMWInst(AtomicRMWInst &SI); Instruction *visitBranchInst(BranchInst &BI); Instruction *visitFenceInst(FenceInst &FI); Instruction *visitSwitchInst(SwitchInst &SI); |