static Value *splitStore(StoreInst *Inst, ConversionState &State) { if (Inst->isVolatile() || Inst->isAtomic()) report_fatal_error("Can't split volatile/atomic stores"); if (cast<IntegerType>(Inst->getValueOperand()->getType())->getBitWidth() % 8 != 0) report_fatal_error("Stores must be a multiple of 8 bits"); Value *OrigPtr = State.getConverted(Inst->getPointerOperand()); // OrigPtr is now a placeholder in recursive calls, and so has no name. if (OrigPtr->getName().empty()) OrigPtr->setName(Inst->getPointerOperand()->getName()); Value *OrigVal = State.getConverted(Inst->getValueOperand()); unsigned Width = cast<IntegerType>( Inst->getValueOperand()->getType())->getBitWidth(); unsigned LoWidth = Width; while (!isLegalSize(LoWidth)) LoWidth -= 8; IntegerType *LoType = IntegerType::get(Inst->getContext(), LoWidth); IntegerType *HiType = IntegerType::get(Inst->getContext(), Width - LoWidth); IRBuilder<> IRB(Inst->getParent(), Inst); Value *BCLo = IRB.CreateBitCast( OrigPtr, LoType->getPointerTo(), OrigPtr->getName() + ".loty"); Value *LoTrunc = IRB.CreateTrunc( OrigVal, LoType, OrigVal->getName() + ".lo"); IRB.CreateAlignedStore(LoTrunc, BCLo, Inst->getAlignment()); Value *HiLShr = IRB.CreateLShr( OrigVal, LoWidth, OrigVal->getName() + ".hi.sh"); Value *GEPHi = IRB.CreateConstGEP1_32(BCLo, 1, OrigPtr->getName() + ".hi"); Value *HiTrunc = IRB.CreateTrunc( HiLShr, HiType, OrigVal->getName() + ".hi"); Value *BCHi = IRB.CreateBitCast( GEPHi, HiType->getPointerTo(), OrigPtr->getName() + ".hity"); Value *StoreHi = IRB.CreateStore(HiTrunc, BCHi); if (!isLegalSize(Width - LoWidth)) { // HiTrunc is still illegal, and is redundant with the truncate in the // recursive call, so just get rid of it. State.recordConverted(cast<Instruction>(HiTrunc), HiLShr, /*TakeName=*/false); StoreHi = splitStore(cast<StoreInst>(StoreHi), State); // BCHi was still illegal, and has been replaced with a placeholder in the // recursive call. Since it is redundant with BCLo in the recursive call, // just splice it out entirely. State.recordConverted(cast<Instruction>(BCHi), GEPHi, /*TakeName=*/false); } State.recordConverted(Inst, StoreHi, /*TakeName=*/false); return StoreHi; }
// Split an illegal load into multiple legal loads and return the resulting // promoted value. The size of the load is assumed to be a multiple of 8. static Value *splitLoad(LoadInst *Inst, ConversionState &State) { if (Inst->isVolatile() || Inst->isAtomic()) report_fatal_error("Can't split volatile/atomic loads"); if (cast<IntegerType>(Inst->getType())->getBitWidth() % 8 != 0) report_fatal_error("Loads must be a multiple of 8 bits"); Value *OrigPtr = State.getConverted(Inst->getPointerOperand()); // OrigPtr is a placeholder in recursive calls, and so has no name if (OrigPtr->getName().empty()) OrigPtr->setName(Inst->getPointerOperand()->getName()); unsigned Width = cast<IntegerType>(Inst->getType())->getBitWidth(); Type *NewType = getPromotedType(Inst->getType()); unsigned LoWidth = Width; while (!isLegalSize(LoWidth)) LoWidth -= 8; IntegerType *LoType = IntegerType::get(Inst->getContext(), LoWidth); IntegerType *HiType = IntegerType::get(Inst->getContext(), Width - LoWidth); IRBuilder<> IRB(Inst->getParent(), Inst); Value *BCLo = IRB.CreateBitCast( OrigPtr, LoType->getPointerTo(), OrigPtr->getName() + ".loty"); Value *LoadLo = IRB.CreateAlignedLoad( BCLo, Inst->getAlignment(), Inst->getName() + ".lo"); Value *LoExt = IRB.CreateZExt(LoadLo, NewType, LoadLo->getName() + ".ext"); Value *GEPHi = IRB.CreateConstGEP1_32(BCLo, 1, OrigPtr->getName() + ".hi"); Value *BCHi = IRB.CreateBitCast( GEPHi, HiType->getPointerTo(), OrigPtr->getName() + ".hity"); Value *LoadHi = IRB.CreateLoad(BCHi, Inst->getName() + ".hi"); if (!isLegalSize(Width - LoWidth)) { LoadHi = splitLoad(cast<LoadInst>(LoadHi), State); // BCHi was still illegal, and has been replaced with a placeholder in the // recursive call. Since it is redundant with BCLo in the recursive call, // just splice it out entirely. State.recordConverted(cast<Instruction>(BCHi), GEPHi, /*TakeName=*/false); } Value *HiExt = IRB.CreateZExt(LoadHi, NewType, LoadHi->getName() + ".ext"); Value *HiShift = IRB.CreateShl(HiExt, LoWidth, HiExt->getName() + ".sh"); Value *Result = IRB.CreateOr(LoExt, HiShift); State.recordConverted(Inst, Result); return Result; }