<commit_before>//===-- SIShrinkInstructions.cpp - Shrink Instructions --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
/// The pass tries to use the 32-bit encoding for instructions when possible.
//===----------------------------------------------------------------------===//
//

#include "AMDGPU.h"
#include "AMDGPUSubtarget.h"
#include "SIInstrInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetMachine.h"

#define DEBUG_TYPE "si-shrink-instructions"

STATISTIC(NumInstructionsShrunk,
          "Number of 64-bit instruction reduced to 32-bit.");
STATISTIC(NumLiteralConstantsFolded,
          "Number of literal constants folded into 32-bit instructions.");

namespace llvm {
  void initializeSIShrinkInstructionsPass(PassRegistry&);
}

using namespace llvm;

namespace {

class SIShrinkInstructions : public MachineFunctionPass {
public:
  static char ID;

public:
  SIShrinkInstructions() : MachineFunctionPass(ID) {
  }

  bool runOnMachineFunction(MachineFunction &MF) override;

  const char *getPassName() const override {
    return "SI Shrink Instructions";
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    MachineFunctionPass::getAnalysisUsage(AU);
  }
};

} // End anonymous namespace.

INITIALIZE_PASS_BEGIN(SIShrinkInstructions, DEBUG_TYPE,
                      "SI Lower il Copies", false, false)
INITIALIZE_PASS_END(SIShrinkInstructions, DEBUG_TYPE,
                    "SI Lower il Copies", false, false)

char SIShrinkInstructions::ID = 0;

FunctionPass *llvm::createSIShrinkInstructionsPass() {
  return new SIShrinkInstructions();
}

static bool isVGPR(const MachineOperand *MO, const SIRegisterInfo &TRI,
                   const MachineRegisterInfo &MRI) {
  if (!MO->isReg())
    return false;

  if (TargetRegisterInfo::isVirtualRegister(MO->getReg()))
    return TRI.hasVGPRs(MRI.getRegClass(MO->getReg()));

  return TRI.hasVGPRs(TRI.getPhysRegClass(MO->getReg()));
}

static bool canShrink(MachineInstr &MI, const SIInstrInfo *TII,
                      const SIRegisterInfo &TRI,
                      const MachineRegisterInfo &MRI) {

  const MachineOperand *Src2 = TII->getNamedOperand(MI, AMDGPU::OpName::src2);
  // Can't shrink instruction with three operands.
  if (Src2)
    return false;

  const MachineOperand *Src1 = TII->getNamedOperand(MI, AMDGPU::OpName::src1);
  const MachineOperand *Src1Mod =
      TII->getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);

  if (Src1 && (!isVGPR(Src1, TRI, MRI) || (Src1Mod && Src1Mod->getImm() != 0)))
    return false;

  // We don't need to check src0, all input types are legal, so just make
  // sure src0 isn't using any modifiers.
  const MachineOperand *Src0Mod =
      TII->getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
  if (Src0Mod && Src0Mod->getImm() != 0)
    return false;

  // Check output modifiers
  const MachineOperand *Omod = TII->getNamedOperand(MI, AMDGPU::OpName::omod);
  if (Omod && Omod->getImm() != 0)
    return false;

  const MachineOperand *Clamp = TII->getNamedOperand(MI, AMDGPU::OpName::clamp);
  return !Clamp || Clamp->getImm() == 0;
}

/// \brief This function checks \p MI for operands defined by a move immediate
/// instruction and then folds the literal constant into the instruction if it
/// can.  This function assumes that \p MI is a VOP1, VOP2, or VOPC instruction
/// and will only fold literal constants if we are still in SSA.
static void foldImmediates(MachineInstr &MI, const SIInstrInfo *TII,
                           MachineRegisterInfo &MRI, bool TryToCommute = true) {

  if (!MRI.isSSA())
    return;

  assert(TII->isVOP1(MI.getOpcode()) || TII->isVOP2(MI.getOpcode()) ||
         TII->isVOPC(MI.getOpcode()));

  const SIRegisterInfo &TRI = TII->getRegisterInfo();
  MachineOperand *Src0 = TII->getNamedOperand(MI, AMDGPU::OpName::src0);

  // Only one literal constant is allowed per instruction, so if src0 is a
  // literal constant then we can't do any folding.
  if (Src0->isImm() && TII->isLiteralConstant(*Src0))
    return;

  // Literal constants and SGPRs can only be used in Src0, so if Src0 is an
  // SGPR, we cannot commute the instruction, so we can't fold any literal
  // constants.
  if (Src0->isReg() && !isVGPR(Src0, TRI, MRI))
    return;

  // Try to fold Src0
  if (Src0->isReg()) {
    unsigned Reg = Src0->getReg();
    MachineInstr *Def = MRI.getUniqueVRegDef(Reg);
    if (Def && Def->isMoveImmediate()) {
      MachineOperand &MovSrc = Def->getOperand(1);
      bool ConstantFolded = false;

      if (MovSrc.isImm() && isUInt<32>(MovSrc.getImm())) {
        Src0->ChangeToImmediate(MovSrc.getImm());
        ConstantFolded = true;
      } else if (MovSrc.isFPImm()) {
        const ConstantFP *CFP = MovSrc.getFPImm();
        if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle) {
          Src0->ChangeToFPImmediate(CFP);
          ConstantFolded = true;
        }
      }
      if (ConstantFolded) {
        if (MRI.use_empty(Reg))
          Def->eraseFromParent();
        ++NumLiteralConstantsFolded;
        return;
      }
    }
  }

  // We have failed to fold src0, so commute the instruction and try again.
  if (TryToCommute && MI.isCommutable() && TII->commuteInstruction(&MI))
    foldImmediates(MI, TII, MRI, false);

}

bool SIShrinkInstructions::runOnMachineFunction(MachineFunction &MF) {
  MachineRegisterInfo &MRI = MF.getRegInfo();
  const SIInstrInfo *TII =
      static_cast<const SIInstrInfo *>(MF.getSubtarget().getInstrInfo());
  const SIRegisterInfo &TRI = TII->getRegisterInfo();
  std::vector<unsigned> I1Defs;

  for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
                                                  BI != BE; ++BI) {

    MachineBasicBlock &MBB = *BI;
    MachineBasicBlock::iterator I, Next;
    for (I = MBB.begin(); I != MBB.end(); I = Next) {
      Next = std::next(I);
      MachineInstr &MI = *I;

      if (!TII->hasVALU32BitEncoding(MI.getOpcode()))
        continue;

      if (!canShrink(MI, TII, TRI, MRI)) {
        // Try commuting the instruction and see if that enables us to shrink
        // it.
        if (!MI.isCommutable() || !TII->commuteInstruction(&MI) ||
            !canShrink(MI, TII, TRI, MRI))
          continue;
      }

      int Op32 = AMDGPU::getVOPe32(MI.getOpcode());

      // Op32 could be -1 here if we started with an instruction that had a
      // a 32-bit encoding and then commuted it to an instruction that did not.
      if (Op32 == -1)
        continue;

      if (TII->isVOPC(Op32)) {
        unsigned DstReg = MI.getOperand(0).getReg();
        if (TargetRegisterInfo::isVirtualRegister(DstReg)) {
          // VOPC instructions can only write to the VCC register.  We can't
          // force them to use VCC here, because the register allocator has
          // trouble with sequences like this, which cause the allocator to run
          // out of registers if vreg0 and vreg1 belong to the VCCReg register
          // class:
          // vreg0 = VOPC;
          // vreg1 = VOPC;
          // S_AND_B64 vreg0, vreg1
          //
          // So, instead of forcing the instruction to write to VCC, we provide
          // a hint to the register allocator to use VCC and then we we will run
          // this pass again after RA and shrink it if it outputs to VCC.
          MRI.setRegAllocationHint(MI.getOperand(0).getReg(), 0, AMDGPU::VCC);
          continue;
        }
        if (DstReg != AMDGPU::VCC)
          continue;
      }

      // We can shrink this instruction
      DEBUG(dbgs() << "Shrinking "; MI.dump(); dbgs() << '\n';);

      MachineInstrBuilder Inst32 =
          BuildMI(MBB, I, MI.getDebugLoc(), TII->get(Op32));

      // dst
      Inst32.addOperand(MI.getOperand(0));

      Inst32.addOperand(*TII->getNamedOperand(MI, AMDGPU::OpName::src0));

      const MachineOperand *Src1 =
          TII->getNamedOperand(MI, AMDGPU::OpName::src1);
      if (Src1)
        Inst32.addOperand(*Src1);

      ++NumInstructionsShrunk;
      MI.eraseFromParent();

      foldImmediates(*Inst32, TII, MRI);
      DEBUG(dbgs() << "e32 MI = " << *Inst32 << '\n');

    }
  }
  return false;
}
<commit_msg>R600/SI: Simplify code with hasModifiersSet<commit_after>//===-- SIShrinkInstructions.cpp - Shrink Instructions --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
/// The pass tries to use the 32-bit encoding for instructions when possible.
//===----------------------------------------------------------------------===//
//

#include "AMDGPU.h"
#include "AMDGPUSubtarget.h"
#include "SIInstrInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetMachine.h"

#define DEBUG_TYPE "si-shrink-instructions"

STATISTIC(NumInstructionsShrunk,
          "Number of 64-bit instruction reduced to 32-bit.");
STATISTIC(NumLiteralConstantsFolded,
          "Number of literal constants folded into 32-bit instructions.");

namespace llvm {
  void initializeSIShrinkInstructionsPass(PassRegistry&);
}

using namespace llvm;

namespace {

class SIShrinkInstructions : public MachineFunctionPass {
public:
  static char ID;

public:
  SIShrinkInstructions() : MachineFunctionPass(ID) {
  }

  bool runOnMachineFunction(MachineFunction &MF) override;

  const char *getPassName() const override {
    return "SI Shrink Instructions";
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    MachineFunctionPass::getAnalysisUsage(AU);
  }
};

} // End anonymous namespace.

INITIALIZE_PASS_BEGIN(SIShrinkInstructions, DEBUG_TYPE,
                      "SI Lower il Copies", false, false)
INITIALIZE_PASS_END(SIShrinkInstructions, DEBUG_TYPE,
                    "SI Lower il Copies", false, false)

char SIShrinkInstructions::ID = 0;

FunctionPass *llvm::createSIShrinkInstructionsPass() {
  return new SIShrinkInstructions();
}

static bool isVGPR(const MachineOperand *MO, const SIRegisterInfo &TRI,
                   const MachineRegisterInfo &MRI) {
  if (!MO->isReg())
    return false;

  if (TargetRegisterInfo::isVirtualRegister(MO->getReg()))
    return TRI.hasVGPRs(MRI.getRegClass(MO->getReg()));

  return TRI.hasVGPRs(TRI.getPhysRegClass(MO->getReg()));
}

static bool canShrink(MachineInstr &MI, const SIInstrInfo *TII,
                      const SIRegisterInfo &TRI,
                      const MachineRegisterInfo &MRI) {

  const MachineOperand *Src2 = TII->getNamedOperand(MI, AMDGPU::OpName::src2);
  // Can't shrink instruction with three operands.
  if (Src2)
    return false;

  const MachineOperand *Src1 = TII->getNamedOperand(MI, AMDGPU::OpName::src1);
  const MachineOperand *Src1Mod =
      TII->getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);

  if (Src1 && (!isVGPR(Src1, TRI, MRI) || (Src1Mod && Src1Mod->getImm() != 0)))
    return false;

  // We don't need to check src0, all input types are legal, so just make sure
  // src0 isn't using any modifiers.
  if (TII->hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
    return false;

  // Check output modifiers
  if (TII->hasModifiersSet(MI, AMDGPU::OpName::omod))
    return false;

  if (TII->hasModifiersSet(MI, AMDGPU::OpName::clamp))
    return false;

  return true;
}

/// \brief This function checks \p MI for operands defined by a move immediate
/// instruction and then folds the literal constant into the instruction if it
/// can.  This function assumes that \p MI is a VOP1, VOP2, or VOPC instruction
/// and will only fold literal constants if we are still in SSA.
static void foldImmediates(MachineInstr &MI, const SIInstrInfo *TII,
                           MachineRegisterInfo &MRI, bool TryToCommute = true) {

  if (!MRI.isSSA())
    return;

  assert(TII->isVOP1(MI.getOpcode()) || TII->isVOP2(MI.getOpcode()) ||
         TII->isVOPC(MI.getOpcode()));

  const SIRegisterInfo &TRI = TII->getRegisterInfo();
  MachineOperand *Src0 = TII->getNamedOperand(MI, AMDGPU::OpName::src0);

  // Only one literal constant is allowed per instruction, so if src0 is a
  // literal constant then we can't do any folding.
  if (Src0->isImm() && TII->isLiteralConstant(*Src0))
    return;

  // Literal constants and SGPRs can only be used in Src0, so if Src0 is an
  // SGPR, we cannot commute the instruction, so we can't fold any literal
  // constants.
  if (Src0->isReg() && !isVGPR(Src0, TRI, MRI))
    return;

  // Try to fold Src0
  if (Src0->isReg()) {
    unsigned Reg = Src0->getReg();
    MachineInstr *Def = MRI.getUniqueVRegDef(Reg);
    if (Def && Def->isMoveImmediate()) {
      MachineOperand &MovSrc = Def->getOperand(1);
      bool ConstantFolded = false;

      if (MovSrc.isImm() && isUInt<32>(MovSrc.getImm())) {
        Src0->ChangeToImmediate(MovSrc.getImm());
        ConstantFolded = true;
      } else if (MovSrc.isFPImm()) {
        const ConstantFP *CFP = MovSrc.getFPImm();
        if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle) {
          Src0->ChangeToFPImmediate(CFP);
          ConstantFolded = true;
        }
      }
      if (ConstantFolded) {
        if (MRI.use_empty(Reg))
          Def->eraseFromParent();
        ++NumLiteralConstantsFolded;
        return;
      }
    }
  }

  // We have failed to fold src0, so commute the instruction and try again.
  if (TryToCommute && MI.isCommutable() && TII->commuteInstruction(&MI))
    foldImmediates(MI, TII, MRI, false);

}

bool SIShrinkInstructions::runOnMachineFunction(MachineFunction &MF) {
  MachineRegisterInfo &MRI = MF.getRegInfo();
  const SIInstrInfo *TII =
      static_cast<const SIInstrInfo *>(MF.getSubtarget().getInstrInfo());
  const SIRegisterInfo &TRI = TII->getRegisterInfo();
  std::vector<unsigned> I1Defs;

  for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
                                                  BI != BE; ++BI) {

    MachineBasicBlock &MBB = *BI;
    MachineBasicBlock::iterator I, Next;
    for (I = MBB.begin(); I != MBB.end(); I = Next) {
      Next = std::next(I);
      MachineInstr &MI = *I;

      if (!TII->hasVALU32BitEncoding(MI.getOpcode()))
        continue;

      if (!canShrink(MI, TII, TRI, MRI)) {
        // Try commuting the instruction and see if that enables us to shrink
        // it.
        if (!MI.isCommutable() || !TII->commuteInstruction(&MI) ||
            !canShrink(MI, TII, TRI, MRI))
          continue;
      }

      int Op32 = AMDGPU::getVOPe32(MI.getOpcode());

      // Op32 could be -1 here if we started with an instruction that had a
      // a 32-bit encoding and then commuted it to an instruction that did not.
      if (Op32 == -1)
        continue;

      if (TII->isVOPC(Op32)) {
        unsigned DstReg = MI.getOperand(0).getReg();
        if (TargetRegisterInfo::isVirtualRegister(DstReg)) {
          // VOPC instructions can only write to the VCC register.  We can't
          // force them to use VCC here, because the register allocator has
          // trouble with sequences like this, which cause the allocator to run
          // out of registers if vreg0 and vreg1 belong to the VCCReg register
          // class:
          // vreg0 = VOPC;
          // vreg1 = VOPC;
          // S_AND_B64 vreg0, vreg1
          //
          // So, instead of forcing the instruction to write to VCC, we provide
          // a hint to the register allocator to use VCC and then we we will run
          // this pass again after RA and shrink it if it outputs to VCC.
          MRI.setRegAllocationHint(MI.getOperand(0).getReg(), 0, AMDGPU::VCC);
          continue;
        }
        if (DstReg != AMDGPU::VCC)
          continue;
      }

      // We can shrink this instruction
      DEBUG(dbgs() << "Shrinking "; MI.dump(); dbgs() << '\n';);

      MachineInstrBuilder Inst32 =
          BuildMI(MBB, I, MI.getDebugLoc(), TII->get(Op32));

      // dst
      Inst32.addOperand(MI.getOperand(0));

      Inst32.addOperand(*TII->getNamedOperand(MI, AMDGPU::OpName::src0));

      const MachineOperand *Src1 =
          TII->getNamedOperand(MI, AMDGPU::OpName::src1);
      if (Src1)
        Inst32.addOperand(*Src1);

      ++NumInstructionsShrunk;
      MI.eraseFromParent();

      foldImmediates(*Inst32, TII, MRI);
      DEBUG(dbgs() << "e32 MI = " << *Inst32 << '\n');

    }
  }
  return false;
}
<|endoftext|>


<commit_before>
#include <SFML/Config.hpp>
#include <SFML/Graphics.hpp>
#include <sfeMovie/Movie.hpp>
#include <iostream>
#include <algorithm>

/*
 * Here is a little use sample for sfeMovie.
 * It'll open and display the movie specified by MOVIE_FILE above.
 *
 * This sample implements basic controls as follow:
 *  - Escape key to exit
 *  - Space key to play/pause the movie playback
 *  - S key to stop and go back to the beginning of the movie
 *  - F key to toggle between windowed and fullscreen mode
 *  - A key to select the next audio stream
 *  - V key to select the next video stream
 */

void my_pause()
{
#ifdef SFML_SYSTEM_WINDOWS
    system("PAUSE");
#endif
}

std::string StatusToString(sfe::Status status)
{
    switch (status)
    {
        case sfe::Stopped:  return "Stopped";
        case sfe::Paused:   return "Paused";
        case sfe::Playing:  return "Playing";
        default:            return "unknown status";
    }
}

std::string mediaTypeToString(sfe::MediaType type)
{
    switch (type)
    {
        case sfe::Audio:    return "audio";
        case sfe::Subtitle:    return "subtitle";
        case sfe::Video:    return "video";
        case sfe::Unknown:    return "unknown";
        default:            return "(null)";
    }
}

void drawControls(sf::RenderWindow& window, const sfe::Movie& movie)
{
    const int kHorizontalMargin = 10;
    const int kVerticalMargin = 10;
    const int kTimelineBackgroundHeight = 20;
    const int kTimelineInnerMargin = 4;

    sf::RectangleShape background(sf::Vector2f(window.getSize().x - 2 * kHorizontalMargin, kTimelineBackgroundHeight));
    background.setPosition(kHorizontalMargin, window.getSize().y - kTimelineBackgroundHeight - kVerticalMargin);
    background.setFillColor(sf::Color(0, 0, 0, 255/2));

    sf::RectangleShape border(sf::Vector2f(background.getSize().x - 2 * kTimelineInnerMargin, background.getSize().y - 2 * kTimelineInnerMargin));
    border.setPosition(background.getPosition().x + kTimelineInnerMargin, background.getPosition().y + kTimelineInnerMargin);
    border.setFillColor(sf::Color::Transparent);
    border.setOutlineColor(sf::Color::White);
    border.setOutlineThickness(1.0);

    float fprogress = movie.getPlayingOffset().asSeconds() / movie.getDuration().asSeconds();
    sf::RectangleShape progress(sf::Vector2f(1, border.getSize().y - 2 * border.getOutlineThickness()));
    progress.setPosition(border.getPosition().x + border.getOutlineThickness() + fprogress * (border.getSize().x - 2 * border.getOutlineThickness()), border.getPosition().y + border.getOutlineThickness());
    progress.setFillColor(sf::Color::White);

    window.draw(background);
    window.draw(border);
    window.draw(progress);
}

void printMovieInfo(const sfe::Movie& movie)
{
    std::cout << "Status: " << StatusToString(movie.getStatus()) << std::endl;
    std::cout << "Position: " << movie.getPlayingOffset().asSeconds() << "s" << std::endl;
    std::cout << "Duration: " << movie.getDuration().asSeconds() << "s" << std::endl;
    std::cout << "Size: " << movie.getSize().x << "x" << movie.getSize().y << std::endl;
    std::cout << "Framerate: " << movie.getFramerate() << " FPS (average)" << std::endl;
    std::cout << "Volume: " << movie.getVolume() << std::endl;
    std::cout << "Sample rate: " << movie.getSampleRate() << std::endl;
    std::cout << "Channel count: " << movie.getChannelCount() << std::endl;

    const sfe::Streams& videoStreams = movie.getStreams(sfe::Video);
    const sfe::Streams& audioStreams = movie.getStreams(sfe::Audio);

    std::cout << videoStreams.size() + audioStreams.size() << " streams found in the media" << std::endl;

    for (sfe::Streams::const_iterator it = videoStreams.begin(); it != videoStreams.end(); ++it)
    {
        std::cout << " #" << it->identifier << " : " << mediaTypeToString(it->type) << std::endl;
    }

    for (sfe::Streams::const_iterator it = audioStreams.begin(); it != audioStreams.end(); ++it)
    {
        std::cout << " #" << it->identifier << " : " << mediaTypeToString(it->type);

        if (!it->language.empty())
            std::cout << " (language: " << it->language << ")";
        std::cout << std::endl;
    }
}

int main(int argc, const char *argv[])
{
    if (argc < 2)
    {
        std::cout << "Usage: " << std::string(argv[0]) << " movie_path" << std::endl;
        my_pause();
        return 1;
    }

    std::string mediaFile = std::string(argv[1]);
    std::cout << "Going to open movie file \"" << mediaFile << "\"" << std::endl;

    sfe::Movie movie;
    if (!movie.openFromFile(mediaFile))
    {
        my_pause();
        return 1;
    }

    bool fullscreen = false;
    sf::VideoMode desktopMode = sf::VideoMode::getDesktopMode();
    int width = std::min((int)desktopMode.width, movie.getSize().x);
    int height = std::min((int)desktopMode.height, movie.getSize().y);

    // Create window
    sf::RenderWindow window(sf::VideoMode(width, height), "sfeMovie Player",
                            sf::Style::Close | sf::Style::Resize);
    movie.fit(0, 0, width, height);
    printMovieInfo(movie);

    // Allow stream selection
    const sfe::Streams& audioStreams = movie.getStreams(sfe::Audio);
    const sfe::Streams& videoStreams = movie.getStreams(sfe::Video);
    const sfe::Streams& subtitleStreams = movie.getStreams(sfe::Subtitle);
    int selectedVideoStreamId = 0;
    int selectedAudioStreamId = 0;
    int selectedSubtitleStreamId = 0;

    // Scale movie to the window drawing area and enable VSync
    window.setFramerateLimit(60);
    window.setVerticalSyncEnabled(true);
    movie.play();

    while (window.isOpen())
    {
        sf::Event ev;
        while (window.pollEvent(ev))
        {
            // Window closure
            if (ev.type == sf::Event::Closed ||
                (ev.type == sf::Event::KeyPressed &&
                 ev.key.code == sf::Keyboard::Escape))
            {
                window.close();
            }

            if (ev.type == sf::Event::KeyPressed)
            {
                if (ev.key.code == sf::Keyboard::Space)
                {
                    if (movie.getStatus() == sfe::Playing)
                    {
                        movie.pause();
                    }
                    else
                    {
                        movie.play();
                    }
                }
                else if (ev.key.code == sf::Keyboard::P)
                {
                    movie.stop();
                }
                else if (ev.key.code == sf::Keyboard::F)
                {
                    fullscreen = !fullscreen;

                    if (fullscreen)
                        window.create(desktopMode, "sfeMovie Player", sf::Style::Fullscreen);
                    else
                        window.create(sf::VideoMode(width, height), "sfeMovie Player",
                                      sf::Style::Close | sf::Style::Resize);

                    movie.fit(0, 0, window.getSize().x, window.getSize().y);
                }
                else if (ev.key.code == sf::Keyboard::P)
                {
                    printMovieInfo(movie);
                }
                else if (ev.key.code == sf::Keyboard::V)
                {
                    if (videoStreams.size() > 1)
                    {
                        selectedVideoStreamId++;
                        selectedVideoStreamId %= videoStreams.size();
                        movie.selectStream(videoStreams[selectedVideoStreamId]);
                        std::cout << "Selected video stream #" << videoStreams[selectedVideoStreamId].identifier
                        << std::endl;
                    }
                }
                else if (ev.key.code == sf::Keyboard::A)
                {
                    if (audioStreams.size() > 1)
                    {
                        selectedAudioStreamId++;
                        selectedAudioStreamId %= audioStreams.size();
                        movie.selectStream(audioStreams[selectedAudioStreamId]);
                        std::cout << "Selected audio stream #" << audioStreams[selectedAudioStreamId].identifier
                        << std::endl;
                    }
                }
                else if (ev.key.code == sf::Keyboard::S)
                {
                    if (subtitleStreams.size() > 1)
                    {
                        selectedSubtitleStreamId++;
                        selectedSubtitleStreamId %= subtitleStreams.size();
                        movie.selectStream(subtitleStreams[selectedSubtitleStreamId]);
                        std::cout << "Selected subtitle stream #" << subtitleStreams[selectedSubtitleStreamId].identifier
                            << std::endl;
                    }
                }
            }
            else if (ev.type == sf::Event::MouseWheelMoved)
            {
                float volume = movie.getVolume() + 10 * ev.mouseWheel.delta;
                volume = std::min(volume, 100.f);
                volume = std::max(volume, 0.f);
                movie.setVolume(volume);
            }
            else if (ev.type == sf::Event::Resized)
            {
                movie.fit(0, 0, window.getSize().x, window.getSize().y);
                window.setView(sf::View(sf::FloatRect(0, 0, window.getSize().x, window.getSize().y)));
            }
        }

        movie.update();

        // Render movie
        window.clear();
        window.draw(movie);
        drawControls(window, movie);
        window.display();
    }

    return 0;
}

<commit_msg>#7 DIsplay correct info about the available subtitle streams<commit_after>
#include <SFML/Config.hpp>
#include <SFML/Graphics.hpp>
#include <sfeMovie/Movie.hpp>
#include <iostream>
#include <algorithm>

/*
 * Here is a little use sample for sfeMovie.
 * It'll open and display the movie specified by MOVIE_FILE above.
 *
 * This sample implements basic controls as follow:
 *  - Escape key to exit
 *  - Space key to play/pause the movie playback
 *  - S key to stop and go back to the beginning of the movie
 *  - F key to toggle between windowed and fullscreen mode
 *  - A key to select the next audio stream
 *  - V key to select the next video stream
 */

void my_pause()
{
#ifdef SFML_SYSTEM_WINDOWS
    system("PAUSE");
#endif
}

std::string StatusToString(sfe::Status status)
{
    switch (status)
    {
        case sfe::Stopped:  return "Stopped";
        case sfe::Paused:   return "Paused";
        case sfe::Playing:  return "Playing";
        default:            return "unknown status";
    }
}

std::string mediaTypeToString(sfe::MediaType type)
{
    switch (type)
    {
        case sfe::Audio:    return "audio";
        case sfe::Subtitle:    return "subtitle";
        case sfe::Video:    return "video";
        case sfe::Unknown:    return "unknown";
        default:            return "(null)";
    }
}

void drawControls(sf::RenderWindow& window, const sfe::Movie& movie)
{
    const int kHorizontalMargin = 10;
    const int kVerticalMargin = 10;
    const int kTimelineBackgroundHeight = 20;
    const int kTimelineInnerMargin = 4;

    sf::RectangleShape background(sf::Vector2f(window.getSize().x - 2 * kHorizontalMargin, kTimelineBackgroundHeight));
    background.setPosition(kHorizontalMargin, window.getSize().y - kTimelineBackgroundHeight - kVerticalMargin);
    background.setFillColor(sf::Color(0, 0, 0, 255/2));

    sf::RectangleShape border(sf::Vector2f(background.getSize().x - 2 * kTimelineInnerMargin, background.getSize().y - 2 * kTimelineInnerMargin));
    border.setPosition(background.getPosition().x + kTimelineInnerMargin, background.getPosition().y + kTimelineInnerMargin);
    border.setFillColor(sf::Color::Transparent);
    border.setOutlineColor(sf::Color::White);
    border.setOutlineThickness(1.0);

    float fprogress = movie.getPlayingOffset().asSeconds() / movie.getDuration().asSeconds();
    sf::RectangleShape progress(sf::Vector2f(1, border.getSize().y - 2 * border.getOutlineThickness()));
    progress.setPosition(border.getPosition().x + border.getOutlineThickness() + fprogress * (border.getSize().x - 2 * border.getOutlineThickness()), border.getPosition().y + border.getOutlineThickness());
    progress.setFillColor(sf::Color::White);

    window.draw(background);
    window.draw(border);
    window.draw(progress);
}

void printMovieInfo(const sfe::Movie& movie)
{
    std::cout << "Status: " << StatusToString(movie.getStatus()) << std::endl;
    std::cout << "Position: " << movie.getPlayingOffset().asSeconds() << "s" << std::endl;
    std::cout << "Duration: " << movie.getDuration().asSeconds() << "s" << std::endl;
    std::cout << "Size: " << movie.getSize().x << "x" << movie.getSize().y << std::endl;
    std::cout << "Framerate: " << movie.getFramerate() << " FPS (average)" << std::endl;
    std::cout << "Volume: " << movie.getVolume() << std::endl;
    std::cout << "Sample rate: " << movie.getSampleRate() << std::endl;
    std::cout << "Channel count: " << movie.getChannelCount() << std::endl;

    const sfe::Streams& videoStreams = movie.getStreams(sfe::Video);
    const sfe::Streams& audioStreams = movie.getStreams(sfe::Audio);
    const sfe::Streams& subtitleStreams = movie.getStreams(sfe::Subtitle);

    std::cout << videoStreams.size() + audioStreams.size() + subtitleStreams.size() << " streams found in the media" << std::endl;

    for (sfe::Streams::const_iterator it = videoStreams.begin(); it != videoStreams.end(); ++it)
    {
        std::cout << " #" << it->identifier << " : " << mediaTypeToString(it->type) << std::endl;
    }

    for (sfe::Streams::const_iterator it = audioStreams.begin(); it != audioStreams.end(); ++it)
    {
        std::cout << " #" << it->identifier << " : " << mediaTypeToString(it->type);

        if (!it->language.empty())
            std::cout << " (language: " << it->language << ")";
        std::cout << std::endl;
    }

    for (sfe::Streams::const_iterator it = subtitleStreams.begin(); it != subtitleStreams.end(); ++it)
    {
        std::cout << " #" << it->identifier << " : " << mediaTypeToString(it->type);

        if (!it->language.empty())
            std::cout << " (language: " << it->language << ")";
        std::cout << std::endl;
    }
}

int main(int argc, const char *argv[])
{
    if (argc < 2)
    {
        std::cout << "Usage: " << std::string(argv[0]) << " movie_path" << std::endl;
        my_pause();
        return 1;
    }

    std::string mediaFile = std::string(argv[1]);
    std::cout << "Going to open movie file \"" << mediaFile << "\"" << std::endl;

    sfe::Movie movie;
    if (!movie.openFromFile(mediaFile))
    {
        my_pause();
        return 1;
    }

    bool fullscreen = false;
    sf::VideoMode desktopMode = sf::VideoMode::getDesktopMode();
    int width = std::min((int)desktopMode.width, movie.getSize().x);
    int height = std::min((int)desktopMode.height, movie.getSize().y);

    // Create window
    sf::RenderWindow window(sf::VideoMode(width, height), "sfeMovie Player",
                            sf::Style::Close | sf::Style::Resize);
    movie.fit(0, 0, width, height);
    printMovieInfo(movie);

    // Allow stream selection
    const sfe::Streams& audioStreams = movie.getStreams(sfe::Audio);
    const sfe::Streams& videoStreams = movie.getStreams(sfe::Video);
    const sfe::Streams& subtitleStreams = movie.getStreams(sfe::Subtitle);
    int selectedVideoStreamId = 0;
    int selectedAudioStreamId = 0;
    int selectedSubtitleStreamId = 0;

    // Scale movie to the window drawing area and enable VSync
    window.setFramerateLimit(60);
    window.setVerticalSyncEnabled(true);
    movie.play();

    while (window.isOpen())
    {
        sf::Event ev;
        while (window.pollEvent(ev))
        {
            // Window closure
            if (ev.type == sf::Event::Closed ||
                (ev.type == sf::Event::KeyPressed &&
                 ev.key.code == sf::Keyboard::Escape))
            {
                window.close();
            }

            if (ev.type == sf::Event::KeyPressed)
            {
                if (ev.key.code == sf::Keyboard::Space)
                {
                    if (movie.getStatus() == sfe::Playing)
                    {
                        movie.pause();
                    }
                    else
                    {
                        movie.play();
                    }
                }
                else if (ev.key.code == sf::Keyboard::P)
                {
                    movie.stop();
                }
                else if (ev.key.code == sf::Keyboard::F)
                {
                    fullscreen = !fullscreen;

                    if (fullscreen)
                        window.create(desktopMode, "sfeMovie Player", sf::Style::Fullscreen);
                    else
                        window.create(sf::VideoMode(width, height), "sfeMovie Player",
                                      sf::Style::Close | sf::Style::Resize);

                    movie.fit(0, 0, window.getSize().x, window.getSize().y);
                }
                else if (ev.key.code == sf::Keyboard::I)
                {
                    printMovieInfo(movie);
                }
                else if (ev.key.code == sf::Keyboard::V)
                {
                    if (videoStreams.size() > 1)
                    {
                        selectedVideoStreamId++;
                        selectedVideoStreamId %= videoStreams.size();
                        movie.selectStream(videoStreams[selectedVideoStreamId]);
                        std::cout << "Selected video stream #" << videoStreams[selectedVideoStreamId].identifier
                        << std::endl;
                    }
                }
                else if (ev.key.code == sf::Keyboard::A)
                {
                    if (audioStreams.size() > 1)
                    {
                        selectedAudioStreamId++;
                        selectedAudioStreamId %= audioStreams.size();
                        movie.selectStream(audioStreams[selectedAudioStreamId]);
                        std::cout << "Selected audio stream #" << audioStreams[selectedAudioStreamId].identifier
                        << std::endl;
                    }
                }
                else if (ev.key.code == sf::Keyboard::S)
                {
                    if (subtitleStreams.size() > 0)
                    {
                        selectedSubtitleStreamId++;
                        selectedSubtitleStreamId %= subtitleStreams.size() + 1;

                        if (selectedSubtitleStreamId == subtitleStreams.size())
                        {
                            movie.selectStream(sfe::StreamDescriptor::NoSelection(sfe::Subtitle));
                            std::cout << "Unselected subtitle stream" << std::endl;
                        }
                        else
                        {
                            movie.selectStream(subtitleStreams[selectedSubtitleStreamId]);
                            std::cout << "Selected subtitle stream #" << subtitleStreams[selectedSubtitleStreamId].identifier
                            << std::endl;
                        }
                    }
                }
            }
            else if (ev.type == sf::Event::MouseWheelMoved)
            {
                float volume = movie.getVolume() + 10 * ev.mouseWheel.delta;
                volume = std::min(volume, 100.f);
                volume = std::max(volume, 0.f);
                movie.setVolume(volume);
            }
            else if (ev.type == sf::Event::Resized)
            {
                movie.fit(0, 0, window.getSize().x, window.getSize().y);
                window.setView(sf::View(sf::FloatRect(0, 0, window.getSize().x, window.getSize().y)));
            }
        }

        movie.update();

        // Render movie
        window.clear();
        window.draw(movie);
        drawControls(window, movie);
        window.display();
    }

    return 0;
}

<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/path_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/plugin/npobject_util.h"
#include "googleurl/src/url_util.h"
#include "webkit/glue/webkit_glue.h"

namespace webkit_glue {

bool GetExeDirectory(std::wstring *path) {
  return PathService::Get(base::DIR_EXE, path);
}

bool GetApplicationDirectory(std::wstring *path) {
  return PathService::Get(chrome::DIR_APP, path);
}

bool IsPluginRunningInRendererProcess() {
  return !IsPluginProcess();
}

std::wstring GetWebKitLocale() {
  // The browser process should have passed the locale to the renderer via the
  // --lang command line flag.
  CommandLine parsed_command_line;
  const std::wstring& lang =
      parsed_command_line.GetSwitchValue(switches::kLang);
  DCHECK(!lang.empty());
  return lang;
}

std::wstring GetLocalizedString(int message_id) {
  return ResourceBundle::GetSharedInstance().GetLocalizedString(message_id);
}

}  // namespace webkit_glue

<commit_msg>Allow lang to be blank in the renderer and plugin if running in single process mode. Review URL: http://codereview.chromium.org/5602<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/path_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/plugin/npobject_util.h"
#include "googleurl/src/url_util.h"
#include "webkit/glue/webkit_glue.h"

namespace webkit_glue {

bool GetExeDirectory(std::wstring *path) {
  return PathService::Get(base::DIR_EXE, path);
}

bool GetApplicationDirectory(std::wstring *path) {
  return PathService::Get(chrome::DIR_APP, path);
}

bool IsPluginRunningInRendererProcess() {
  return !IsPluginProcess();
}

std::wstring GetWebKitLocale() {
  // The browser process should have passed the locale to the renderer via the
  // --lang command line flag.  In single process mode, this will return the
  // wrong value.  TODO(tc): Fix this for single process mode.
  CommandLine parsed_command_line;
  const std::wstring& lang =
      parsed_command_line.GetSwitchValue(switches::kLang);
  DCHECK(!lang.empty() ||
      (!parsed_command_line.HasSwitch(switches::kRendererProcess) &&
       !parsed_command_line.HasSwitch(switches::kPluginProcess)));
  return lang;
}

std::wstring GetLocalizedString(int message_id) {
  return ResourceBundle::GetSharedInstance().GetLocalizedString(message_id);
}

}  // namespace webkit_glue

<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/ipc_message.h"

#include "base/logging.h"
#include "build/build_config.h"

namespace IPC {

//------------------------------------------------------------------------------

Message::~Message() {
}

Message::Message()
    : Pickle(sizeof(Header)) {
  header()->routing = header()->type = header()->flags = 0;
#if defined(OS_POSIX)
  header()->num_fds = 0;
#endif
  InitLoggingVariables();
}

Message::Message(int32 routing_id, uint16 type, PriorityValue priority)
    : Pickle(sizeof(Header)) {
  header()->routing = routing_id;
  header()->type = type;
  header()->flags = priority;
#if defined(OS_POSIX)
  header()->num_fds = 0;
#endif
  InitLoggingVariables();
}

Message::Message(const char* data, int data_len) : Pickle(data, data_len) {
  InitLoggingVariables();
}

Message::Message(const Message& other) : Pickle(other) {
  InitLoggingVariables();
  descriptor_set_.TakeFrom(&other.descriptor_set_);
}

void Message::InitLoggingVariables() {
#ifdef IPC_MESSAGE_LOG_ENABLED
  received_time_ = 0;
  dont_log_ = false;
  log_data_ = NULL;
#endif
}

Message& Message::operator=(const Message& other) {
  *static_cast<Pickle*>(this) = other;
  return *this;
}

#ifdef IPC_MESSAGE_LOG_ENABLED
void Message::set_sent_time(int64 time) {
  DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
  header()->flags |= HAS_SENT_TIME_BIT;
  WriteInt64(time);
}

int64 Message::sent_time() const {
  if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
    return 0;

  const char* data = end_of_payload();
  data -= sizeof(int64);
  return *(reinterpret_cast<const int64*>(data));
}

void Message::set_received_time(int64 time) const {
  received_time_ = time;
}
#endif

}  // namespace IPC

<commit_msg>Windows: build fix<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/ipc_message.h"

#include "base/logging.h"
#include "build/build_config.h"

namespace IPC {

//------------------------------------------------------------------------------

Message::~Message() {
}

Message::Message()
    : Pickle(sizeof(Header)) {
  header()->routing = header()->type = header()->flags = 0;
#if defined(OS_POSIX)
  header()->num_fds = 0;
#endif
  InitLoggingVariables();
}

Message::Message(int32 routing_id, uint16 type, PriorityValue priority)
    : Pickle(sizeof(Header)) {
  header()->routing = routing_id;
  header()->type = type;
  header()->flags = priority;
#if defined(OS_POSIX)
  header()->num_fds = 0;
#endif
  InitLoggingVariables();
}

Message::Message(const char* data, int data_len) : Pickle(data, data_len) {
  InitLoggingVariables();
}

Message::Message(const Message& other) : Pickle(other) {
  InitLoggingVariables();
#if defined(OS_POSIX)
  descriptor_set_.TakeFrom(&other.descriptor_set_);
#endif
}

void Message::InitLoggingVariables() {
#ifdef IPC_MESSAGE_LOG_ENABLED
  received_time_ = 0;
  dont_log_ = false;
  log_data_ = NULL;
#endif
}

Message& Message::operator=(const Message& other) {
  *static_cast<Pickle*>(this) = other;
  return *this;
}

#ifdef IPC_MESSAGE_LOG_ENABLED
void Message::set_sent_time(int64 time) {
  DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
  header()->flags |= HAS_SENT_TIME_BIT;
  WriteInt64(time);
}

int64 Message::sent_time() const {
  if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
    return 0;

  const char* data = end_of_payload();
  data -= sizeof(int64);
  return *(reinterpret_cast<const int64*>(data));
}

void Message::set_received_time(int64 time) const {
  received_time_ = time;
}
#endif

}  // namespace IPC

<|endoftext|>


<commit_before>//===- IndVarSimplify.cpp - Induction Variable Elimination ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Guarantees that all loops with identifiable, linear, induction variables will
// be transformed to have a single, canonical, induction variable.  After this
// pass runs, it guarantees the the first PHI node of the header block in the
// loop is the canonical induction variable if there is one.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/CFG.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
using namespace llvm;

namespace {
  Statistic<> NumRemoved ("indvars", "Number of aux indvars removed");
  Statistic<> NumInserted("indvars", "Number of canonical indvars added");

  class IndVarSimplify : public FunctionPass {
    LoopInfo *Loops;
    TargetData *TD;
  public:
    virtual bool runOnFunction(Function &) {
      Loops = &getAnalysis<LoopInfo>();
      TD = &getAnalysis<TargetData>();

      // Induction Variables live in the header nodes of loops
      bool Changed = false;
      for (unsigned i = 0, e = Loops->getTopLevelLoops().size(); i != e; ++i)
        Changed |= runOnLoop(Loops->getTopLevelLoops()[i]);
      return Changed;
    }

    unsigned getTypeSize(const Type *Ty) {
      if (unsigned Size = Ty->getPrimitiveSize())
        return Size;
      return TD->getTypeSize(Ty);  // Must be a pointer
    }

    Value *ComputeAuxIndVarValue(InductionVariable &IV, Value *CIV);
    void ReplaceIndVar(InductionVariable &IV, Value *Counter);

    bool runOnLoop(Loop *L);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<TargetData>();   // Need pointer size
      AU.addRequired<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.addPreservedID(LoopSimplifyID);
      AU.setPreservesCFG();
    }
  };
  RegisterOpt<IndVarSimplify> X("indvars", "Canonicalize Induction Variables");
}

Pass *llvm::createIndVarSimplifyPass() {
  return new IndVarSimplify();
}

bool IndVarSimplify::runOnLoop(Loop *Loop) {
  // Transform all subloops before this loop...
  bool Changed = false;
  for (unsigned i = 0, e = Loop->getSubLoops().size(); i != e; ++i)
    Changed |= runOnLoop(Loop->getSubLoops()[i]);

  // Get the header node for this loop.  All of the phi nodes that could be
  // induction variables must live in this basic block.
  //
  BasicBlock *Header = Loop->getHeader();

  // Loop over all of the PHI nodes in the basic block, calculating the
  // induction variables that they represent... stuffing the induction variable
  // info into a vector...
  //
  std::vector<InductionVariable> IndVars;    // Induction variables for block
  BasicBlock::iterator AfterPHIIt = Header->begin();
  for (; PHINode *PN = dyn_cast<PHINode>(AfterPHIIt); ++AfterPHIIt)
    IndVars.push_back(InductionVariable(PN, Loops));
  // AfterPHIIt now points to first non-phi instruction...

  // If there are no phi nodes in this basic block, there can't be indvars...
  if (IndVars.empty()) return Changed;

  // Loop over the induction variables, looking for a canonical induction
  // variable, and checking to make sure they are not all unknown induction
  // variables.  Keep track of the largest integer size of the induction
  // variable.
  //
  InductionVariable *Canonical = 0;
  unsigned MaxSize = 0;

  for (unsigned i = 0; i != IndVars.size(); ++i) {
    InductionVariable &IV = IndVars[i];

    if (IV.InductionType != InductionVariable::Unknown) {
      unsigned IVSize = getTypeSize(IV.Phi->getType());

      if (IV.InductionType == InductionVariable::Canonical &&
          !isa<PointerType>(IV.Phi->getType()) && IVSize >= MaxSize)
        Canonical = &IV;

      if (IVSize > MaxSize) MaxSize = IVSize;

      // If this variable is larger than the currently identified canonical
      // indvar, the canonical indvar is not usable.
      if (Canonical && IVSize > getTypeSize(Canonical->Phi->getType()))
        Canonical = 0;
    }
  }

  // No induction variables, bail early... don't add a canonical indvar
  if (MaxSize == 0) return Changed;

  // Okay, we want to convert other induction variables to use a canonical
  // indvar.  If we don't have one, add one now...
  if (!Canonical) {
    // Create the PHI node for the new induction variable, and insert the phi
    // node at the start of the PHI nodes...
    const Type *IVType;
    switch (MaxSize) {
    default: assert(0 && "Unknown integer type size!");
    case 1: IVType = Type::UByteTy; break;
    case 2: IVType = Type::UShortTy; break;
    case 4: IVType = Type::UIntTy; break;
    case 8: IVType = Type::ULongTy; break;
    }

    PHINode *PN = new PHINode(IVType, "cann-indvar", Header->begin());

    // Create the increment instruction to add one to the counter...
    Instruction *Add = BinaryOperator::create(Instruction::Add, PN,
                                              ConstantUInt::get(IVType, 1),
                                              "next-indvar", AfterPHIIt);

    // Figure out which block is incoming and which is the backedge for the loop
    BasicBlock *Incoming, *BackEdgeBlock;
    pred_iterator PI = pred_begin(Header);
    assert(PI != pred_end(Header) && "Loop headers should have 2 preds!");
    if (Loop->contains(*PI)) {  // First pred is back edge...
      BackEdgeBlock = *PI++;
      Incoming      = *PI++;
    } else {
      Incoming      = *PI++;
      BackEdgeBlock = *PI++;
    }
    assert(PI == pred_end(Header) && "Loop headers should have 2 preds!");

    // Add incoming values for the PHI node...
    PN->addIncoming(Constant::getNullValue(IVType), Incoming);
    PN->addIncoming(Add, BackEdgeBlock);

    // Analyze the new induction variable...
    IndVars.push_back(InductionVariable(PN, Loops));
    assert(IndVars.back().InductionType == InductionVariable::Canonical &&
           "Just inserted canonical indvar that is not canonical!");
    Canonical = &IndVars.back();
    ++NumInserted;
    Changed = true;
  } else {
    // If we have a canonical induction variable, make sure that it is the first
    // one in the basic block.
    if (&Header->front() != Canonical->Phi)
      Header->getInstList().splice(Header->begin(), Header->getInstList(),
                                   Canonical->Phi);
  }

  DEBUG(std::cerr << "Induction variables:\n");

  // Get the current loop iteration count, which is always the value of the
  // canonical phi node...
  //
  PHINode *IterCount = Canonical->Phi;

  // Loop through and replace all of the auxiliary induction variables with
  // references to the canonical induction variable...
  //
  for (unsigned i = 0; i != IndVars.size(); ++i) {
    InductionVariable *IV = &IndVars[i];

    DEBUG(IV->print(std::cerr));

    // Don't modify the canonical indvar or unrecognized indvars...
    if (IV != Canonical && IV->InductionType != InductionVariable::Unknown) {
      ReplaceIndVar(*IV, IterCount);
      Changed = true;
      ++NumRemoved;
    }
  }

  return Changed;
}

/// ComputeAuxIndVarValue - Given an auxillary induction variable, compute and
/// return a value which will always be equal to the induction variable PHI, but
/// is based off of the canonical induction variable CIV.
///
Value *IndVarSimplify::ComputeAuxIndVarValue(InductionVariable &IV, Value *CIV){
  Instruction *Phi = IV.Phi;
  const Type *IVTy = Phi->getType();
  if (isa<PointerType>(IVTy))    // If indexing into a pointer, make the
    IVTy = TD->getIntPtrType();  // index the appropriate type.

  BasicBlock::iterator AfterPHIIt = Phi;
  while (isa<PHINode>(AfterPHIIt)) ++AfterPHIIt;

  Value *Val = CIV;
  if (Val->getType() != IVTy)
    Val = new CastInst(Val, IVTy, Val->getName(), AfterPHIIt);

  if (!isa<ConstantInt>(IV.Step) ||   // If the step != 1
      !cast<ConstantInt>(IV.Step)->equalsInt(1)) {

    // If the types are not compatible, insert a cast now...
    if (IV.Step->getType() != IVTy)
      IV.Step = new CastInst(IV.Step, IVTy, IV.Step->getName(), AfterPHIIt);

    Val = BinaryOperator::create(Instruction::Mul, Val, IV.Step,
                                 Phi->getName()+"-scale", AfterPHIIt);
  }

  // If this is a pointer indvar...
  if (isa<PointerType>(Phi->getType())) {
    std::vector<Value*> Idx;
    // FIXME: this should not be needed when we fix PR82!
    if (Val->getType() != Type::LongTy)
      Val = new CastInst(Val, Type::LongTy, Val->getName(), AfterPHIIt);
    Idx.push_back(Val);
    Val = new GetElementPtrInst(IV.Start, Idx,
                                Phi->getName()+"-offset",
                                AfterPHIIt);

  } else if (!isa<Constant>(IV.Start) ||   // If Start != 0...
             !cast<Constant>(IV.Start)->isNullValue()) {
    // If the types are not compatible, insert a cast now...
    if (IV.Start->getType() != IVTy)
      IV.Start = new CastInst(IV.Start, IVTy, IV.Start->getName(),
                               AfterPHIIt);

    // Insert the instruction after the phi nodes...
    Val = BinaryOperator::create(Instruction::Add, Val, IV.Start,
                                 Phi->getName()+"-offset", AfterPHIIt);
  }

  // If the PHI node has a different type than val is, insert a cast now...
  if (Val->getType() != Phi->getType())
    Val = new CastInst(Val, Phi->getType(), Val->getName(), AfterPHIIt);

  // Move the PHI name to it's new equivalent value...
  std::string OldName = Phi->getName();
  Phi->setName("");
  Val->setName(OldName);

  return Val;
}

// ReplaceIndVar - Replace all uses of the specified induction variable with
// expressions computed from the specified loop iteration counter variable.
// Return true if instructions were deleted.
void IndVarSimplify::ReplaceIndVar(InductionVariable &IV, Value *CIV) {
  Value *IndVarVal = 0;
  PHINode *Phi = IV.Phi;

  assert(Phi->getNumOperands() == 4 &&
         "Only expect induction variables in canonical loops!");

  // Remember the incoming values used by the PHI node
  std::vector<Value*> PHIOps;
  PHIOps.reserve(2);
  PHIOps.push_back(Phi->getIncomingValue(0));
  PHIOps.push_back(Phi->getIncomingValue(1));

  // Delete all of the operands of the PHI node... FIXME, this should be more
  // intelligent.
  Phi->dropAllReferences();

  // Now that we are rid of unneeded uses of the PHI node, replace any remaining
  // ones with the appropriate code using the canonical induction variable.
  while (!Phi->use_empty()) {
    Instruction *U = cast<Instruction>(Phi->use_back());

    // TODO: Perform LFTR here if possible
    if (0) {

    } else {
      // Replace all uses of the old PHI node with the new computed value...
      if (IndVarVal == 0)
        IndVarVal = ComputeAuxIndVarValue(IV, CIV);
      U->replaceUsesOfWith(Phi, IndVarVal);
    }
  }

  // If the PHI is the last user of any instructions for computing PHI nodes
  // that are irrelevant now, delete those instructions.
  while (!PHIOps.empty()) {
    Instruction *MaybeDead = dyn_cast<Instruction>(PHIOps.back());
    PHIOps.pop_back();

    if (MaybeDead && isInstructionTriviallyDead(MaybeDead) &&
        (!isa<PHINode>(MaybeDead) ||
         MaybeDead->getParent() != Phi->getParent())) {
      PHIOps.insert(PHIOps.end(), MaybeDead->op_begin(),
                    MaybeDead->op_end());
      MaybeDead->getParent()->getInstList().erase(MaybeDead);

      // Erase any duplicates entries in the PHIOps list.
      std::vector<Value*>::iterator It =
        std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
      while (It != PHIOps.end()) {
        PHIOps.erase(It);
        It = std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
      }
    }
  }

  // Delete the old, now unused, phi node...
  Phi->getParent()->getInstList().erase(Phi);
}

<commit_msg>More minor non-functional changes.  This now computes the exit condition, though it doesn't do anything with it.<commit_after>//===- IndVarSimplify.cpp - Induction Variable Elimination ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Guarantees that all loops with identifiable, linear, induction variables will
// be transformed to have a single, canonical, induction variable.  After this
// pass runs, it guarantees the the first PHI node of the header block in the
// loop is the canonical induction variable if there is one.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "indvar"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/CFG.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
using namespace llvm;

namespace {
  Statistic<> NumRemoved ("indvars", "Number of aux indvars removed");
  Statistic<> NumInserted("indvars", "Number of canonical indvars added");

  class IndVarSimplify : public FunctionPass {
    LoopInfo *Loops;
    TargetData *TD;
    bool Changed;
  public:
    virtual bool runOnFunction(Function &) {
      Loops = &getAnalysis<LoopInfo>();
      TD = &getAnalysis<TargetData>();
      Changed = false;

      // Induction Variables live in the header nodes of loops
      for (unsigned i = 0, e = Loops->getTopLevelLoops().size(); i != e; ++i)
        runOnLoop(Loops->getTopLevelLoops()[i]);
      return Changed;
    }

    unsigned getTypeSize(const Type *Ty) {
      if (unsigned Size = Ty->getPrimitiveSize())
        return Size;
      return TD->getTypeSize(Ty);  // Must be a pointer
    }

    Value *ComputeAuxIndVarValue(InductionVariable &IV, Value *CIV);
    void ReplaceIndVar(InductionVariable &IV, Value *Counter);

    void runOnLoop(Loop *L);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<TargetData>();   // Need pointer size
      AU.addRequired<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.addPreservedID(LoopSimplifyID);
      AU.setPreservesCFG();
    }
  };
  RegisterOpt<IndVarSimplify> X("indvars", "Canonicalize Induction Variables");
}

Pass *llvm::createIndVarSimplifyPass() {
  return new IndVarSimplify();
}

void IndVarSimplify::runOnLoop(Loop *Loop) {
  // Transform all subloops before this loop...
  for (unsigned i = 0, e = Loop->getSubLoops().size(); i != e; ++i)
    runOnLoop(Loop->getSubLoops()[i]);

  // Get the header node for this loop.  All of the phi nodes that could be
  // induction variables must live in this basic block.
  //
  BasicBlock *Header = Loop->getHeader();

  // Loop over all of the PHI nodes in the basic block, calculating the
  // induction variables that they represent... stuffing the induction variable
  // info into a vector...
  //
  std::vector<InductionVariable> IndVars;    // Induction variables for block
  BasicBlock::iterator AfterPHIIt = Header->begin();
  for (; PHINode *PN = dyn_cast<PHINode>(AfterPHIIt); ++AfterPHIIt)
    IndVars.push_back(InductionVariable(PN, Loops));
  // AfterPHIIt now points to first non-phi instruction...

  // If there are no phi nodes in this basic block, there can't be indvars...
  if (IndVars.empty()) return;

  // Loop over the induction variables, looking for a canonical induction
  // variable, and checking to make sure they are not all unknown induction
  // variables.  Keep track of the largest integer size of the induction
  // variable.
  //
  InductionVariable *Canonical = 0;
  unsigned MaxSize = 0;

  for (unsigned i = 0; i != IndVars.size(); ++i) {
    InductionVariable &IV = IndVars[i];

    if (IV.InductionType != InductionVariable::Unknown) {
      unsigned IVSize = getTypeSize(IV.Phi->getType());

      if (IV.InductionType == InductionVariable::Canonical &&
          !isa<PointerType>(IV.Phi->getType()) && IVSize >= MaxSize)
        Canonical = &IV;

      if (IVSize > MaxSize) MaxSize = IVSize;

      // If this variable is larger than the currently identified canonical
      // indvar, the canonical indvar is not usable.
      if (Canonical && IVSize > getTypeSize(Canonical->Phi->getType()))
        Canonical = 0;
    }
  }

  // No induction variables, bail early... don't add a canonical indvar
  if (MaxSize == 0) return;

  // Figure out what the exit condition of the loop is.  We can currently only
  // handle loops with a single exit.  If we cannot figure out what the
  // termination condition is, we leave this variable set to null.
  //
  SetCondInst *TermCond = 0;
  if (Loop->getExitBlocks().size() == 1) {
    // Get ExitingBlock - the basic block in the loop which contains the branch
    // out of the loop.
    BasicBlock *Exit = Loop->getExitBlocks()[0];
    pred_iterator PI = pred_begin(Exit);
    assert(PI != pred_end(Exit) && "Should have one predecessor in loop!");
    BasicBlock *ExitingBlock = *PI;
    assert(++PI == pred_end(Exit) && "Exit block should have one pred!");
    assert(Loop->isLoopExit(ExitingBlock) && "Exiting block is not loop exit!");

    // Since the block is in the loop, yet branches out of it, we know that the
    // block must end with multiple destination terminator.  Which means it is
    // either a conditional branch, a switch instruction, or an invoke.
    if (BranchInst *BI = dyn_cast<BranchInst>(ExitingBlock->getTerminator())) {
      assert(BI->isConditional() && "Unconditional branch has multiple succs?");
      TermCond = dyn_cast<SetCondInst>(BI->getCondition());
    } else {
      // NOTE: if people actually exit loops with switch instructions, we could
      // handle them, but I don't think this is important enough to spend time
      // thinking about.
      assert(isa<SwitchInst>(ExitingBlock->getTerminator()) ||
             isa<InvokeInst>(ExitingBlock->getTerminator()) &&
             "Unknown multi-successor terminator!");
    }
  }

  if (TermCond)
    DEBUG(std::cerr << "INDVAR: Found termination condition: " << *TermCond);

  // Okay, we want to convert other induction variables to use a canonical
  // indvar.  If we don't have one, add one now...
  if (!Canonical) {
    // Create the PHI node for the new induction variable, and insert the phi
    // node at the start of the PHI nodes...
    const Type *IVType;
    switch (MaxSize) {
    default: assert(0 && "Unknown integer type size!");
    case 1: IVType = Type::UByteTy; break;
    case 2: IVType = Type::UShortTy; break;
    case 4: IVType = Type::UIntTy; break;
    case 8: IVType = Type::ULongTy; break;
    }

    PHINode *PN = new PHINode(IVType, "cann-indvar", Header->begin());

    // Create the increment instruction to add one to the counter...
    Instruction *Add = BinaryOperator::create(Instruction::Add, PN,
                                              ConstantUInt::get(IVType, 1),
                                              "next-indvar", AfterPHIIt);

    // Figure out which block is incoming and which is the backedge for the loop
    BasicBlock *Incoming, *BackEdgeBlock;
    pred_iterator PI = pred_begin(Header);
    assert(PI != pred_end(Header) && "Loop headers should have 2 preds!");
    if (Loop->contains(*PI)) {  // First pred is back edge...
      BackEdgeBlock = *PI++;
      Incoming      = *PI++;
    } else {
      Incoming      = *PI++;
      BackEdgeBlock = *PI++;
    }
    assert(PI == pred_end(Header) && "Loop headers should have 2 preds!");

    // Add incoming values for the PHI node...
    PN->addIncoming(Constant::getNullValue(IVType), Incoming);
    PN->addIncoming(Add, BackEdgeBlock);

    // Analyze the new induction variable...
    IndVars.push_back(InductionVariable(PN, Loops));
    assert(IndVars.back().InductionType == InductionVariable::Canonical &&
           "Just inserted canonical indvar that is not canonical!");
    Canonical = &IndVars.back();
    ++NumInserted;
    Changed = true;
    DEBUG(std::cerr << "INDVAR: Inserted canonical iv: " << *PN);
  } else {
    // If we have a canonical induction variable, make sure that it is the first
    // one in the basic block.
    if (&Header->front() != Canonical->Phi)
      Header->getInstList().splice(Header->begin(), Header->getInstList(),
                                   Canonical->Phi);
    DEBUG(std::cerr << "IndVar: Existing canonical iv used: "
                    << *Canonical->Phi);
  }

  DEBUG(std::cerr << "INDVAR: Replacing Induction variables:\n");

  // Get the current loop iteration count, which is always the value of the
  // canonical phi node...
  //
  PHINode *IterCount = Canonical->Phi;

  // Loop through and replace all of the auxiliary induction variables with
  // references to the canonical induction variable...
  //
  for (unsigned i = 0; i != IndVars.size(); ++i) {
    InductionVariable *IV = &IndVars[i];

    DEBUG(IV->print(std::cerr));

    // Don't modify the canonical indvar or unrecognized indvars...
    if (IV != Canonical && IV->InductionType != InductionVariable::Unknown) {
      ReplaceIndVar(*IV, IterCount);
      Changed = true;
      ++NumRemoved;
    }
  }
}

/// ComputeAuxIndVarValue - Given an auxillary induction variable, compute and
/// return a value which will always be equal to the induction variable PHI, but
/// is based off of the canonical induction variable CIV.
///
Value *IndVarSimplify::ComputeAuxIndVarValue(InductionVariable &IV, Value *CIV){
  Instruction *Phi = IV.Phi;
  const Type *IVTy = Phi->getType();
  if (isa<PointerType>(IVTy))    // If indexing into a pointer, make the
    IVTy = TD->getIntPtrType();  // index the appropriate type.

  BasicBlock::iterator AfterPHIIt = Phi;
  while (isa<PHINode>(AfterPHIIt)) ++AfterPHIIt;

  Value *Val = CIV;
  if (Val->getType() != IVTy)
    Val = new CastInst(Val, IVTy, Val->getName(), AfterPHIIt);

  if (!isa<ConstantInt>(IV.Step) ||   // If the step != 1
      !cast<ConstantInt>(IV.Step)->equalsInt(1)) {

    // If the types are not compatible, insert a cast now...
    if (IV.Step->getType() != IVTy)
      IV.Step = new CastInst(IV.Step, IVTy, IV.Step->getName(), AfterPHIIt);

    Val = BinaryOperator::create(Instruction::Mul, Val, IV.Step,
                                 Phi->getName()+"-scale", AfterPHIIt);
  }

  // If this is a pointer indvar...
  if (isa<PointerType>(Phi->getType())) {
    std::vector<Value*> Idx;
    // FIXME: this should not be needed when we fix PR82!
    if (Val->getType() != Type::LongTy)
      Val = new CastInst(Val, Type::LongTy, Val->getName(), AfterPHIIt);
    Idx.push_back(Val);
    Val = new GetElementPtrInst(IV.Start, Idx,
                                Phi->getName()+"-offset",
                                AfterPHIIt);

  } else if (!isa<Constant>(IV.Start) ||   // If Start != 0...
             !cast<Constant>(IV.Start)->isNullValue()) {
    // If the types are not compatible, insert a cast now...
    if (IV.Start->getType() != IVTy)
      IV.Start = new CastInst(IV.Start, IVTy, IV.Start->getName(),
                               AfterPHIIt);

    // Insert the instruction after the phi nodes...
    Val = BinaryOperator::create(Instruction::Add, Val, IV.Start,
                                 Phi->getName()+"-offset", AfterPHIIt);
  }

  // If the PHI node has a different type than val is, insert a cast now...
  if (Val->getType() != Phi->getType())
    Val = new CastInst(Val, Phi->getType(), Val->getName(), AfterPHIIt);

  // Move the PHI name to it's new equivalent value...
  std::string OldName = Phi->getName();
  Phi->setName("");
  Val->setName(OldName);

  return Val;
}

// ReplaceIndVar - Replace all uses of the specified induction variable with
// expressions computed from the specified loop iteration counter variable.
// Return true if instructions were deleted.
void IndVarSimplify::ReplaceIndVar(InductionVariable &IV, Value *CIV) {
  Value *IndVarVal = 0;
  PHINode *Phi = IV.Phi;

  assert(Phi->getNumOperands() == 4 &&
         "Only expect induction variables in canonical loops!");

  // Remember the incoming values used by the PHI node
  std::vector<Value*> PHIOps;
  PHIOps.reserve(2);
  PHIOps.push_back(Phi->getIncomingValue(0));
  PHIOps.push_back(Phi->getIncomingValue(1));

  // Delete all of the operands of the PHI node... so that the to-be-deleted PHI
  // node does not cause any expressions to be computed that would not otherwise
  // be.
  Phi->dropAllReferences();

  // Now that we are rid of unneeded uses of the PHI node, replace any remaining
  // ones with the appropriate code using the canonical induction variable.
  while (!Phi->use_empty()) {
    Instruction *U = cast<Instruction>(Phi->use_back());

    // TODO: Perform LFTR here if possible
    if (0) {

    } else {
      // Replace all uses of the old PHI node with the new computed value...
      if (IndVarVal == 0)
        IndVarVal = ComputeAuxIndVarValue(IV, CIV);
      U->replaceUsesOfWith(Phi, IndVarVal);
    }
  }

  // If the PHI is the last user of any instructions for computing PHI nodes
  // that are irrelevant now, delete those instructions.
  while (!PHIOps.empty()) {
    Instruction *MaybeDead = dyn_cast<Instruction>(PHIOps.back());
    PHIOps.pop_back();

    if (MaybeDead && isInstructionTriviallyDead(MaybeDead) &&
        (!isa<PHINode>(MaybeDead) ||
         MaybeDead->getParent() != Phi->getParent())) {
      PHIOps.insert(PHIOps.end(), MaybeDead->op_begin(),
                    MaybeDead->op_end());
      MaybeDead->getParent()->getInstList().erase(MaybeDead);

      // Erase any duplicates entries in the PHIOps list.
      std::vector<Value*>::iterator It =
        std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
      while (It != PHIOps.end()) {
        PHIOps.erase(It);
        It = std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
      }
    }
  }

  // Delete the old, now unused, phi node...
  Phi->getParent()->getInstList().erase(Phi);
}

<|endoftext|>


<commit_before>//===- IndVarSimplify.cpp - Induction Variable Elimination ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Guarantees that all loops with identifiable, linear, induction variables will
// be transformed to have a single, canonical, induction variable.  After this
// pass runs, it guarantees the the first PHI node of the header block in the
// loop is the canonical induction variable if there is one.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/iPHINode.h"
#include "llvm/iOther.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/CFG.h"
#include "llvm/Transforms/Utils/Local.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
#include "Support/STLExtras.h"
#include <algorithm>
using namespace llvm;

namespace {
  Statistic<> NumRemoved ("indvars", "Number of aux indvars removed");
  Statistic<> NumInserted("indvars", "Number of canonical indvars added");
}

// InsertCast - Cast Val to Ty, setting a useful name on the cast if Val has a
// name...
//
static Instruction *InsertCast(Value *Val, const Type *Ty,
                               Instruction *InsertBefore) {
  return new CastInst(Val, Ty, Val->getName()+"-casted", InsertBefore);
}

static bool TransformLoop(LoopInfo *Loops, Loop *Loop) {
  // Transform all subloops before this loop...
  bool Changed = reduce_apply_bool(Loop->getSubLoops().begin(),
                                   Loop->getSubLoops().end(),
                              std::bind1st(std::ptr_fun(TransformLoop), Loops));
  // Get the header node for this loop.  All of the phi nodes that could be
  // induction variables must live in this basic block.
  //
  BasicBlock *Header = Loop->getHeader();

  // Loop over all of the PHI nodes in the basic block, calculating the
  // induction variables that they represent... stuffing the induction variable
  // info into a vector...
  //
  std::vector<InductionVariable> IndVars;    // Induction variables for block
  BasicBlock::iterator AfterPHIIt = Header->begin();
  for (; PHINode *PN = dyn_cast<PHINode>(AfterPHIIt); ++AfterPHIIt)
    IndVars.push_back(InductionVariable(PN, Loops));
  // AfterPHIIt now points to first non-phi instruction...

  // If there are no phi nodes in this basic block, there can't be indvars...
  if (IndVars.empty()) return Changed;

  // Loop over the induction variables, looking for a canonical induction
  // variable, and checking to make sure they are not all unknown induction
  // variables.
  //
  bool FoundIndVars = false;
  InductionVariable *Canonical = 0;
  for (unsigned i = 0; i < IndVars.size(); ++i) {
    if (IndVars[i].InductionType == InductionVariable::Canonical &&
        !isa<PointerType>(IndVars[i].Phi->getType()))
      Canonical = &IndVars[i];
    if (IndVars[i].InductionType != InductionVariable::Unknown)
      FoundIndVars = true;
  }

  // No induction variables, bail early... don't add a canonical indvar
  if (!FoundIndVars) return Changed;

  // Okay, we want to convert other induction variables to use a canonical
  // indvar.  If we don't have one, add one now...
  if (!Canonical) {
    // Create the PHI node for the new induction variable, and insert the phi
    // node at the start of the PHI nodes...
    PHINode *PN = new PHINode(Type::UIntTy, "cann-indvar", Header->begin());

    // Create the increment instruction to add one to the counter...
    Instruction *Add = BinaryOperator::create(Instruction::Add, PN,
                                              ConstantUInt::get(Type::UIntTy,1),
                                              "add1-indvar", AfterPHIIt);

    // Figure out which block is incoming and which is the backedge for the loop
    BasicBlock *Incoming, *BackEdgeBlock;
    pred_iterator PI = pred_begin(Header);
    assert(PI != pred_end(Header) && "Loop headers should have 2 preds!");
    if (Loop->contains(*PI)) {  // First pred is back edge...
      BackEdgeBlock = *PI++;
      Incoming      = *PI++;
    } else {
      Incoming      = *PI++;
      BackEdgeBlock = *PI++;
    }
    assert(PI == pred_end(Header) && "Loop headers should have 2 preds!");

    // Add incoming values for the PHI node...
    PN->addIncoming(Constant::getNullValue(Type::UIntTy), Incoming);
    PN->addIncoming(Add, BackEdgeBlock);

    // Analyze the new induction variable...
    IndVars.push_back(InductionVariable(PN, Loops));
    assert(IndVars.back().InductionType == InductionVariable::Canonical &&
           "Just inserted canonical indvar that is not canonical!");
    Canonical = &IndVars.back();
    ++NumInserted;
    Changed = true;
  } else {
    // If we have a canonical induction variable, make sure that it is the first
    // one in the basic block.
    if (&Header->front() != Canonical->Phi)
      Header->getInstList().splice(Header->begin(), Header->getInstList(),
                                   Canonical->Phi);
  }

  DEBUG(std::cerr << "Induction variables:\n");

  // Get the current loop iteration count, which is always the value of the
  // canonical phi node...
  //
  PHINode *IterCount = Canonical->Phi;

  // Loop through and replace all of the auxiliary induction variables with
  // references to the canonical induction variable...
  //
  for (unsigned i = 0; i < IndVars.size(); ++i) {
    InductionVariable *IV = &IndVars[i];

    DEBUG(IV->print(std::cerr));

    while (isa<PHINode>(AfterPHIIt)) ++AfterPHIIt;

    // Don't do math with pointers...
    const Type *IVTy = IV->Phi->getType();
    if (isa<PointerType>(IVTy)) IVTy = Type::ULongTy;

    // Don't modify the canonical indvar or unrecognized indvars...
    if (IV != Canonical && IV->InductionType != InductionVariable::Unknown) {
      Instruction *Val = IterCount;
      if (!isa<ConstantInt>(IV->Step) ||   // If the step != 1
          !cast<ConstantInt>(IV->Step)->equalsInt(1)) {

        // If the types are not compatible, insert a cast now...
        if (Val->getType() != IVTy)
          Val = InsertCast(Val, IVTy, AfterPHIIt);
        if (IV->Step->getType() != IVTy)
          IV->Step = InsertCast(IV->Step, IVTy, AfterPHIIt);

        Val = BinaryOperator::create(Instruction::Mul, Val, IV->Step,
                                     IV->Phi->getName()+"-scale", AfterPHIIt);
      }

      // If the start != 0
      if (IV->Start != Constant::getNullValue(IV->Start->getType())) {
        // If the types are not compatible, insert a cast now...
        if (Val->getType() != IVTy)
          Val = InsertCast(Val, IVTy, AfterPHIIt);
        if (IV->Start->getType() != IVTy)
          IV->Start = InsertCast(IV->Start, IVTy, AfterPHIIt);

        // Insert the instruction after the phi nodes...
        Val = BinaryOperator::create(Instruction::Add, Val, IV->Start,
                                     IV->Phi->getName()+"-offset", AfterPHIIt);
      }

      // If the PHI node has a different type than val is, insert a cast now...
      if (Val->getType() != IV->Phi->getType())
        Val = InsertCast(Val, IV->Phi->getType(), AfterPHIIt);

      // Replace all uses of the old PHI node with the new computed value...
      IV->Phi->replaceAllUsesWith(Val);

      // Move the PHI name to it's new equivalent value...
      std::string OldName = IV->Phi->getName();
      IV->Phi->setName("");
      Val->setName(OldName);

      // Get the incoming values used by the PHI node
      std::vector<Value*> PHIOps;
      PHIOps.reserve(IV->Phi->getNumIncomingValues());
      for (unsigned i = 0, e = IV->Phi->getNumIncomingValues(); i != e; ++i)
        PHIOps.push_back(IV->Phi->getIncomingValue(i));

      // Delete the old, now unused, phi node...
      Header->getInstList().erase(IV->Phi);

      // If the PHI is the last user of any instructions for computing PHI nodes
      // that are irrelevant now, delete those instructions.
      while (!PHIOps.empty()) {
        Instruction *MaybeDead = dyn_cast<Instruction>(PHIOps.back());
        PHIOps.pop_back();

        if (MaybeDead && isInstructionTriviallyDead(MaybeDead)) {
          PHIOps.insert(PHIOps.end(), MaybeDead->op_begin(),
                        MaybeDead->op_end());
          MaybeDead->getParent()->getInstList().erase(MaybeDead);

          // Erase any duplicates entries in the PHIOps list.
          std::vector<Value*>::iterator It =
            std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
          while (It != PHIOps.end()) {
            PHIOps.erase(It);
            It = std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
          }

          // Erasing the instruction could invalidate the AfterPHI iterator!
          AfterPHIIt = Header->begin();
        }
      }

      Changed = true;
      ++NumRemoved;
    }
  }

  return Changed;
}

namespace {
  struct InductionVariableSimplify : public FunctionPass {
    virtual bool runOnFunction(Function &) {
      LoopInfo &LI = getAnalysis<LoopInfo>();

      // Induction Variables live in the header nodes of loops
      return reduce_apply_bool(LI.getTopLevelLoops().begin(),
                               LI.getTopLevelLoops().end(),
                               std::bind1st(std::ptr_fun(TransformLoop), &LI));
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.setPreservesCFG();
    }
  };
  RegisterOpt<InductionVariableSimplify> X("indvars",
                                           "Canonicalize Induction Variables");
}

Pass *llvm::createIndVarSimplifyPass() {
  return new InductionVariableSimplify();
}

<commit_msg>Fix PR194<commit_after>//===- IndVarSimplify.cpp - Induction Variable Elimination ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Guarantees that all loops with identifiable, linear, induction variables will
// be transformed to have a single, canonical, induction variable.  After this
// pass runs, it guarantees the the first PHI node of the header block in the
// loop is the canonical induction variable if there is one.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/iPHINode.h"
#include "llvm/iOther.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/CFG.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
using namespace llvm;

namespace {
  Statistic<> NumRemoved ("indvars", "Number of aux indvars removed");
  Statistic<> NumInserted("indvars", "Number of canonical indvars added");

  class IndVarSimplify : public FunctionPass {
    LoopInfo *Loops;
    TargetData *TD;
  public:
    virtual bool runOnFunction(Function &) {
      Loops = &getAnalysis<LoopInfo>();
      TD = &getAnalysis<TargetData>();

      // Induction Variables live in the header nodes of loops
      bool Changed = false;
      for (unsigned i = 0, e = Loops->getTopLevelLoops().size(); i != e; ++i)
        Changed |= runOnLoop(Loops->getTopLevelLoops()[i]);
      return Changed;
    }

    unsigned getTypeSize(const Type *Ty) {
      if (unsigned Size = Ty->getPrimitiveSize())
        return Size;
      return TD->getTypeSize(Ty);  // Must be a pointer
    }

    bool runOnLoop(Loop *L);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<TargetData>();   // Need pointer size
      AU.addRequired<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.addPreservedID(LoopSimplifyID);
      AU.setPreservesCFG();
    }
  };
  RegisterOpt<IndVarSimplify> X("indvars", "Canonicalize Induction Variables");
}

Pass *llvm::createIndVarSimplifyPass() {
  return new IndVarSimplify();
}

bool IndVarSimplify::runOnLoop(Loop *Loop) {
  // Transform all subloops before this loop...
  bool Changed = false;
  for (unsigned i = 0, e = Loop->getSubLoops().size(); i != e; ++i)
    Changed |= runOnLoop(Loop->getSubLoops()[i]);

  // Get the header node for this loop.  All of the phi nodes that could be
  // induction variables must live in this basic block.
  //
  BasicBlock *Header = Loop->getHeader();

  // Loop over all of the PHI nodes in the basic block, calculating the
  // induction variables that they represent... stuffing the induction variable
  // info into a vector...
  //
  std::vector<InductionVariable> IndVars;    // Induction variables for block
  BasicBlock::iterator AfterPHIIt = Header->begin();
  for (; PHINode *PN = dyn_cast<PHINode>(AfterPHIIt); ++AfterPHIIt)
    IndVars.push_back(InductionVariable(PN, Loops));
  // AfterPHIIt now points to first non-phi instruction...

  // If there are no phi nodes in this basic block, there can't be indvars...
  if (IndVars.empty()) return Changed;

  // Loop over the induction variables, looking for a canonical induction
  // variable, and checking to make sure they are not all unknown induction
  // variables.  Keep track of the largest integer size of the induction
  // variable.
  //
  InductionVariable *Canonical = 0;
  unsigned MaxSize = 0;

  for (unsigned i = 0; i != IndVars.size(); ++i) {
    InductionVariable &IV = IndVars[i];

    if (IV.InductionType != InductionVariable::Unknown) {
      unsigned IVSize = getTypeSize(IV.Phi->getType());

      if (IV.InductionType == InductionVariable::Canonical &&
          !isa<PointerType>(IV.Phi->getType()) && IVSize >= MaxSize)
        Canonical = &IV;

      if (IVSize > MaxSize) MaxSize = IVSize;

      // If this variable is larger than the currently identified canonical
      // indvar, the canonical indvar is not usable.
      if (Canonical && IVSize > getTypeSize(Canonical->Phi->getType()))
        Canonical = 0;
    }
  }

  // No induction variables, bail early... don't add a canonical indvar
  if (MaxSize == 0) return Changed;

  // Okay, we want to convert other induction variables to use a canonical
  // indvar.  If we don't have one, add one now...
  if (!Canonical) {
    // Create the PHI node for the new induction variable, and insert the phi
    // node at the start of the PHI nodes...
    const Type *IVType;
    switch (MaxSize) {
    default: assert(0 && "Unknown integer type size!");
    case 1: IVType = Type::UByteTy; break;
    case 2: IVType = Type::UShortTy; break;
    case 4: IVType = Type::UIntTy; break;
    case 8: IVType = Type::ULongTy; break;
    }

    PHINode *PN = new PHINode(IVType, "cann-indvar", Header->begin());

    // Create the increment instruction to add one to the counter...
    Instruction *Add = BinaryOperator::create(Instruction::Add, PN,
                                              ConstantUInt::get(IVType, 1),
                                              "next-indvar", AfterPHIIt);

    // Figure out which block is incoming and which is the backedge for the loop
    BasicBlock *Incoming, *BackEdgeBlock;
    pred_iterator PI = pred_begin(Header);
    assert(PI != pred_end(Header) && "Loop headers should have 2 preds!");
    if (Loop->contains(*PI)) {  // First pred is back edge...
      BackEdgeBlock = *PI++;
      Incoming      = *PI++;
    } else {
      Incoming      = *PI++;
      BackEdgeBlock = *PI++;
    }
    assert(PI == pred_end(Header) && "Loop headers should have 2 preds!");

    // Add incoming values for the PHI node...
    PN->addIncoming(Constant::getNullValue(IVType), Incoming);
    PN->addIncoming(Add, BackEdgeBlock);

    // Analyze the new induction variable...
    IndVars.push_back(InductionVariable(PN, Loops));
    assert(IndVars.back().InductionType == InductionVariable::Canonical &&
           "Just inserted canonical indvar that is not canonical!");
    Canonical = &IndVars.back();
    ++NumInserted;
    Changed = true;
  } else {
    // If we have a canonical induction variable, make sure that it is the first
    // one in the basic block.
    if (&Header->front() != Canonical->Phi)
      Header->getInstList().splice(Header->begin(), Header->getInstList(),
                                   Canonical->Phi);
  }

  DEBUG(std::cerr << "Induction variables:\n");

  // Get the current loop iteration count, which is always the value of the
  // canonical phi node...
  //
  PHINode *IterCount = Canonical->Phi;

  // Loop through and replace all of the auxiliary induction variables with
  // references to the canonical induction variable...
  //
  for (unsigned i = 0; i != IndVars.size(); ++i) {
    InductionVariable *IV = &IndVars[i];

    DEBUG(IV->print(std::cerr));

    while (isa<PHINode>(AfterPHIIt)) ++AfterPHIIt;

    // Don't do math with pointers...
    const Type *IVTy = IV->Phi->getType();
    if (isa<PointerType>(IVTy)) IVTy = Type::ULongTy;

    // Don't modify the canonical indvar or unrecognized indvars...
    if (IV != Canonical && IV->InductionType != InductionVariable::Unknown) {
      Instruction *Val = IterCount;
      if (!isa<ConstantInt>(IV->Step) ||   // If the step != 1
          !cast<ConstantInt>(IV->Step)->equalsInt(1)) {

        // If the types are not compatible, insert a cast now...
        if (Val->getType() != IVTy)
          Val = new CastInst(Val, IVTy, Val->getName(), AfterPHIIt);
        if (IV->Step->getType() != IVTy)
          IV->Step = new CastInst(IV->Step, IVTy, IV->Step->getName(),
                                  AfterPHIIt);

        Val = BinaryOperator::create(Instruction::Mul, Val, IV->Step,
                                     IV->Phi->getName()+"-scale", AfterPHIIt);
      }

      // If the start != 0
      if (IV->Start != Constant::getNullValue(IV->Start->getType())) {
        // If the types are not compatible, insert a cast now...
        if (Val->getType() != IVTy)
          Val = new CastInst(Val, IVTy, Val->getName(), AfterPHIIt);
        if (IV->Start->getType() != IVTy)
          IV->Start = new CastInst(IV->Start, IVTy, IV->Start->getName(),
                                   AfterPHIIt);

        // Insert the instruction after the phi nodes...
        Val = BinaryOperator::create(Instruction::Add, Val, IV->Start,
                                     IV->Phi->getName()+"-offset", AfterPHIIt);
      }

      // If the PHI node has a different type than val is, insert a cast now...
      if (Val->getType() != IV->Phi->getType())
        Val = new CastInst(Val, IV->Phi->getType(), Val->getName(), AfterPHIIt);

      // Replace all uses of the old PHI node with the new computed value...
      IV->Phi->replaceAllUsesWith(Val);

      // Move the PHI name to it's new equivalent value...
      std::string OldName = IV->Phi->getName();
      IV->Phi->setName("");
      Val->setName(OldName);

      // Get the incoming values used by the PHI node
      std::vector<Value*> PHIOps;
      PHIOps.reserve(IV->Phi->getNumIncomingValues());
      for (unsigned i = 0, e = IV->Phi->getNumIncomingValues(); i != e; ++i)
        PHIOps.push_back(IV->Phi->getIncomingValue(i));

      // Delete the old, now unused, phi node...
      Header->getInstList().erase(IV->Phi);

      // If the PHI is the last user of any instructions for computing PHI nodes
      // that are irrelevant now, delete those instructions.
      while (!PHIOps.empty()) {
        Instruction *MaybeDead = dyn_cast<Instruction>(PHIOps.back());
        PHIOps.pop_back();

        if (MaybeDead && isInstructionTriviallyDead(MaybeDead)) {
          PHIOps.insert(PHIOps.end(), MaybeDead->op_begin(),
                        MaybeDead->op_end());
          MaybeDead->getParent()->getInstList().erase(MaybeDead);

          // Erase any duplicates entries in the PHIOps list.
          std::vector<Value*>::iterator It =
            std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
          while (It != PHIOps.end()) {
            PHIOps.erase(It);
            It = std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
          }

          // Erasing the instruction could invalidate the AfterPHI iterator!
          AfterPHIIt = Header->begin();
        }
      }

      Changed = true;
      ++NumRemoved;
    }
  }

  return Changed;
}

<|endoftext|>