[llvm] r273779 - Revert "[SimplifyCFG] Stop inserting calls to llvm.trap for UB"

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 25 01:19:55 PDT 2016


Author: majnemer
Date: Sat Jun 25 03:19:55 2016
New Revision: 273779

URL: http://llvm.org/viewvc/llvm-project?rev=273779&view=rev
Log:
Revert "[SimplifyCFG] Stop inserting calls to llvm.trap for UB"

This reverts commit r273778, it seems to break UBSan :/

Added:
    llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll
Modified:
    llvm/trunk/include/llvm/Transforms/Utils/Local.h
    llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
    llvm/trunk/lib/Transforms/IPO/PruneEH.cpp
    llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
    llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
    llvm/trunk/lib/Transforms/Utils/Local.cpp
    llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp
    llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll
    llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll

Modified: llvm/trunk/include/llvm/Transforms/Utils/Local.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=273779&r1=273778&r2=273779&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/Local.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/Local.h Sat Jun 25 03:19:55 2016
@@ -296,7 +296,7 @@ unsigned removeAllNonTerminatorAndEHPadI
 
 /// Insert an unreachable instruction before the specified
 /// instruction, making it and the rest of the code in the block dead.
-unsigned changeToUnreachable(Instruction *I);
+unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap);
 
 /// Replace 'BB's terminator with one that does not have an unwind successor
 /// block. Rewrites `invoke` to `call`, etc. Updates any PHIs in unwind

Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=273779&r1=273778&r2=273779&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Sat Jun 25 03:19:55 2016
@@ -963,9 +963,9 @@ void WinEHPrepare::removeImplausibleInst
           BasicBlock::iterator CallI =
               std::prev(BB->getTerminator()->getIterator());
           auto *CI = cast<CallInst>(&*CallI);
-          changeToUnreachable(CI);
+          changeToUnreachable(CI, /*UseLLVMTrap=*/false);
         } else {
-          changeToUnreachable(&I);
+          changeToUnreachable(&I, /*UseLLVMTrap=*/false);
         }
 
         // There are no more instructions in the block (except for unreachable),
@@ -986,7 +986,7 @@ void WinEHPrepare::removeImplausibleInst
         IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
       if (IsUnreachableRet || IsUnreachableCatchret ||
           IsUnreachableCleanupret) {
-        changeToUnreachable(TI);
+        changeToUnreachable(TI, /*UseLLVMTrap=*/false);
       } else if (isa<InvokeInst>(TI)) {
         if (Personality == EHPersonality::MSVC_CXX && CleanupPad) {
           // Invokes within a cleanuppad for the MSVC++ personality never

Modified: llvm/trunk/lib/Transforms/IPO/PruneEH.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PruneEH.cpp?rev=273779&r1=273778&r2=273779&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/PruneEH.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/PruneEH.cpp Sat Jun 25 03:19:55 2016
@@ -258,7 +258,7 @@ void PruneEH::DeleteBasicBlock(BasicBloc
 
   if (TokenInst) {
     if (!isa<TerminatorInst>(TokenInst))
-      changeToUnreachable(TokenInst->getNextNode());
+      changeToUnreachable(TokenInst->getNextNode(), /*UseLLVMTrap=*/false);
   } else {
     // Get the list of successors of this block.
     std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB));

Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=273779&r1=273778&r2=273779&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Sat Jun 25 03:19:55 2016
@@ -1802,7 +1802,8 @@ static bool runIPSCCP(Module &M, const D
         DEBUG(dbgs() << "  BasicBlock Dead:" << *BB);
 
         ++NumDeadBlocks;
-        NumInstRemoved += changeToUnreachable(BB->getFirstNonPHI());
+        NumInstRemoved +=
+            changeToUnreachable(BB->getFirstNonPHI(), /*UseLLVMTrap=*/false);
 
         MadeChanges = true;
 

Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=273779&r1=273778&r2=273779&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Sat Jun 25 03:19:55 2016
@@ -1833,7 +1833,7 @@ bool llvm::InlineFunction(CallSite CS, I
       // As such, we replace the cleanupret with unreachable.
       if (auto *CleanupRet = dyn_cast<CleanupReturnInst>(BB->getTerminator()))
         if (CleanupRet->unwindsToCaller() && EHPadForCallUnwindsLocally)
-          changeToUnreachable(CleanupRet);
+          changeToUnreachable(CleanupRet, /*UseLLVMTrap=*/false);
 
       Instruction *I = BB->getFirstNonPHI();
       if (!I->isEHPad())

Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=273779&r1=273778&r2=273779&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/Local.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/Local.cpp Sat Jun 25 03:19:55 2016
@@ -42,13 +42,11 @@
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Operator.h"
-#include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/ValueHandle.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
-using namespace llvm::PatternMatch;
 
 #define DEBUG_TYPE "local"
 
@@ -1312,13 +1310,21 @@ unsigned llvm::removeAllNonTerminatorAnd
   return NumDeadInst;
 }
 
-unsigned llvm::changeToUnreachable(Instruction *I) {
+unsigned llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap) {
   BasicBlock *BB = I->getParent();
   // Loop over all of the successors, removing BB's entry from any PHI
   // nodes.
-  for (BasicBlock *Succ : successors(BB))
-    Succ->removePredecessor(BB);
+  for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
+    (*SI)->removePredecessor(BB);
 
+  // Insert a call to llvm.trap right before this.  This turns the undefined
+  // behavior into a hard fail instead of falling through into random code.
+  if (UseLLVMTrap) {
+    Function *TrapFn =
+      Intrinsic::getDeclaration(BB->getParent()->getParent(), Intrinsic::trap);
+    CallInst *CallTrap = CallInst::Create(TrapFn, "", I);
+    CallTrap->setDebugLoc(I->getDebugLoc());
+  }
   new UnreachableInst(I->getContext(), I);
 
   // All instructions after this are dead.
@@ -1368,14 +1374,22 @@ static bool markAliveBlocks(Function &F,
     // Do a quick scan of the basic block, turning any obviously unreachable
     // instructions into LLVM unreachable insts.  The instruction combining pass
     // canonicalizes unreachable insts into stores to null or undef.
-    for (Instruction &I : *BB) {
+    for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;++BBI){
       // Assumptions that are known to be false are equivalent to unreachable.
       // Also, if the condition is undefined, then we make the choice most
       // beneficial to the optimizer, and choose that to also be unreachable.
-      if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) {
+      if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(BBI)) {
         if (II->getIntrinsicID() == Intrinsic::assume) {
-          if (match(II->getArgOperand(0), m_CombineOr(m_Zero(), m_Undef()))) {
-            changeToUnreachable(II);
+          bool MakeUnreachable = false;
+          if (isa<UndefValue>(II->getArgOperand(0)))
+            MakeUnreachable = true;
+          else if (ConstantInt *Cond =
+                   dyn_cast<ConstantInt>(II->getArgOperand(0)))
+            MakeUnreachable = Cond->isZero();
+
+          if (MakeUnreachable) {
+            // Don't insert a call to llvm.trap right before the unreachable.
+            changeToUnreachable(&*BBI, false);
             Changed = true;
             break;
           }
@@ -1390,19 +1404,19 @@ static bool markAliveBlocks(Function &F,
           // Note: unlike in llvm.assume, it is not "obviously profitable" for
           // guards to treat `undef` as `false` since a guard on `undef` can
           // still be useful for widening.
-          if (match(II->getArgOperand(0), m_Zero()))
-            if (!isa<UnreachableInst>(II->getNextNode())) {
-              changeToUnreachable(II->getNextNode());
+          if (auto *CI = dyn_cast<ConstantInt>(II->getArgOperand(0)))
+            if (CI->isZero() && !isa<UnreachableInst>(II->getNextNode())) {
+              changeToUnreachable(II->getNextNode(), /*UseLLVMTrap=*/ false);
               Changed = true;
               break;
             }
         }
       }
 
-      if (auto *CI = dyn_cast<CallInst>(&I)) {
+      if (CallInst *CI = dyn_cast<CallInst>(BBI)) {
         Value *Callee = CI->getCalledValue();
         if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
-          changeToUnreachable(CI);
+          changeToUnreachable(CI, /*UseLLVMTrap=*/false);
           Changed = true;
           break;
         }
@@ -1410,8 +1424,10 @@ static bool markAliveBlocks(Function &F,
           // If we found a call to a no-return function, insert an unreachable
           // instruction after it.  Make sure there isn't *already* one there
           // though.
-          if (!isa<UnreachableInst>(CI->getNextNode())) {
-            changeToUnreachable(CI->getNextNode());
+          ++BBI;
+          if (!isa<UnreachableInst>(BBI)) {
+            // Don't insert a call to llvm.trap right before the unreachable.
+            changeToUnreachable(&*BBI, false);
             Changed = true;
           }
           break;
@@ -1421,7 +1437,7 @@ static bool markAliveBlocks(Function &F,
       // Store to undef and store to null are undefined and used to signal that
       // they should be changed to unreachable by passes that can't modify the
       // CFG.
-      if (auto *SI = dyn_cast<StoreInst>(&I)) {
+      if (StoreInst *SI = dyn_cast<StoreInst>(BBI)) {
         // Don't touch volatile stores.
         if (SI->isVolatile()) continue;
 
@@ -1430,7 +1446,7 @@ static bool markAliveBlocks(Function &F,
         if (isa<UndefValue>(Ptr) ||
             (isa<ConstantPointerNull>(Ptr) &&
              SI->getPointerAddressSpace() == 0)) {
-          changeToUnreachable(SI);
+          changeToUnreachable(SI, true);
           Changed = true;
           break;
         }
@@ -1442,7 +1458,7 @@ static bool markAliveBlocks(Function &F,
       // Turn invokes that call 'nounwind' functions into ordinary calls.
       Value *Callee = II->getCalledValue();
       if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
-        changeToUnreachable(II);
+        changeToUnreachable(II, true);
         Changed = true;
       } else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) {
         if (II->use_empty() && II->onlyReadsMemory()) {
@@ -1495,9 +1511,9 @@ static bool markAliveBlocks(Function &F,
     }
 
     Changed |= ConstantFoldTerminator(BB, true);
-    for (BasicBlock *Succ : successors(BB))
-      if (Reachable.insert(Succ).second)
-        Worklist.push_back(Succ);
+    for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
+      if (Reachable.insert(*SI).second)
+        Worklist.push_back(*SI);
   } while (!Worklist.empty());
   return Changed;
 }

Modified: llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp?rev=273779&r1=273778&r2=273779&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp Sat Jun 25 03:19:55 2016
@@ -491,7 +491,7 @@ ReprocessLoop:
 
       // Zap the dead pred's terminator and replace it with unreachable.
       TerminatorInst *TI = P->getTerminator();
-      changeToUnreachable(TI);
+      changeToUnreachable(TI, /*UseLLVMTrap=*/false);
       Changed = true;
     }
   }

Modified: llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll?rev=273779&r1=273778&r2=273779&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll (original)
+++ llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll Sat Jun 25 03:19:55 2016
@@ -12,6 +12,7 @@ declare i32 @fn()
 ; CHECK-LABEL: @f1(
 define i8* @f1() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
 entry:
+; CHECK: call void @llvm.trap()
 ; CHECK: unreachable
   %call = invoke noalias i8* undef()
           to label %invoke.cont unwind label %lpad
@@ -30,6 +31,7 @@ lpad:
 ; CHECK-LABEL: @f2(
 define i8* @f2() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
 entry:
+; CHECK: call void @llvm.trap()
 ; CHECK: unreachable
   %call = invoke noalias i8* null()
           to label %invoke.cont unwind label %lpad

Added: llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll?rev=273779&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll Sat Jun 25 03:19:55 2016
@@ -0,0 +1,22 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+; Radar 9342286
+; Assign DebugLoc to trap instruction.
+define void @foo() nounwind ssp !dbg !0 {
+; CHECK: call void @llvm.trap(), !dbg
+  store i32 42, i32* null, !dbg !5
+  ret void, !dbg !7
+}
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!10}
+
+!0 = distinct !DISubprogram(name: "foo", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !2, file: !8, scope: !1, type: !3)
+!1 = !DIFile(filename: "foo.c", directory: "/private/tmp")
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "Apple clang version 3.0 (tags/Apple/clang-206.1) (based on LLVM 3.0svn)", isOptimized: true, emissionKind: FullDebug, file: !8, enums: !{}, retainedTypes: !{})
+!3 = !DISubroutineType(types: !4)
+!4 = !{null}
+!5 = !DILocation(line: 4, column: 2, scope: !6)
+!6 = distinct !DILexicalBlock(line: 3, column: 12, file: !8, scope: !0)
+!7 = !DILocation(line: 5, column: 1, scope: !6)
+!8 = !DIFile(filename: "foo.c", directory: "/private/tmp")
+!10 = !{i32 1, !"Debug Info Version", i32 3}

Modified: llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll?rev=273779&r1=273778&r2=273779&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll (original)
+++ llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll Sat Jun 25 03:19:55 2016
@@ -28,6 +28,7 @@ entry:
         ret void
         
 ; CHECK-LABEL: @test2(
+; CHECK: call void @llvm.trap
 ; CHECK: unreachable
 }
 




More information about the llvm-commits mailing list