From 59bd053fc5205471d23da7ca3469b5a926b78b40 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Tue, 3 Jul 2007 18:37:08 +0000 Subject: [PATCH] Add support for performing GVNPRE on cast instructions, and add a testcase for this. llvm-svn: 37856 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp | 134 ++++++++++++++++++++++---- llvm/test/Transforms/GVNPRE/cast.ll | 17 ++++ 2 files changed, 133 insertions(+), 18 deletions(-) create mode 100644 llvm/test/Transforms/GVNPRE/cast.ll diff --git a/llvm/lib/Transforms/Scalar/GVNPRE.cpp b/llvm/lib/Transforms/Scalar/GVNPRE.cpp index 8f245a15391f..65af1a25ee8f 100644 --- a/llvm/lib/Transforms/Scalar/GVNPRE.cpp +++ b/llvm/lib/Transforms/Scalar/GVNPRE.cpp @@ -629,8 +629,41 @@ Value* GVNPRE::phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) { if (V == 0) return 0; + // Unary Operations + if (isa(V)) { + User* U = cast(V); + + Value* newOp1 = 0; + if (isa(U->getOperand(0))) + newOp1 = phi_translate(U->getOperand(0), pred, succ); + else + newOp1 = U->getOperand(0); + + if (newOp1 == 0) + return 0; + + if (newOp1 != U->getOperand(0)) { + Instruction* newVal = 0; + if (CastInst* C = dyn_cast(U)) + newVal = CastInst::create(C->getOpcode(), + newOp1, C->getType(), + C->getName()+".expr"); + + uint32_t v = VN.lookup_or_add(newVal); + + Value* leader = find_leader(availableOut[pred], v); + if (leader == 0) { + createdExpressions.push_back(newVal); + return newVal; + } else { + VN.erase(newVal); + delete newVal; + return leader; + } + } + // Binary Operations - if (isa(V) || isa(V) || + } if (isa(V) || isa(V) || isa(V)) { User* U = cast(V); @@ -783,8 +816,22 @@ void GVNPRE::clean(SmallPtrSet& set, BitVector& presentInSet) { for (unsigned i = 0; i < worklist.size(); ++i) { Value* v = worklist[i]; + // Handle unary ops + if (isa(v)) { + User* U = cast(v); + + bool lhsValid = !isa(U->getOperand(0)); + lhsValid |= presentInSet.test(VN.lookup(U->getOperand(0))); + if (lhsValid) + lhsValid = !dependsOnInvoke(U->getOperand(0)); + + if (!lhsValid) { + set.erase(U); + presentInSet.flip(VN.lookup(U)); + } + // Handle binary ops - if (isa(v) || isa(v) || + } else if (isa(v) || isa(v) || isa(v)) { User* U = cast(v); @@ -843,9 +890,23 @@ void GVNPRE::topo_sort(SmallPtrSet& set, std::vector& vec) { while (!stack.empty()) { Value* e = stack.back(); - + + // Handle unary ops + if (isa(e)) { + User* U = cast(e); + Value* l = find_leader(set, VN.lookup(U->getOperand(0))); + + if (l != 0 && isa(l) && + visited.count(l) == 0) + stack.push_back(l); + else { + vec.push_back(e); + visited.insert(e); + stack.pop_back(); + } + // Handle binary ops - if (isa(e) || isa(e) || + } else if (isa(e) || isa(e) || isa(e)) { User* U = cast(e); Value* l = find_leader(set, VN.lookup(U->getOperand(0))); @@ -935,7 +996,8 @@ bool GVNPRE::elimination() { if (isa(BI) || isa(BI) || isa(BI) || isa(BI) || - isa(BI) || isa(BI)) { + isa(BI) || isa(BI) || + isa(BI)) { Value *leader = find_leader(availableOut[BB], VN.lookup(BI)); if (leader != 0) @@ -990,7 +1052,27 @@ void GVNPRE::buildsets_availout(BasicBlock::iterator I, availNumbers.resize(VN.size()); currPhis.insert(p); + + // Handle unary ops + } else if (isa(I)) { + User* U = cast(I); + Value* leftValue = U->getOperand(0); + unsigned num = VN.lookup_or_add(U); + expNumbers.resize(VN.size()); + availNumbers.resize(VN.size()); + + if (isa(leftValue)) + if (!expNumbers.test(VN.lookup(leftValue))) { + currExps.insert(leftValue); + expNumbers.set(VN.lookup(leftValue)); + } + + if (!expNumbers.test(VN.lookup(U))) { + currExps.insert(U); + expNumbers.set(num); + } + // Handle binary ops } else if (isa(I) || isa(I) || isa(I)) { @@ -1266,21 +1348,31 @@ void GVNPRE::insertion_pre(Value* e, BasicBlock* BB, isa(U->getOperand(0)) || isa(U->getOperand(0)) || isa(U->getOperand(0)) || - isa(U->getOperand(0))) + isa(U->getOperand(0)) || + isa(U->getOperand(0))) s1 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(0))); else s1 = U->getOperand(0); Value* s2 = 0; - if (isa(U->getOperand(1)) || - isa(U->getOperand(1)) || - isa(U->getOperand(1)) || - isa(U->getOperand(1)) || - isa(U->getOperand(1)) || - isa(U->getOperand(1))) - s2 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(1))); - else - s2 = U->getOperand(1); + + if (isa(U) || + isa(U) || + isa(U) || + isa(U) || + isa(U) || + isa(U)) + if (isa(U->getOperand(1)) || + isa(U->getOperand(1)) || + isa(U->getOperand(1)) || + isa(U->getOperand(1)) || + isa(U->getOperand(1)) || + isa(U->getOperand(1)) || + isa(U->getOperand(1))) { + s2 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(1))); + } else { + s2 = U->getOperand(1); + } // Ternary Operators Value* s3 = 0; @@ -1292,10 +1384,12 @@ void GVNPRE::insertion_pre(Value* e, BasicBlock* BB, isa(U->getOperand(2)) || isa(U->getOperand(2)) || isa(U->getOperand(2)) || - isa(U->getOperand(2))) + isa(U->getOperand(2)) || + isa(U->getOperand(2))) { s3 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(2))); - else + } else { s3 = U->getOperand(2); + } Value* newVal = 0; if (BinaryOperator* BO = dyn_cast(U)) @@ -1319,6 +1413,10 @@ void GVNPRE::insertion_pre(Value* e, BasicBlock* BB, newVal = new SelectInst(S->getCondition(), S->getTrueValue(), S->getFalseValue(), S->getName()+".gvnpre", (*PI)->getTerminator()); + else if (CastInst* C = dyn_cast(U)) + newVal = CastInst::create(C->getOpcode(), s1, C->getType(), + C->getName()+".gvnpre", + (*PI)->getTerminator()); VN.add(newVal, VN.lookup(U)); @@ -1365,7 +1463,7 @@ unsigned GVNPRE::insertion_mergepoint(std::vector& workList, if (isa(e) || isa(e) || isa(e) || isa(e) || - isa(e) || isa(e)) { + isa(e) || isa(e) || isa(e)) { if (find_leader(availableOut[D->getIDom()->getBlock()], VN.lookup(e)) != 0) continue; diff --git a/llvm/test/Transforms/GVNPRE/cast.ll b/llvm/test/Transforms/GVNPRE/cast.ll new file mode 100644 index 000000000000..3536a14571fb --- /dev/null +++ b/llvm/test/Transforms/GVNPRE/cast.ll @@ -0,0 +1,17 @@ +; RUN: llvm-as < %s | opt -gvnpre | llvm-dis | grep b.gvnpre + +define i32 @extract() { +entry: ; preds = %cond_false, %entry + br i1 true, label %cond_true, label %cond_false + +cond_true: + br label %end + +cond_false: + %a = sext i16 0 to i32 + br label %end + +end: + %b = sext i16 0 to i32 + ret i32 %b +}