diff options
author | Erik Verbruggen <erikjv@me.com> | 2014-03-28 14:42:34 +0000 |
---|---|---|
committer | Erik Verbruggen <erikjv@me.com> | 2014-03-28 14:42:34 +0000 |
commit | cc58a593a2b975bd46a25749287872d0d6978488 (patch) | |
tree | 89a2c8c4113f6ffbc77d4e98da54ec212be21087 /lib/Transforms/Scalar | |
parent | 1f072c36d0e248d69932a830b698458f032c644d (diff) | |
download | llvm-cc58a593a2b975bd46a25749287872d0d6978488.tar.gz llvm-cc58a593a2b975bd46a25749287872d0d6978488.tar.bz2 llvm-cc58a593a2b975bd46a25749287872d0d6978488.tar.xz |
Revert "GVN: merge overflow intrinsics with non-overflow instructions."
This reverts commit r203553, and follow-up commits r203558 and r203574.
I will follow this up on the mailinglist to do it in a way that won't
cause subtle PRE bugs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205009 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar')
-rw-r--r-- | lib/Transforms/Scalar/GVN.cpp | 182 |
1 files changed, 58 insertions, 124 deletions
diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 53c120530f..33c387cb71 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -111,11 +111,10 @@ namespace { uint32_t nextValueNumber; Expression create_expression(Instruction* I); - Expression create_intrinsic_expression(CallInst *C, uint32_t opcode, - bool IsCommutative); Expression create_cmp_expression(unsigned Opcode, CmpInst::Predicate Predicate, Value *LHS, Value *RHS); + Expression create_extractvalue_expression(ExtractValueInst* EI); uint32_t lookup_or_add_call(CallInst* C); public: ValueTable() : nextValueNumber(1) { } @@ -189,33 +188,6 @@ Expression ValueTable::create_expression(Instruction *I) { for (InsertValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end(); II != IE; ++II) e.varargs.push_back(*II); - } else if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(I)) { - for (ExtractValueInst::idx_iterator II = EVI->idx_begin(), - IE = EVI->idx_end(); II != IE; ++II) - e.varargs.push_back(*II); - } - - return e; -} - -Expression ValueTable::create_intrinsic_expression(CallInst *C, uint32_t opcode, - bool IsCommutative) { - Expression e; - e.opcode = opcode; - StructType *ST = cast<StructType>(C->getType()); - assert(ST); - e.type = *ST->element_begin(); - - for (unsigned i = 0, ei = C->getNumArgOperands(); i < ei; ++i) - e.varargs.push_back(lookup_or_add(C->getArgOperand(i))); - if (IsCommutative) { - // Ensure that commutative instructions that only differ by a permutation - // of their operands get the same value number by sorting the operand value - // numbers. Since all commutative instructions have two operands it is more - // efficient to sort by hand rather than using, say, std::sort. - assert(C->getNumArgOperands() == 2 && "Unsupported commutative instruction!"); - if (e.varargs[0] > e.varargs[1]) - std::swap(e.varargs[0], e.varargs[1]); } return e; @@ -240,6 +212,58 @@ Expression ValueTable::create_cmp_expression(unsigned Opcode, return e; } +Expression ValueTable::create_extractvalue_expression(ExtractValueInst *EI) { + assert(EI != 0 && "Not an ExtractValueInst?"); + Expression e; + e.type = EI->getType(); + e.opcode = 0; + + IntrinsicInst *I = dyn_cast<IntrinsicInst>(EI->getAggregateOperand()); + if (I != 0 && EI->getNumIndices() == 1 && *EI->idx_begin() == 0 ) { + // EI might be an extract from one of our recognised intrinsics. If it + // is we'll synthesize a semantically equivalent expression instead on + // an extract value expression. + switch (I->getIntrinsicID()) { + case Intrinsic::sadd_with_overflow: + case Intrinsic::uadd_with_overflow: + e.opcode = Instruction::Add; + break; + case Intrinsic::ssub_with_overflow: + case Intrinsic::usub_with_overflow: + e.opcode = Instruction::Sub; + break; + case Intrinsic::smul_with_overflow: + case Intrinsic::umul_with_overflow: + e.opcode = Instruction::Mul; + break; + default: + break; + } + + if (e.opcode != 0) { + // Intrinsic recognized. Grab its args to finish building the expression. + assert(I->getNumArgOperands() == 2 && + "Expect two args for recognised intrinsics."); + e.varargs.push_back(lookup_or_add(I->getArgOperand(0))); + e.varargs.push_back(lookup_or_add(I->getArgOperand(1))); + return e; + } + } + + // Not a recognised intrinsic. Fall back to producing an extract value + // expression. + e.opcode = EI->getOpcode(); + for (Instruction::op_iterator OI = EI->op_begin(), OE = EI->op_end(); + OI != OE; ++OI) + e.varargs.push_back(lookup_or_add(*OI)); + + for (ExtractValueInst::idx_iterator II = EI->idx_begin(), IE = EI->idx_end(); + II != IE; ++II) + e.varargs.push_back(*II); + + return e; +} + //===----------------------------------------------------------------------===// // ValueTable External Functions //===----------------------------------------------------------------------===// @@ -373,29 +397,8 @@ uint32_t ValueTable::lookup_or_add(Value *V) { Instruction* I = cast<Instruction>(V); Expression exp; switch (I->getOpcode()) { - case Instruction::Call: { - CallInst *C = cast<CallInst>(I); - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(C)) { - switch (II->getIntrinsicID()) { - case Intrinsic::sadd_with_overflow: - case Intrinsic::uadd_with_overflow: - exp = create_intrinsic_expression(C, Instruction::Add, true); - break; - case Intrinsic::ssub_with_overflow: - case Intrinsic::usub_with_overflow: - exp = create_intrinsic_expression(C, Instruction::Sub, false); - break; - case Intrinsic::smul_with_overflow: - case Intrinsic::umul_with_overflow: - exp = create_intrinsic_expression(C, Instruction::Mul, true); - break; - default: - return lookup_or_add_call(C); - } - } else { - return lookup_or_add_call(C); - } - } break; + case Instruction::Call: + return lookup_or_add_call(cast<CallInst>(I)); case Instruction::Add: case Instruction::FAdd: case Instruction::Sub: @@ -434,9 +437,11 @@ uint32_t ValueTable::lookup_or_add(Value *V) { case Instruction::ShuffleVector: case Instruction::InsertValue: case Instruction::GetElementPtr: - case Instruction::ExtractValue: exp = create_expression(I); break; + case Instruction::ExtractValue: + exp = create_extractvalue_expression(cast<ExtractValueInst>(I)); + break; default: valueNumbering[V] = nextValueNumber; return nextValueNumber++; @@ -2184,54 +2189,6 @@ bool GVN::propagateEquality(Value *LHS, Value *RHS, return Changed; } -static bool normalOpAfterIntrinsic(Instruction *I, Value *Repl) -{ - switch (I->getOpcode()) { - case Instruction::Add: - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Repl)) - return II->getIntrinsicID() == Intrinsic::sadd_with_overflow - || II->getIntrinsicID() == Intrinsic::uadd_with_overflow; - return false; - case Instruction::Sub: - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Repl)) - return II->getIntrinsicID() == Intrinsic::ssub_with_overflow - || II->getIntrinsicID() == Intrinsic::usub_with_overflow; - return false; - case Instruction::Mul: - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Repl)) - return II->getIntrinsicID() == Intrinsic::smul_with_overflow - || II->getIntrinsicID() == Intrinsic::umul_with_overflow; - return false; - default: - return false; - } -} - -static bool intrinsicAterNormalOp(Instruction *I, Value *Repl) -{ - IntrinsicInst *II = dyn_cast<IntrinsicInst>(I); - if (!II) - return false; - - Instruction *RI = dyn_cast<Instruction>(Repl); - if (!RI) - return false; - - switch (RI->getOpcode()) { - case Instruction::Add: - return II->getIntrinsicID() == Intrinsic::sadd_with_overflow - || II->getIntrinsicID() == Intrinsic::uadd_with_overflow; - case Instruction::Sub: - return II->getIntrinsicID() == Intrinsic::ssub_with_overflow - || II->getIntrinsicID() == Intrinsic::usub_with_overflow; - case Instruction::Mul: - return II->getIntrinsicID() == Intrinsic::smul_with_overflow - || II->getIntrinsicID() == Intrinsic::umul_with_overflow; - default: - return false; - } -} - /// processInstruction - When calculating availability, handle an instruction /// by inserting it into the appropriate sets bool GVN::processInstruction(Instruction *I) { @@ -2345,27 +2302,6 @@ bool GVN::processInstruction(Instruction *I) { return false; } - if (normalOpAfterIntrinsic(I, repl)) { - // An intrinsic followed by a normal operation (e.g. sadd_with_overflow - // followed by a sadd): replace the second instruction with an extract. - IntrinsicInst *II = cast<IntrinsicInst>(repl); - assert(II); - repl = ExtractValueInst::Create(II, 0, I->getName() + ".repl", I); - } else if (intrinsicAterNormalOp(I, repl)) { - // A normal operation followed by an intrinsic (e.g. sadd followed by a - // sadd_with_overflow). - // Clone the intrinsic, and insert it before the replacing instruction. Then - // replace the (current) instruction with the cloned one. In a subsequent - // run, the original replacement (the non-intrinsic) will be be replaced by - // the new intrinsic. - Instruction *RI = dyn_cast<Instruction>(repl); - assert(RI); - Instruction *newIntrinsic = I->clone(); - newIntrinsic->setName(I->getName() + ".repl"); - newIntrinsic->insertBefore(RI); - repl = newIntrinsic; - } - // Remove it! patchAndReplaceAllUsesWith(I, repl); if (MD && repl->getType()->getScalarType()->isPointerTy()) @@ -2550,8 +2486,6 @@ bool GVN::performPRE(Function &F) { predMap.push_back(std::make_pair(static_cast<Value *>(0), P)); PREPred = P; ++NumWithout; - } else if (predV->getType() != CurInst->getType()) { - continue; } else if (predV == CurInst) { /* CurInst dominates this predecessor. */ NumWithout = 2; |