Unverified Commit d22b41d3 authored by Arendelle's avatar Arendelle Committed by GitHub
Browse files

[llvm] Add support for atomicrmw and cmpxchg in AssumeBundleBuilder (#194630)



The assume builder currently only preserves dereferenceable, nonnull,
and alignment knowledge for regular load/store instructions and calls.
Atomic memory accessing instructions (atomicrmw and cmpxchg) also
dereference their pointer operands, but were previously skipped, causing
useful knowledge to be lost across these operations.

Add handling for AtomicRMWInst and AtomicCmpXchgInst in
AssumeBuilderState::addInstruction(), using the same addAccessedPtr()
path as loads and stores. The accessed type is taken from the value
operand (atomicrmw) or compare operand (cmpxchg), which corresponds to
the in-memory element type, and the alignment is taken from the
instruction's explicit alignment.

Add a test to verify that assume bundles are correctly generated before
atomicrmw and cmpxchg instructions.

---------

Co-authored-by: default avatarNikita Popov <github@npopov.com>
parent 6ef67130
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -274,7 +274,13 @@ struct AssumeBuilderState {
      return addAccessedPtr(I, Store->getPointerOperand(),
                            Store->getValueOperand()->getType(),
                            Store->getAlign());
    // TODO: Add support for the other Instructions.
    if (auto *RMW = dyn_cast<AtomicRMWInst>(I))
      return addAccessedPtr(I, RMW->getPointerOperand(),
                            RMW->getValOperand()->getType(), RMW->getAlign());
    if (auto *CmpXchg = dyn_cast<AtomicCmpXchgInst>(I))
      return addAccessedPtr(I, CmpXchg->getPointerOperand(),
                            CmpXchg->getCompareOperand()->getType(),
                            CmpXchg->getAlign());
    // TODO: Maybe we should look around and merge with other llvm.assume.
  }
};
+17 −0
Original line number Diff line number Diff line
; RUN: opt -passes=assume-builder --enable-knowledge-retention -S %s | FileCheck %s

define void @test_atomic_accesses(ptr %p, ptr %q) {
; CHECK-LABEL: define {{[^@]+}}@test_atomic_accesses
; CHECK-SAME: (ptr [[P:%.*]], ptr [[Q:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 8) ]
; CHECK-NEXT:    [[OLD:%.*]] = atomicrmw add ptr [[P]], i32 1 monotonic, align 8
; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[Q]], i64 8), "nonnull"(ptr [[Q]]), "align"(ptr [[Q]], i64 16) ]
; CHECK-NEXT:    [[PAIR:%.*]] = cmpxchg ptr [[Q]], i64 0, i64 1 monotonic monotonic, align 16
; CHECK-NEXT:    ret void
;
entry:
  %old = atomicrmw add ptr %p, i32 1 monotonic, align 8
  %pair = cmpxchg ptr %q, i64 0, i64 1 monotonic monotonic, align 16
  ret void
}