class CallLowering {
const TargetLowering *TLI;
- protected:
+public:
+ struct ArgInfo {
+ unsigned Reg;
+ Type *Ty;
+ ISD::ArgFlagsTy Flags;
+
+ ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{})
+ : Reg(Reg), Ty(Ty), Flags(Flags) {}
+ };
+
+protected:
/// Getter for generic TargetLowering class.
const TargetLowering *getTLI() const {
return TLI;
return static_cast<const XXXTargetLowering *>(TLI);
}
- struct ArgInfo {
- unsigned Reg;
- Type *Ty;
- ISD::ArgFlagsTy Flags;
-
- ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{})
- : Reg(Reg), Ty(Ty), Flags(Flags) {}
- };
template <typename FuncInfoTy>
void setArgFlags(ArgInfo &Arg, unsigned OpNum, const DataLayout &DL,
/// Translate an LLVM store instruction into generic IR.
bool translateStore(const User &U);
+ bool translateMemcpy(const CallInst &CI);
+
bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID);
/// Translate call instruction.
return true;
}
+bool IRTranslator::translateMemcpy(const CallInst &CI) {
+ LLT SizeTy{*CI.getArgOperand(2)->getType(), *DL};
+ if (cast<PointerType>(CI.getArgOperand(0)->getType())->getAddressSpace() !=
+ 0 ||
+ cast<PointerType>(CI.getArgOperand(1)->getType())->getAddressSpace() !=
+ 0 ||
+ SizeTy.getSizeInBits() != DL->getPointerSizeInBits(0))
+ return false;
+
+ SmallVector<CallLowering::ArgInfo, 8> Args;
+ for (int i = 0; i < 3; ++i) {
+ const auto &Arg = CI.getArgOperand(i);
+ Args.emplace_back(getOrCreateVReg(*Arg), Arg->getType());
+ }
+
+ MachineOperand Callee = MachineOperand::CreateES("memcpy");
+
+ return CLI->lowerCall(MIRBuilder, Callee,
+ CallLowering::ArgInfo(0, CI.getType()), Args);
+}
bool IRTranslator::translateKnownIntrinsic(const CallInst &CI,
Intrinsic::ID ID) {
case Intrinsic::ssub_with_overflow: Op = TargetOpcode::G_SSUBO; break;
case Intrinsic::umul_with_overflow: Op = TargetOpcode::G_UMULO; break;
case Intrinsic::smul_with_overflow: Op = TargetOpcode::G_SMULO; break;
+ case Intrinsic::memcpy:
+ return translateMemcpy(CI);
}
LLT Ty{*CI.getOperand(0)->getType(), *DL};
ret void()* @allocai64
}
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32 %align, i1 %volatile)
+define void @test_memcpy(i8* %dst, i8* %src, i64 %size) {
+; CHECK-LABEL: name: test_memcpy
+; CHECK: [[DST:%[0-9]+]](p0) = COPY %x0
+; CHECK: [[SRC:%[0-9]+]](p0) = COPY %x1
+; CHECK: [[SIZE:%[0-9]+]](s64) = COPY %x2
+; CHECK: %x0 = COPY [[DST]]
+; CHECK: %x1 = COPY [[SRC]]
+; CHECK: %x2 = COPY [[SIZE]]
+; CHECK: BL $memcpy, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %x0, implicit %x1, implicit %x2
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %size, i32 1, i1 0)
+ ret void
+}