diff options
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp | 17 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/atomic.ll | 39 |
2 files changed, 50 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 638ae85d230..aa72244463e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -327,6 +327,8 @@ static LoadInst *combineLoadToNewType(InstCombiner &IC, LoadInst &LI, Type *NewT LoadInst *NewLoad = IC.Builder->CreateAlignedLoad( IC.Builder->CreateBitCast(Ptr, NewTy->getPointerTo(AS)), LI.getAlignment(), LI.getName() + Suffix); + NewLoad->setAtomic(LI.getOrdering(), LI.getSynchScope()); + assert(!LI.isVolatile() && "volatile unhandled here"); MDBuilder MDB(NewLoad->getContext()); for (const auto &MDPair : MD) { unsigned ID = MDPair.first; @@ -399,6 +401,8 @@ static StoreInst *combineStoreToNewValue(InstCombiner &IC, StoreInst &SI, Value StoreInst *NewStore = IC.Builder->CreateAlignedStore( V, IC.Builder->CreateBitCast(Ptr, V->getType()->getPointerTo(AS)), SI.getAlignment()); + NewStore->setAtomic(SI.getOrdering(), SI.getSynchScope()); + assert(!SI.isVolatile() && "volatile unhandled here"); for (const auto &MDPair : MD) { unsigned ID = MDPair.first; MDNode *N = MDPair.second; @@ -456,9 +460,9 @@ static StoreInst *combineStoreToNewValue(InstCombiner &IC, StoreInst &SI, Value /// later. However, it is risky in case some backend or other part of LLVM is /// relying on the exact type loaded to select appropriate atomic operations. static Instruction *combineLoadToOperationType(InstCombiner &IC, LoadInst &LI) { - // FIXME: We could probably with some care handle both volatile and atomic - // loads here but it isn't clear that this is important. - if (!LI.isSimple()) + // FIXME: We could probably with some care handle both volatile and ordered + // atomic loads here but it isn't clear that this is important. + if (!LI.isUnordered()) return nullptr; if (LI.use_empty()) @@ -892,6 +896,7 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { V1->setAtomic(LI.getOrdering(), LI.getSynchScope()); V2->setAlignment(Align); V2->setAtomic(LI.getOrdering(), LI.getSynchScope()); + assert(!LI.isVolatile() && "volatile unhandled here"); return SelectInst::Create(SI->getCondition(), V1, V2); } @@ -934,9 +939,9 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { /// the store instruction as otherwise there is no way to signal whether it was /// combined or not: IC.EraseInstFromFunction returns a null pointer. static bool combineStoreToValueType(InstCombiner &IC, StoreInst &SI) { - // FIXME: We could probably with some care handle both volatile and atomic - // stores here but it isn't clear that this is important. - if (!SI.isSimple()) + // FIXME: We could probably with some care handle both volatile and ordered + // atomic stores here but it isn't clear that this is important. + if (!SI.isUnordered()) return false; Value *V = SI.getValueOperand(); diff --git a/llvm/test/Transforms/InstCombine/atomic.ll b/llvm/test/Transforms/InstCombine/atomic.ll index ac698c8425e..408bc8166e9 100644 --- a/llvm/test/Transforms/InstCombine/atomic.ll +++ b/llvm/test/Transforms/InstCombine/atomic.ll @@ -172,3 +172,42 @@ define i32 @test17(i1 %cnd) { %x = load atomic i32, i32* %addr seq_cst, align 4 ret i32 %x } + +declare void @clobber() + +define i32 @test18(float* %p) { +; CHECK-LABEL: define i32 @test18( +; CHECK: load atomic i32, i32* [[A:%.*]] unordered, align 4 +; CHECK: store atomic i32 [[B:%.*]], i32* [[C:%.*]] unordered, align 4 + %x = load atomic float, float* %p unordered, align 4 + call void @clobber() ;; keep the load around + store atomic float %x, float* %p unordered, align 4 + ret i32 0 +} + +; TODO: probably also legal in this case +define i32 @test19(float* %p) { +; CHECK-LABEL: define i32 @test19( +; CHECK: load atomic float, float* %p seq_cst, align 4 +; CHECK: store atomic float %x, float* %p seq_cst, align 4 + %x = load atomic float, float* %p seq_cst, align 4 + call void @clobber() ;; keep the load around + store atomic float %x, float* %p seq_cst, align 4 + ret i32 0 +} + +define i32 @test20(i32** %p, i8* %v) { +; CHECK-LABEL: define i32 @test20( +; CHECK: store atomic i8* %v, i8** [[D:%.*]] unordered, align 4 + %cast = bitcast i8* %v to i32* + store atomic i32* %cast, i32** %p unordered, align 4 + ret i32 0 +} +; TODO: probably also legal in this case +define i32 @test21(i32** %p, i8* %v) { +; CHECK-LABEL: define i32 @test21( +; CHECK: store atomic i32* %cast, i32** %p monotonic, align 4 + %cast = bitcast i8* %v to i32* + store atomic i32* %cast, i32** %p monotonic, align 4 + ret i32 0 +} |

