/// expandCaseRange - Expand case range into explicit case values within the
/// range
bool WriteBitcodePass::expandCaseRange(Function &F) {
  bool Changed = false;

  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
    SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator());
    if (SI == NULL) {
      continue;
    }

    for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end();
         i != e; ++i) {
      IntegersSubset& CaseRanges = i.getCaseValueEx();

      // All case ranges are already in single case values
      if (CaseRanges.isSingleNumbersOnly()) {
        continue;
      }

      // Create a new case
      Type *IntTy = SI->getCondition()->getType();
      IntegersSubsetToBB CaseBuilder;
      Changed = true;

      for (unsigned ri = 0, rn = CaseRanges.getNumItems(); ri != rn; ++ri) {
        IntegersSubset::Range r = CaseRanges.getItem(ri);
        bool IsSingleNumber = CaseRanges.isSingleNumber(ri);

        if (IsSingleNumber) {
          CaseBuilder.add(r);
        } else {
          const APInt &Low = r.getLow();
          const APInt &High = r.getHigh();

          for (APInt V = Low; V != High; V++) {
            assert(r.isInRange(V) && "Unexpected out-of-range case value!");
            CaseBuilder.add(IntItem::fromType(IntTy, V));
          }
        }

        IntegersSubset Case = CaseBuilder.getCase();
        i.setValueEx(Case);
      }
    }
  }
  return Changed;
}
static void convertInstruction(Instruction *Inst, ConversionState &State) {
  if (SExtInst *Sext = dyn_cast<SExtInst>(Inst)) {
    Value *Op = Sext->getOperand(0);
    Value *NewInst = NULL;
    // If the operand to be extended is illegal, we first need to fill its
    // upper bits (which are zero) with its sign bit.
    if (shouldConvert(Op)) {
      NewInst = getSignExtend(State.getConverted(Op), Op, Sext);
    }
    // If the converted type of the operand is the same as the converted
    // type of the result, we won't actually be changing the type of the
    // variable, just its value.
    if (getPromotedType(Op->getType()) !=
        getPromotedType(Sext->getType())) {
      NewInst = new SExtInst(
          NewInst ? NewInst : State.getConverted(Op),
          getPromotedType(cast<IntegerType>(Sext->getType())),
          Sext->getName() + ".sext", Sext);
    }
    // Now all the bits of the result are correct, but we need to restore
    // the bits above its type to zero.
    if (shouldConvert(Sext)) {
      NewInst = getClearUpper(NewInst, Sext->getType(), Sext);
    }
    assert(NewInst && "Failed to convert sign extension");
    State.recordConverted(Sext, NewInst);
  } else if (ZExtInst *Zext = dyn_cast<ZExtInst>(Inst)) {
    Value *Op = Zext->getOperand(0);
    Value *NewInst = NULL;
    // TODO(dschuff): Some of these zexts could be no-ops.
    if (shouldConvert(Op)) {
      NewInst = getClearUpper(State.getConverted(Op),
                              Op->getType(),
                              Zext);
    }
    // If the converted type of the operand is the same as the converted
    // type of the result, we won't actually be changing the type of the
    // variable, just its value.
    if (getPromotedType(Op->getType()) !=
        getPromotedType(Zext->getType())) {
      NewInst = CastInst::CreateZExtOrBitCast(
          NewInst ? NewInst : State.getConverted(Op),
          getPromotedType(cast<IntegerType>(Zext->getType())),
          "", Zext);
    }
    assert(NewInst);
    State.recordConverted(Zext, NewInst);
  } else if (TruncInst *Trunc = dyn_cast<TruncInst>(Inst)) {
    Value *Op = Trunc->getOperand(0);
    Value *NewInst = NULL;
    // If the converted type of the operand is the same as the converted
    // type of the result, we won't actually be changing the type of the
    // variable, just its value.
    if (getPromotedType(Op->getType()) !=
        getPromotedType(Trunc->getType())) {
      NewInst = new TruncInst(
          State.getConverted(Op),
          getPromotedType(cast<IntegerType>(Trunc->getType())),
          State.getConverted(Op)->getName() + ".trunc",
          Trunc);
    }
    // Restoring the upper-bits-are-zero invariant effectively truncates the
    // value.
    if (shouldConvert(Trunc)) {
      NewInst = getClearUpper(NewInst ? NewInst : Op,
                              Trunc->getType(),
                              Trunc);
    }
    assert(NewInst);
    State.recordConverted(Trunc, NewInst);
  } else if (AllocaInst *Alloc = dyn_cast<AllocaInst>(Inst)) {
    // Don't handle arrays of illegal types, but we could handle an array
    // with size specified as an illegal type, as unlikely as that seems.
    if (shouldConvert(Alloc) && Alloc->isArrayAllocation())
      report_fatal_error("Can't convert arrays of illegal type");
    AllocaInst *NewInst = new AllocaInst(
        getPromotedType(Alloc->getAllocatedType()),
        State.getConverted(Alloc->getArraySize()),
        "", Alloc);
    NewInst->setAlignment(Alloc->getAlignment());
    State.recordConverted(Alloc, NewInst);
  } else if (BitCastInst *BCInst = dyn_cast<BitCastInst>(Inst)) {
    // Only handle pointers. Ints can't be casted to/from other ints
    Type *DestType = shouldConvert(BCInst) ?
        getPromotedType(BCInst->getDestTy()) : BCInst->getDestTy();
    BitCastInst *NewInst = new BitCastInst(
        State.getConverted(BCInst->getOperand(0)),
        DestType,
        "", BCInst);
    State.recordConverted(BCInst, NewInst);
  } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
    if (shouldConvert(Load)) {
      splitLoad(Load, State);
    }
  } else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
    if (shouldConvert(Store->getValueOperand())) {
      splitStore(Store, State);
    }
  } else if (isa<CallInst>(Inst)) {
    report_fatal_error("can't convert calls with illegal types");
  } else if (BinaryOperator *Binop = dyn_cast<BinaryOperator>(Inst)) {
    Value *NewInst = NULL;
    if (Binop->getOpcode() == Instruction::AShr) {
      // The AShr operand needs to be sign-extended to the promoted size
      // before shifting. Because the sign-extension is implemented with
      // with AShr, it can be combined with the original operation.
      Value *Op = Binop->getOperand(0);
      Value *ShiftAmount = NULL;
      APInt SignShiftAmt = APInt(
          getPromotedType(Op->getType())->getIntegerBitWidth(),
          getPromotedType(Op->getType())->getIntegerBitWidth() -
          Op->getType()->getIntegerBitWidth());
      NewInst = BinaryOperator::Create(
          Instruction::Shl,
          State.getConverted(Op),
          ConstantInt::get(getPromotedType(Op->getType()), SignShiftAmt),
          State.getConverted(Op)->getName() + ".getsign",
          Binop);
      if (ConstantInt *C = dyn_cast<ConstantInt>(
              State.getConverted(Binop->getOperand(1)))) {
        ShiftAmount = ConstantInt::get(getPromotedType(Op->getType()),
                                       SignShiftAmt + C->getValue());
      } else {
        ShiftAmount = BinaryOperator::Create(
            Instruction::Add,
            State.getConverted(Binop->getOperand(1)),
            ConstantInt::get(
                getPromotedType(Binop->getOperand(1)->getType()),
                SignShiftAmt),
            State.getConverted(Op)->getName() + ".shamt", Binop);
      }
      NewInst = BinaryOperator::Create(
          Instruction::AShr,
          NewInst,
          ShiftAmount,
          Binop->getName() + ".result", Binop);
    } else {
      // If the original operation is not AShr, just recreate it as usual.
      NewInst = BinaryOperator::Create(
          Binop->getOpcode(),
          State.getConverted(Binop->getOperand(0)),
          State.getConverted(Binop->getOperand(1)),
          Binop->getName() + ".result", Binop);
      if (isa<OverflowingBinaryOperator>(NewInst)) {
        cast<BinaryOperator>(NewInst)->setHasNoUnsignedWrap
            (Binop->hasNoUnsignedWrap());
        cast<BinaryOperator>(NewInst)->setHasNoSignedWrap(
            Binop->hasNoSignedWrap());
      }
    }

    // Now restore the invariant if necessary.
    // This switch also sanity-checks the operation.
    switch (Binop->getOpcode()) {
      case Instruction::And:
      case Instruction::Or:
      case Instruction::Xor:
      case Instruction::LShr:
        // These won't change the upper bits.
        break;
        // These can change the upper bits, unless we are sure they never
        // overflow. So clear them now.
      case Instruction::Add:
      case Instruction::Sub:
        if (!(Binop->hasNoUnsignedWrap() && Binop->hasNoSignedWrap()))
          NewInst = getClearUpper(NewInst, Binop->getType(), Binop);
        break;
      case Instruction::Shl:
        if (!Binop->hasNoUnsignedWrap())
          NewInst = getClearUpper(NewInst, Binop->getType(), Binop);
        break;
        // We modified the upper bits ourselves when implementing AShr
      case Instruction::AShr:
        NewInst = getClearUpper(NewInst, Binop->getType(), Binop);
        break;
        // We should not see FP operators here.
        // We don't handle mul/div.
      case Instruction::FAdd:
      case Instruction::FSub:
      case Instruction::Mul:
      case Instruction::FMul:
      case Instruction::UDiv:
      case Instruction::SDiv:
      case Instruction::FDiv:
      case Instruction::URem:
      case Instruction::SRem:
      case Instruction::FRem:
      case Instruction::BinaryOpsEnd:
        errs() << *Inst << "\n";
        llvm_unreachable("Cannot handle binary operator");
        break;
    }

    State.recordConverted(Binop, NewInst);
  } else if (ICmpInst *Cmp = dyn_cast<ICmpInst>(Inst)) {
    Value *Op0, *Op1;
    // For signed compares, operands are sign-extended to their
    // promoted type. For unsigned or equality compares, the comparison
    // is equivalent with the larger type because they are already
    // zero-extended.
    if (Cmp->isSigned()) {
      Op0 = getSignExtend(State.getConverted(Cmp->getOperand(0)),
                          Cmp->getOperand(0),
                          Cmp);
      Op1 = getSignExtend(State.getConverted(Cmp->getOperand(1)),
                          Cmp->getOperand(1),
                          Cmp);
    } else {
      Op0 = State.getConverted(Cmp->getOperand(0));
      Op1 = State.getConverted(Cmp->getOperand(1));
    }
    ICmpInst *NewInst = new ICmpInst(
        Cmp, Cmp->getPredicate(), Op0, Op1, "");
    State.recordConverted(Cmp, NewInst);
  } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) {
    SelectInst *NewInst = SelectInst::Create(
        Select->getCondition(),
        State.getConverted(Select->getTrueValue()),
        State.getConverted(Select->getFalseValue()),
        "", Select);
    State.recordConverted(Select, NewInst);
  } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) {
    PHINode *NewPhi = PHINode::Create(
        getPromotedType(Phi->getType()),
        Phi->getNumIncomingValues(),
        "", Phi);
    for (unsigned I = 0, E = Phi->getNumIncomingValues(); I < E; ++I) {
      NewPhi->addIncoming(State.getConverted(Phi->getIncomingValue(I)),
                          Phi->getIncomingBlock(I));
    }
    State.recordConverted(Phi, NewPhi);
  } else if (SwitchInst *Switch = dyn_cast<SwitchInst>(Inst)) {
    SwitchInst *NewInst = SwitchInst::Create(
        State.getConverted(Switch->getCondition()),
        Switch->getDefaultDest(),
        Switch->getNumCases(),
        Switch);
    for (SwitchInst::CaseIt I = Switch->case_begin(),
             E = Switch->case_end();
         I != E; ++I) {
      // Build a new case from the ranges that map to the successor BB. Each
      // range consists of a high and low value which are typed, so the ranges
      // must be rebuilt and a new case constructed from them.
      IntegersSubset CaseRanges = I.getCaseValueEx();
      IntegersSubsetToBB CaseBuilder;
      for (unsigned RI = 0, RE = CaseRanges.getNumItems(); RI < RE; ++RI) {
        CaseBuilder.add(
            IntItem::fromConstantInt(cast<ConstantInt>(convertConstant(
                CaseRanges.getItem(RI).getLow().toConstantInt()))),
            IntItem::fromConstantInt(cast<ConstantInt>(convertConstant(
                CaseRanges.getItem(RI).getHigh().toConstantInt()))));
      }
      IntegersSubset Case = CaseBuilder.getCase();
      NewInst->addCase(Case, I.getCaseSuccessor());
    }
    Switch->eraseFromParent();
  } else {
    errs() << *Inst<<"\n";
    llvm_unreachable("unhandled instruction");
  }
}