From: Nikita Popov Date: Tue, 18 Apr 2023 16:22:37 +0000 (+0200) Subject: [GlobalOpt] Don't evaluate large memset (PR62191) X-Git-Tag: upstream/17.0.6~11177 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a722e2366bede3d476c5bf3ff11428102aa4891f;p=platform%2Fupstream%2Fllvm.git [GlobalOpt] Don't evaluate large memset (PR62191) If the memset is large, checking every single byte of the global may be very slow. Add an upper bound on the size of memset we handle. For the common special case of memset zeroinitializer to zero, add a fastpath that checks just that and is not length limited. Fixes https://github.com/llvm/llvm-project/issues/62191. --- diff --git a/llvm/lib/Transforms/Utils/Evaluator.cpp b/llvm/lib/Transforms/Utils/Evaluator.cpp index 52e4c9e..23c1ca3 100644 --- a/llvm/lib/Transforms/Utils/Evaluator.cpp +++ b/llvm/lib/Transforms/Utils/Evaluator.cpp @@ -413,16 +413,28 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB, } Constant *Val = getVal(MSI->getValue()); - APInt Len = LenC->getValue(); - while (Len != 0) { - Constant *DestVal = ComputeLoadResult(GV, Val->getType(), Offset); - if (DestVal != Val) { - LLVM_DEBUG(dbgs() << "Memset is not a no-op at offset " - << Offset << " of " << *GV << ".\n"); + // Avoid the byte-per-byte scan if we're memseting a zeroinitializer + // to zero. + if (!Val->isNullValue() || MutatedMemory.contains(GV) || + !GV->hasDefinitiveInitializer() || + !GV->getInitializer()->isNullValue()) { + APInt Len = LenC->getValue(); + if (Len.ugt(64 * 1024)) { + LLVM_DEBUG(dbgs() << "Not evaluating large memset of size " + << Len << "\n"); return false; } - ++Offset; - --Len; + + while (Len != 0) { + Constant *DestVal = ComputeLoadResult(GV, Val->getType(), Offset); + if (DestVal != Val) { + LLVM_DEBUG(dbgs() << "Memset is not a no-op at offset " + << Offset << " of " << *GV << ".\n"); + return false; + } + ++Offset; + --Len; + } } LLVM_DEBUG(dbgs() << "Ignoring no-op memset.\n"); diff --git a/llvm/test/Transforms/GlobalOpt/ctor-memset.ll b/llvm/test/Transforms/GlobalOpt/ctor-memset.ll index 92b4a7d..b116358 100644 --- a/llvm/test/Transforms/GlobalOpt/ctor-memset.ll +++ b/llvm/test/Transforms/GlobalOpt/ctor-memset.ll @@ -3,7 +3,7 @@ target datalayout = "p1:32:32" -@llvm.global_ctors = appending global [9 x { i32, ptr, ptr }] [ +@llvm.global_ctors = appending global [11 x { i32, ptr, ptr }] [ { i32, ptr, ptr } { i32 65535, ptr @ctor0, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor1, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor2, ptr null }, @@ -12,11 +12,16 @@ target datalayout = "p1:32:32" { i32, ptr, ptr } { i32 65535, ptr @ctor5, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor6, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor7, ptr null }, - { i32, ptr, ptr } { i32 65535, ptr @ctor8, ptr null } + { i32, ptr, ptr } { i32 65535, ptr @ctor8, ptr null }, + { i32, ptr, ptr } { i32 65535, ptr @ctor9, ptr null }, + { i32, ptr, ptr } { i32 65535, ptr @ctor10, ptr null } ] + +; memset of all-zero global +@g0 = global { i32, i32 } zeroinitializer ;. -; CHECK: @[[LLVM_GLOBAL_CTORS:[a-zA-Z0-9_$"\\.-]+]] = appending global [3 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @ctor3, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor4, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor7, ptr null }] +; CHECK: @[[LLVM_GLOBAL_CTORS:[a-zA-Z0-9_$"\\.-]+]] = appending global [4 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @ctor3, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor4, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor7, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor10, ptr null }] ; CHECK: @[[G0:[a-zA-Z0-9_$"\\.-]+]] = local_unnamed_addr global { i32, i32 } zeroinitializer ; CHECK: @[[G1:[a-zA-Z0-9_$"\\.-]+]] = local_unnamed_addr global { i32, i32, i32 } { i32 0, i32 0, i32 1 } ; CHECK: @[[G2:[a-zA-Z0-9_$"\\.-]+]] = local_unnamed_addr global { i32, i32, i32 } { i32 1, i32 0, i32 0 } @@ -26,10 +31,9 @@ target datalayout = "p1:32:32" ; CHECK: @[[G6:[a-zA-Z0-9_$"\\.-]+]] = local_unnamed_addr global { i32, i32 } { i32 -1, i32 -1 } ; CHECK: @[[G7:[a-zA-Z0-9_$"\\.-]+]] = local_unnamed_addr global { i32, i32 } { i32 -1, i32 1 } ; CHECK: @[[G8:[a-zA-Z0-9_$"\\.-]+]] = local_unnamed_addr addrspace(1) global { i32, i32 } zeroinitializer +; CHECK: @[[G9:[a-zA-Z0-9_$"\\.-]+]] = local_unnamed_addr global [100000000 x i32] zeroinitializer +; CHECK: @[[G10:[a-zA-Z0-9_$"\\.-]+]] = local_unnamed_addr global { [99999999 x i32], i32 } { [99999999 x i32] zeroinitializer, i32 1 } ;. - -; memset of all-zero global -@g0 = global { i32, i32 } zeroinitializer define internal void @ctor0() { call void @llvm.memset.p0.i64(ptr @g0, i8 0, i64 8, i1 false) ret void @@ -113,6 +117,24 @@ define internal void @ctor8() { ret void } +@g9 = global [100000000 x i32] zeroinitializer + +define internal void @ctor9() { + call void @llvm.memset.p0.i64(ptr @g9, i8 0, i64 100000000, i1 false) + ret void +} + +@g10 = global { [99999999 x i32], i32 } { [99999999 x i32 ] zeroinitializer, i32 1 } + +define internal void @ctor10() { +; CHECK-LABEL: @ctor10( +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr @g10, i8 0, i64 100000000, i1 false) +; CHECK-NEXT: ret void +; + call void @llvm.memset.p0.i64(ptr @g10, i8 0, i64 100000000, i1 false) + ret void +} + declare void @llvm.memset.p0.i64(ptr, i8, i64, i1) ;. ; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }