[llvm] df116d1 - [MemCpyOpt] Fix the invalid code modification for GEP (#68479)

via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 9 03:54:22 PDT 2023


Author: Kai Yan
Date: 2023-10-09T12:54:16+02:00
New Revision: df116d1dc42d3d4d6264f87bdb1c32af5802ddab

URL: https://github.com/llvm/llvm-project/commit/df116d1dc42d3d4d6264f87bdb1c32af5802ddab
DIFF: https://github.com/llvm/llvm-project/commit/df116d1dc42d3d4d6264f87bdb1c32af5802ddab.diff

LOG: [MemCpyOpt] Fix the invalid code modification for GEP (#68479)

Relocate the GEP modification to a later stage of the function
performCallSlotOptzn(), ensuring that the code remains unchanged if the
optimization fails.

Co-authored-by: aklkaiyan <aklkaiyan at tencent.com>

Added: 
    llvm/test/Transforms/MemCpyOpt/memcpy-gep-modification.ll

Modified: 
    llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 783ef57805610b9..688bcfa57158975 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1043,12 +1043,13 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpyLoad,
 
   // Since we're changing the parameter to the callsite, we need to make sure
   // that what would be the new parameter dominates the callsite.
+  bool NeedMoveGEP = false;
   if (!DT->dominates(cpyDest, C)) {
     // Support moving a constant index GEP before the call.
     auto *GEP = dyn_cast<GetElementPtrInst>(cpyDest);
     if (GEP && GEP->hasAllConstantIndices() &&
         DT->dominates(GEP->getPointerOperand(), C))
-      GEP->moveBefore(C);
+      NeedMoveGEP = true;
     else
       return false;
   }
@@ -1101,6 +1102,11 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpyLoad,
     cast<AllocaInst>(cpyDest)->setAlignment(srcAlign);
   }
 
+  if (NeedMoveGEP) {
+    auto *GEP = dyn_cast<GetElementPtrInst>(cpyDest);
+    GEP->moveBefore(C);
+  }
+
   if (SkippedLifetimeStart) {
     SkippedLifetimeStart->moveBefore(C);
     MSSAU->moveBefore(MSSA->getMemoryAccess(SkippedLifetimeStart),

diff  --git a/llvm/test/Transforms/MemCpyOpt/memcpy-gep-modification.ll b/llvm/test/Transforms/MemCpyOpt/memcpy-gep-modification.ll
new file mode 100644
index 000000000000000..ba6faf3578c5027
--- /dev/null
+++ b/llvm/test/Transforms/MemCpyOpt/memcpy-gep-modification.ll
@@ -0,0 +1,60 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=memcpyopt < %s -verify-memoryssa | FileCheck %s
+
+%struct.MaskedType = type { i8, i8 }
+
+declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #0
+declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #0
+declare void @MaskedFunction1(ptr, ptr addrspace(1))
+declare void @MaskedFunction2(ptr, ptr)
+
+define i8 @test_gep_not_modified(ptr %in0, ptr %in1) {
+; CHECK-LABEL: @test_gep_not_modified(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FUNCALLOC:%.*]] = alloca [[STRUCT_MASKEDTYPE:%.*]], align 4
+; CHECK-NEXT:    [[PTRALLOC:%.*]] = alloca i8, align 1
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[PTRALLOC]])
+; CHECK-NEXT:    [[ADDRSPACECAST:%.*]] = addrspacecast ptr [[PTRALLOC]] to ptr addrspace(1)
+; CHECK-NEXT:    call void @MaskedFunction1(ptr [[IN1:%.*]], ptr addrspace(1) [[ADDRSPACECAST]])
+; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, ptr [[PTRALLOC]], align 1
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr [[PTRALLOC]])
+; CHECK-NEXT:    [[GETELEMPTR1:%.*]] = getelementptr inbounds [[STRUCT_MASKEDTYPE]], ptr [[FUNCALLOC]], i32 0, i32 1
+; CHECK-NEXT:    store i8 [[LOAD1]], ptr [[GETELEMPTR1]], align 1
+; CHECK-NEXT:    ret i8 0
+;
+entry:
+  %funcAlloc = alloca %struct.MaskedType, align 4
+  %ptrAlloc = alloca i8, align 1
+  call void @llvm.lifetime.start.p0(i64 4, ptr %ptrAlloc) #0
+  %addrspaceCast = addrspacecast ptr %ptrAlloc to ptr addrspace(1)
+  call void @MaskedFunction1(ptr %in1, ptr addrspace(1) %addrspaceCast)
+  %load1 = load i8, ptr %ptrAlloc, align 1
+  call void @llvm.lifetime.end.p0(i64 4, ptr %ptrAlloc) #0
+  %getElemPtr1 = getelementptr inbounds %struct.MaskedType, ptr %funcAlloc, i32 0, i32 1
+  store i8 %load1, ptr %getElemPtr1, align 1
+  ret i8 0
+}
+
+define i8 @test_gep_modified(ptr %in0, ptr %in1) {
+; CHECK-LABEL: @test_gep_modified(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FUNCALLOC:%.*]] = alloca [[STRUCT_MASKEDTYPE:%.*]], align 4
+; CHECK-NEXT:    [[PTRALLOC:%.*]] = alloca i8, align 1
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[PTRALLOC]])
+; CHECK-NEXT:    [[GETELEMPTR1:%.*]] = getelementptr inbounds [[STRUCT_MASKEDTYPE]], ptr [[FUNCALLOC]], i32 0, i32 1
+; CHECK-NEXT:    call void @MaskedFunction2(ptr [[IN1:%.*]], ptr [[GETELEMPTR1]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr [[PTRALLOC]])
+; CHECK-NEXT:    ret i8 0
+;
+entry:
+  %funcAlloc = alloca %struct.MaskedType, align 4
+  %ptrAlloc = alloca i8, align 1
+  call void @llvm.lifetime.start.p0(i64 4, ptr %ptrAlloc) #0
+  call void @MaskedFunction2(ptr %in1, ptr %ptrAlloc)
+  %load1 = load i8, ptr %ptrAlloc, align 1
+  call void @llvm.lifetime.end.p0(i64 4, ptr %ptrAlloc) #0
+  %getElemPtr1 = getelementptr inbounds %struct.MaskedType, ptr %funcAlloc, i32 0, i32 1
+  store i8 %load1, ptr %getElemPtr1, align 1
+  ret i8 0
+}
+


        


More information about the llvm-commits mailing list