[llvm] e187361 - [Attributor] Teach AAPointerInfo about atomic cmxchg and rmw
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 5 07:27:42 PDT 2022
Author: Johannes Doerfert
Date: 2022-10-05T06:48:00-07:00
New Revision: e18736149c67cff47492617aa02b31f3d6067a51
URL: https://github.com/llvm/llvm-project/commit/e18736149c67cff47492617aa02b31f3d6067a51
DIFF: https://github.com/llvm/llvm-project/commit/e18736149c67cff47492617aa02b31f3d6067a51.diff
LOG: [Attributor] Teach AAPointerInfo about atomic cmxchg and rmw
The atomic operations behave similar to a store except that we don't
know the new value and we read the result first.
Added:
Modified:
llvm/lib/Transforms/IPO/AttributorAttributes.cpp
llvm/test/Transforms/Attributor/value-simplify-pointer-info-struct.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 642f1f16f20c..2a3ca28b97c4 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -14,6 +14,7 @@
#include "llvm/Transforms/IPO/Attributor.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SCCIterator.h"
@@ -1374,27 +1375,47 @@ struct AAPointerInfoFloating : public AAPointerInfoImpl {
LoadI->getType());
}
- if (auto *StoreI = dyn_cast<StoreInst>(Usr)) {
- if (StoreI->getValueOperand() == CurPtr) {
- LLVM_DEBUG(dbgs() << "[AAPointerInfo] Escaping use in store "
- << *StoreI << "\n");
- return false;
+ auto HandleStoreLike = [&](Instruction &I, Value *ValueOp, Type &ValueTy,
+ ArrayRef<Value *> OtherOps, AccessKind AK) {
+ for (auto *OtherOp : OtherOps) {
+ if (OtherOp == CurPtr) {
+ LLVM_DEBUG(
+ dbgs()
+ << "[AAPointerInfo] Escaping use in store like instruction "
+ << I << "\n");
+ return false;
+ }
}
+
// If the access is to a pointer that may or may not be the associated
// value, e.g. due to a PHI, we cannot assume it will be written.
- AccessKind AK = AccessKind::AK_W;
if (getUnderlyingObject(CurPtr) == &AssociatedValue)
AK = AccessKind(AK | AccessKind::AK_MUST);
else
AK = AccessKind(AK | AccessKind::AK_MAY);
bool UsedAssumedInformation = false;
- Optional<Value *> Content =
- A.getAssumedSimplified(*StoreI->getValueOperand(), *this,
- UsedAssumedInformation, AA::Interprocedural);
- return handleAccess(A, *StoreI, *CurPtr, Content, AK,
- OffsetInfoMap[CurPtr].Offset, Changed,
- StoreI->getValueOperand()->getType());
- }
+ Optional<Value *> Content = nullptr;
+ if (ValueOp)
+ Content = A.getAssumedSimplified(
+ *ValueOp, *this, UsedAssumedInformation, AA::Interprocedural);
+ return handleAccess(A, I, *CurPtr, Content, AK,
+ OffsetInfoMap[CurPtr].Offset, Changed, &ValueTy);
+ };
+
+ if (auto *StoreI = dyn_cast<StoreInst>(Usr))
+ return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
+ *StoreI->getValueOperand()->getType(),
+ {StoreI->getValueOperand()}, AccessKind::AK_W);
+ if (auto *RMWI = dyn_cast<AtomicRMWInst>(Usr))
+ return HandleStoreLike(*RMWI, nullptr,
+ *RMWI->getValOperand()->getType(),
+ {RMWI->getValOperand()}, AccessKind::AK_RW);
+ if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Usr))
+ return HandleStoreLike(
+ *CXI, nullptr, *CXI->getNewValOperand()->getType(),
+ {CXI->getCompareOperand(), CXI->getNewValOperand()},
+ AccessKind::AK_RW);
+
if (auto *CB = dyn_cast<CallBase>(Usr)) {
if (CB->isLifetimeStartOrEnd())
return true;
diff --git a/llvm/test/Transforms/Attributor/value-simplify-pointer-info-struct.ll b/llvm/test/Transforms/Attributor/value-simplify-pointer-info-struct.ll
index 988c3be5b462..a8139321c401 100644
--- a/llvm/test/Transforms/Attributor/value-simplify-pointer-info-struct.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify-pointer-info-struct.ll
@@ -6,12 +6,13 @@
;
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-%struct.S = type { i32, double, ptr }
+%struct.S = type { i32, double, ptr, i32 }
; struct S {
; int a;
; double b;
; struct S* c;
+; int written;
; };
;
; static const struct S GlobalS = {42, 3.14, 0};
@@ -27,18 +28,20 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16
; return r;
; }
;
- at GlobalS = internal constant %struct.S { i32 42, double 3.140000e+00, ptr null }, align 8
+ at GlobalS = internal constant %struct.S { i32 42, double 3.140000e+00, ptr null, i32 0 }, align 8
declare void @harmless_use(ptr nocapture readonly) nofree norecurse nosync nounwind readnone willreturn nocallback
;.
-; CHECK: @[[GLOBALS:[a-zA-Z0-9_$"\\.-]+]] = internal constant [[STRUCT_S:%.*]] { i32 42, double 3.140000e+00, ptr null }, align 8
+; CHECK: @[[GLOBALS:[a-zA-Z0-9_$"\\.-]+]] = internal constant [[STRUCT_S:%.*]] { i32 42, double 3.140000e+00, ptr null, i32 0 }, align 8
;.
-define i32 @testOneFieldGlobalS() {
-; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
+define i32 @testOneFieldGlobalS(i32 %cmpx) {
+; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@testOneFieldGlobalS
-; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
+; CHECK-SAME: (i32 [[CMPX:%.*]]) #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: entry:
+; CHECK-NEXT: [[RMW:%.*]] = atomicrmw add ptr getelementptr inbounds ([[STRUCT_S:%.*]], ptr @GlobalS, i32 0, i32 3), i32 1 monotonic, align 4
+; CHECK-NEXT: [[CXI:%.*]] = cmpxchg ptr getelementptr inbounds ([[STRUCT_S]], ptr @GlobalS, i32 0, i32 3), i32 [[CMPX]], i32 7 acq_rel monotonic, align 4
; CHECK-NEXT: br label [[IF_END:%.*]]
; CHECK: if.then:
; CHECK-NEXT: unreachable
@@ -57,6 +60,8 @@ define i32 @testOneFieldGlobalS() {
entry:
%i = load i32, ptr @GlobalS, align 8
call void @harmless_use(ptr @GlobalS)
+ %rmw = atomicrmw add ptr getelementptr inbounds (%struct.S, ptr @GlobalS, i32 0, i32 3), i32 1 monotonic, align 4
+ %cxi = cmpxchg ptr getelementptr inbounds (%struct.S, ptr @GlobalS, i32 0, i32 3), i32 %cmpx, i32 7 acq_rel monotonic
%cmp = icmp ne i32 %i, 42
br i1 %cmp, label %if.then, label %if.end
@@ -92,7 +97,7 @@ if.end7: ; preds = %if.then5, %if.end4
define i32 @testOneFieldGlobalS_type_mismatch() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@testOneFieldGlobalS_type_mismatch
-; CHECK-SAME: () #[[ATTR1]] {
+; CHECK-SAME: () #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[I:%.*]] = load double, ptr @GlobalS, align 8
; CHECK-NEXT: [[IC:%.*]] = fptosi double [[I]] to i32
@@ -158,7 +163,7 @@ if.end7: ; preds = %if.then5, %if.end4
define i32 @testOneFieldGlobalS_byte_offset_wrong() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@testOneFieldGlobalS_byte_offset_wrong
-; CHECK-SAME: () #[[ATTR1]] {
+; CHECK-SAME: () #[[ATTR2]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[I:%.*]] = load i32, ptr getelementptr inbounds (i32, ptr @GlobalS, i32 1), align 8
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I]], 42
@@ -221,5 +226,6 @@ if.end7: ; preds = %if.then5, %if.end4
}
;.
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree norecurse nosync nounwind readnone willreturn }
-; CHECK: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
+; CHECK: attributes #[[ATTR1]] = { nofree norecurse nounwind readnone willreturn }
+; CHECK: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn }
;.
More information about the llvm-commits
mailing list