diff --git a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp --- a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -344,7 +344,9 @@ // If we hit load/store with the same invariant.group metadata (and the // same pointer operand) we can assume that value pointed by pointer // operand didn't change. - if ((isa(U) || isa(U)) && + if ((isa(U) || + (isa(U) && + cast(U)->getPointerOperand() == Ptr)) && U->hasMetadata(LLVMContext::MD_invariant_group)) ClosestDependency = GetClosestDependency(ClosestDependency, U); } diff --git a/llvm/test/Transforms/GVN/storeinvgroup.ll b/llvm/test/Transforms/GVN/storeinvgroup.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GVN/storeinvgroup.ll @@ -0,0 +1,65 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -gvn -S -o - < %s | FileCheck %s + +; ModuleID = 'tc.ll' +source_filename = "Main.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.c = type { double, double } + +@.str = private unnamed_addr constant [4 x i8] c"%f\0A\00", align 1 + +; Function Attrs: norecurse uwtable mustprogress +define i32 @main() local_unnamed_addr { +; CHECK-LABEL: @main( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @malloc(i64 32) +; CHECK-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to %struct.c* +; CHECK-NEXT: [[A1:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], %struct.c* [[TMP0]], i64 1, i32 0 +; CHECK-NEXT: store double 1.234500e+00, double* [[A1]], align 8 +; CHECK-NEXT: [[ARRAYIDX7_I_I:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 16 +; CHECK-NEXT: [[MALLOCCALL19_I:%.*]] = call noalias i8* @malloc(i64 8) +; CHECK-NEXT: [[_MALLOCCACHE_I:%.*]] = bitcast i8* [[MALLOCCALL19_I]] to %struct.c** +; CHECK-NEXT: [[C2:%.*]] = bitcast i8* [[ARRAYIDX7_I_I]] to %struct.c* +; CHECK-NEXT: store %struct.c* [[C2]], %struct.c** [[_MALLOCCACHE_I]], align 8, !invariant.group !2 +; CHECK-NEXT: [[A10_I_I:%.*]] = getelementptr inbounds [[STRUCT_C]], %struct.c* [[C2]], i64 0, i32 0 +; CHECK-NEXT: [[CALL4:%.*]] = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), double 1.234500e+00) +; CHECK-NEXT: ret i32 0 +; +entry: + %call = tail call noalias i8* @malloc(i64 32) + %0 = bitcast i8* %call to %struct.c* + %a1 = getelementptr inbounds %struct.c, %struct.c* %0, i64 1, i32 0 + store double 1.23450000e+00, double* %a1, align 8 + %arrayidx7.i.i = getelementptr inbounds i8, i8* %call, i64 16 + %malloccall19.i = call noalias i8* @malloc(i64 8) + %_malloccache.i = bitcast i8* %malloccall19.i to %struct.c** + %c2 = bitcast i8* %arrayidx7.i.i to %struct.c* + %g3 = getelementptr inbounds %struct.c*, %struct.c** %_malloccache.i, i64 0 + store %struct.c* %c2, %struct.c** %g3, align 8, !invariant.group !7 + %a10.i.i = getelementptr inbounds %struct.c, %struct.c* %c2, i64 0, i32 0 + %iload = load double, double* %a10.i.i, align 8, !invariant.group !8 + %call4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), double %iload) + ret i32 0 +} + +; Function Attrs: inaccessiblememonly nofree nounwind willreturn +declare dso_local noalias noundef i8* @malloc(i64 noundef) + +; Function Attrs: nofree nounwind +declare dso_local noundef i32 @printf(i8* nocapture noundef readonly, ...) + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 13.0.0 (git%github.com:llvm/llvm-project d163e75c81c1609855b98cbdffa0141c70d8578d)"} +!2 = distinct !{!2, !3} +!3 = !{!"llvm.loop.mustprogress"} +!4 = !{!5} +!5 = distinct !{!5, !6, !"diffe_Z1pP1cPd: %q"} +!6 = distinct !{!6, !"diffe_Z1pP1cPd"} +!7 = distinct !{} +!8 = distinct !{} +!9 = distinct !{!9, !3}