diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 29223daab7a..118f412d4ab 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -7673,18 +7673,40 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { unsigned Size = MemOpLength->getZExtValue(); unsigned Align = cast(CI.getOperand(4))->getZExtValue(); PointerType *NewPtrTy = NULL; + unsigned numBits = Size << 3; // Destination pointer type is always i8 * // If Size is 8 then use Int64Ty // If Size is 4 then use Int32Ty // If Size is 2 then use Int16Ty // If Size is 1 then use Int8Ty if (Size && Size <=8 && !(Size&(Size-1))) - NewPtrTy = PointerType::get(IntegerType::get(Size<<3)); + NewPtrTy = PointerType::get(IntegerType::get(numBits)); if (NewPtrTy) { - Value *Src = InsertCastBefore(Instruction::BitCast, CI.getOperand(2), NewPtrTy, CI); + Value *L = NULL; + // If source is a null terminated constant c string then try to use immediate store. + if (Constant *C = dyn_cast(CI.getOperand(2))) { + const std::string &Str = C->getStringValue(); + if (!Str.empty()) { + APInt StrVal(numBits, 0); + unsigned len = Str.length(); + APInt SingleChar(numBits, 0); + for (unsigned i = 0; i < len; i++) { + SingleChar = (uint64_t) Str[i]; + StrVal = (StrVal << 8) | SingleChar; + } + // Append NULL at the end. + SingleChar = 0; + StrVal = (StrVal << 8) | SingleChar; + L = ConstantInt::get(StrVal); + } + } + // Otherwise load source from memory. + if (L == NULL) { + Value *Src = InsertCastBefore(Instruction::BitCast, CI.getOperand(2), NewPtrTy, CI); + L = new LoadInst(Src, "tmp", false, Align, &CI); + } Value *Dest = InsertCastBefore(Instruction::BitCast, CI.getOperand(1), NewPtrTy, CI); - Value *L = new LoadInst(Src, "tmp", false, Align, &CI); Value *NS = new StoreInst(L, Dest, false, Align, &CI); CI.replaceAllUsesWith(NS); Changed = true;