Commit 385351ba by John Porto

Fixes ARM32 VFP calling convetion.

Packs VFP arguments as tight as the ABI wants, and adds tests for float and double arguments. vector argument tests will come soon. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1348393002 .
parent 52863b13
...@@ -538,26 +538,31 @@ void InstARM32Vmov::emitSingleDestMultiSource(const Cfg *Func) const { ...@@ -538,26 +538,31 @@ void InstARM32Vmov::emitSingleDestMultiSource(const Cfg *Func) const {
Src1->emit(Func); Src1->emit(Func);
} }
namespace {
bool isVariableWithoutRegister(const Operand *Op) {
if (const auto *OpV = llvm::dyn_cast<const Variable>(Op)) {
return !OpV->hasReg();
}
return false;
}
bool isMemoryAccess(Operand *Op) {
return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op);
}
} // end of anonymous namespace
void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const { void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
Variable *Dest = getDest(); Variable *Dest = getDest();
if (Dest->hasReg()) { if (Dest->hasReg()) {
IceString ActualOpcode = "vmov";
Operand *Src0 = getSrc(0); Operand *Src0 = getSrc(0);
if (const auto *Src0V = llvm::dyn_cast<Variable>(Src0)) { const char *ActualOpcode = isMemoryAccess(Src0) ? "vldr" : "vmov";
if (!Src0V->hasReg()) {
ActualOpcode = IceString("vldr");
}
} else {
if (llvm::isa<OperandARM32Mem>(Src0))
ActualOpcode = IceString("vldr");
}
Str << "\t" << ActualOpcode << "\t"; Str << "\t" << ActualOpcode << "\t";
getDest()->emit(Func); Dest->emit(Func);
Str << ", "; Str << ", ";
getSrc(0)->emit(Func); Src0->emit(Func);
} else { } else {
Variable *Src0 = llvm::cast<Variable>(getSrc(0)); Variable *Src0 = llvm::cast<Variable>(getSrc(0));
assert(Src0->hasReg()); assert(Src0->hasReg());
...@@ -897,8 +902,8 @@ void InstARM32Str::emit(const Cfg *Func) const { ...@@ -897,8 +902,8 @@ void InstARM32Str::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 2); assert(getSrcSize() == 2);
Type Ty = getSrc(0)->getType(); Type Ty = getSrc(0)->getType();
Str << "\t" const char *Opcode = isScalarFloatingType(Ty) ? "vstr" : "str";
<< "str" << getWidthString(Ty) << getPredicate() << "\t"; Str << "\t" << Opcode << getWidthString(Ty) << getPredicate() << "\t";
getSrc(0)->emit(Func); getSrc(0)->emit(Func);
Str << ", "; Str << ", ";
getSrc(1)->emit(Func); getSrc(1)->emit(Func);
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
/// entirely of the lowering sequence for each high-level instruction. /// entirely of the lowering sequence for each high-level instruction.
/// ///
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "IceTargetLoweringARM32.h" #include "IceTargetLoweringARM32.h"
#include "IceCfg.h" #include "IceCfg.h"
...@@ -465,39 +464,50 @@ bool TargetARM32::CallingConv::I32InReg(int32_t *Reg) { ...@@ -465,39 +464,50 @@ bool TargetARM32::CallingConv::I32InReg(int32_t *Reg) {
} }
bool TargetARM32::CallingConv::FPInReg(Type Ty, int32_t *Reg) { bool TargetARM32::CallingConv::FPInReg(Type Ty, int32_t *Reg) {
if (NumFPRegUnits >= ARM32_MAX_FP_REG_UNITS) if (!VFPRegsFree.any()) {
return false; return false;
}
if (isVectorType(Ty)) { if (isVectorType(Ty)) {
NumFPRegUnits = Utils::applyAlignment(NumFPRegUnits, 4);
// Q registers are declared in reverse order, so RegARM32::Reg_q0 > // Q registers are declared in reverse order, so RegARM32::Reg_q0 >
// RegARM32::Reg_q1. Therefore, we need to subtract NumFPRegUnits from // RegARM32::Reg_q1. Therefore, we need to subtract QRegStart from Reg_q0.
// Reg_q0. Same thing goes for D registers. // Same thing goes for D registers.
static_assert(RegARM32::Reg_q0 > RegARM32::Reg_q1, static_assert(RegARM32::Reg_q0 > RegARM32::Reg_q1,
"ARM32 Q registers are possibly declared incorrectly."); "ARM32 Q registers are possibly declared incorrectly.");
*Reg = RegARM32::Reg_q0 - (NumFPRegUnits / 4);
NumFPRegUnits += 4; int32_t QRegStart = (VFPRegsFree & ValidV128Regs).find_first();
// If this bumps us past the boundary, don't allocate to a register and if (QRegStart >= 0) {
// leave any previously speculatively consumed registers as consumed. VFPRegsFree.reset(QRegStart, QRegStart + 4);
if (NumFPRegUnits > ARM32_MAX_FP_REG_UNITS) *Reg = RegARM32::Reg_q0 - (QRegStart / 4);
return false; return true;
}
} else if (Ty == IceType_f64) { } else if (Ty == IceType_f64) {
static_assert(RegARM32::Reg_d0 > RegARM32::Reg_d1, static_assert(RegARM32::Reg_d0 > RegARM32::Reg_d1,
"ARM32 D registers are possibly declared incorrectly."); "ARM32 D registers are possibly declared incorrectly.");
NumFPRegUnits = Utils::applyAlignment(NumFPRegUnits, 2);
*Reg = RegARM32::Reg_d0 - (NumFPRegUnits / 2); int32_t DRegStart = (VFPRegsFree & ValidF64Regs).find_first();
NumFPRegUnits += 2; if (DRegStart >= 0) {
// If this bumps us past the boundary, don't allocate to a register and VFPRegsFree.reset(DRegStart, DRegStart + 2);
// leave any previously speculatively consumed registers as consumed. *Reg = RegARM32::Reg_d0 - (DRegStart / 2);
if (NumFPRegUnits > ARM32_MAX_FP_REG_UNITS) return true;
return false; }
} else { } else {
static_assert(RegARM32::Reg_s0 < RegARM32::Reg_s1, static_assert(RegARM32::Reg_s0 < RegARM32::Reg_s1,
"ARM32 S registers are possibly declared incorrectly."); "ARM32 S registers are possibly declared incorrectly.");
assert(Ty == IceType_f32); assert(Ty == IceType_f32);
*Reg = RegARM32::Reg_s0 + NumFPRegUnits; int32_t SReg = VFPRegsFree.find_first();
++NumFPRegUnits; assert(SReg >= 0);
VFPRegsFree.reset(SReg);
*Reg = RegARM32::Reg_s0 + SReg;
return true;
} }
return true;
// Parameter allocation failed. From now on, every fp register must be placed
// on the stack. We clear VFRegsFree in case there are any "holes" from S and
// D registers.
VFPRegsFree.clear();
return false;
} }
void TargetARM32::lowerArguments() { void TargetARM32::lowerArguments() {
...@@ -2235,6 +2245,8 @@ void TargetARM32::lowerCast(const InstCast *Inst) { ...@@ -2235,6 +2245,8 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
UnimplementedError(Func->getContext()->getFlags()); UnimplementedError(Func->getContext()->getFlags());
break; break;
case IceType_v4i32: case IceType_v4i32:
// avoid cryptic liveness errors
Context.insert(InstFakeDef::create(Func, Dest));
UnimplementedError(Func->getContext()->getFlags()); UnimplementedError(Func->getContext()->getFlags());
break; break;
case IceType_v4f32: case IceType_v4f32:
...@@ -2768,9 +2780,10 @@ void TargetARM32::lowerStore(const InstStore *Inst) { ...@@ -2768,9 +2780,10 @@ void TargetARM32::lowerStore(const InstStore *Inst) {
Variable *ValueLo = legalizeToReg(loOperand(Value)); Variable *ValueLo = legalizeToReg(loOperand(Value));
_str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr)));
_str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr)));
} else if (isVectorType(Ty)) {
UnimplementedError(Func->getContext()->getFlags());
} else { } else {
if (isVectorType(Ty)) {
UnimplementedError(Func->getContext()->getFlags());
}
Variable *ValueR = legalizeToReg(Value); Variable *ValueR = legalizeToReg(Value);
_str(ValueR, NewAddr); _str(ValueR, NewAddr);
} }
...@@ -2832,7 +2845,10 @@ Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { ...@@ -2832,7 +2845,10 @@ Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) {
Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) {
Type Ty = Src->getType(); Type Ty = Src->getType();
Variable *Reg = makeReg(Ty, RegNum); Variable *Reg = makeReg(Ty, RegNum);
if (isVectorType(Ty) || isFloatingType(Ty)) { if (isVectorType(Ty)) {
// TODO(jpp): Src must be a register, or an address with base register.
_vmov(Reg, Src);
} else if (isFloatingType(Ty)) {
_vmov(Reg, Src); _vmov(Reg, Src);
} else { } else {
// Mov's Src operand can really only be the flexible second operand type or // Mov's Src operand can really only be the flexible second operand type or
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include "IceRegistersARM32.h" #include "IceRegistersARM32.h"
#include "IceTargetLowering.h" #include "IceTargetLowering.h"
#include "llvm/ADT/SmallBitVector.h"
namespace Ice { namespace Ice {
// Class encapsulating ARM cpu features / instruction set. // Class encapsulating ARM cpu features / instruction set.
...@@ -461,19 +463,34 @@ protected: ...@@ -461,19 +463,34 @@ protected:
/// Helper class that understands the Calling Convention and register /// Helper class that understands the Calling Convention and register
/// assignments. The first few integer type parameters can use r0-r3, /// assignments. The first few integer type parameters can use r0-r3,
/// regardless of their position relative to the floating-point/vector /// regardless of their position relative to the floating-point/vector
/// arguments in the argument list. Floating-point and vector arguments can /// arguments in the argument list. Floating-point and vector arguments
/// use q0-q3 (aka d0-d7, s0-s15). Technically, arguments that can start with /// can use q0-q3 (aka d0-d7, s0-s15). For more information on the topic,
/// registers but extend beyond the available registers can be split between /// see the ARM Architecture Procedure Calling Standards (AAPCS).
/// the registers and the stack. However, this is typically for passing GPR ///
/// structs by value, and PNaCl transforms expand this out. /// Technically, arguments that can start with registers but extend beyond the
/// available registers can be split between the registers and the stack.
/// However, this is typically for passing GPR structs by value, and PNaCl
/// transforms expand this out.
/// ///
/// Also, at the point before the call, the stack must be aligned. /// At (public) function entry, the stack must be 8-byte aligned.
class CallingConv { class CallingConv {
CallingConv(const CallingConv &) = delete; CallingConv(const CallingConv &) = delete;
CallingConv &operator=(const CallingConv &) = delete; CallingConv &operator=(const CallingConv &) = delete;
public: public:
CallingConv() {} CallingConv()
: VFPRegsFree(ARM32_MAX_FP_REG_UNITS, true),
ValidF64Regs(ARM32_MAX_FP_REG_UNITS),
ValidV128Regs(ARM32_MAX_FP_REG_UNITS) {
for (uint32_t i = 0; i < ARM32_MAX_FP_REG_UNITS; ++i) {
if ((i % 2) == 0) {
ValidF64Regs[i] = true;
}
if ((i % 4) == 0) {
ValidV128Regs[i] = true;
}
}
}
~CallingConv() = default; ~CallingConv() = default;
bool I64InRegs(std::pair<int32_t, int32_t> *Regs); bool I64InRegs(std::pair<int32_t, int32_t> *Regs);
...@@ -481,12 +498,14 @@ protected: ...@@ -481,12 +498,14 @@ protected:
bool FPInReg(Type Ty, int32_t *Reg); bool FPInReg(Type Ty, int32_t *Reg);
static constexpr uint32_t ARM32_MAX_GPR_ARG = 4; static constexpr uint32_t ARM32_MAX_GPR_ARG = 4;
// Units of S registers still available to S/D/Q arguments. // TODO(jpp): comment.
static constexpr uint32_t ARM32_MAX_FP_REG_UNITS = 16; static constexpr uint32_t ARM32_MAX_FP_REG_UNITS = 16;
private: private:
uint32_t NumGPRRegsUsed = 0; uint32_t NumGPRRegsUsed = 0;
uint32_t NumFPRegUnits = 0; llvm::SmallBitVector VFPRegsFree;
llvm::SmallBitVector ValidF64Regs;
llvm::SmallBitVector ValidV128Regs;
}; };
private: private:
......
; Tests validating the vfp calling convention for ARM32.
;
; RUN: %if --need=target_ARM32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm --assemble \
; RUN: --disassemble --target arm32 -i %s --args -O2 --skip-unimplemented \
; RUN: | %if --need=target_ARM32 --need=allow_dump \
; RUN: --command FileCheck %s
; RUN: %if --need=target_ARM32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm --assemble --disassemble --target arm32 \
; RUN: -i %s --args -Om1 --skip-unimplemented \
; RUN: | %if --need=target_ARM32 --need=allow_dump \
; RUN: --command FileCheck %s
; Boring tests ensuring float arguments are allocated "correctly." Unfortunately
; this test cannot verify whether the right arguments are being allocated to the
; right register.
declare void @float1(float %p0)
declare void @float2(float %p0, float %p1)
declare void @float3(float %p0, float %p1, float %p2)
declare void @float4(float %p0, float %p1, float %p2, float %p3)
declare void @float5(float %p0, float %p1, float %p2, float %p3, float %p4)
declare void @float6(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5)
declare void @float7(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6)
declare void @float8(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7)
declare void @float9(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7, float %p8)
declare void @float10(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7, float %p8, float %p9)
declare void @float11(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7, float %p8, float %p9,
float %p10)
declare void @float12(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7, float %p8, float %p9,
float %p10, float %p11)
declare void @float13(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7, float %p8, float %p9,
float %p10, float %p11, float %p12)
declare void @float14(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7, float %p8, float %p9,
float %p10, float %p11, float %p12, float %p13)
declare void @float15(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7, float %p8, float %p9,
float %p10, float %p11, float %p12, float %p13,
float %p14)
declare void @float16(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7, float %p8, float %p9,
float %p10, float %p11, float %p12, float %p13,
float %p14, float %p15)
declare void @float17(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7, float %p8, float %p9,
float %p10, float %p11, float %p12, float %p13,
float %p14, float %p15, float %p16)
declare void @float18(float %p0, float %p1, float %p2, float %p3, float %p4,
float %p5, float %p6, float %p7, float %p8, float %p9,
float %p10, float %p11, float %p12, float %p13,
float %p14, float %p15, float %p16, float %p17)
define void @floatHarness() nounwind {
; CHECK-LABEL: floatHarness
call void @float1(float 1.0)
; CHECK-DAG: vldr s0
; CHECK: bl {{.*}} float1
call void @float2(float 1.0, float 2.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK: bl {{.*}} float2
call void @float3(float 1.0, float 2.0, float 3.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK: bl {{.*}} float3
call void @float4(float 1.0, float 2.0, float 3.0, float 4.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK: bl {{.*}} float4
call void @float5(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK: bl {{.*}} float5
call void @float6(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK: bl {{.*}} float6
call void @float7(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK: bl {{.*}} float7
call void @float8(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK: bl {{.*}} float8
call void @float9(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0, float 9.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK-DAG: vldr s8
; CHECK: bl {{.*}} float9
call void @float10(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0, float 9.0, float 10.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK-DAG: vldr s8
; CHECK-DAG: vldr s9
; CHECK: bl {{.*}} float10
call void @float11(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0, float 9.0, float 10.0,
float 11.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK-DAG: vldr s8
; CHECK-DAG: vldr s9
; CHECK-DAG: vldr s10
; CHECK: bl {{.*}} float11
call void @float12(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0, float 9.0, float 10.0,
float 11.0, float 12.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK-DAG: vldr s8
; CHECK-DAG: vldr s9
; CHECK-DAG: vldr s10
; CHECK-DAG: vldr s11
; CHECK: bl {{.*}} float12
call void @float13(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0, float 9.0, float 10.0,
float 11.0, float 12.0, float 13.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK-DAG: vldr s8
; CHECK-DAG: vldr s9
; CHECK-DAG: vldr s10
; CHECK-DAG: vldr s11
; CHECK-DAG: vldr s12
; CHECK: bl {{.*}} float13
call void @float14(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0, float 9.0, float 10.0,
float 11.0, float 12.0, float 13.0, float 14.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK-DAG: vldr s8
; CHECK-DAG: vldr s9
; CHECK-DAG: vldr s10
; CHECK-DAG: vldr s11
; CHECK-DAG: vldr s12
; CHECK-DAG: vldr s13
; CHECK: bl {{.*}} float14
call void @float15(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0, float 9.0, float 10.0,
float 11.0, float 12.0, float 13.0, float 14.0,
float 15.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK-DAG: vldr s8
; CHECK-DAG: vldr s9
; CHECK-DAG: vldr s10
; CHECK-DAG: vldr s11
; CHECK-DAG: vldr s12
; CHECK-DAG: vldr s13
; CHECK-DAG: vldr s14
; CHECK: bl {{.*}} float15
call void @float16(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0, float 9.0, float 10.0,
float 11.0, float 12.0, float 13.0, float 14.0,
float 15.0, float 16.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK-DAG: vldr s8
; CHECK-DAG: vldr s9
; CHECK-DAG: vldr s10
; CHECK-DAG: vldr s11
; CHECK-DAG: vldr s12
; CHECK-DAG: vldr s13
; CHECK-DAG: vldr s14
; CHECK-DAG: vldr s15
; CHECK: bl {{.*}} float16
call void @float17(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0, float 9.0, float 10.0,
float 11.0, float 12.0, float 13.0, float 14.0,
float 15.0, float 16.0, float 17.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK-DAG: vldr s8
; CHECK-DAG: vldr s9
; CHECK-DAG: vldr s10
; CHECK-DAG: vldr s11
; CHECK-DAG: vldr s12
; CHECK-DAG: vldr s13
; CHECK-DAG: vldr s14
; CHECK-DAG: vldr s15
; CHECK-DAG: vstr s{{.*}}, [sp]
; CHECK: bl {{.*}} float17
call void @float18(float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
float 6.0, float 7.0, float 8.0, float 9.0, float 10.0,
float 11.0, float 12.0, float 13.0, float 14.0,
float 15.0, float 16.0, float 17.0, float 18.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr s1
; CHECK-DAG: vldr s2
; CHECK-DAG: vldr s3
; CHECK-DAG: vldr s4
; CHECK-DAG: vldr s5
; CHECK-DAG: vldr s6
; CHECK-DAG: vldr s7
; CHECK-DAG: vldr s8
; CHECK-DAG: vldr s9
; CHECK-DAG: vldr s10
; CHECK-DAG: vldr s11
; CHECK-DAG: vldr s12
; CHECK-DAG: vldr s13
; CHECK-DAG: vldr s14
; CHECK-DAG: vldr s15
; CHECK-DAG: vstr s{{.*}}, [sp]
; CHECK-DAG: vstr s{{.*}}, [sp, #4]
; CHECK: bl {{.*}} float18
ret void
}
declare void @double1(double %p0)
declare void @double2(double %p0, double %p1)
declare void @double3(double %p0, double %p1, double %p2)
declare void @double4(double %p0, double %p1, double %p2, double %p3)
declare void @double5(double %p0, double %p1, double %p2, double %p3,
double %p4)
declare void @double6(double %p0, double %p1, double %p2, double %p3,
double %p4, double %p5)
declare void @double7(double %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6)
declare void @double8(double %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6, double %p7)
declare void @double9(double %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6, double %p7,
double %p8)
declare void @double10(double %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6, double %p7,
double %p8, double %p9)
define void @doubleHarness() nounwind {
; CHECK-LABEL: doubleHarness
call void @double1(double 1.0)
; CHECK-DAG: vldr d0
; CHECK: bl {{.*}} double1
call void @double2(double 1.0, double 2.0)
; CHECK-DAG: vldr d0
; CHECK-DAG: vldr d1
; CHECK: bl {{.*}} double2
call void @double3(double 1.0, double 2.0, double 3.0)
; CHECK-DAG: vldr d0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK: bl {{.*}} double3
call void @double4(double 1.0, double 2.0, double 3.0, double 4.0)
; CHECK-DAG: vldr d0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK: bl {{.*}} double4
call void @double5(double 1.0, double 2.0, double 3.0, double 4.0,
double 5.0)
; CHECK-DAG: vldr d0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK: bl {{.*}} double5
call void @double6(double 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0)
; CHECK-DAG: vldr d0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK: bl {{.*}} double6
call void @double7(double 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0)
; CHECK-DAG: vldr d0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK: bl {{.*}} double7
call void @double8(double 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0, double 8.0)
; CHECK-DAG: vldr d0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK-DAG: vldr d7
; CHECK: bl {{.*}} double8
call void @double9(double 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0, double 8.0,
double 9.0)
; CHECK-DAG: vldr d0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK-DAG: vldr d7
; CHECK-DAG: vstr d{{.*}}, [sp]
; CHECK: bl {{.*}} double9
call void @double10(double 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0, double 8.0,
double 9.0, double 10.0)
; CHECK-DAG: vldr d0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK-DAG: vldr d7
; CHECK-DAG: vstr d{{.*}}, [sp]
; CHECK-DAG: vstr d{{.*}}, [sp, #8]
; CHECK: bl {{.*}} double10
ret void
}
declare void @testFDF(float %p0, double %p1, float %p2)
declare void @testFDDF(float %p0, double %p1, double %p2, float %p3)
declare void @testFDDDF(float %p0, double %p1, double %p2, double %p3,
float %p4)
declare void @testFDDDDF(float %p0, double %p1, double %p2, double %p3,
double %p4, float %p5)
declare void @testFDDDDDF(float %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, float %p6)
declare void @testFDDDDDDF(float %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6, float %p7)
declare void @testFDDDDDDDF(float %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6, double %p7,
float %p8)
declare void @testFDDDDDDDFD(float %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6, double %p7,
float %p8, double %p9)
declare void @testFDDDDDDDDF(float %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6, double %p7,
double %p8, float %p9)
declare void @testFDDDDDDDDDF(float %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6, double %p7,
double %p8, double %p9, float %p10)
declare void @testFDDDDDDDDFD(float %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6, double %p7,
double %p8, float %p9, double %p10)
declare void @testFDDDDDDDDFDF(float %p0, double %p1, double %p2, double %p3,
double %p4, double %p5, double %p6, double %p7,
double %p8, float %p9, double %p10, float %p11)
define void @packsFloats() nounwind {
; CHECK-LABEL: packsFloats
call void @testFDF(float 1.0, double 2.0, float 3.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr s1
; CHECK: bl {{.*}} testFDF
call void @testFDDF(float 1.0, double 2.0, double 3.0, float 4.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr s1
; CHECK: bl {{.*}} testFDDF
call void @testFDDDF(float 1.0, double 2.0, double 3.0, double 4.0,
float 5.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr s1
; CHECK: bl {{.*}} testFDDDF
call void @testFDDDDF(float 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, float 6.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr s1
; CHECK: bl {{.*}} testFDDDDF
call void @testFDDDDDF(float 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, float 7.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr s1
; CHECK: bl {{.*}} testFDDDDDF
call void @testFDDDDDDF(float 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0, float 8.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK-DAG: vldr s1
; CHECK: bl {{.*}} testFDDDDDDF
call void @testFDDDDDDDF(float 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0, double 8.0,
float 9.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK-DAG: vldr d7
; CHECK-DAG: vldr s1
; CHECK: bl {{.*}} testFDDDDDDDF
call void @testFDDDDDDDFD(float 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0, double 8.0,
float 9.0, double 10.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK-DAG: vldr d7
; CHECK-DAG: vstr d{{.*}}, [sp]
; CHECK-DAG: vldr s1
; CHECK: bl {{.*}} testFDDDDDDDFD
call void @testFDDDDDDDDF(float 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0, double 8.0,
double 9.0, float 10.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK-DAG: vldr d7
; CHECK-DAG: vstr d{{.*}}, [sp]
; CHECK-DAG: vstr s{{.*}}, [sp, #8]
; CHECK: bl {{.*}} testFDDDDDDDDF
call void @testFDDDDDDDDDF(float 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0, double 8.0,
double 9.0, double 10.0, float 11.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK-DAG: vldr d7
; CHECK-DAG: vstr d{{.*}}, [sp]
; CHECK-DAG: vstr d{{.*}}, [sp, #8]
; CHECK-DAG: vstr s{{.*}}, [sp, #16]
; CHECK: bl {{.*}} testFDDDDDDDDDF
call void @testFDDDDDDDDFD(float 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0, double 8.0,
double 9.0, float 10.0, double 11.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK-DAG: vldr d7
; CHECK-DAG: vstr d{{.*}}, [sp]
; CHECK-DAG: vstr s{{.*}}, [sp, #8]
; CHECK-DAG: vstr d{{.*}}, [sp, #16]
; CHECK: bl {{.*}} testFDDDDDDDDFD
call void @testFDDDDDDDDFDF(float 1.0, double 2.0, double 3.0, double 4.0,
double 5.0, double 6.0, double 7.0, double 8.0,
double 9.0, float 10.0, double 11.0, float 12.0)
; CHECK-DAG: vldr s0
; CHECK-DAG: vldr d1
; CHECK-DAG: vldr d2
; CHECK-DAG: vldr d3
; CHECK-DAG: vldr d4
; CHECK-DAG: vldr d5
; CHECK-DAG: vldr d6
; CHECK-DAG: vldr d7
; CHECK-DAG: vstr d{{.*}}, [sp]
; CHECK-DAG: vstr s{{.*}}, [sp, #8]
; CHECK-DAG: vstr d{{.*}}, [sp, #16]
; CHECK-DAG: vstr s{{.*}}, [sp, #24]
; CHECK: bl {{.*}} testFDDDDDDDDFD
ret void
}
; TODO(jpp): add tests for stack alignment.
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
; https://code.google.com/p/nativeclient/issues/detail?id=4304 ; https://code.google.com/p/nativeclient/issues/detail?id=4304
RUN: %p2i --expect-fail --tbc -i %p/Input/phi-invalid.tbc --insts 2>&1 \ RUN: %p2i --expect-fail --tbc -i %p/Input/phi-invalid.tbc --insts 2>&1 \
RUN: --filetype=obj --args -o /dev/null \
RUN: | FileCheck --check-prefix=BADPHI %s RUN: | FileCheck --check-prefix=BADPHI %s
; BADPHI: Phi error: ; BADPHI: Phi error:
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