[LLVMdev] How to change the type of an Instruction?

Nick Lewycky nicholas at mxc.ca
Mon Jan 24 09:01:58 PST 2011


On 01/24/2011 04:41 AM, Douglas do Couto Teixeira wrote:
> Hi,
>
> Nick, thanks for the reply.
> I still have a problem: I only need to "clone" an Instruction, changing
> its type. That is, I would like to keep all characteristics of the old
> Instruction and create a new one only with a different type.

Sure, but what about its operands? An "add" instruction must have the 
same type as its operands, what do you want to do with them? Suppose 
you're going from a 32-bit add to a 64-bit add, do the old operands get 
zero extended? Sign extended? You'll need to insert instructions for 
that (unless they're constants in which case you can use constant 
expressions). Similarly, what if the old type is a float and the new one 
is an int? float to signed int, float to unsigned int, or bitcast (only 
legal sometimes)?

  I am trying
> create a new Instruction thus:
>
> %3 = add nsw i32 %1, %2 ; <i16> [#uses=2]  //Old Instruction
>
> Value* Op0 = I->getOperand(0);
> Value* Op1 = I->getOperand(1);
> Value* V0 = new Value(Type::getInt16Ty(Op0->getContext()),
> Op0->getValueID());

Hunh, Value's constructor is protected.

In any event, Value is pure base. Constructing one this way will never 
get you what you want. If the ValueID indicates an Instruction, go 
through Instruction to create one.

> Value* V1 = new Value(Type::getInt16Ty(Op1->getContext()),
> Op1->getValueID());
> Instruction* newInst = BinaryOperator::CreateNSWAdd(V0, V1, "test");
> errs() << "NewInst:\n" << *newInst << "\n";
>
>
> But I get something like this:
>
> %test = add nsw i16 <badref>, <badref> ; <i16> [#uses=0]

The two instructions V0 and V1 you created were never inserted into the 
BasicBlock so they can't be numbered, and also they don't have names.

> What I am doing wrong?

Suppose that you're going from i32 to i16. Your only choice with that 
particular pair of types is a truncate. So:

   IRBuilder builder(OldInst);
   Value *V0 = builder.CreateTrunc(Op0, Type::getInt16Ty());
   Value *V1 = builder.CreateTrunc(Op1, Type::getInt16Ty());
   Value *Add = builder.CreateNSWAdd(V0, V1, "test");

The IRBuilder will take care of the distinction between instructions and 
constants for you. Note that I have not tested the above code, it may 
need some fixing before it compiles.

Nick

>
>
> Best,
>
> Douglas
>
> On Fri, Jan 21, 2011 at 8:25 PM, Nick Lewycky <nlewycky at google.com
> <mailto:nlewycky at google.com>> wrote:
>
>     On 21 January 2011 12:56, Douglas do Couto Teixeira
>     <douglasdocouto at gmail.com <mailto:douglasdocouto at gmail.com>> wrote:
>
>         Hello guys,
>
>         I wonder how I can change the type of an integer variable. For
>         instance, given the instruction "%3 = add i32 %1, %2" I would
>         like to alter the instruction to "%3 = add i16 %1, %2". Is there
>         any way to do this?
>
>
>     No. Instead you create a new Instruction, in this case with
>     BinaryOperator::CreateAdd, then OldInst->replaceAllUsesWith(NewInst)
>     to update all the users, then OldInst->eraseFromParent() since it's
>     now dead code.
>
>     Also, all values have types immutably assigned at creation, so
>     you'll need to insert casts (trunc instructions in your case) to
>     cast %1 and %2 from i32 to i16 for the smaller add.
>
>     Nick
>
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev




More information about the llvm-dev mailing list