]> granicus.if.org Git - llvm/commitdiff
Create PHI node for the return value only when the return value has uses.
authorTaewook Oh <twoh@fb.com>
Mon, 28 Aug 2017 18:57:00 +0000 (18:57 +0000)
committerTaewook Oh <twoh@fb.com>
Mon, 28 Aug 2017 18:57:00 +0000 (18:57 +0000)
Summary:
Currently, a phi node is created in the normal destination to unify the return values from promoted calls and the original indirect call. This patch makes this phi node to be created only when the return value has uses.

This patch is necessary to generate valid code, as compiler crashes with the attached test case without this patch. Without this patch, an illegal phi node that has no incoming value from `entry`/`catch` is created in `cleanup` block.

I think existing implementation is good as far as there is at least one use of the original indirect call. `insertCallRetPHI` creates a new phi node in the normal destination block only when the original indirect call dominates its use and the normal destination block. Otherwise, `fixupPHINodeForNormalDest` will handle the unification of return values naturally without creating a new phi node. However, if there's no use, `insertCallRetPHI` still creates a new phi node even when the original indirect call does not dominate the normal destination block, because `getCallRetPHINode` returns false.

Reviewers: xur, davidxl, danielcdh

Reviewed By: xur

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D37176

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311906 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
test/Transforms/PGOProfile/icp_covariant_call_return.ll
test/Transforms/PGOProfile/icp_invoke_nouse.ll [new file with mode: 0644]

index 39a818afff228c8a8fd0852a4dce5f26d8039f4b..1cf8090b02c80414af94d5dda53ca31220d1e027 100644 (file)
@@ -508,6 +508,9 @@ static void insertCallRetPHI(Instruction *Inst, Instruction *CallResult,
   if (Inst->getType()->isVoidTy())
     return;
 
+  if (Inst->use_empty())
+    return;
+
   BasicBlock *RetValBB = CallResult->getParent();
 
   BasicBlock *PHIBB;
index 64f2025b924e219398c3acdbaece70699bbbbd74..fc5054e3a574c86876886b6df20cbcf87bc0e3a3 100644 (file)
@@ -12,7 +12,7 @@ declare noalias i8* @_Znwm(i64)
 declare void @_ZN1DC2Ev(%struct.D*);
 declare %struct.Derived* @_ZN1D4funcEv(%struct.D*);
 
-define i32 @bar() {
+define %struct.Base* @bar() {
 entry:
   %call = call noalias i8* @_Znwm(i64 8)
   %tmp = bitcast i8* %call to %struct.D*
@@ -36,7 +36,7 @@ entry:
 ; ICALL-PROM:if.end.icp:
 ; ICALL-PROM:  [[PHI_RET:%[0-9]+]] = phi %struct.Base* [ %call1, %if.false.orig_indirect ], [ [[DIRCALL_RET_CAST]], %if.true.direct_targ ]
   %call1 = call %struct.Base* %tmp3(%struct.B* %tmp1), !prof !1
-  ret i32 0
+  ret %struct.Base* %call1
 }
 
 !1 = !{!"VP", i32 0, i64 12345, i64 -3913987384944532146, i64 12345}
diff --git a/test/Transforms/PGOProfile/icp_invoke_nouse.ll b/test/Transforms/PGOProfile/icp_invoke_nouse.ll
new file mode 100644 (file)
index 0000000..5a1e635
--- /dev/null
@@ -0,0 +1,69 @@
+; RUN: opt < %s -icp-lto -pgo-icall-prom -S | FileCheck %s --check-prefix=ICP
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@_ZTISt9exception = external constant i8*
+@pfptr = global i32()* null, align 8
+
+define internal i32 @_ZL4bar1v() !PGOFuncName !0 {
+entry:
+  ret i32 100 
+}
+
+; Function Attrs: uwtable
+define i32 @_Z3fooi(i32 %x) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %tobool = icmp eq i32 %x, 0
+  br i1 %tobool, label %if.end, label %cleanup
+
+if.end:                                           ; preds = %entry
+  %fptr = load i32 ()*, i32 ()** @pfptr, align 8
+; ICP:  [[BITCAST_IC1:%[0-9]+]] = bitcast i32 ()* %fptr to i8*
+; ICP:  [[CMP_IC1:%[0-9]+]] = icmp eq i8* [[BITCAST_IC1]], bitcast (i32 ()* @_ZL4bar1v to i8*)
+; ICP:  br i1 [[CMP_IC1]], label %[[TRUE_LABEL_IC1:.*]], label %[[FALSE_LABEL_IC1:.*]], !prof [[BRANCH_WEIGHT:![0-9]+]]
+; ICP:[[TRUE_LABEL_IC1]]:
+; ICP:  invoke i32 @_ZL4bar1v()
+; ICP:          to label %[[DCALL_NORMAL_DEST_IC1:.*]] unwind label %lpad
+; ICP:[[FALSE_LABEL_IC1]]:
+  %call = invoke i32 %fptr()
+          to label %cleanup unwind label %lpad, !prof !1
+
+; ICP:[[DCALL_NORMAL_DEST_IC1]]:
+; ICP:  br label %cleanup
+
+lpad:                                             ; preds = %if.end
+  %0 = landingpad { i8*, i32 }
+          cleanup
+          catch i8* bitcast (i8** @_ZTISt9exception to i8*)
+  %1 = extractvalue { i8*, i32 } %0, 1
+  %2 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTISt9exception to i8*))
+  %matches = icmp eq i32 %1, %2
+  br i1 %matches, label %catch, label %ehcleanup
+
+catch:                                            ; preds = %lpad
+  %3 = extractvalue { i8*, i32 } %0, 0
+  %4 = tail call i8* @__cxa_begin_catch(i8* %3)
+  tail call void @__cxa_end_catch()
+  br label %cleanup
+
+cleanup:                                          ; preds = %catch, %if.end, %entry
+; ICP-NOT: %[0-9]+ = phi 
+  ret i32 0
+
+ehcleanup:                                        ; preds = %lpad
+  resume { i8*, i32 } %0
+}
+
+declare i32 @_Z3barv() local_unnamed_addr
+
+declare i32 @__gxx_personality_v0(...)
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.eh.typeid.for(i8*)
+
+declare i8* @__cxa_begin_catch(i8*) local_unnamed_addr
+
+declare void @__cxa_end_catch() local_unnamed_addr
+
+!0 = !{!"invoke.ll:_ZL4bar1v"}
+!1 = !{!"VP", i32 0, i64 10000, i64 -2732222848796217051, i64 10000}