//===- AVRShift.cpp - Shift Expansion Pass --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
/// Expand 32-bit shift instructions (shl, lshr, ashr) to inline loops, just
/// like avr-gcc. This must be done in IR because otherwise the type legalizer
/// will turn 32-bit shifts into (non-existing) library calls such as __ashlsi3.
//
//===----------------------------------------------------------------------===//

#include "AVR.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"

using namespace llvm;

namespace {

class AVRShiftExpand : public FunctionPass {
public:
  static char ID;

  AVRShiftExpand() : FunctionPass(ID) {}

  bool runOnFunction(Function &F) override;

  StringRef getPassName() const override { return "AVR Shift Expansion"; }

private:
  void expand(BinaryOperator *BI);
};

} // end of anonymous namespace

char AVRShiftExpand::ID = 0;

INITIALIZE_PASS(AVRShiftExpand, "avr-shift-expand", "AVR Shift Expansion",
                false, false)

Pass *llvm::createAVRShiftExpandPass() { return new AVRShiftExpand(); }

bool AVRShiftExpand::runOnFunction(Function &F) {
  SmallVector<BinaryOperator *, 1> ShiftInsts;
  auto &Ctx = F.getContext();
  for (Instruction &I : instructions(F)) {
    if (!I.isShift())
      // Only expand shift instructions (shl, lshr, ashr).
      continue;
    if (I.getType() != Type::getInt32Ty(Ctx))
      // Only expand plain i32 types.
      continue;
    if (isa<ConstantInt>(I.getOperand(1)))
      // Only expand when the shift amount is not known.
      // Known shift amounts are (currently) better expanded inline.
      continue;
    ShiftInsts.push_back(cast<BinaryOperator>(&I));
  }

  // The expanding itself needs to be done separately as expand() will remove
  // these instructions. Removing instructions while iterating over a basic
  // block is not a great idea.
  for (auto *I : ShiftInsts) {
    expand(I);
  }

  // Return whether this function expanded any shift instructions.
  return ShiftInsts.size() > 0;
}

void AVRShiftExpand::expand(BinaryOperator *BI) {
  auto &Ctx = BI->getContext();
  IRBuilder<> Builder(BI);
  Type *Int32Ty = Type::getInt32Ty(Ctx);
  Type *Int8Ty = Type::getInt8Ty(Ctx);
  Value *Int8Zero = ConstantInt::get(Int8Ty, 0);

  // Split the current basic block at the point of the existing shift
  // instruction and insert a new basic block for the loop.
  BasicBlock *BB = BI->getParent();
  Function *F = BB->getParent();
  BasicBlock *EndBB = BB->splitBasicBlock(BI, "shift.done");
  BasicBlock *LoopBB = BasicBlock::Create(Ctx, "shift.loop", F, EndBB);

  // Truncate the shift amount to i8, which is trivially lowered to a single
  // AVR register.
  Builder.SetInsertPoint(&BB->back());
  Value *ShiftAmount = Builder.CreateTrunc(BI->getOperand(1), Int8Ty);

  // Replace the unconditional branch that splitBasicBlock created with a
  // conditional branch.
  Value *Cmp1 = Builder.CreateICmpEQ(ShiftAmount, Int8Zero);
  Builder.CreateCondBr(Cmp1, EndBB, LoopBB);
  BB->back().eraseFromParent();

  // Create the loop body starting with PHI nodes.
  Builder.SetInsertPoint(LoopBB);
  PHINode *ShiftAmountPHI = Builder.CreatePHI(Int8Ty, 2);
  ShiftAmountPHI->addIncoming(ShiftAmount, BB);
  PHINode *ValuePHI = Builder.CreatePHI(Int32Ty, 2);
  ValuePHI->addIncoming(BI->getOperand(0), BB);

  // Subtract the shift amount by one, as we're shifting one this loop
  // iteration.
  Value *ShiftAmountSub =
      Builder.CreateSub(ShiftAmountPHI, ConstantInt::get(Int8Ty, 1));
  ShiftAmountPHI->addIncoming(ShiftAmountSub, LoopBB);

  // Emit the actual shift instruction. The difference is that this shift
  // instruction has a constant shift amount, which can be emitted inline
  // without a library call.
  Value *ValueShifted;
  switch (BI->getOpcode()) {
  case Instruction::Shl:
    ValueShifted = Builder.CreateShl(ValuePHI, ConstantInt::get(Int32Ty, 1));
    break;
  case Instruction::LShr:
    ValueShifted = Builder.CreateLShr(ValuePHI, ConstantInt::get(Int32Ty, 1));
    break;
  case Instruction::AShr:
    ValueShifted = Builder.CreateAShr(ValuePHI, ConstantInt::get(Int32Ty, 1));
    break;
  default:
    llvm_unreachable("asked to expand an instruction that is not a shift");
  }
  ValuePHI->addIncoming(ValueShifted, LoopBB);

  // Branch to either the loop again (if there is more to shift) or to the
  // basic block after the loop (if all bits are shifted).
  Value *Cmp2 = Builder.CreateICmpEQ(ShiftAmountSub, Int8Zero);
  Builder.CreateCondBr(Cmp2, EndBB, LoopBB);

  // Collect the resulting value. This is necessary in the IR but won't produce
  // any actual instructions.
  Builder.SetInsertPoint(BI);
  PHINode *Result = Builder.CreatePHI(Int32Ty, 2);
  Result->addIncoming(BI->getOperand(0), BB);
  Result->addIncoming(ValueShifted, LoopBB);

  // Replace the original shift instruction.
  BI->replaceAllUsesWith(Result);
  BI->eraseFromParent();
}
