Replacing LLVM IR instructions which have different types

I have a question about replacing LLVM IR instructions. If you have know something about it, I would be appreciate it if you could enlighten me.

I want to transform instructions like the following.
From

%32 = getelementptr inbounds i16, i16* %31, i32 0
%33 = bitcast i16* %32 to <4 x i16>*
%wide.load = load <4 x i16>, <4 x i16>* %33, align 2, !tbaa !4

To

%32 = getelementptr inbounds i16, i16* %31, i32 0
%33 = load i16, i16* %32, align 2, !tbaa !4

I tried to make it possible, and wrote the code like following.

LoadInst *LI = dyn_cast<LoadInst>(Inst);
IRBuilder<> Builder(LI);
auto SInst = LI->getPrevNode(); // Bitcaset instruction
if (SInst->getOpcode() == Instruction::BitCast) {
    Value  *BaseAddr = SInst->getOperand(0); // *i16 type 
    LoadInst *Orig = Builder.CreateLoad(cast<PointerType>(SInst->getOperand(0)->getType())->getElementType(), BaseAddr);
    ReplaceInstWithInst(BB.getInstList(), Inst, Orig->clone());
    SInst->eraseFromParent();
}

But some errors were output like Assertion `New->getType() == getType() && "replaceAllUses of value with new value of different type!"' failed when executing ReplaceInstWithInst() function. This means the old Load instruction has <i16 x 4> type and the new Load instruction has i16 type.

How can I write the transformation code to make what I want to do possibel?

As I understand it your Orig is the new load you want to have. So can’t you just erase the old load? I.e. replace the line ReplaceInstWithInst(BB.getInstList(), Inst, Orig->clone()); with LI->eraseFromParent()?

Converting it to a scalar load provides just one i16, but the original gave 4. You need to decide what value the users of the other lanes of that vector are going to see.

Some options:

  1. If you don’t care you can insertelement the i16 you just loaded into a <4 x i16> poison vector.
  2. If you want them all to see that single i16 it’s the same insertelement followed by a shufflevector to replicate it across all 4 lanes.
  3. If you want them to see the original values before your transformation you’re going to have to insert 3 more loads and combine them into a single vector with a series of insertelement instructions.

Thank you for your reply!
I thoght I had to execute ReplaceInstWithInst() to insert a new instruction into Basic Block, but your reply noticed me that it is possible to insert it by just only executing LoadInst *Orig = Builder.CreateLoad(cast<PointerType>(SInst->getOperand(0)->getType())->getElementType(), BaseAddr);. So just only executing LI->eraseFromParent() makes it possible what I want to do.

Thanks.

Thank you for your reply, @TNorthover.
I’m going to adopt first option, and I don’t care about the other 3 values except for the loaded i16 value. It seems strange to you, but I have to do it to achieve what I want to do in my research, whose content I can’t tell you in detail.
Anyway you helped me to get my head staright and I thank you for that.