Skip to content

Commit

Permalink
[CGP] Support opaque pointers in address mode fold
Browse files Browse the repository at this point in the history
Rather than inspecting the pointer element type, use the access
type of the load/store/atomicrmw/cmpxchg.

In the process of doing this, simplify the logic by storing the
address + type in MemoryUses, rather than an Instruction + Operand
pair (which was then used to fetch the address).
  • Loading branch information
nikic committed Sep 12, 2021
1 parent 8e86c0e commit 4189e5f
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 26 deletions.
40 changes: 14 additions & 26 deletions llvm/lib/CodeGen/CodeGenPrepare.cpp
Expand Up @@ -4859,10 +4859,9 @@ static constexpr int MaxMemoryUsesToScan = 20;

/// Recursively walk all the uses of I until we find a memory use.
/// If we find an obviously non-foldable instruction, return true.
/// Add the ultimately found memory instructions to MemoryUses.
/// Add accessed addresses and types to MemoryUses.
static bool FindAllMemoryUses(
Instruction *I,
SmallVectorImpl<std::pair<Instruction *, unsigned>> &MemoryUses,
Instruction *I, SmallVectorImpl<std::pair<Value *, Type *>> &MemoryUses,
SmallPtrSetImpl<Instruction *> &ConsideredInsts, const TargetLowering &TLI,
const TargetRegisterInfo &TRI, bool OptSize, ProfileSummaryInfo *PSI,
BlockFrequencyInfo *BFI, int SeenInsts = 0) {
Expand All @@ -4883,31 +4882,28 @@ static bool FindAllMemoryUses(

Instruction *UserI = cast<Instruction>(U.getUser());
if (LoadInst *LI = dyn_cast<LoadInst>(UserI)) {
MemoryUses.push_back(std::make_pair(LI, U.getOperandNo()));
MemoryUses.push_back({U.get(), LI->getType()});
continue;
}

if (StoreInst *SI = dyn_cast<StoreInst>(UserI)) {
unsigned opNo = U.getOperandNo();
if (opNo != StoreInst::getPointerOperandIndex())
if (U.getOperandNo() != StoreInst::getPointerOperandIndex())
return true; // Storing addr, not into addr.
MemoryUses.push_back(std::make_pair(SI, opNo));
MemoryUses.push_back({U.get(), SI->getValueOperand()->getType()});
continue;
}

if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(UserI)) {
unsigned opNo = U.getOperandNo();
if (opNo != AtomicRMWInst::getPointerOperandIndex())
if (U.getOperandNo() != AtomicRMWInst::getPointerOperandIndex())
return true; // Storing addr, not into addr.
MemoryUses.push_back(std::make_pair(RMW, opNo));
MemoryUses.push_back({U.get(), RMW->getValOperand()->getType()});
continue;
}

if (AtomicCmpXchgInst *CmpX = dyn_cast<AtomicCmpXchgInst>(UserI)) {
unsigned opNo = U.getOperandNo();
if (opNo != AtomicCmpXchgInst::getPointerOperandIndex())
if (U.getOperandNo() != AtomicCmpXchgInst::getPointerOperandIndex())
return true; // Storing addr, not into addr.
MemoryUses.push_back(std::make_pair(CmpX, opNo));
MemoryUses.push_back({U.get(), CmpX->getCompareOperand()->getType()});
continue;
}

Expand Down Expand Up @@ -5017,7 +5013,7 @@ isProfitableToFoldIntoAddressingMode(Instruction *I, ExtAddrMode &AMBefore,
// we can remove the addressing mode and effectively trade one live register
// for another (at worst.) In this context, folding an addressing mode into
// the use is just a particularly nice way of sinking it.
SmallVector<std::pair<Instruction*,unsigned>, 16> MemoryUses;
SmallVector<std::pair<Value *, Type *>, 16> MemoryUses;
SmallPtrSet<Instruction*, 16> ConsideredInsts;
if (FindAllMemoryUses(I, MemoryUses, ConsideredInsts, TLI, TRI, OptSize,
PSI, BFI))
Expand All @@ -5033,18 +5029,10 @@ isProfitableToFoldIntoAddressingMode(Instruction *I, ExtAddrMode &AMBefore,
// growth since most architectures have some reasonable small and fast way to
// compute an effective address. (i.e LEA on x86)
SmallVector<Instruction*, 32> MatchedAddrModeInsts;
for (unsigned i = 0, e = MemoryUses.size(); i != e; ++i) {
Instruction *User = MemoryUses[i].first;
unsigned OpNo = MemoryUses[i].second;

// Get the access type of this use. If the use isn't a pointer, we don't
// know what it accesses.
Value *Address = User->getOperand(OpNo);
PointerType *AddrTy = dyn_cast<PointerType>(Address->getType());
if (!AddrTy)
return false;
Type *AddressAccessTy = AddrTy->getElementType();
unsigned AS = AddrTy->getAddressSpace();
for (const std::pair<Value *, Type *> &Pair : MemoryUses) {
Value *Address = Pair.first;
Type *AddressAccessTy = Pair.second;
unsigned AS = Address->getType()->getPointerAddressSpace();

// Do a match against the root of this address, ignoring profitability. This
// will tell us if the addressing mode for the memory operation will
Expand Down
1 change: 1 addition & 0 deletions llvm/test/CodeGen/X86/merge_store.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -opaque-pointers | FileCheck %s

define void @merge_store(i32* nocapture %a) {
; CHECK-LABEL: merge_store:
Expand Down

0 comments on commit 4189e5f

Please sign in to comment.