#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"
return NumDeadInst;
}
-unsigned llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap) {
+unsigned llvm::changeToUnreachable(Instruction *I) {
BasicBlock *BB = I->getParent();
// Loop over all of the successors, removing BB's entry from any PHI
// nodes.
- 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());
- }
+ for (BasicBlock *Succ : successors(BB))
+ Succ->removePredecessor(BB);
+
new UnreachableInst(I->getContext(), I);
// All instructions after this are dead.
// 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 (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;++BBI){
+ for (Instruction &I : *BB) {
// 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>(BBI)) {
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) {
if (II->getIntrinsicID() == Intrinsic::assume) {
- 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);
+ if (match(II->getArgOperand(0), m_CombineOr(m_Zero(), m_Undef()))) {
+ changeToUnreachable(II);
Changed = true;
break;
}
// 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 (auto *CI = dyn_cast<ConstantInt>(II->getArgOperand(0)))
- if (CI->isZero() && !isa<UnreachableInst>(II->getNextNode())) {
- changeToUnreachable(II->getNextNode(), /*UseLLVMTrap=*/ false);
+ if (match(II->getArgOperand(0), m_Zero()))
+ if (!isa<UnreachableInst>(II->getNextNode())) {
+ changeToUnreachable(II->getNextNode());
Changed = true;
break;
}
}
}
- if (CallInst *CI = dyn_cast<CallInst>(BBI)) {
+ if (auto *CI = dyn_cast<CallInst>(&I)) {
Value *Callee = CI->getCalledValue();
if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
- changeToUnreachable(CI, /*UseLLVMTrap=*/false);
+ changeToUnreachable(CI);
Changed = true;
break;
}
// 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.
- ++BBI;
- if (!isa<UnreachableInst>(BBI)) {
- // Don't insert a call to llvm.trap right before the unreachable.
- changeToUnreachable(&*BBI, false);
+ if (!isa<UnreachableInst>(CI->getNextNode())) {
+ changeToUnreachable(CI->getNextNode());
Changed = true;
}
break;
// 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 (StoreInst *SI = dyn_cast<StoreInst>(BBI)) {
+ if (auto *SI = dyn_cast<StoreInst>(&I)) {
// Don't touch volatile stores.
if (SI->isVolatile()) continue;
if (isa<UndefValue>(Ptr) ||
(isa<ConstantPointerNull>(Ptr) &&
SI->getPointerAddressSpace() == 0)) {
- changeToUnreachable(SI, true);
+ changeToUnreachable(SI);
Changed = true;
break;
}
// Turn invokes that call 'nounwind' functions into ordinary calls.
Value *Callee = II->getCalledValue();
if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
- changeToUnreachable(II, true);
+ changeToUnreachable(II);
Changed = true;
} else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) {
if (II->use_empty() && II->onlyReadsMemory()) {
}
Changed |= ConstantFoldTerminator(BB, true);
- for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
- if (Reachable.insert(*SI).second)
- Worklist.push_back(*SI);
+ for (BasicBlock *Succ : successors(BB))
+ if (Reachable.insert(Succ).second)
+ Worklist.push_back(Succ);
} while (!Worklist.empty());
return Changed;
}
+++ /dev/null
-; 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}