Index: llvm/lib/Transforms/Scalar/LICM.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LICM.cpp +++ llvm/lib/Transforms/Scalar/LICM.cpp @@ -1896,9 +1896,8 @@ if (isa(Object)) return true; - // TODO: Also handle sret. if (auto *A = dyn_cast(Object)) - return A->hasByValAttr(); + return A->hasByValAttr() || A->hasStructRetAttr(); // TODO: Noalias has nothing to do with writability, this should check for // an allocator function. Index: llvm/test/Transforms/LICM/scalar-promote.ll =================================================================== --- llvm/test/Transforms/LICM/scalar-promote.ll +++ llvm/test/Transforms/LICM/scalar-promote.ll @@ -883,7 +883,6 @@ ret void } -; TODO: The store can be promoted, as sret memory is writable. define void @sret_cond_store(i32* sret(i32) noalias %ptr) { ; CHECK-LABEL: @sret_cond_store( ; CHECK-NEXT: [[PTR_PROMOTED:%.*]] = load i32, i32* [[PTR:%.*]], align 4 @@ -894,9 +893,10 @@ ; CHECK-NEXT: br i1 [[C]], label [[LOOP_LATCH]], label [[EXIT:%.*]] ; CHECK: loop.latch: ; CHECK-NEXT: [[V_INC]] = add i32 [[V_INC1]], 1 -; CHECK-NEXT: store i32 [[V_INC]], i32* [[PTR]], align 4 ; CHECK-NEXT: br label [[LOOP]] ; CHECK: exit: +; CHECK-NEXT: [[V_INC1_LCSSA:%.*]] = phi i32 [ [[V_INC1]], [[LOOP]] ] +; CHECK-NEXT: store i32 [[V_INC1_LCSSA]], i32* [[PTR]], align 4 ; CHECK-NEXT: ret void ; br label %loop