[llvm-commits] [dragonegg] r164882 - in /dragonegg/trunk: src/Convert.cpp test/validator/c/NoReturn.c

Duncan Sands baldrick at free.fr
Fri Sep 28 21:24:00 PDT 2012


Author: baldrick
Date: Fri Sep 28 23:23:59 2012
New Revision: 164882

URL: http://llvm.org/viewvc/llvm-project?rev=164882&view=rev
Log:
Don't bother outputting unreachable return blocks.

Added:
    dragonegg/trunk/test/validator/c/NoReturn.c
Modified:
    dragonegg/trunk/src/Convert.cpp

Modified: dragonegg/trunk/src/Convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=164882&r1=164881&r2=164882&view=diff
==============================================================================
--- dragonegg/trunk/src/Convert.cpp (original)
+++ dragonegg/trunk/src/Convert.cpp Fri Sep 28 23:23:59 2012
@@ -1165,9 +1165,6 @@
   // rather than in the order we come across them. This is only done to make the
   // IR more readable and is not needed for correctness.
   EmitVariablesInScope(DECL_INITIAL(FnDecl));
-
-  // Create a new block for the return node, but don't insert it yet.
-  ReturnBB = BasicBlock::Create(Context, "return");
 }
 
 /// EmitVariablesInScope - Output a declaration for every variable in the
@@ -1317,88 +1314,99 @@
 }
 
 Function *TreeToLLVM::FinishFunctionBody() {
-  // Insert the return block at the end of the function.
-  BeginBlock(ReturnBB);
-
-  SmallVector <Value *, 4> RetVals;
-
-  // If the function returns a value, get it into a register and return it now.
-  if (!Fn->getReturnType()->isVoidTy()) {
-    tree TreeRetVal = DECL_RESULT(FnDecl);
-    LValue ResultLV = EmitLV(TreeRetVal);
-    assert(!ResultLV.isBitfield() && "Bitfields not allowed here!");
-
-    if (!isa<AGGREGATE_TYPE>(TREE_TYPE(TreeRetVal)) &&
-        !isa<COMPLEX_TYPE>(TREE_TYPE(TreeRetVal))) {
-      // If the DECL_RESULT is a scalar type, just load out the return value
-      // and return it.
-      LoadInst *Load = Builder.CreateAlignedLoad(ResultLV.Ptr,
-                                                 ResultLV.getAlignment());
-      RetVals.push_back(Builder.CreateBitCast(Load, Fn->getReturnType()));
-    } else {
-      uint64_t ResultSize =
-        getTargetData().getTypeAllocSize(ConvertType(TREE_TYPE(TreeRetVal)));
-      uint64_t ReturnSize =
-        getTargetData().getTypeAllocSize(Fn->getReturnType());
-
-      // The load does not necessarily start at the beginning of the aggregate
-      // (x86-64).
-      if (ReturnOffset >= ResultSize) {
-        // Also catches the case of an empty return value.
-        RetVals.push_back(UndefValue::get(Fn->getReturnType()));
+  if (ReturnBB) {
+    // Insert the return block at the end of the function.
+    BeginBlock(ReturnBB);
+
+    SmallVector <Value *, 4> RetVals;
+
+    // If the function returns a value, get it into a register and return it now.
+    if (!Fn->getReturnType()->isVoidTy()) {
+      tree TreeRetVal = DECL_RESULT(FnDecl);
+      LValue ResultLV = EmitLV(TreeRetVal);
+      assert(!ResultLV.isBitfield() && "Bitfields not allowed here!");
+
+      if (!isa<AGGREGATE_TYPE>(TREE_TYPE(TreeRetVal)) &&
+          !isa<COMPLEX_TYPE>(TREE_TYPE(TreeRetVal))) {
+        // If the DECL_RESULT is a scalar type, just load out the return value
+        // and return it.
+        LoadInst *Load = Builder.CreateAlignedLoad(ResultLV.Ptr,
+                                                   ResultLV.getAlignment());
+        RetVals.push_back(Builder.CreateBitCast(Load, Fn->getReturnType()));
       } else {
-        // Advance to the point we want to load from.
-        if (ReturnOffset) {
-          ResultLV.Ptr =
-            Builder.CreateBitCast(ResultLV.Ptr, Type::getInt8PtrTy(Context));
-          ResultLV.Ptr =
-            Builder.CreateGEP(ResultLV.Ptr,
-                              ConstantInt::get(TD.getIntPtrType(Context),
-                                               ReturnOffset));
-          ResultLV.setAlignment(MinAlign(ResultLV.getAlignment(), ReturnOffset));
-          ResultSize -= ReturnOffset;
-        }
+        uint64_t ResultSize =
+          getTargetData().getTypeAllocSize(ConvertType(TREE_TYPE(TreeRetVal)));
+        uint64_t ReturnSize =
+          getTargetData().getTypeAllocSize(Fn->getReturnType());
+
+        // The load does not necessarily start at the beginning of the aggregate
+        // (x86-64).
+        if (ReturnOffset >= ResultSize) {
+          // Also catches the case of an empty return value.
+          RetVals.push_back(UndefValue::get(Fn->getReturnType()));
+        } else {
+          // Advance to the point we want to load from.
+          if (ReturnOffset) {
+            ResultLV.Ptr =
+              Builder.CreateBitCast(ResultLV.Ptr, Type::getInt8PtrTy(Context));
+            ResultLV.Ptr =
+              Builder.CreateGEP(ResultLV.Ptr,
+                                ConstantInt::get(TD.getIntPtrType(Context),
+                                                 ReturnOffset));
+            ResultLV.setAlignment(MinAlign(ResultLV.getAlignment(), ReturnOffset));
+            ResultSize -= ReturnOffset;
+          }
 
-        // A place to build up the function return value.
-        MemRef ReturnLoc = CreateTempLoc(Fn->getReturnType());
+          // A place to build up the function return value.
+          MemRef ReturnLoc = CreateTempLoc(Fn->getReturnType());
 
-        // Copy out DECL_RESULT while being careful to not overrun the source or
-        // destination buffers.
-        uint64_t OctetsToCopy = std::min(ResultSize, ReturnSize);
-        EmitMemCpy(ReturnLoc.Ptr, ResultLV.Ptr, Builder.getInt64(OctetsToCopy),
-                   std::min(ReturnLoc.getAlignment(), ResultLV.getAlignment()));
-
-        if (StructType *STy = dyn_cast<StructType>(Fn->getReturnType())) {
-          llvm::Value *Idxs[2];
-          Idxs[0] = Builder.getInt32(0);
-          for (unsigned ri = 0; ri < STy->getNumElements(); ++ri) {
-            Idxs[1] = Builder.getInt32(ri);
-            Value *GEP = Builder.CreateGEP(ReturnLoc.Ptr, Idxs, "mrv_gep");
-            Value *E = Builder.CreateLoad(GEP, "mrv");
-            RetVals.push_back(E);
+          // Copy out DECL_RESULT while being careful to not overrun the source or
+          // destination buffers.
+          uint64_t OctetsToCopy = std::min(ResultSize, ReturnSize);
+          EmitMemCpy(ReturnLoc.Ptr, ResultLV.Ptr, Builder.getInt64(OctetsToCopy),
+                     std::min(ReturnLoc.getAlignment(), ResultLV.getAlignment()));
+
+          if (StructType *STy = dyn_cast<StructType>(Fn->getReturnType())) {
+            llvm::Value *Idxs[2];
+            Idxs[0] = Builder.getInt32(0);
+            for (unsigned ri = 0; ri < STy->getNumElements(); ++ri) {
+              Idxs[1] = Builder.getInt32(ri);
+              Value *GEP = Builder.CreateGEP(ReturnLoc.Ptr, Idxs, "mrv_gep");
+              Value *E = Builder.CreateLoad(GEP, "mrv");
+              RetVals.push_back(E);
+            }
+            // If the return type specifies an empty struct then return one.
+            if (RetVals.empty())
+              RetVals.push_back(UndefValue::get(Fn->getReturnType()));
+          } else {
+            // Otherwise, this aggregate result must be something that is returned
+            // in a scalar register for this target.  We must bit convert the
+            // aggregate to the specified scalar type, which we do by casting the
+            // pointer and loading.
+            RetVals.push_back(Builder.CreateLoad(ReturnLoc.Ptr, "retval"));
           }
-          // If the return type specifies an empty struct then return one.
-          if (RetVals.empty())
-            RetVals.push_back(UndefValue::get(Fn->getReturnType()));
-        } else {
-          // Otherwise, this aggregate result must be something that is returned
-          // in a scalar register for this target.  We must bit convert the
-          // aggregate to the specified scalar type, which we do by casting the
-          // pointer and loading.
-          RetVals.push_back(Builder.CreateLoad(ReturnLoc.Ptr, "retval"));
         }
       }
     }
-  }
-  if (RetVals.empty())
-    Builder.CreateRetVoid();
-  else if (RetVals.size() == 1 && RetVals[0]->getType() == Fn->getReturnType()){
-    Builder.CreateRet(RetVals[0]);
-  } else {
-    assert(Fn->getReturnType()->isAggregateType() && "Return type mismatch!");
-    Builder.CreateAggregateRet(RetVals.data(), (unsigned)RetVals.size());
+    if (RetVals.empty())
+      Builder.CreateRetVoid();
+    else if (RetVals.size() == 1 && RetVals[0]->getType() == Fn->getReturnType()){
+      Builder.CreateRet(RetVals[0]);
+    } else {
+      assert(Fn->getReturnType()->isAggregateType() && "Return type mismatch!");
+      Builder.CreateAggregateRet(RetVals.data(), (unsigned)RetVals.size());
+    }
+  } else { // !ReturnBB
+    BasicBlock *CurBB = Builder.GetInsertBlock();
+    // If the previous block has no terminator then it must be empty, remove it.
+    if (CurBB->getTerminator() == 0) {
+      assert(CurBB->getName().empty() && CurBB->begin() == CurBB->end() &&
+             "Falling through to a block that doesn't exist!");
+      CurBB->eraseFromParent();
+    }
   }
 
+
   // Populate phi nodes with their operands now that all ssa names have been
   // defined and all basic blocks output.
   PopulatePhiNodes();
@@ -1407,14 +1415,16 @@
   EmitLandingPads();
   EmitFailureBlocks();
 
-  if (EmitDebugInfo()) {
+  if (ReturnBB) {
     // FIXME: This should be output just before the return call generated above.
     // But because EmitFunctionEnd pops the region stack, that means that if the
     // call to PopulatePhiNodes (for example) generates complicated debug info,
     // then the debug info logic barfs.  Testcases showing this are 20011126-2.c
     // or pr42221.c from the gcc testsuite compiled with -g -O3.
-    TheDebugInfo->EmitStopPoint(ReturnBB, Builder);
-    TheDebugInfo->EmitFunctionEnd(true);
+    if (EmitDebugInfo()) {
+      TheDebugInfo->EmitStopPoint(ReturnBB, Builder);
+      TheDebugInfo->EmitFunctionEnd(true);
+    }
   }
 
 #ifdef NDEBUG
@@ -8561,6 +8571,10 @@
   }
 
   // Emit a branch to the exit label.
+  if (!ReturnBB)
+    // Create a new block for the return node, but don't insert it yet.
+    ReturnBB = BasicBlock::Create(Context, "return");
+
   Builder.CreateBr(ReturnBB);
 }
 

Added: dragonegg/trunk/test/validator/c/NoReturn.c
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/test/validator/c/NoReturn.c?rev=164882&view=auto
==============================================================================
--- dragonegg/trunk/test/validator/c/NoReturn.c (added)
+++ dragonegg/trunk/test/validator/c/NoReturn.c Fri Sep 28 23:23:59 2012
@@ -0,0 +1,6 @@
+// RUN: %dragonegg -S %s -o - | FileCheck %s
+
+void foo() {
+  exit(1);
+// CHECK-NOT: ret void
+}





More information about the llvm-commits mailing list