improve optimization of invoke instructions:
authorNuno Lopes <nunoplopes@sapo.pt>
Mon, 25 Jun 2012 17:11:47 +0000 (17:11 +0000)
committerNuno Lopes <nunoplopes@sapo.pt>
Mon, 25 Jun 2012 17:11:47 +0000 (17:11 +0000)
 - simplifycfg:  invoke undef/null -> unreachable
 - instcombine:  invoke new  -> invoke expect(0, 0)  (an arbitrary NOOP intrinsic;  only done if the allocated memory is unused, of course)
 - verifier:  allow invoke of intrinsics  (to make the previous step work)

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

lib/Transforms/InstCombine/InstructionCombining.cpp
lib/Transforms/Scalar/SimplifyCFGPass.cpp
lib/VMCore/Verifier.cpp
test/Transforms/InstCombine/objsize-64.ll
test/Transforms/SimplifyCFG/invoke.ll [new file with mode: 0644]

index 269ea1516ff089770bebb2db2f8000535209a66c..07793ac6b5f051dd4fafcb9042b3f98b8ae29c2b 100644 (file)
@@ -1169,7 +1169,14 @@ Instruction *InstCombiner::visitMalloc(Instruction &MI) {
     }
 
     if (InvokeInst *II = dyn_cast<InvokeInst>(&MI)) {
-      BranchInst::Create(II->getNormalDest(), II->getParent());
+      // Replace invoke with a NOOP intrinsic to maintain the original CFG
+      Module *M = II->getParent()->getParent()->getParent();
+      IntegerType *Ty = IntegerType::get(II->getContext(), 8);
+      ConstantInt *CI = ConstantInt::get(Ty, 0);
+      Value *Args[] = {CI, CI};
+      Function *F = Intrinsic::getDeclaration(M, Intrinsic::expect, Ty);
+      InvokeInst::Create(F, II->getNormalDest(), II->getUnwindDest(), Args,
+                         "dummy", II->getParent());
     }
     return EraseInstFromFunction(MI);
   }
index a66b3e38258fd0dcac6220abfae681a5b301deb7..594369780ac396d83c44df9496e02b232160adc1 100644 (file)
@@ -157,11 +157,16 @@ static bool MarkAliveBlocks(BasicBlock *BB,
     }
 
     // Turn invokes that call 'nounwind' functions into ordinary calls.
-    if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
-      if (II->doesNotThrow()) {
+    if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
+      Value *Callee = II->getCalledValue();
+      if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
+        ChangeToUnreachable(II, true);
+        Changed = true;
+      } else if (II->doesNotThrow()) {
         ChangeToCall(II);
         Changed = true;
       }
+    }
 
     Changed |= ConstantFoldTerminator(BB, true);
     for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
index 477b81dc67f5e002216caa39f2a28229c885833e..9a9b0b7e0b3d6c61eb5909d2e6f32538b521d6ba 100644 (file)
@@ -1636,7 +1636,8 @@ void Verifier::visitInstruction(Instruction &I) {
     if (Function *F = dyn_cast<Function>(I.getOperand(i))) {
       // Check to make sure that the "address of" an intrinsic function is never
       // taken.
-      Assert1(!F->isIntrinsic() || (i + 1 == e && isa<CallInst>(I)),
+      CallSite CS(&I);
+      Assert1(!F->isIntrinsic() || (CS && i == (CS.isCall() ? e-1 : 2)),
               "Cannot take the address of an intrinsic!", &I);
       Assert1(F->getParent() == Mod, "Referencing function in another module!",
               &I);
index 77b43ecd235c3c8201eaf394446945c3e4e1968f..7a39f461948f246cd05f0708ecabcb4be83f353a 100644 (file)
@@ -19,7 +19,7 @@ define i64 @f1() {
 ; CHECK: @f2
 define i64 @f2() nounwind uwtable ssp {
 entry:
-; CHECK: br label
+; CHECK: invoke i8 @llvm.expect.i8(i8 0, i8 0)
   %call = invoke noalias i8* @_Znwm(i64 13)
           to label %invoke.cont unwind label %lpad
 
diff --git a/test/Transforms/SimplifyCFG/invoke.ll b/test/Transforms/SimplifyCFG/invoke.ll
new file mode 100644 (file)
index 0000000..c9169d4
--- /dev/null
@@ -0,0 +1,45 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
+declare i32 @__gxx_personality_v0(...)
+declare void @__cxa_call_unexpected(i8*)
+declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readonly
+
+
+; CHECK: @f1
+define i8* @f1() nounwind uwtable ssp {
+entry:
+; CHECK: call void @llvm.trap()
+; CHECK: unreachable
+  %call = invoke noalias i8* undef()
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+  ret i8* %call
+
+lpad:
+  %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+          filter [0 x i8*] zeroinitializer
+  %1 = extractvalue { i8*, i32 } %0, 0
+  tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
+  unreachable
+}
+
+; CHECK: @f2
+define i8* @f2() nounwind uwtable ssp {
+entry:
+; CHECK: call void @llvm.trap()
+; CHECK: unreachable
+  %call = invoke noalias i8* null()
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+  ret i8* %call
+
+lpad:
+  %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+          filter [0 x i8*] zeroinitializer
+  %1 = extractvalue { i8*, i32 } %0, 0
+  tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
+  unreachable
+}