Commit b85cde16 by Srdjan Obucina Committed by Jim Stichnoth

Subzero, MIPS32: Introduction of genTargetHelperCallFor

genTargetHelperCallFor provides framework for calling Subzero runtime functions. This patch implements calls and tests for some of the available functions, but not all. Current lowerCall implementation does not allow more (Handling of FP return values is missing). R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2317653004 . Patch from Srdjan Obucina <srdjan.obucina@imgtec.com>.
parent 84ea9a70
......@@ -215,6 +215,381 @@ uint32_t TargetMIPS32::getStackAlignment() const {
return MIPS32_STACK_ALIGNMENT_BYTES;
}
void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) {
constexpr bool NoTailCall = false;
constexpr bool IsTargetHelperCall = true;
switch (Instr->getKind()) {
default:
return;
case Inst::Arithmetic: {
Variable *Dest = Instr->getDest();
const Type DestTy = Dest->getType();
const InstArithmetic::OpKind Op =
llvm::cast<InstArithmetic>(Instr)->getOp();
if (isVectorType(DestTy)) {
switch (Op) {
default:
break;
case InstArithmetic::Fdiv:
case InstArithmetic::Frem:
case InstArithmetic::Sdiv:
case InstArithmetic::Srem:
case InstArithmetic::Udiv:
case InstArithmetic::Urem:
scalarizeArithmetic(Op, Dest, Instr->getSrc(0), Instr->getSrc(1));
Instr->setDeleted();
return;
}
}
switch (DestTy) {
default:
return;
case IceType_i64: {
RuntimeHelper HelperID = RuntimeHelper::H_Num;
switch (Op) {
default:
return;
case InstArithmetic::Udiv:
HelperID = RuntimeHelper::H_udiv_i64;
break;
case InstArithmetic::Sdiv:
HelperID = RuntimeHelper::H_sdiv_i64;
break;
case InstArithmetic::Urem:
HelperID = RuntimeHelper::H_urem_i64;
break;
case InstArithmetic::Srem:
HelperID = RuntimeHelper::H_srem_i64;
break;
}
if (HelperID == RuntimeHelper::H_Num) {
return;
}
Operand *TargetHelper = Ctx->getRuntimeHelperFunc(HelperID);
constexpr SizeT MaxArgs = 2;
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(Instr->getSrc(0));
Call->addArg(Instr->getSrc(1));
Instr->setDeleted();
return;
}
case IceType_i32:
case IceType_i16:
case IceType_i8: {
InstCast::OpKind CastKind;
RuntimeHelper HelperID = RuntimeHelper::H_Num;
switch (Op) {
default:
return;
case InstArithmetic::Udiv:
HelperID = RuntimeHelper::H_udiv_i32;
CastKind = InstCast::Zext;
break;
case InstArithmetic::Sdiv:
HelperID = RuntimeHelper::H_sdiv_i32;
CastKind = InstCast::Sext;
break;
case InstArithmetic::Urem:
HelperID = RuntimeHelper::H_urem_i32;
CastKind = InstCast::Zext;
break;
case InstArithmetic::Srem:
HelperID = RuntimeHelper::H_srem_i32;
CastKind = InstCast::Sext;
break;
}
if (HelperID == RuntimeHelper::H_Num) {
return;
}
Operand *Src0 = Instr->getSrc(0);
Operand *Src1 = Instr->getSrc(1);
if (DestTy != IceType_i32) {
// Src0 and Src1 have to be zero-, or signed-extended to i32. For Src0,
// we just insert a InstCast right before the call to the helper.
Variable *Src0_32 = Func->makeVariable(IceType_i32);
Context.insert<InstCast>(CastKind, Src0_32, Src0);
Src0 = Src0_32;
if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) {
const int32_t ShAmt = (DestTy == IceType_i16) ? 16 : 24;
int32_t NewC = C->getValue();
if (CastKind == InstCast::Zext) {
NewC &= ~(0x80000000l >> ShAmt);
} else {
NewC = (NewC << ShAmt) >> ShAmt;
}
Src1 = Ctx->getConstantInt32(NewC);
} else {
Variable *Src1_32 = Func->makeVariable(IceType_i32);
Context.insert<InstCast>(CastKind, Src1_32, Src1);
Src1 = Src1_32;
}
}
Operand *TargetHelper = Ctx->getRuntimeHelperFunc(HelperID);
constexpr SizeT MaxArgs = 2;
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
assert(Src0->getType() == IceType_i32);
Call->addArg(Src0);
assert(Src1->getType() == IceType_i32);
Call->addArg(Src1);
Instr->setDeleted();
return;
}
case IceType_f32:
case IceType_f64: {
if (Op != InstArithmetic::Frem) {
return;
}
constexpr SizeT MaxArgs = 2;
Operand *TargetHelper = Ctx->getRuntimeHelperFunc(
DestTy == IceType_f32 ? RuntimeHelper::H_frem_f32
: RuntimeHelper::H_frem_f64);
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(Instr->getSrc(0));
Call->addArg(Instr->getSrc(1));
Instr->setDeleted();
return;
}
}
llvm::report_fatal_error("Control flow should never have reached here.");
}
case Inst::Cast: {
Variable *Dest = Instr->getDest();
Operand *Src0 = Instr->getSrc(0);
const Type DestTy = Dest->getType();
const Type SrcTy = Src0->getType();
auto *CastInstr = llvm::cast<InstCast>(Instr);
const InstCast::OpKind CastKind = CastInstr->getCastKind();
switch (CastKind) {
default:
return;
case InstCast::Fptosi:
case InstCast::Fptoui: {
if (DestTy != IceType_i64) {
return;
}
const bool DestIsSigned = CastKind == InstCast::Fptosi;
const bool Src0IsF32 = isFloat32Asserting32Or64(SrcTy);
Operand *TargetHelper = Ctx->getRuntimeHelperFunc(
Src0IsF32 ? (DestIsSigned ? RuntimeHelper::H_fptosi_f32_i64
: RuntimeHelper::H_fptoui_f32_i64)
: (DestIsSigned ? RuntimeHelper::H_fptosi_f64_i64
: RuntimeHelper::H_fptoui_f64_i64));
static constexpr SizeT MaxArgs = 1;
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(Src0);
Instr->setDeleted();
return;
}
case InstCast::Sitofp:
case InstCast::Uitofp: {
if (SrcTy != IceType_i64) {
return;
}
const bool SourceIsSigned = CastKind == InstCast::Sitofp;
const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType());
Operand *TargetHelper = Ctx->getRuntimeHelperFunc(
DestIsF32 ? (SourceIsSigned ? RuntimeHelper::H_sitofp_i64_f32
: RuntimeHelper::H_uitofp_i64_f32)
: (SourceIsSigned ? RuntimeHelper::H_sitofp_i64_f64
: RuntimeHelper::H_uitofp_i64_f64));
static constexpr SizeT MaxArgs = 1;
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(Src0);
Instr->setDeleted();
return;
}
case InstCast::Bitcast: {
if (DestTy == SrcTy) {
return;
}
Variable *CallDest = Dest;
RuntimeHelper HelperID = RuntimeHelper::H_Num;
switch (DestTy) {
default:
return;
case IceType_i8:
assert(SrcTy == IceType_v8i1);
HelperID = RuntimeHelper::H_bitcast_8xi1_i8;
CallDest = Func->makeVariable(IceType_i32);
break;
case IceType_i16:
assert(SrcTy == IceType_v16i1);
HelperID = RuntimeHelper::H_bitcast_16xi1_i16;
CallDest = Func->makeVariable(IceType_i32);
break;
case IceType_v8i1: {
assert(SrcTy == IceType_i8);
HelperID = RuntimeHelper::H_bitcast_i8_8xi1;
Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
// Arguments to functions are required to be at least 32 bits wide.
Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0);
Src0 = Src0AsI32;
} break;
case IceType_v16i1: {
assert(SrcTy == IceType_i16);
HelperID = RuntimeHelper::H_bitcast_i16_16xi1;
Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
// Arguments to functions are required to be at least 32 bits wide.
Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0);
Src0 = Src0AsI32;
} break;
}
constexpr SizeT MaxSrcs = 1;
InstCall *Call = makeHelperCall(HelperID, CallDest, MaxSrcs);
Call->addArg(Src0);
Context.insert(Call);
// The PNaCl ABI disallows i8/i16 return types, so truncate the helper
// call result to the appropriate type as necessary.
if (CallDest->getType() != Dest->getType())
Context.insert<InstCast>(InstCast::Trunc, Dest, CallDest);
Instr->setDeleted();
return;
}
case InstCast::Trunc: {
if (DestTy == SrcTy) {
return;
}
if (!isVectorType(SrcTy)) {
return;
}
assert(typeNumElements(DestTy) == typeNumElements(SrcTy));
assert(typeElementType(DestTy) == IceType_i1);
assert(isVectorIntegerType(SrcTy));
return;
}
case InstCast::Sext:
case InstCast::Zext: {
if (DestTy == SrcTy) {
return;
}
if (!isVectorType(DestTy)) {
return;
}
assert(typeNumElements(DestTy) == typeNumElements(SrcTy));
assert(typeElementType(SrcTy) == IceType_i1);
assert(isVectorIntegerType(DestTy));
return;
}
}
llvm::report_fatal_error("Control flow should never have reached here.");
}
case Inst::IntrinsicCall: {
Variable *Dest = Instr->getDest();
auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr);
Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID;
switch (ID) {
default:
return;
case Intrinsics::Ctpop: {
Operand *Src0 = IntrinsicCall->getArg(0);
Operand *TargetHelper =
Ctx->getRuntimeHelperFunc(isInt32Asserting32Or64(Src0->getType())
? RuntimeHelper::H_call_ctpop_i32
: RuntimeHelper::H_call_ctpop_i64);
static constexpr SizeT MaxArgs = 1;
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(Src0);
Instr->setDeleted();
return;
}
case Intrinsics::Longjmp: {
static constexpr SizeT MaxArgs = 2;
static constexpr Variable *NoDest = nullptr;
Operand *TargetHelper =
Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_longjmp);
auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(IntrinsicCall->getArg(0));
Call->addArg(IntrinsicCall->getArg(1));
Instr->setDeleted();
return;
}
case Intrinsics::Memcpy: {
static constexpr SizeT MaxArgs = 3;
static constexpr Variable *NoDest = nullptr;
Operand *TargetHelper =
Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_memcpy);
auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(IntrinsicCall->getArg(0));
Call->addArg(IntrinsicCall->getArg(1));
Call->addArg(IntrinsicCall->getArg(2));
Instr->setDeleted();
return;
}
case Intrinsics::Memmove: {
static constexpr SizeT MaxArgs = 3;
static constexpr Variable *NoDest = nullptr;
Operand *TargetHelper =
Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_memmove);
auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(IntrinsicCall->getArg(0));
Call->addArg(IntrinsicCall->getArg(1));
Call->addArg(IntrinsicCall->getArg(2));
Instr->setDeleted();
return;
}
case Intrinsics::Memset: {
Operand *ValOp = IntrinsicCall->getArg(1);
assert(ValOp->getType() == IceType_i8);
Variable *ValExt = Func->makeVariable(stackSlotType());
Context.insert<InstCast>(InstCast::Zext, ValExt, ValOp);
static constexpr SizeT MaxArgs = 3;
static constexpr Variable *NoDest = nullptr;
Operand *TargetHelper =
Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_memset);
auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(IntrinsicCall->getArg(0));
Call->addArg(ValExt);
Call->addArg(IntrinsicCall->getArg(2));
Instr->setDeleted();
return;
}
case Intrinsics::NaClReadTP: {
if (SandboxingType == ST_NaCl) {
return;
}
static constexpr SizeT MaxArgs = 0;
assert(SandboxingType != ST_Nonsfi);
Operand *TargetHelper =
Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_read_tp);
Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, NoTailCall,
IsTargetHelperCall);
Instr->setDeleted();
return;
}
case Intrinsics::Setjmp: {
static constexpr SizeT MaxArgs = 1;
Operand *TargetHelper =
Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_setjmp);
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(IntrinsicCall->getArg(0));
Instr->setDeleted();
return;
}
}
llvm::report_fatal_error("Control flow should never have reached here.");
}
}
}
void TargetMIPS32::findMaxStackOutArgsSize() {
// MinNeededOutArgsBytes should be updated if the Target ever creates a
// high-level InstCall that requires more stack bytes.
......@@ -1830,8 +2205,7 @@ void TargetMIPS32::lowerCall(const InstCall *Instr) {
ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_F0);
break;
case IceType_f64:
ReturnReg = makeReg(IceType_f32, RegMIPS32::Reg_F0);
ReturnRegHi = makeReg(IceType_f32, RegMIPS32::Reg_F1);
ReturnReg = makeReg(IceType_f64, RegMIPS32::Reg_F0);
break;
case IceType_v4i1:
case IceType_v8i1:
......@@ -1907,8 +2281,9 @@ void TargetMIPS32::lowerCall(const InstCall *Instr) {
} else {
assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 ||
Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 ||
isScalarFloatingType(Dest->getType()) ||
isVectorType(Dest->getType()));
if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) {
if (isVectorType(Dest->getType())) {
UnimplementedLoweringError(this, Instr);
return;
} else {
......@@ -2302,7 +2677,7 @@ void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
void TargetMIPS32::lowerLoad(const InstLoad *Instr) {
// A Load instruction can be treated the same as an Assign instruction, after
// the source operand is transformed into an OperandARM32Mem operand.
// the source operand is transformed into an OperandMIPS32Mem operand.
Type Ty = Instr->getDest()->getType();
Operand *Src0 = formMemoryOperand(Instr->getSourceAddress(), Ty);
Variable *DestLoad = Instr->getDest();
......
......@@ -565,7 +565,7 @@ protected:
(void)Instr;
return 0;
}
void genTargetHelperCallFor(Inst *Instr) override { (void)Instr; }
void genTargetHelperCallFor(Inst *Instr) override;
void doAddressOptLoad() override;
void doAddressOptStore() override;
void randomlyInsertNop(float Probability,
......
......@@ -408,6 +408,9 @@ entry:
; ARM32: bne
; ARM32: bl {{.*}} __divdi3
; MIPS32-LABEL: div64BitSigned
; MIPS32: jal {{.*}} __divdi3
define internal i64 @div64BitSignedConst(i64 %a) {
entry:
%div = sdiv i64 %a, 12345678901234
......@@ -431,6 +434,9 @@ entry:
; ARM32: movw {{.*}} ; 0xb3a
; ARM32: bl {{.*}} __divdi3
; MIPS32-LABEL: div64BitSignedConst
; MIPS32: jal {{.*}} __divdi3
define internal i64 @div64BitUnsigned(i64 %a, i64 %b) {
entry:
%div = udiv i64 %a, %b
......@@ -447,6 +453,9 @@ entry:
; ARM32: bne
; ARM32: bl {{.*}} __udivdi3
; MIPS32-LABEL: div64BitUnsigned
; MIPS32: jal {{.*}} __udivdi3
define internal i64 @rem64BitSigned(i64 %a, i64 %b) {
entry:
%rem = srem i64 %a, %b
......@@ -463,6 +472,9 @@ entry:
; ARM32: bne
; ARM32: bl {{.*}} __moddi3
; MIPS32-LABEL: rem64BitSigned
; MIPS32: jal {{.*}} __moddi3
define internal i64 @rem64BitUnsigned(i64 %a, i64 %b) {
entry:
%rem = urem i64 %a, %b
......@@ -479,6 +491,9 @@ entry:
; ARM32: bne
; ARM32: bl {{.*}} __umoddi3
; MIPS32-LABEL: rem64BitUnsigned
; MIPS32: jal {{.*}} __umoddi3
define internal i64 @shl64BitSigned(i64 %a, i64 %b) {
entry:
%shl = shl i64 %a, %b
......
......@@ -171,8 +171,7 @@ entry:
; ARM32HWDIV: sdiv
; MIPS32-LABEL: Sdiv
; MIPS32: div
; MIPS32: mflo
; MIPS32: jal {{.*}} __divsi3
define internal i32 @SdivConst(i32 %a) {
entry:
......@@ -191,8 +190,7 @@ entry:
; ARM32HWDIV: sdiv
; MIPS32-LABEL: SdivConst
; MIPS32: div
; MIPS32: mflo
; MIPS32: jal {{.*}} __divsi3
define internal i32 @Srem(i32 %a, i32 %b) {
entry:
......@@ -214,8 +212,7 @@ entry:
; ARM32HWDIV: mls
; MIPS32-LABEL: Srem
; MIPS32: div
; MIPS32: mfhi
; MIPS32: jal {{.*}} __modsi3
define internal i32 @Udiv(i32 %a, i32 %b) {
entry:
......@@ -235,8 +232,7 @@ entry:
; ARM32HWDIV: udiv
; MIPS32-LABEL: Udiv
; MIPS32: divu
; MIPS32: mflo
; MIPS32: jal {{.*}} __udivsi3
define internal i32 @Urem(i32 %a, i32 %b) {
entry:
......@@ -257,8 +253,7 @@ entry:
; ARM32HWDIV: mls
; MIPS32-LABEL: Urem
; MIPS32: divu
; MIPS32: mfhi
; MIPS32: jal {{.*}} __umodsi3
; The following tests check that shift instructions don't try to use a
; ConstantRelocatable as an immediate operand.
......
......@@ -145,6 +145,8 @@ entry:
; CHECK: call {{.*}} R_{{.*}} fmodf
; ARM32-LABEL: remFloat
; ARM32: bl {{.*}} fmodf
; MIPS32-LABEL: remFloat
; MIPS32: jal {{.*}} fmodf
define internal double @remDouble(double %a, double %b) {
entry:
......@@ -155,3 +157,5 @@ entry:
; CHECK: call {{.*}} R_{{.*}} fmod
; ARM32-LABEL: remDouble
; ARM32: bl {{.*}} fmod
; MIPS32-LABEL: remDouble
; MIPS32: jal {{.*}} fmod
......@@ -16,6 +16,12 @@
; RUN: | %if --need=target_ARM32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix ARM32 %s
; RUN: %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm --assemble --disassemble --target mips32\
; RUN: -i %s --args -Om1 --skip-unimplemented \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix MIPS32 %s
declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1)
......@@ -34,6 +40,8 @@ entry:
; OM1: call {{.*}} memcpy
; ARM32-LABEL: test_memcpy
; ARM32: bl {{.*}} memcpy
; MIPS32-LABEL: test_memcpy
; MIPS32: jal {{.*}} memcpy
define internal void @test_memcpy_long_const_len(i32 %iptr_dst, i32 %iptr_src) {
entry:
......@@ -49,6 +57,8 @@ entry:
; OM1: call {{.*}} memcpy
; ARM32-LABEL: test_memcpy_long_const_len
; ARM32: bl {{.*}} memcpy
; MIPS32-LABEL: test_memcpy_long_const_len
; MIPS32: jal {{.*}} memcpy
define internal void @test_memcpy_very_small_const_len(i32 %iptr_dst,
i32 %iptr_src) {
......@@ -67,6 +77,8 @@ entry:
; OM1: call {{.*}} memcpy
; ARM32-LABEL: test_memcpy_very_small_const_len
; ARM32: bl {{.*}} memcpy
; MIPS32-LABEL: test_memcpy_very_small_const_len
; MIPS32: jal {{.*}} memcpy
define internal void @test_memcpy_const_len_3(i32 %iptr_dst, i32 %iptr_src) {
entry:
......@@ -86,6 +98,8 @@ entry:
; OM1: call {{.*}} memcpy
; ARM32-LABEL: test_memcpy_const_len_3
; ARM32: bl {{.*}} memcpy
; MIPS32-LABEL: test_memcpy_const_len_3
; MIPS32: jal {{.*}} memcpy
define internal void @test_memcpy_mid_const_len(i32 %iptr_dst, i32 %iptr_src) {
entry:
......@@ -105,6 +119,8 @@ entry:
; OM1: call {{.*}} memcpy
; ARM32-LABEL: test_memcpy_mid_const_len
; ARM32: bl {{.*}} memcpy
; MIPS32-LABEL: test_memcpy_mid_const_len
; MIPS32: jal {{.*}} memcpy
define internal void @test_memcpy_mid_const_len_overlap(i32 %iptr_dst,
i32 %iptr_src) {
......@@ -125,6 +141,8 @@ entry:
; OM1: call {{.*}} memcpy
; ARM32-LABEL: test_memcpy_mid_const_len_overlap
; ARM32: bl {{.*}} memcpy
; MIPS32-LABEL: test_memcpy_mid_const_len_overlap
; MIPS32: jal {{.*}} memcpy
define internal void @test_memcpy_big_const_len_overlap(i32 %iptr_dst,
i32 %iptr_src) {
......@@ -145,6 +163,8 @@ entry:
; OM1: call {{.*}} memcpy
; ARM32-LABEL: test_memcpy_big_const_len_overlap
; ARM32: bl {{.*}} memcpy
; MIPS32-LABEL: test_memcpy_big_const_len_overlap
; MIPS32: jal {{.*}} memcpy
define internal void @test_memcpy_large_const_len(i32 %iptr_dst,
i32 %iptr_src) {
......@@ -167,6 +187,8 @@ entry:
; OM1: call {{.*}} memcpy
; ARM32-LABEL: test_memcpy_large_const_len
; ARM32: bl {{.*}} memcpy
; MIPS32-LABEL: test_memcpy_large_const_len
; MIPS32: jal {{.*}} memcpy
define internal void @test_memmove(i32 %iptr_dst, i32 %iptr_src, i32 %len) {
entry:
......@@ -182,6 +204,8 @@ entry:
; OM1: call {{.*}} memmove
; ARM32-LABEL: test_memmove
; ARM32: bl {{.*}} memmove
; MIPS32-LABEL: test_memmove
; MIPS32: jal {{.*}} memmove
define internal void @test_memmove_long_const_len(i32 %iptr_dst,
i32 %iptr_src) {
......@@ -198,6 +222,8 @@ entry:
; OM1: call {{.*}} memmove
; ARM32-LABEL: test_memmove_long_const_len
; ARM32: bl {{.*}} memmove
; MIPS32-LABEL: test_memmove_long_const_len
; MIPS32: jal {{.*}} memmove
define internal void @test_memmove_very_small_const_len(i32 %iptr_dst,
i32 %iptr_src) {
......@@ -216,6 +242,8 @@ entry:
; OM1: call {{.*}} memmove
; ARM32-LABEL: test_memmove_very_small_const_len
; ARM32: bl {{.*}} memmove
; MIPS32-LABEL: test_memmove_very_small_const_len
; MIPS32: jal {{.*}} memmove
define internal void @test_memmove_const_len_3(i32 %iptr_dst, i32 %iptr_src) {
entry:
......@@ -235,6 +263,8 @@ entry:
; OM1: call {{.*}} memmove
; ARM32-LABEL: test_memmove_const_len_3
; ARM32: bl {{.*}} memmove
; MIPS32-LABEL: test_memmove_const_len_3
; MIPS32: jal {{.*}} memmove
define internal void @test_memmove_mid_const_len(i32 %iptr_dst, i32 %iptr_src) {
entry:
......@@ -254,6 +284,8 @@ entry:
; OM1: call {{.*}} memmove
; ARM32-LABEL: test_memmove_mid_const_len
; ARM32: bl {{.*}} memmove
; MIPS32-LABEL: test_memmove_mid_const_len
; MIPS32: jal {{.*}} memmove
define internal void @test_memmove_mid_const_len_overlap(i32 %iptr_dst,
i32 %iptr_src) {
......@@ -274,6 +306,8 @@ entry:
; OM1: call {{.*}} memmove
; ARM32-LABEL: test_memmove_mid_const_len_overlap
; ARM32: bl {{.*}} memmove
; MIPS32-LABEL: test_memmove_mid_const_len_overlap
; MIPS32: jal {{.*}} memmove
define internal void @test_memmove_big_const_len_overlap(i32 %iptr_dst,
i32 %iptr_src) {
......@@ -294,6 +328,8 @@ entry:
; OM1: call {{.*}} memmove
; ARM32-LABEL: test_memmove_big_const_len_overlap
; ARM32: bl {{.*}} memmove
; MIPS32-LABEL: test_memmove_big_const_len_overlap
; MIPS32: jal {{.*}} memmove
define internal void @test_memmove_large_const_len(i32 %iptr_dst,
i32 %iptr_src) {
......@@ -316,6 +352,8 @@ entry:
; OM1: call {{.*}} memmove
; ARM32-LABEL: test_memmove_large_const_len
; ARM32: bl {{.*}} memmove
; MIPS32-LABEL: test_memmove_large_const_len
; MIPS32: jal {{.*}} memmove
define internal void @test_memset(i32 %iptr_dst, i32 %wide_val, i32 %len) {
entry:
......@@ -334,6 +372,8 @@ entry:
; ARM32-LABEL: test_memset
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset
; MIPS32: jal {{.*}} memset
define internal void @test_memset_const_len_align(i32 %iptr_dst,
i32 %wide_val) {
......@@ -353,6 +393,8 @@ entry:
; ARM32-LABEL: test_memset_const_len_align
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_const_len_align
; MIPS32: jal {{.*}} memset
define internal void @test_memset_long_const_len_zero_val_align(
i32 %iptr_dst) {
......@@ -369,6 +411,8 @@ entry:
; ARM32-LABEL: test_memset_long_const_len_zero_val_align
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_long_const_len_zero_val_align
; MIPS32: jal {{.*}} memset
define internal void @test_memset_const_val(i32 %iptr_dst, i32 %len) {
entry:
......@@ -384,6 +428,8 @@ entry:
; ARM32-LABEL: test_memset_const_val
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_const_val
; MIPS32: jal {{.*}} memset
define internal void @test_memset_const_val_len_very_small(i32 %iptr_dst) {
entry:
......@@ -399,6 +445,8 @@ entry:
; ARM32-LABEL: test_memset_const_val_len_very_small
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_const_val_len_very_small
; MIPS32: jal {{.*}} memset
define internal void @test_memset_const_val_len_3(i32 %iptr_dst) {
entry:
......@@ -415,6 +463,8 @@ entry:
; ARM32-LABEL: test_memset_const_val_len_3
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_const_val_len_3
; MIPS32: jal {{.*}} memset
define internal void @test_memset_const_val_len_mid(i32 %iptr_dst) {
entry:
......@@ -432,6 +482,8 @@ entry:
; ARM32-LABEL: test_memset_const_val_len_mid
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_const_val_len_mid
; MIPS32: jal {{.*}} memset
; Same as above, but with a negative value.
define internal void @test_memset_const_neg_val_len_mid(i32 %iptr_dst) {
......@@ -450,6 +502,8 @@ entry:
; ARM32-LABEL: test_memset_const_neg_val_len_mid
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_const_neg_val_len_mid
; MIPS32: jal {{.*}} memset
define internal void @test_memset_zero_const_len_small(i32 %iptr_dst) {
entry:
......@@ -467,6 +521,8 @@ entry:
; ARM32-LABEL: test_memset_zero_const_len_small
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_zero_const_len_small
; MIPS32: jal {{.*}} memset
define internal void @test_memset_zero_const_len_small_overlap(i32 %iptr_dst) {
entry:
......@@ -484,6 +540,8 @@ entry:
; ARM32-LABEL: test_memset_zero_const_len_small_overlap
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_zero_const_len_small_overlap
; MIPS32: jal {{.*}} memset
define internal void @test_memset_zero_const_len_big_overlap(i32 %iptr_dst) {
entry:
......@@ -501,6 +559,8 @@ entry:
; ARM32-LABEL: test_memset_zero_const_len_big_overlap
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_zero_const_len_big_overlap
; MIPS32: jal {{.*}} memset
define internal void @test_memset_zero_const_len_large(i32 %iptr_dst) {
entry:
......@@ -519,3 +579,5 @@ entry:
; ARM32-LABEL: test_memset_zero_const_len_large
; ARM32: uxtb
; ARM32: bl {{.*}} memset
; MIPS32-LABEL: test_memset_zero_const_len_large
; MIPS32: jal {{.*}} memset
......@@ -34,6 +34,13 @@
; RUN: | %if --need=target_ARM32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix ARM32 %s
; RUN: %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm --assemble --disassemble --target mips32\
; RUN: -i %s --args -Om1 --skip-unimplemented \
; RUN: -allow-externally-defined-symbols \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix MIPS32 %s
declare i8* @llvm.nacl.read.tp()
declare void @llvm.nacl.longjmp(i8*, i32)
declare i32 @llvm.nacl.setjmp(i8*)
......@@ -67,6 +74,8 @@ entry:
; CHECKO2REM: mov e{{.*}},{{(DWORD PTR )?}}gs:0x0
; CHECKO2UNSANDBOXEDREM-LABEL: test_nacl_read_tp
; CHECKO2UNSANDBOXEDREM: call {{.*}} R_{{.*}} __nacl_read_tp
; MIPS32-LABEL: test_nacl_read_tp
; MIPS32: jal {{.*}} __nacl_read_tp
define internal i32 @test_nacl_read_tp_more_addressing() {
entry:
......@@ -94,6 +103,8 @@ entry:
; CHECKO2UNSANDBOXEDREM-LABEL: test_nacl_read_tp_more_addressing
; CHECKO2UNSANDBOXEDREM: call {{.*}} R_{{.*}} __nacl_read_tp
; CHECKO2UNSANDBOXEDREM: call {{.*}} R_{{.*}} __nacl_read_tp
; MIPS32-LABEL: test_nacl_read_tp_more_addressing
; MIPS32: jal {{.*}} __nacl_read_tp
define internal i32 @test_nacl_read_tp_dead(i32 %a) {
entry:
......@@ -107,6 +118,8 @@ entry:
; CHECKO2REM-NOT: mov e{{.*}}, DWORD PTR gs:0x0
; CHECKO2UNSANDBOXEDREM-LABEL: test_nacl_read_tp_dead
; CHECKO2UNSANDBOXEDREM-NOT: call {{.*}} R_{{.*}} __nacl_read_tp
; MIPS32-LABEL: test_nacl_read_tp_dead
; MIPS32: jal {{.*}} __nacl_read_tp
define internal i32 @test_setjmplongjmp(i32 %iptr_env) {
entry:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment