diff options
| -rw-r--r-- | llvm/lib/Transforms/Utils/LowerSwitch.cpp | 14 | ||||
| -rw-r--r-- | llvm/test/Transforms/Util/lowerswitch.ll | 48 | 
2 files changed, 59 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/Utils/LowerSwitch.cpp b/llvm/lib/Transforms/Utils/LowerSwitch.cpp index 76ad35832dc..e99ecfef19c 100644 --- a/llvm/lib/Transforms/Utils/LowerSwitch.cpp +++ b/llvm/lib/Transforms/Utils/LowerSwitch.cpp @@ -74,7 +74,7 @@ namespace {      LowerSwitch() : FunctionPass(ID) {        initializeLowerSwitchPass(*PassRegistry::getPassRegistry()); -    }  +    }      bool runOnFunction(Function &F) override; @@ -327,7 +327,7 @@ BasicBlock* LowerSwitch::newLeafBlock(CaseRange& Leaf, Value* Val,      } else if (Leaf.Low->isZero()) {        // Val >= 0 && Val <= Hi --> Val <=u Hi        Comp = new ICmpInst(*NewLeaf, ICmpInst::ICMP_ULE, Val, Leaf.High, -                          "SwitchLeaf");       +                          "SwitchLeaf");      } else {        // Emit V-Lo <=u Hi-Lo        Constant* NegLo = ConstantExpr::getNeg(Leaf.Low); @@ -354,7 +354,7 @@ BasicBlock* LowerSwitch::newLeafBlock(CaseRange& Leaf, Value* Val,      for (uint64_t j = 0; j < Range; ++j) {        PN->removeIncomingValue(OrigBlock);      } -     +      int BlockIdx = PN->getBasicBlockIndex(OrigBlock);      assert(BlockIdx != -1 && "Switch didn't go to this successor??");      PN->setIncomingBlock((unsigned)BlockIdx, NewLeaf); @@ -495,6 +495,10 @@ void LowerSwitch::processSwitchInst(SwitchInst *SI,      }  #endif +    // As the default block in the switch is unreachable, update the PHI nodes +    // (remove the entry to the default block) to reflect this. +    Default->removePredecessor(OrigBlock); +      // Use the most popular block as the new default, reducing the number of      // cases.      assert(MaxPop > 0 && PopSucc); @@ -508,6 +512,10 @@ void LowerSwitch::processSwitchInst(SwitchInst *SI,      if (Cases.empty()) {        BranchInst::Create(Default, CurBlock);        SI->eraseFromParent(); +      // As all the cases have been replaced with a single branch, only keep +      // one entry in the PHI nodes. +      for (unsigned I = 0 ; I < (MaxPop - 1) ; ++I) +        PopSucc->removePredecessor(OrigBlock);        return;      }    } diff --git a/llvm/test/Transforms/Util/lowerswitch.ll b/llvm/test/Transforms/Util/lowerswitch.ll index 70e1e239b3d..5f5134e71a2 100644 --- a/llvm/test/Transforms/Util/lowerswitch.ll +++ b/llvm/test/Transforms/Util/lowerswitch.ll @@ -242,3 +242,51 @@ cleanup:                                          ; preds = %for.body7, %if.then  unreachable:                                      ; preds = %cleanup    unreachable  } + +; Test that the PHI node in cleanup17 is removed as the switch default block is +; not reachable. +define void @test4() { +; CHECK-LABEL: @test4 +entry: +  switch i32 undef, label %cleanup17 [ +    i32 0, label %return +    i32 9, label %return +  ] + +cleanup17: +; CHECK: cleanup17: +; CHECK-NOT: phi i16 [ undef, %entry ] +; CHECK: return: + +  %retval.4 = phi i16 [ undef, %entry ] +  unreachable + +return: +  ret void +} + +; Test that the PHI node in for.inc is updated correctly as the switch is +; replaced with a single branch to for.inc +define void @test5() { +; CHECK-LABEL: @test5 +entry: +  br i1 undef, label %cleanup10, label %cleanup10.thread + +cleanup10.thread: +  br label %for.inc + +cleanup10: +  switch i32 undef, label %unreachable [ +    i32 0, label %for.inc +    i32 4, label %for.inc +  ] + +for.inc: +; CHECK: for.inc: +; CHECK-NEXT: phi i16 [ 0, %cleanup10.thread ], [ undef, %cleanup10 ] +%0 = phi i16 [ undef, %cleanup10 ], [ 0, %cleanup10.thread ], [ undef, %cleanup10 ] +  unreachable + +unreachable: +  unreachable +}  | 

