diff options
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/GVN.cpp | 176 | 
1 files changed, 118 insertions, 58 deletions
| diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index 33c387cb71c..f40d34f2488 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -111,10 +111,11 @@ 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) { } @@ -193,6 +194,29 @@ Expression ValueTable::create_expression(Instruction *I) {    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; +} +  Expression ValueTable::create_cmp_expression(unsigned Opcode,                                               CmpInst::Predicate Predicate,                                               Value *LHS, Value *RHS) { @@ -212,58 +236,6 @@ 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  //===----------------------------------------------------------------------===// @@ -397,8 +369,29 @@ uint32_t ValueTable::lookup_or_add(Value *V) {    Instruction* I = cast<Instruction>(V);    Expression exp;    switch (I->getOpcode()) { -    case Instruction::Call: -      return lookup_or_add_call(cast<CallInst>(I)); +    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::Add:      case Instruction::FAdd:      case Instruction::Sub: @@ -437,10 +430,8 @@ uint32_t ValueTable::lookup_or_add(Value *V) {      case Instruction::ShuffleVector:      case Instruction::InsertValue:      case Instruction::GetElementPtr: -      exp = create_expression(I); -      break;      case Instruction::ExtractValue: -      exp = create_extractvalue_expression(cast<ExtractValueInst>(I)); +      exp = create_expression(I);        break;      default:        valueNumbering[V] = nextValueNumber; @@ -2189,6 +2180,54 @@ 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) { @@ -2302,6 +2341,27 @@ 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()) | 

