ytgui / temp

0 stars 0 forks source link

LLVM 4 - Passes #34

Closed ytgui closed 5 years ago

ytgui commented 5 years ago
  1. https://llvm.org/docs/Passes.html
  2. print all passes name in o3
  3. read an ir pass
  4. read an dag pass (has dag pass?)
ytgui commented 5 years ago

Simple Print

namespace {

class Hello : public FunctionPass {
public:
  static char ID; // Pass identification, replacement for typeid
  Hello() : FunctionPass(ID) {}

  bool runOnFunction(Function &F) override {
    dbgs() << "Function: ";
    dbgs() << F.getName() << "\n";

    for (BasicBlock &BB : F) {
      for (Instruction &I : BB) {
        I.dump();
      }
    }

    dbgs() << "----------\n";
    return false;
  }

private:
  void printType(Type *Ty) {}
};

}

char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass");
ytgui commented 5 years ago

More Complicated

bool runOnFunction(Function &F) {
    SmallVector<Instruction *, 16> WorkList;
    for (BasicBlock &BB : F) {
      for (Instruction &I : BB) {
        if (isa<IntrinsicInst>(&I)) {
          WorkList.push_back(&I);
        }
      }
    }

    bool Changed = false;
    while (not WorkList.empty()) {
      Instruction *I = WorkList.pop_back_val();
      if (matchStInt32To16(I)) {
        Changed |= hackStInt32To16(I);
      } else if (matchLdInt16To32(I)) {
        Changed |= hackLdInt16To32(I);
      }
    }
    return Changed;
  }

bool matchStInt32To16(Instruction *I) const {
    IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
    if (II->getIntrinsicID() != Intrinsic::xxxxxxx_st_iuav) {
      return false;
    }

    Instruction *Child0 = dyn_cast<Instruction>(I->getOperand(0));
    if (Child0->getOpcode() != Instruction::Trunc) {
      return false;
    }
    if (not Child0->getType()->isIntegerTy()) {
      return false;
    }
    if (Child0->getType()->getIntegerBitWidth() != 16) {
      return false;
    }
    return true;
  }

bool hackStInt32To16(Instruction *I) const {
    // -----
    // %res = i32 xxx
    // %value = trunc i32 res to i16
    // %offset = mul i32 %_3_, 2
    // call void @llvm.xxxxxx.st.iuav.i16(i16 value, i32 offset, i32 desc)
    // -----
    Function *F = I->getFunction();
    IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);

    // Child0 is value
    Instruction *Child0 = dyn_cast<Instruction>(I->getOperand(0));

    // Child1 is offset
    Value *Child1 = I->getOperand(1);

    // Child2 is constant
    Value *Child2 = I->getOperand(2);

    // build offset and mask
    IRBuilder<> Builder(I);
    ConstantInt *Const2 = Builder.getInt32(2);
    ConstantInt *Const8 = Builder.getInt32(8);
    Value *Div4 = Builder.CreateLShr(Child1, Const2);
    Value *Mul4 = Builder.CreateShl(Div4, Const2);
    Value *Mod4 = Builder.CreateSub(Child1, Mul4);
    Value *Shift = Builder.CreateMul(Mod4, Const8);
    Value *RMask = Builder.CreateLShr(Builder.getInt32(0xffff0000), Shift);

    // read with mask
    llvm::Function *LD0 = llvm::Intrinsic::getDeclaration(
        F->getParent(), llvm::Intrinsic::xxxxxxx_ld_iuav, Builder.getInt32Ty());
    Value *Res0 = Builder.CreateCall(LD0, {Mul4, Child2});
    Res0 = Builder.CreateAnd(Res0, RMask);

    // write
    llvm::Function *ST0 = llvm::Intrinsic::getDeclaration(
        F->getParent(), II->getIntrinsicID(), Builder.getInt32Ty());
    Value *Val0 = Builder.CreateShl(Child0->getOperand(0), Shift);
    Builder.CreateCall(ST0, {Builder.CreateOr(Res0, Val0), Mul4, Child2});

    // erase
    I->eraseFromParent();
    return true;
  }