mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
ARM & AArch64: make use of common cmpxchg idioms after expansion
The C and C++ semantics for compare_exchange require it to return a bool indicating success. This gets mapped to LLVM IR which follows each cmpxchg with an icmp of the value loaded against the desired value. When lowered to ldxr/stxr loops, this extra comparison is redundant: its results are implicit in the control-flow of the function. This commit makes two changes: it replaces that icmp with appropriate PHI nodes, and then makes sure earlyCSE is called after expansion to actually make use of the opportunities revealed. I've also added -{arm,aarch64}-enable-atomic-tidy options, so that existing fragile tests aren't perturbed too much by the change. Many of them either rely on undef/unreachable too pervasively to be restored to something well-defined (particularly while making sure they test the same obscure assert from many years ago), or depend on a particular CFG shape, which is disrupted by SimplifyCFG. rdar://problem/16227836 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209883 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -53,6 +53,12 @@ static cl::opt<bool>
|
||||
EnableLoadStoreOpt("aarch64-load-store-opt", cl::desc("Enable the load/store pair"
|
||||
" optimization pass"), cl::init(true), cl::Hidden);
|
||||
|
||||
static cl::opt<bool>
|
||||
EnableAtomicTidy("aarch64-atomic-cfg-tidy", cl::Hidden,
|
||||
cl::desc("Run SimplifyCFG after expanding atomic operations"
|
||||
" to make use of cmpxchg flow-based information"),
|
||||
cl::init(true));
|
||||
|
||||
extern "C" void LLVMInitializeAArch64Target() {
|
||||
// Register the target.
|
||||
RegisterTargetMachine<AArch64leTargetMachine> X(TheAArch64leTarget);
|
||||
@@ -113,6 +119,7 @@ public:
|
||||
return getTM<AArch64TargetMachine>();
|
||||
}
|
||||
|
||||
void addIRPasses() override;
|
||||
bool addPreISel() override;
|
||||
bool addInstSelector() override;
|
||||
bool addILPOpts() override;
|
||||
@@ -135,6 +142,20 @@ TargetPassConfig *AArch64TargetMachine::createPassConfig(PassManagerBase &PM) {
|
||||
return new AArch64PassConfig(this, PM);
|
||||
}
|
||||
|
||||
void AArch64PassConfig::addIRPasses() {
|
||||
// Always expand atomic operations, we don't deal with atomicrmw or cmpxchg
|
||||
// ourselves.
|
||||
addPass(createAtomicExpandLoadLinkedPass(TM));
|
||||
|
||||
// Cmpxchg instructions are often used with a subsequent comparison to
|
||||
// determine whether it succeeded. We can exploit existing control-flow in
|
||||
// ldrex/strex loops to simplify this, but it needs tidying up.
|
||||
if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
|
||||
addPass(createCFGSimplificationPass());
|
||||
|
||||
TargetPassConfig::addIRPasses();
|
||||
}
|
||||
|
||||
// Pass Pipeline Configuration
|
||||
bool AArch64PassConfig::addPreISel() {
|
||||
// Run promote constant before global merge, so that the promoted constants
|
||||
@@ -146,10 +167,6 @@ bool AArch64PassConfig::addPreISel() {
|
||||
if (TM->getOptLevel() != CodeGenOpt::None)
|
||||
addPass(createAArch64AddressTypePromotionPass());
|
||||
|
||||
// Always expand atomic operations, we don't deal with atomicrmw or cmpxchg
|
||||
// ourselves.
|
||||
addPass(createAtomicExpandLoadLinkedPass(TM));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user