diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -533,17 +533,14 @@ auto Iter = AdditionalUsers.find(I); if (Iter != AdditionalUsers.end()) { - // Cache Instructions to update and update later - // in order to avoid iterator invalidation - SmallPtrSet toNotify; - for (User *U : Iter->second) { - if (auto *UI = dyn_cast(U)) { - toNotify.insert(UI); - } - } - for (Instruction *UI : toNotify) { + // Copy additional users before notifying them of changes, because new + // users may be added, potentially invalidating the iterator. + SmallVector ToNotify; + for (User *U : Iter->second) + if (auto *UI = dyn_cast(U)) + ToNotify.push_back(UI); + for (Instruction *UI : ToNotify) OperandChangedState(UI); - } } } void handleCallOverdefined(CallBase &CB); diff --git a/llvm/test/Transforms/SCCP/pr49582-iterator-invalidation.ll b/llvm/test/Transforms/SCCP/pr49582-iterator-invalidation.ll --- a/llvm/test/Transforms/SCCP/pr49582-iterator-invalidation.ll +++ b/llvm/test/Transforms/SCCP/pr49582-iterator-invalidation.ll @@ -1,10 +1,11 @@ ; RUN: opt < %s -ipsccp -disable-output -; PR49582 +; PR49582: This test checks for an iterator invalidation issue, which only gets +; exposed on a large-enough test case. We intentionally do not check the output. @c = external dso_local global i32*, align 8 @d = external dso_local global i32, align 4 -define dso_local void @_Z1hi(i32 %i) #0 { +define void @f(i32 %i) { entry: br label %for.cond @@ -147,7 +148,7 @@ br label %if.end628 if.else78: ; preds = %if.then - %call = call i32 @_Z1biii() + %call = call i32 @g() %tobool79 = icmp ne i32 %call, 0 br i1 %tobool79, label %if.then80, label %if.else123 @@ -214,12 +215,12 @@ br label %if.end628 if.else123: ; preds = %if.else78 - %call124 = call i32 @_Z1biii() + %call124 = call i32 @g() %tobool125 = icmp ne i32 %call124, 0 br i1 %tobool125, label %if.then126, label %if.end628 if.then126: ; preds = %if.else123 - %call127 = call i32 @_Z1biii() + %call127 = call i32 @g() %tobool128 = icmp ne i32 %call127, 0 br i1 %tobool128, label %if.then129, label %if.else164 @@ -320,7 +321,7 @@ br label %if.end628 if.else205: ; preds = %if.else195 - %call206 = call i32 @_Z1aii() + %call206 = call i32 @h() %tobool207 = icmp ne i32 %call206, 0 br i1 %tobool207, label %if.then208, label %if.else217 @@ -352,7 +353,7 @@ br label %if.end628 if.else227: ; preds = %if.else217 - %call228 = call i32 @_Z1biii() + %call228 = call i32 @g() %tobool229 = icmp ne i32 %call228, 0 br i1 %tobool229, label %if.then230, label %if.else245 @@ -405,7 +406,7 @@ br label %if.end628 if.else268: ; preds = %if.else258 - %call269 = call i32 @_Z1aii() + %call269 = call i32 @h() %tobool270 = icmp ne i32 %call269, 0 br i1 %tobool270, label %if.then271, label %if.else279 @@ -432,7 +433,7 @@ br label %if.end628 if.else287: ; preds = %if.else279 - %call288 = call i32 @_Z1biii() + %call288 = call i32 @g() %tobool289 = icmp ne i32 %call288, 0 br i1 %tobool289, label %if.then290, label %if.else307 @@ -480,7 +481,7 @@ br label %if.end628 if.else324: ; preds = %if.else307 - %call325 = call i32 @_Z1biii() + %call325 = call i32 @g() %tobool326 = icmp ne i32 %call325, 0 br i1 %tobool326, label %if.then327, label %if.else475 @@ -521,7 +522,7 @@ if.end344: ; preds = %if.then342, %if.end340 %e.14 = phi i32 [ %inc343, %if.then342 ], [ %e.13, %if.end340 ] - %call345 = call i32 @_Z1biii() + %call345 = call i32 @g() %tobool346 = icmp ne i32 %call345, 0 br i1 %tobool346, label %if.then347, label %if.else398 @@ -593,7 +594,7 @@ br label %if.end628 if.else398: ; preds = %if.end344 - %call399 = call i32 @_Z1aii() + %call399 = call i32 @h() %tobool400 = icmp ne i32 %call399, 0 br i1 %tobool400, label %if.then401, label %if.else409 @@ -607,7 +608,7 @@ br label %if.end628 if.else409: ; preds = %if.else398 - %call410 = call i32 @_Z1aii() + %call410 = call i32 @h() %tobool411 = icmp ne i32 %call410, 0 br i1 %tobool411, label %if.then412, label %if.else420 @@ -621,7 +622,7 @@ br label %if.end628 if.else420: ; preds = %if.else409 - %call421 = call i32 @_Z1aii() + %call421 = call i32 @h() %tobool422 = icmp ne i32 %call421, 0 br i1 %tobool422, label %if.then423, label %if.else431 @@ -635,7 +636,7 @@ br label %if.end628 if.else431: ; preds = %if.else420 - %call432 = call i32 @_Z1aii() + %call432 = call i32 @h() %tobool433 = icmp ne i32 %call432, 0 br i1 %tobool433, label %if.then434, label %if.else440 @@ -648,7 +649,7 @@ br label %if.end628 if.else440: ; preds = %if.else431 - %call441 = call i32 @_Z1aii() + %call441 = call i32 @h() %tobool442 = icmp ne i32 %call441, 0 br i1 %tobool442, label %if.then443, label %if.else451 @@ -664,7 +665,7 @@ br label %if.end628 if.else451: ; preds = %if.else440 - %call452 = call i32 @_Z1aii() + %call452 = call i32 @h() %tobool453 = icmp ne i32 %call452, 0 br i1 %tobool453, label %if.then454, label %if.else460 @@ -686,12 +687,12 @@ br label %if.end628 if.else475: ; preds = %if.else324 - %call476 = call i32 @_Z1biii() + %call476 = call i32 @g() %tobool477 = icmp ne i32 %call476, 0 br i1 %tobool477, label %if.then478, label %if.else509 if.then478: ; preds = %if.else475 - %call479 = call i32 @_Z1aii() + %call479 = call i32 @h() %tobool480 = icmp ne i32 %call479, 0 br i1 %tobool480, label %if.then481, label %if.else487 @@ -704,7 +705,7 @@ br label %if.end628 if.else487: ; preds = %if.then478 - %call488 = call i32 @_Z1aii() + %call488 = call i32 @h() %tobool489 = icmp ne i32 %call488, 0 br i1 %tobool489, label %if.then490, label %if.else496 @@ -731,7 +732,7 @@ br label %if.end628 if.else509: ; preds = %if.else475 - %call510 = call i32 @_Z1biii() + %call510 = call i32 @g() %tobool511 = icmp ne i32 %call510, 0 br i1 %tobool511, label %if.then512, label %if.else565 @@ -792,7 +793,7 @@ br label %if.end628 if.else565: ; preds = %if.else509 - %call566 = call i32 @_Z1biii() + %call566 = call i32 @g() %tobool567 = icmp ne i32 %call566, 0 br i1 %tobool567, label %if.then568, label %if.else590 @@ -819,7 +820,7 @@ br label %if.end628 if.else590: ; preds = %if.else565 - %call591 = call i32 @_Z1biii() + %call591 = call i32 @g() %tobool592 = icmp ne i32 %call591, 0 br i1 %tobool592, label %if.then593, label %if.end628 @@ -844,16 +845,10 @@ br label %for.cond } -declare dso_local i32 @_Z1biii() #0 +declare i32 @g() -declare dso_local i32 @_Z1aii() #0 +declare i32 @h() ; Function Attrs: nofree nosync nounwind willreturn declare void @llvm.assume(i1 noundef) #1 -attributes #0 = { "tune-cpu"="generic" } -attributes #1 = { nofree nosync nounwind willreturn } - -!llvm.ident = !{!0} - -!0 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 29d46760599b32504f4dfda4de69aca8b9f1f65e)"}