diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp @@ -152,13 +152,5 @@ return replaceOperand(RMWI, 1, ConstantFP::getNegativeZero(RMWI.getType())); } - // Check if the required ordering is compatible with an atomic load. - if (Ordering != AtomicOrdering::Acquire && - Ordering != AtomicOrdering::Monotonic) - return nullptr; - - LoadInst *Load = new LoadInst(RMWI.getType(), RMWI.getPointerOperand(), "", - false, DL.getABITypeAlign(RMWI.getType()), - Ordering, RMWI.getSyncScopeID()); - return Load; + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/atomicrmw.ll b/llvm/test/Transforms/InstCombine/atomicrmw.ll --- a/llvm/test/Transforms/InstCombine/atomicrmw.ll +++ b/llvm/test/Transforms/InstCombine/atomicrmw.ll @@ -1,11 +1,12 @@ ; RUN: opt -passes=instcombine -S -o - %s | FileCheck %s -; Check that we can replace `atomicrmw LHS, 0` with `load atomic LHS`. -; This is possible when: -; - LHS, 0 == LHS -; - the ordering of atomicrmw is compatible with a load (i.e., no release semantic) +; Check that we don't replace `atomicrmw LHS, 0` with `load atomic LHS`. +; Doing that would lose the store semantic of the `atomicrmw` operation. +; This may enable some other optimizations that would otherwise be illegal when +; the store semantic was present (e.g., like dropping a fence). ; CHECK-LABEL: atomic_add_zero -; CHECK-NEXT: %res = load atomic i32, ptr %addr monotonic, align 4 +; Idempotent atomicrmw are still canonicalized. +; CHECK-NEXT: %res = atomicrmw or ptr %addr, i32 0 monotonic ; CHECK-NEXT: ret i32 %res define i32 @atomic_add_zero(ptr %addr) { %res = atomicrmw add ptr %addr, i32 0 monotonic @@ -13,15 +14,16 @@ } ; CHECK-LABEL: atomic_or_zero -; CHECK-NEXT: %res = load atomic i32, ptr %addr monotonic, align 4 +; CHECK-NEXT: %res = atomicrmw or ptr %addr, i32 0 monotonic ; CHECK-NEXT: ret i32 %res define i32 @atomic_or_zero(ptr %addr) { - %res = atomicrmw add ptr %addr, i32 0 monotonic + %res = atomicrmw or ptr %addr, i32 0 monotonic ret i32 %res } ; CHECK-LABEL: atomic_sub_zero -; CHECK-NEXT: %res = load atomic i32, ptr %addr monotonic, align 4 +; Idempotent atomicrmw are still canonicalized. +; CHECK-NEXT: %res = atomicrmw or ptr %addr, i32 0 monotonic ; CHECK-NEXT: ret i32 %res define i32 @atomic_sub_zero(ptr %addr) { %res = atomicrmw sub ptr %addr, i32 0 monotonic @@ -29,14 +31,16 @@ } ; CHECK-LABEL: atomic_and_allones -; CHECK-NEXT: %res = load atomic i32, ptr %addr monotonic, align 4 +; Idempotent atomicrmw are still canonicalized. +; CHECK-NEXT: %res = atomicrmw or ptr %addr, i32 0 monotonic ; CHECK-NEXT: ret i32 %res define i32 @atomic_and_allones(ptr %addr) { %res = atomicrmw and ptr %addr, i32 -1 monotonic ret i32 %res } ; CHECK-LABEL: atomic_umin_uint_max -; CHECK-NEXT: %res = load atomic i32, ptr %addr monotonic, align 4 +; Idempotent atomicrmw are still canonicalized. +; CHECK-NEXT: %res = atomicrmw or ptr %addr, i32 0 monotonic ; CHECK-NEXT: ret i32 %res define i32 @atomic_umin_uint_max(ptr %addr) { %res = atomicrmw umin ptr %addr, i32 -1 monotonic @@ -44,7 +48,8 @@ } ; CHECK-LABEL: atomic_umax_zero -; CHECK-NEXT: %res = load atomic i32, ptr %addr monotonic, align 4 +; Idempotent atomicrmw are still canonicalized. +; CHECK-NEXT: %res = atomicrmw or ptr %addr, i32 0 monotonic ; CHECK-NEXT: ret i32 %res define i32 @atomic_umax_zero(ptr %addr) { %res = atomicrmw umax ptr %addr, i32 0 monotonic @@ -52,7 +57,8 @@ } ; CHECK-LABEL: atomic_min_smax_char -; CHECK-NEXT: %res = load atomic i8, ptr %addr monotonic, align 1 +; Idempotent atomicrmw are still canonicalized. +; CHECK-NEXT: %res = atomicrmw or ptr %addr, i8 0 monotonic ; CHECK-NEXT: ret i8 %res define i8 @atomic_min_smax_char(ptr %addr) { %res = atomicrmw min ptr %addr, i8 127 monotonic @@ -60,7 +66,8 @@ } ; CHECK-LABEL: atomic_max_smin_char -; CHECK-NEXT: %res = load atomic i8, ptr %addr monotonic, align 1 +; Idempotent atomicrmw are still canonicalized. +; CHECK-NEXT: %res = atomicrmw or ptr %addr, i8 0 monotonic ; CHECK-NEXT: ret i8 %res define i8 @atomic_max_smin_char(ptr %addr) { %res = atomicrmw max ptr %addr, i8 -128 monotonic @@ -68,7 +75,8 @@ } ; CHECK-LABEL: atomic_fsub -; CHECK-NEXT: %res = load atomic float, ptr %addr monotonic, align 4 +; Idempotent atomicrmw are still canonicalized. +; CHECK-NEXT: %res = atomicrmw fadd ptr %addr, float -0.000000e+00 monotonic ; CHECK-NEXT: ret float %res define float @atomic_fsub_zero(ptr %addr) { %res = atomicrmw fsub ptr %addr, float 0.0 monotonic @@ -76,7 +84,7 @@ } ; CHECK-LABEL: atomic_fadd -; CHECK-NEXT: %res = load atomic float, ptr %addr monotonic, align 4 +; CHECK-NEXT: %res = atomicrmw fadd ptr %addr, float -0.000000e+00 monotonic ; CHECK-NEXT: ret float %res define float @atomic_fadd_zero(ptr %addr) { %res = atomicrmw fadd ptr %addr, float -0.0 monotonic @@ -110,7 +118,7 @@ ; Check that the transformation properly preserve the syncscope. ; CHECK-LABEL: atomic_syncscope -; CHECK-NEXT: %res = load atomic i16, ptr %addr syncscope("some_syncscope") acquire, align 2 +; CHECK-NEXT: %res = atomicrmw or ptr %addr, i16 0 syncscope("some_syncscope") acquire ; CHECK-NEXT: ret i16 %res define i16 @atomic_syncscope(ptr %addr) { %res = atomicrmw or ptr %addr, i16 0 syncscope("some_syncscope") acquire @@ -138,7 +146,8 @@ } ; CHECK-LABEL: atomic_xor_zero -; CHECK-NEXT: %res = load atomic i16, ptr %addr monotonic, align 2 +; Idempotent atomicrmw are still canonicalized. +; CHECK-NEXT: %res = atomicrmw or ptr %addr, i16 0 monotonic ; CHECK-NEXT: ret i16 %res define i16 @atomic_xor_zero(ptr %addr) { %res = atomicrmw xor ptr %addr, i16 0 monotonic