From 43a5aa62d467eecb5ab44d3d6aad9cb33da714c5 Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Sat, 23 May 2015 12:18:10 +0000 Subject: [PATCH] [PowerPC] Fix fast-isel when compare is split from branch When the compare feeding a branch was in a different BB from the branch, we'd try to "regenerate" the compare in the block with the branch, possibly trying to make use of values not available there. Copy a page from AArch64's play book here to fix the problem (at least in terms of correctness). Fixes PR23640. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238097 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCFastISel.cpp | 51 ++++++++------ test/CodeGen/PowerPC/fast-isel-icmp-split.ll | 72 ++++++++++++++++++++ 2 files changed, 104 insertions(+), 19 deletions(-) create mode 100644 test/CodeGen/PowerPC/fast-isel-icmp-split.ll diff --git a/lib/Target/PowerPC/PPCFastISel.cpp b/lib/Target/PowerPC/PPCFastISel.cpp index 002616babd4..0b8e23c4ebf 100644 --- a/lib/Target/PowerPC/PPCFastISel.cpp +++ b/lib/Target/PowerPC/PPCFastISel.cpp @@ -144,6 +144,7 @@ class PPCFastISel final : public FastISel { private: bool isTypeLegal(Type *Ty, MVT &VT); bool isLoadTypeLegal(Type *Ty, MVT &VT); + bool isValueAvailable(const Value *V) const; bool isVSFRCRegister(unsigned Register) const { return MRI.getRegClass(Register)->getID() == PPC::VSFRCRegClassID; } @@ -283,6 +284,17 @@ bool PPCFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) { return false; } +bool PPCFastISel::isValueAvailable(const Value *V) const { + if (!isa(V)) + return true; + + const auto *I = cast(V); + if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) + return true; + + return false; +} + // Given a value Obj, create an Address object Addr that represents its // address. Return false if we can't handle it. bool PPCFastISel::PPCComputeAddress(const Value *Obj, Address &Addr) { @@ -731,30 +743,31 @@ bool PPCFastISel::SelectBranch(const Instruction *I) { // For now, just try the simplest case where it's fed by a compare. if (const CmpInst *CI = dyn_cast(BI->getCondition())) { - Optional OptPPCPred = getComparePred(CI->getPredicate()); - if (!OptPPCPred) - return false; - - PPC::Predicate PPCPred = OptPPCPred.getValue(); + if (isValueAvailable(CI)) { + Optional OptPPCPred = getComparePred(CI->getPredicate()); + if (!OptPPCPred) + return false; - // Take advantage of fall-through opportunities. - if (FuncInfo.MBB->isLayoutSuccessor(TBB)) { - std::swap(TBB, FBB); - PPCPred = PPC::InvertPredicate(PPCPred); - } + PPC::Predicate PPCPred = OptPPCPred.getValue(); - unsigned CondReg = createResultReg(&PPC::CRRCRegClass); + // Take advantage of fall-through opportunities. + if (FuncInfo.MBB->isLayoutSuccessor(TBB)) { + std::swap(TBB, FBB); + PPCPred = PPC::InvertPredicate(PPCPred); + } - if (!PPCEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned(), - CondReg)) - return false; + unsigned CondReg = createResultReg(&PPC::CRRCRegClass); - BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::BCC)) - .addImm(PPCPred).addReg(CondReg).addMBB(TBB); - fastEmitBranch(FBB, DbgLoc); - FuncInfo.MBB->addSuccessor(TBB); - return true; + if (!PPCEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned(), + CondReg)) + return false; + BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::BCC)) + .addImm(PPCPred).addReg(CondReg).addMBB(TBB); + fastEmitBranch(FBB, DbgLoc); + FuncInfo.MBB->addSuccessor(TBB); + return true; + } } else if (const ConstantInt *CI = dyn_cast(BI->getCondition())) { uint64_t Imm = CI->getZExtValue(); diff --git a/test/CodeGen/PowerPC/fast-isel-icmp-split.ll b/test/CodeGen/PowerPC/fast-isel-icmp-split.ll new file mode 100644 index 00000000000..459616eb969 --- /dev/null +++ b/test/CodeGen/PowerPC/fast-isel-icmp-split.ll @@ -0,0 +1,72 @@ +; RUN: llc -O0 -relocation-model=pic < %s | FileCheck %s +target datalayout = "E-m:e-i64:64-n32:64" +target triple = "powerpc64-bgq-linux" + +%"class.std::__1::__tree_node.130.151" = type { %"class.std::__1::__tree_node_base.base.128.149", %"class.boost::serialization::extended_type_info.129.150"* } +%"class.std::__1::__tree_node_base.base.128.149" = type <{ %"class.std::__1::__tree_end_node.127.148", %"class.std::__1::__tree_node_base.126.147"*, %"class.std::__1::__tree_node_base.126.147"*, i8 }> +%"class.std::__1::__tree_end_node.127.148" = type { %"class.std::__1::__tree_node_base.126.147"* } +%"class.std::__1::__tree_node_base.126.147" = type <{ %"class.std::__1::__tree_end_node.127.148", %"class.std::__1::__tree_node_base.126.147"*, %"class.std::__1::__tree_node_base.126.147"*, i8, [7 x i8] }> +%"class.boost::serialization::extended_type_info.129.150" = type { i32 (...)**, i32, i8* } + +; Function Attrs: noinline +define void @_ZN5boost13serialization18extended_type_info4findEPKc() #0 align 2 { +entry: + br i1 undef, label %cond.true, label %cond.false + +; CHECK: @_ZN5boost13serialization18extended_type_info4findEPKc + +cond.true: ; preds = %entry + br label %cond.end + +cond.false: ; preds = %entry + unreachable + ; No predecessors! + br label %cond.end + +cond.end: ; preds = %0, %cond.true + invoke void @_ZNKSt3__16__treeIPKN5boost13serialization18extended_type_infoENS2_6detail11key_compareENS_9allocatorIS5_EEE4findIS5_EENS_21__tree_const_iteratorIS5_PNS_11__tree_nodeIS5_PvEElEERKT_() + to label %_ZNKSt3__18multisetIPKN5boost13serialization18extended_type_infoENS2_6detail11key_compareENS_9allocatorIS5_EEE4findERKS5_.exit unwind label %lpad + +_ZNKSt3__18multisetIPKN5boost13serialization18extended_type_infoENS2_6detail11key_compareENS_9allocatorIS5_EEE4findERKS5_.exit: ; preds = %cond.end + br label %invoke.cont + +invoke.cont: ; preds = %_ZNKSt3__18multisetIPKN5boost13serialization18extended_type_infoENS2_6detail11key_compareENS_9allocatorIS5_EEE4findERKS5_.exit + %1 = load %"class.std::__1::__tree_node.130.151"*, %"class.std::__1::__tree_node.130.151"** undef, align 8 + %cmp.i = icmp eq %"class.std::__1::__tree_node.130.151"* undef, %1 + br label %invoke.cont.2 + +invoke.cont.2: ; preds = %invoke.cont + br i1 %cmp.i, label %if.then, label %if.end + +if.then: ; preds = %invoke.cont.2 + br label %cleanup + +lpad: ; preds = %cond.end + %2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + br label %eh.resume + +if.end: ; preds = %invoke.cont.2 + br label %invoke.cont.4 + +invoke.cont.4: ; preds = %if.end + br label %cleanup + +cleanup: ; preds = %invoke.cont.4, %if.then + ret void + +eh.resume: ; preds = %lpad + resume { i8*, i32 } undef +} + +declare i32 @__gxx_personality_v0(...) + +; Function Attrs: noinline +declare void @_ZNKSt3__16__treeIPKN5boost13serialization18extended_type_infoENS2_6detail11key_compareENS_9allocatorIS5_EEE4findIS5_EENS_21__tree_const_iteratorIS5_PNS_11__tree_nodeIS5_PvEElEERKT_() #0 align 2 + +attributes #0 = { noinline "target-cpu"="a2q" } + +!llvm.module.flags = !{!0} + +!0 = !{i32 1, !"PIC Level", i32 2} + -- 2.34.1