[PATCH] Fix detection of devirtualized calls that have no users

Björn Steinbrink bsteinbr at gmail.com
Mon Feb 10 11:08:45 PST 2014


In transformConstExprCastCall, if the replaced call has no users, we
currently don't call ReplaceInstUsesWith, which means that ValueHandlers
aren't notified about the replacement, but only about the removal of the
old call.

This means that we can't immediately detect the devirtualization of such
calls when updating the call graph in the CGSCC pass, because the old
CallSite got invalidated. If some other change then fools the simple
counting logic, we fail to re-run the pass on the current function,
missing further optimization possibilities opened up by the
devirtualized call.

As a fix, we should manually perform the notifications if there are
ValueHandlers present.
---
 lib/Transforms/InstCombine/InstCombineCalls.cpp  |  2 ++
 test/Transforms/InstCombine/cast-call-combine.ll | 22 ++++++++++++++++++++++
 2 files changed, 24 insertions(+)
 create mode 100644 test/Transforms/InstCombine/cast-call-combine.ll

diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 8e308ec..cba88ff 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1227,6 +1227,8 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
 
   if (!Caller->use_empty())
     ReplaceInstUsesWith(*Caller, NV);
+  else if (Caller->hasValueHandle())
+    ValueHandleBase::ValueIsRAUWd(Caller, NV);
 
   EraseInstFromFunction(*Caller);
   return true;
diff --git a/test/Transforms/InstCombine/cast-call-combine.ll b/test/Transforms/InstCombine/cast-call-combine.ll
new file mode 100644
index 0000000..4eb2478
--- /dev/null
+++ b/test/Transforms/InstCombine/cast-call-combine.ll
@@ -0,0 +1,22 @@
+; RUN: opt < %s -always-inline -instcombine -S | FileCheck %s
+
+define internal void @foo(i16*) alwaysinline {
+  ret void
+}
+
+define void @bar() noinline noreturn {
+  unreachable
+}
+
+define void @test() {
+  br i1 false, label %then, label %else
+
+then:
+  call void @bar()
+  unreachable
+
+else:
+  ; CHECK-NOT: call
+  call void bitcast (void (i16*)* @foo to void (i8*)*) (i8* null)
+  ret void
+}
-- 
1.9.0.rc3



More information about the llvm-commits mailing list