简体   繁体   中英

How to change the operand type in the instruction from 32bit to 64bit in LLVM?

I am a newbie to LLVM. And I am trying to change the type of the loop variable (PHINode). For example, I have an IR as follows:

for.cond1.preheader:                              ; preds = %entry, %for.inc15
  %k.03 = phi i32 [ 0, %entry ], [ %inc16, %for.inc15 ]
  br label %for.cond4.preheader

for.cond4.preheader:                              ; preds = %for.cond1.preheader, %for.inc12
  %indvars.iv5 = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next6, %for.inc12 ]
  br label %for.body6

for.body6:                                        ; preds = %for.cond4.preheader, %for.body6
  ......
  %add7 = add nsw i32 %2, 1
  ......

for.inc12:                                        ; preds = %for.body6
  ......

for.inc15:                                        ; preds = %for.inc12
  %inc16 = add nuw nsw i32 %k.03, 1
  %exitcond9 = icmp ne i32 %inc16, 100
  br i1 %exitcond9, label %for.cond1.preheader, label %for.end17, !llvm.loop !7 ​

I want to change the type of the variable %k.03, hoping it will change from 32bit to 64bit. And recursively change all its references (Uses) to 64bit. The effect is as follows:

for.cond1.preheader:                              ; preds = %entry, %for.inc15
  %k.03 = phi i64 [ 0, %entry ], [ %inc16, %for.inc15 ]
  br label %for.cond4.preheader

for.cond4.preheader:                              ; preds = %for.cond1.preheader, %for.inc12
  %indvars.iv5 = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next6, %for.inc12 ]
  br label %for.body6

for.body6:                                        ; preds = %for.cond4.preheader, %for.body6
  ......
  %add7 = add nsw i32 %2, 1
  ......

for.inc12:                                        ; preds = %for.body6
  ......

for.inc15:                                        ; preds = %for.inc12
  %inc16 = add nuw nsw i64 %k.03, 1
  %exitcond9 = icmp ne i64 %inc16, 100
  br i1 %exitcond9, label %for.cond1.preheader, label %for.end17, !llvm.loop !7 ​

Then my approach is as follows:

static void __ChangeInsTo64Bit(User *inst) {
  if (!std::strcmp(cast<Instruction>(inst)->getOpcodeName(), "br")) {
    return;
  }
  if (std::strcmp(cast<Instruction>(inst)->getOpcodeName(), "icmp")) {
    inst->mutateType(inst->getType()->getWithNewBitWidth(64));
  }
  for (auto OI = inst->op_begin(), OE = inst->op_end(); OI != OE; ++OI) {
    Value *val = *OI;
    val->mutateType(val->getType()->getWithNewBitWidth(64));
    LLVM_DEBUG(dbgs() << "The Operand is: " << val->getName() 
                      << "; The bitwidth is: " << val->getType()->getIntegerBitWidth() << "\n");
  }
}

static void  __ChangePHINodeWidthTo64(Loop *OuterLoop, ScalarEvolution *SE) {

  PHINode *OuterPHINode = OuterLoop->getInductionVariable(*SE);
  if (!OuterPHINode) {
    return ;
  }

  unsigned int outerPHIWidth = OuterPHINode->getType()->getIntegerBitWidth();

  if (outerPHIWidth == 32) {
    __ChangeInsTo64Bit(OuterPHINode);
    for (User* user : OuterPHINode->users()) {
      __ChangeInsTo64Bit(user);
      for (User* u : user->users()) {
        __ChangeInsTo64Bit(u);
      }
    }
  }
}

Through the above code, I can achieve my goal, but weirdly modify the data type in the basic block for.body6:

%add7 = add nsw i32 %2, i64 1

This will cause program errors. Can someone help me point out the wrong point in my approach or provide the correct approach?


if (!std::strcmp(cast<Instruction>(inst)->getOpcodeName(), "br")) {
    return;
}

if (std::strcmp(cast<Instruction>(inst)->getOpcodeName(), "icmp")) {
  inst->mutateType(inst->getType()->getWithNewBitWidth(64));
}

That seems like a very janky and error-prone way to do RTTI, especially since LLVM provides the isa<> template for that very purpose.

Case in point, the "icmp" check will match everything that is not icmp (since there is no ! in front of the condition, and I would expect that this is not what you intented.

At the very least, the following is equivalent to your code and a lot more legible:

if (isa<BranchInst>(inst)) {
    return;
}

if (!isa<ICmpInst>(inst)) {
  inst->mutateType(inst->getType()->getWithNewBitWidth(64));
}

Removing the negation in front of the second test should address at least part of your issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM