Commit 928f1297 by Matt Wala

Add support for vector types.

- Add vector types to the type table. - Add support for parsing vector types in llvm2ice. - Legalize undef vector values to zero. Test that undef vector values are lowered correctly. BUG=none R=jvoung@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/353553004
parent 8d7abae9
...@@ -165,6 +165,43 @@ private: ...@@ -165,6 +165,43 @@ private:
} }
} }
Ice::Type convertVectorType(const VectorType *VecTy) const {
unsigned NumElements = VecTy->getNumElements();
const Type *ElementType = VecTy->getElementType();
if (ElementType->isFloatTy()) {
if (NumElements == 4)
return Ice::IceType_v4f32;
} else if (ElementType->isIntegerTy()) {
switch (cast<IntegerType>(ElementType)->getBitWidth()) {
case 1:
if (NumElements == 4)
return Ice::IceType_v4i1;
if (NumElements == 8)
return Ice::IceType_v8i1;
if (NumElements == 16)
return Ice::IceType_v16i1;
break;
case 8:
if (NumElements == 16)
return Ice::IceType_v16i8;
break;
case 16:
if (NumElements == 8)
return Ice::IceType_v8i16;
break;
case 32:
if (NumElements == 4)
return Ice::IceType_v4i32;
break;
}
}
report_fatal_error(std::string("Unhandled vector type: ") +
LLVMObjectAsString(VecTy));
return Ice::IceType_void;
}
Ice::Type convertType(const Type *Ty) const { Ice::Type convertType(const Type *Ty) const {
switch (Ty->getTypeID()) { switch (Ty->getTypeID()) {
case Type::VoidTyID: case Type::VoidTyID:
...@@ -179,6 +216,8 @@ private: ...@@ -179,6 +216,8 @@ private:
return SubzeroPointerType; return SubzeroPointerType;
case Type::FunctionTyID: case Type::FunctionTyID:
return SubzeroPointerType; return SubzeroPointerType;
case Type::VectorTyID:
return convertVectorType(cast<VectorType>(Ty));
default: default:
report_fatal_error(std::string("Invalid PNaCl type: ") + report_fatal_error(std::string("Invalid PNaCl type: ") +
LLVMObjectAsString(Ty)); LLVMObjectAsString(Ty));
......
...@@ -232,6 +232,19 @@ Constant *GlobalContext::getConstantZero(Type Ty) { ...@@ -232,6 +232,19 @@ Constant *GlobalContext::getConstantZero(Type Ty) {
return getConstantFloat(0); return getConstantFloat(0);
case IceType_f64: case IceType_f64:
return getConstantDouble(0); return getConstantDouble(0);
case IceType_v4i1:
case IceType_v8i1:
case IceType_v16i1:
case IceType_v16i8:
case IceType_v8i16:
case IceType_v4i32:
case IceType_v4f32: {
IceString Str;
llvm::raw_string_ostream BaseOS(Str);
Ostream OS(&BaseOS);
OS << "Unsupported constant type: " << Ty;
llvm_unreachable(BaseOS.str().c_str());
} break;
case IceType_void: case IceType_void:
case IceType_NUM: case IceType_NUM:
break; break;
...@@ -251,6 +264,19 @@ ConstantList GlobalContext::getConstantPool(Type Ty) const { ...@@ -251,6 +264,19 @@ ConstantList GlobalContext::getConstantPool(Type Ty) const {
return ConstPool->Floats.getConstantPool(); return ConstPool->Floats.getConstantPool();
case IceType_f64: case IceType_f64:
return ConstPool->Doubles.getConstantPool(); return ConstPool->Doubles.getConstantPool();
case IceType_v4i1:
case IceType_v8i1:
case IceType_v16i1:
case IceType_v16i8:
case IceType_v8i16:
case IceType_v4i32:
case IceType_v4f32: {
IceString Str;
llvm::raw_string_ostream BaseOS(Str);
Ostream OS(&BaseOS);
OS << "Unsupported constant type: " << Ty;
llvm_unreachable(BaseOS.str().c_str());
} break;
case IceType_void: case IceType_void:
case IceType_NUM: case IceType_NUM:
break; break;
......
...@@ -182,6 +182,11 @@ InstX8632Mov::InstX8632Mov(Cfg *Func, Variable *Dest, Operand *Source) ...@@ -182,6 +182,11 @@ InstX8632Mov::InstX8632Mov(Cfg *Func, Variable *Dest, Operand *Source)
addSource(Source); addSource(Source);
} }
InstX8632Movp::InstX8632Movp(Cfg *Func, Variable *Dest, Operand *Source)
: InstX8632(Func, InstX8632::Movp, 1, Dest) {
addSource(Source);
}
InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Operand *Value, OperandX8632 *Mem) InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Operand *Value, OperandX8632 *Mem)
: InstX8632(Func, InstX8632::StoreQ, 2, NULL) { : InstX8632(Func, InstX8632::StoreQ, 2, NULL) {
addSource(Value); addSource(Value);
...@@ -222,6 +227,9 @@ InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source, ...@@ -222,6 +227,9 @@ InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source,
} }
bool InstX8632Mov::isRedundantAssign() const { bool InstX8632Mov::isRedundantAssign() const {
// TODO(stichnot): The isRedundantAssign() implementations for
// InstX8632Mov, InstX8632Movp, and InstX8632Movq are
// identical. Consolidate them.
Variable *Src = llvm::dyn_cast<Variable>(getSrc(0)); Variable *Src = llvm::dyn_cast<Variable>(getSrc(0));
if (Src == NULL) if (Src == NULL)
return false; return false;
...@@ -237,6 +245,19 @@ bool InstX8632Mov::isRedundantAssign() const { ...@@ -237,6 +245,19 @@ bool InstX8632Mov::isRedundantAssign() const {
return false; return false;
} }
bool InstX8632Movp::isRedundantAssign() const {
Variable *Src = llvm::dyn_cast<Variable>(getSrc(0));
if (Src == NULL)
return false;
if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) {
return true;
}
if (!getDest()->hasReg() && !Src->hasReg() &&
Dest->getStackOffset() == Src->getStackOffset())
return true;
return false;
}
bool InstX8632Movq::isRedundantAssign() const { bool InstX8632Movq::isRedundantAssign() const {
Variable *Src = llvm::dyn_cast<Variable>(getSrc(0)); Variable *Src = llvm::dyn_cast<Variable>(getSrc(0));
if (Src == NULL) if (Src == NULL)
...@@ -381,6 +402,7 @@ template <> const char *InstX8632Sbb::Opcode = "sbb"; ...@@ -381,6 +402,7 @@ template <> const char *InstX8632Sbb::Opcode = "sbb";
template <> const char *InstX8632And::Opcode = "and"; template <> const char *InstX8632And::Opcode = "and";
template <> const char *InstX8632Or::Opcode = "or"; template <> const char *InstX8632Or::Opcode = "or";
template <> const char *InstX8632Xor::Opcode = "xor"; template <> const char *InstX8632Xor::Opcode = "xor";
template <> const char *InstX8632Pxor::Opcode = "pxor";
template <> const char *InstX8632Imul::Opcode = "imul"; template <> const char *InstX8632Imul::Opcode = "imul";
template <> const char *InstX8632Mulss::Opcode = "mulss"; template <> const char *InstX8632Mulss::Opcode = "mulss";
template <> const char *InstX8632Div::Opcode = "div"; template <> const char *InstX8632Div::Opcode = "div";
...@@ -693,6 +715,20 @@ void InstX8632Mov::dump(const Cfg *Func) const { ...@@ -693,6 +715,20 @@ void InstX8632Mov::dump(const Cfg *Func) const {
dumpSources(Func); dumpSources(Func);
} }
void InstX8632Movp::emit(const Cfg *Func) const {
// TODO(wala,stichnot): movups works with all vector operands, but
// there exist other instructions (movaps, movdqa, movdqu) that may
// perform better, depending on the data type and alignment of the
// operands.
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1);
Str << "\tmovups\t";
getDest()->emit(Func);
Str << ", ";
getSrc(0)->emit(Func);
Str << "\n";
}
void InstX8632Movq::emit(const Cfg *Func) const { void InstX8632Movq::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1); assert(getSrcSize() == 1);
...@@ -705,6 +741,14 @@ void InstX8632Movq::emit(const Cfg *Func) const { ...@@ -705,6 +741,14 @@ void InstX8632Movq::emit(const Cfg *Func) const {
Str << "\n"; Str << "\n";
} }
void InstX8632Movp::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
Str << "movups." << getDest()->getType() << " ";
dumpDest(Func);
Str << ", ";
dumpSources(Func);
}
void InstX8632Movq::dump(const Cfg *Func) const { void InstX8632Movq::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
Str << "movq." << getDest()->getType() << " "; Str << "movq." << getDest()->getType() << " ";
......
...@@ -75,6 +75,13 @@ ...@@ -75,6 +75,13 @@
X(IceType_i64, "i", "" , "qword ptr") \ X(IceType_i64, "i", "" , "qword ptr") \
X(IceType_f32, "s", "ss", "dword ptr") \ X(IceType_f32, "s", "ss", "dword ptr") \
X(IceType_f64, "d", "sd", "qword ptr") \ X(IceType_f64, "d", "sd", "qword ptr") \
X(IceType_v4i1, "?", "" , "xmmword ptr") \
X(IceType_v8i1, "?", "" , "xmmword ptr") \
X(IceType_v16i1, "?", "" , "xmmword ptr") \
X(IceType_v16i8, "?", "" , "xmmword ptr") \
X(IceType_v8i16, "?", "" , "xmmword ptr") \
X(IceType_v4i32, "?", "" , "xmmword ptr") \
X(IceType_v4f32, "?", "" , "xmmword ptr") \
//#define X(tag, cvt, sdss, width) //#define X(tag, cvt, sdss, width)
#endif // SUBZERO_SRC_ICEINSTX8632_DEF #endif // SUBZERO_SRC_ICEINSTX8632_DEF
...@@ -153,6 +153,7 @@ public: ...@@ -153,6 +153,7 @@ public:
Load, Load,
Mfence, Mfence,
Mov, Mov,
Movp,
Movq, Movq,
Movsx, Movsx,
Movzx, Movzx,
...@@ -161,6 +162,7 @@ public: ...@@ -161,6 +162,7 @@ public:
Or, Or,
Pop, Pop,
Push, Push,
Pxor,
Ret, Ret,
Sar, Sar,
Sbb, Sbb,
...@@ -402,6 +404,7 @@ typedef InstX8632Binop<InstX8632::Sbb> InstX8632Sbb; ...@@ -402,6 +404,7 @@ typedef InstX8632Binop<InstX8632::Sbb> InstX8632Sbb;
typedef InstX8632Binop<InstX8632::And> InstX8632And; typedef InstX8632Binop<InstX8632::And> InstX8632And;
typedef InstX8632Binop<InstX8632::Or> InstX8632Or; typedef InstX8632Binop<InstX8632::Or> InstX8632Or;
typedef InstX8632Binop<InstX8632::Xor> InstX8632Xor; typedef InstX8632Binop<InstX8632::Xor> InstX8632Xor;
typedef InstX8632Binop<InstX8632::Pxor> InstX8632Pxor;
typedef InstX8632Binop<InstX8632::Imul> InstX8632Imul; typedef InstX8632Binop<InstX8632::Imul> InstX8632Imul;
typedef InstX8632Binop<InstX8632::Mulss> InstX8632Mulss; typedef InstX8632Binop<InstX8632::Mulss> InstX8632Mulss;
typedef InstX8632Binop<InstX8632::Divss> InstX8632Divss; typedef InstX8632Binop<InstX8632::Divss> InstX8632Divss;
...@@ -638,6 +641,26 @@ private: ...@@ -638,6 +641,26 @@ private:
virtual ~InstX8632Mov() {} virtual ~InstX8632Mov() {}
}; };
// Move packed - copy 128 bit values between XMM registers or mem128 and
// XMM registers
class InstX8632Movp : public InstX8632 {
public:
static InstX8632Movp *create(Cfg *Func, Variable *Dest, Operand *Source) {
return new (Func->allocate<InstX8632Movp>())
InstX8632Movp(Func, Dest, Source);
}
virtual bool isRedundantAssign() const;
virtual void emit(const Cfg *Func) const;
virtual void dump(const Cfg *Func) const;
static bool classof(const Inst *Inst) { return isClassof(Inst, Movp); }
private:
InstX8632Movp(Cfg *Func, Variable *Dest, Operand *Source);
InstX8632Movp(const InstX8632Movp &) LLVM_DELETED_FUNCTION;
InstX8632Movp &operator=(const InstX8632Movp &) LLVM_DELETED_FUNCTION;
virtual ~InstX8632Movp() {}
};
// This is essentially a "movq" instruction with an OperandX8632Mem // This is essentially a "movq" instruction with an OperandX8632Mem
// operand instead of Variable as the destination. It's important // operand instead of Variable as the destination. It's important
// for liveness that there is no Dest operand. // for liveness that there is no Dest operand.
......
...@@ -120,10 +120,9 @@ public: ...@@ -120,10 +120,9 @@ public:
} }
T getValue() const { return Value; } T getValue() const { return Value; }
using Constant::emit; using Constant::emit;
virtual void emit(GlobalContext *Ctx) const { // The target needs to implement this for each ConstantPrimitive
Ostream &Str = Ctx->getStrEmit(); // specialization.
Str << getValue(); virtual void emit(GlobalContext *Ctx) const;
}
using Constant::dump; using Constant::dump;
virtual void dump(GlobalContext *Ctx) const { virtual void dump(GlobalContext *Ctx) const {
Ostream &Str = Ctx->getStrDump(); Ostream &Str = Ctx->getStrDump();
......
...@@ -160,7 +160,8 @@ void xMacroIntegrityCheck() { ...@@ -160,7 +160,8 @@ void xMacroIntegrityCheck() {
_num _num
}; };
// Define a set of constants based on high-level table entries. // Define a set of constants based on high-level table entries.
#define X(tag, size, align, str) static const int _table1_##tag = tag; #define X(tag, size, align, elts, elty, str) \
static const int _table1_##tag = tag;
ICETYPE_TABLE; ICETYPE_TABLE;
#undef X #undef X
// Define a set of constants based on low-level table entries, // Define a set of constants based on low-level table entries,
...@@ -172,7 +173,8 @@ void xMacroIntegrityCheck() { ...@@ -172,7 +173,8 @@ void xMacroIntegrityCheck() {
#undef X #undef X
// Repeat the static asserts with respect to the high-level // Repeat the static asserts with respect to the high-level
// table entries in case the high-level table has extra entries. // table entries in case the high-level table has extra entries.
#define X(tag, size, align, str) STATIC_ASSERT(_table1_##tag == _table2_##tag); #define X(tag, size, align, elts, elty, str) \
STATIC_ASSERT(_table1_##tag == _table2_##tag);
ICETYPE_TABLE; ICETYPE_TABLE;
#undef X #undef X
} }
...@@ -190,6 +192,7 @@ TargetX8632::TargetX8632(Cfg *Func) ...@@ -190,6 +192,7 @@ TargetX8632::TargetX8632(Cfg *Func)
llvm::SmallBitVector IntegerRegisters(Reg_NUM); llvm::SmallBitVector IntegerRegisters(Reg_NUM);
llvm::SmallBitVector IntegerRegistersI8(Reg_NUM); llvm::SmallBitVector IntegerRegistersI8(Reg_NUM);
llvm::SmallBitVector FloatRegisters(Reg_NUM); llvm::SmallBitVector FloatRegisters(Reg_NUM);
llvm::SmallBitVector VectorRegisters(Reg_NUM);
llvm::SmallBitVector InvalidRegisters(Reg_NUM); llvm::SmallBitVector InvalidRegisters(Reg_NUM);
ScratchRegs.resize(Reg_NUM); ScratchRegs.resize(Reg_NUM);
#define X(val, init, name, name16, name8, scratch, preserved, stackptr, \ #define X(val, init, name, name16, name8, scratch, preserved, stackptr, \
...@@ -197,6 +200,7 @@ TargetX8632::TargetX8632(Cfg *Func) ...@@ -197,6 +200,7 @@ TargetX8632::TargetX8632(Cfg *Func)
IntegerRegisters[val] = isInt; \ IntegerRegisters[val] = isInt; \
IntegerRegistersI8[val] = isI8; \ IntegerRegistersI8[val] = isI8; \
FloatRegisters[val] = isFP; \ FloatRegisters[val] = isFP; \
VectorRegisters[val] = isFP; \
ScratchRegs[val] = scratch; ScratchRegs[val] = scratch;
REGX8632_TABLE; REGX8632_TABLE;
#undef X #undef X
...@@ -208,6 +212,13 @@ TargetX8632::TargetX8632(Cfg *Func) ...@@ -208,6 +212,13 @@ TargetX8632::TargetX8632(Cfg *Func)
TypeToRegisterSet[IceType_i64] = IntegerRegisters; TypeToRegisterSet[IceType_i64] = IntegerRegisters;
TypeToRegisterSet[IceType_f32] = FloatRegisters; TypeToRegisterSet[IceType_f32] = FloatRegisters;
TypeToRegisterSet[IceType_f64] = FloatRegisters; TypeToRegisterSet[IceType_f64] = FloatRegisters;
TypeToRegisterSet[IceType_v4i1] = VectorRegisters;
TypeToRegisterSet[IceType_v8i1] = VectorRegisters;
TypeToRegisterSet[IceType_v16i1] = VectorRegisters;
TypeToRegisterSet[IceType_v16i8] = VectorRegisters;
TypeToRegisterSet[IceType_v8i16] = VectorRegisters;
TypeToRegisterSet[IceType_v4i32] = VectorRegisters;
TypeToRegisterSet[IceType_v4f32] = VectorRegisters;
} }
void TargetX8632::translateO2() { void TargetX8632::translateO2() {
...@@ -1317,6 +1328,21 @@ void TargetX8632::lowerCall(const InstCall *Instr) { ...@@ -1317,6 +1328,21 @@ void TargetX8632::lowerCall(const InstCall *Instr) {
// Leave eax==edx==NULL, and capture the result with the fstp // Leave eax==edx==NULL, and capture the result with the fstp
// instruction. // instruction.
break; break;
case IceType_v4i1:
case IceType_v8i1:
case IceType_v16i1:
case IceType_v16i8:
case IceType_v8i16:
case IceType_v4i32:
case IceType_v4f32: {
// TODO(wala): Handle return values of vector type in the caller.
IceString Ty;
llvm::raw_string_ostream BaseOS(Ty);
Ostream OS(&BaseOS);
OS << Dest->getType();
Func->setError("Unhandled dest type: " + BaseOS.str());
return;
}
} }
} }
// TODO(stichnot): LEAHACK: remove Legal_All (and use default) once // TODO(stichnot): LEAHACK: remove Legal_All (and use default) once
...@@ -2273,6 +2299,8 @@ void TargetX8632::lowerRet(const InstRet *Inst) { ...@@ -2273,6 +2299,8 @@ void TargetX8632::lowerRet(const InstRet *Inst) {
} else if (Src0->getType() == IceType_f32 || } else if (Src0->getType() == IceType_f32 ||
Src0->getType() == IceType_f64) { Src0->getType() == IceType_f64) {
_fld(Src0); _fld(Src0);
} else if (isVectorType(Src0->getType())) {
Reg = legalizeToVar(Src0, false, Reg_xmm0);
} else { } else {
_mov(Reg, Src0, Reg_eax); _mov(Reg, Src0, Reg_eax);
} }
...@@ -2394,6 +2422,19 @@ void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) { ...@@ -2394,6 +2422,19 @@ void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) {
lowerCall(Call); lowerCall(Call);
} }
// Helper for legalize() to emit the right code to lower an operand to a
// register of the appropriate type.
Variable *TargetX8632::copyToReg(Operand *Src, int32_t RegNum) {
Type Ty = Src->getType();
Variable *Reg = makeReg(Ty, RegNum);
if (isVectorType(Src->getType())) {
_movp(Reg, Src);
} else {
_mov(Reg, Src);
}
return Reg;
}
Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
bool AllowOverlap, int32_t RegNum) { bool AllowOverlap, int32_t RegNum) {
// Assert that a physical register is allowed. To date, all calls // Assert that a physical register is allowed. To date, all calls
...@@ -2426,9 +2467,7 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, ...@@ -2426,9 +2467,7 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
} }
if (!(Allowed & Legal_Mem)) { if (!(Allowed & Legal_Mem)) {
Variable *Reg = makeReg(From->getType(), RegNum); From = copyToReg(From, RegNum);
_mov(Reg, From, RegNum);
From = Reg;
} }
return From; return From;
} }
...@@ -2445,8 +2484,20 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, ...@@ -2445,8 +2484,20 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
// overestimated. If the constant being lowered is a 64 bit value, // overestimated. If the constant being lowered is a 64 bit value,
// then the result should be split and the lo and hi components will // then the result should be split and the lo and hi components will
// need to go in uninitialized registers. // need to go in uninitialized registers.
if (isVectorType(From->getType())) {
// There is no support for loading or emitting vector constants, so
// undef values are instead initialized in registers.
Variable *Reg = makeReg(From->getType(), RegNum);
// Insert a FakeDef, since otherwise the live range of Reg might
// be overestimated.
Context.insert(InstFakeDef::create(Func, Reg));
_pxor(Reg, Reg);
return Reg;
} else {
From = Ctx->getConstantZero(From->getType()); From = Ctx->getConstantZero(From->getType());
} }
}
bool NeedsReg = false; bool NeedsReg = false;
if (!(Allowed & Legal_Imm)) if (!(Allowed & Legal_Imm))
// Immediate specifically not allowed // Immediate specifically not allowed
...@@ -2461,9 +2512,7 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, ...@@ -2461,9 +2512,7 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
// On x86, FP constants are lowered to mem operands. // On x86, FP constants are lowered to mem operands.
NeedsReg = true; NeedsReg = true;
if (NeedsReg) { if (NeedsReg) {
Variable *Reg = makeReg(From->getType(), RegNum); From = copyToReg(From, RegNum);
_mov(Reg, From);
From = Reg;
} }
return From; return From;
} }
...@@ -2473,11 +2522,10 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, ...@@ -2473,11 +2522,10 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
// RegNum is required and Var->getRegNum() doesn't match. // RegNum is required and Var->getRegNum() doesn't match.
if ((!(Allowed & Legal_Mem) && !Var->hasReg()) || if ((!(Allowed & Legal_Mem) && !Var->hasReg()) ||
(RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
Variable *Reg = makeReg(From->getType(), RegNum); Variable *Reg = copyToReg(From, RegNum);
if (RegNum == Variable::NoRegister) { if (RegNum == Variable::NoRegister) {
Reg->setPreferredRegister(Var, AllowOverlap); Reg->setPreferredRegister(Var, AllowOverlap);
} }
_mov(Reg, From);
From = Reg; From = Reg;
} }
return From; return From;
...@@ -2579,6 +2627,11 @@ void TargetX8632::postLower() { ...@@ -2579,6 +2627,11 @@ void TargetX8632::postLower() {
} }
} }
template <> void ConstantInteger::emit(GlobalContext *Ctx) const {
Ostream &Str = Ctx->getStrEmit();
Str << getValue();
}
template <> void ConstantFloat::emit(GlobalContext *Ctx) const { template <> void ConstantFloat::emit(GlobalContext *Ctx) const {
Ostream &Str = Ctx->getStrEmit(); Ostream &Str = Ctx->getStrEmit();
// It would be better to prefix with ".L$" instead of "L$", but // It would be better to prefix with ".L$" instead of "L$", but
......
...@@ -136,6 +136,8 @@ protected: ...@@ -136,6 +136,8 @@ protected:
} }
static Type stackSlotType(); static Type stackSlotType();
Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
// The following are helpers that insert lowered x86 instructions // The following are helpers that insert lowered x86 instructions
// with minimal syntactic overhead, so that the lowering code can // with minimal syntactic overhead, so that the lowering code can
// look as close to assembly as practical. // look as close to assembly as practical.
...@@ -202,6 +204,9 @@ protected: ...@@ -202,6 +204,9 @@ protected:
Context.insert(InstX8632Mov::create(Func, Dest, Src0)); Context.insert(InstX8632Mov::create(Func, Dest, Src0));
} }
} }
void _movp(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Movp::create(Func, Dest, Src0));
}
void _movq(Variable *Dest, Operand *Src0) { void _movq(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Movq::create(Func, Dest, Src0)); Context.insert(InstX8632Movq::create(Func, Dest, Src0));
} }
...@@ -275,6 +280,9 @@ protected: ...@@ -275,6 +280,9 @@ protected:
void _xor(Variable *Dest, Operand *Src0) { void _xor(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Xor::create(Func, Dest, Src0)); Context.insert(InstX8632Xor::create(Func, Dest, Src0));
} }
void _pxor(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Pxor::create(Func, Dest, Src0));
}
bool IsEbpBasedFrame; bool IsEbpBasedFrame;
size_t FrameSizeLocals; size_t FrameSizeLocals;
...@@ -313,6 +321,7 @@ private: ...@@ -313,6 +321,7 @@ private:
virtual ~TargetGlobalInitX8632() {} virtual ~TargetGlobalInitX8632() {}
}; };
template <> void ConstantInteger::emit(GlobalContext *Ctx) const;
template <> void ConstantFloat::emit(GlobalContext *Ctx) const; template <> void ConstantFloat::emit(GlobalContext *Ctx) const;
template <> void ConstantDouble::emit(GlobalContext *Ctx) const; template <> void ConstantDouble::emit(GlobalContext *Ctx) const;
......
...@@ -21,10 +21,12 @@ namespace { ...@@ -21,10 +21,12 @@ namespace {
const struct { const struct {
size_t TypeWidthInBytes; size_t TypeWidthInBytes;
size_t TypeAlignInBytes; size_t TypeAlignInBytes;
size_t TypeNumElements;
Type TypeElementType;
const char *DisplayString; const char *DisplayString;
} TypeAttributes[] = { } TypeAttributes[] = {
#define X(tag, size, align, str) \ #define X(tag, size, align, elts, elty, str) \
{ size, align, str } \ { size, align, elts, elty, str } \
, ,
ICETYPE_TABLE ICETYPE_TABLE
#undef X #undef X
...@@ -57,6 +59,28 @@ size_t typeAlignInBytes(Type Ty) { ...@@ -57,6 +59,28 @@ size_t typeAlignInBytes(Type Ty) {
return Align; return Align;
} }
size_t typeNumElements(Type Ty) {
size_t NumElements = 0;
size_t Index = static_cast<size_t>(Ty);
if (Index < TypeAttributesSize) {
NumElements = TypeAttributes[Index].TypeNumElements;
} else {
llvm_unreachable("Invalid type for typeNumElements()");
}
return NumElements;
}
Type typeElementType(Type Ty) {
Type ElementType = IceType_void;
size_t Index = static_cast<size_t>(Ty);
if (Index < TypeAttributesSize) {
ElementType = TypeAttributes[Index].TypeElementType;
} else {
llvm_unreachable("Invalid type for typeElementType()");
}
return ElementType;
}
// ======================== Dump routines ======================== // // ======================== Dump routines ======================== //
template <> Ostream &operator<<(Ostream &Str, const Type &Ty) { template <> Ostream &operator<<(Ostream &Str, const Type &Ty) {
......
...@@ -16,16 +16,23 @@ ...@@ -16,16 +16,23 @@
#define SUBZERO_SRC_ICETYPES_DEF #define SUBZERO_SRC_ICETYPES_DEF
#define ICETYPE_TABLE \ #define ICETYPE_TABLE \
/* enum value, size, align, printable string */ \ /* enum value, size, align, # elts, element type, printable string */ \
/* (size and alignment in bytes) */ \ /* (size and alignment in bytes) */ \
X(IceType_void, 0, 0, "void") \ X(IceType_void, 0, 0, 1, IceType_void, "void") \
X(IceType_i1, 1, 1, "i1") \ X(IceType_i1, 1, 1, 1, IceType_i1, "i1") \
X(IceType_i8, 1, 1, "i8") \ X(IceType_i8, 1, 1, 1, IceType_i8, "i8") \
X(IceType_i16, 2, 1, "i16") \ X(IceType_i16, 2, 1, 1, IceType_i16, "i16") \
X(IceType_i32, 4, 1, "i32") \ X(IceType_i32, 4, 1, 1, IceType_i32, "i32") \
X(IceType_i64, 8, 1, "i64") \ X(IceType_i64, 8, 1, 1, IceType_i64, "i64") \
X(IceType_f32, 4, 4, "float") \ X(IceType_f32, 4, 4, 1, IceType_f32, "float") \
X(IceType_f64, 8, 8, "double") \ X(IceType_f64, 8, 8, 1, IceType_f64, "double") \
//#define X(tag, size, align, str) X(IceType_v4i1, 16, 1, 4, IceType_i1, "<4 x i1>") \
X(IceType_v8i1, 16, 1, 8, IceType_i1, "<8 x i1>") \
X(IceType_v16i1, 16, 1, 16, IceType_i1, "<16 x i1>") \
X(IceType_v16i8, 16, 1, 16, IceType_i8, "<16 x i8>") \
X(IceType_v8i16, 16, 2, 8, IceType_i16, "<8 x i16>") \
X(IceType_v4i32, 16, 4, 4, IceType_i32, "<4 x i32>") \
X(IceType_v4f32, 16, 4, 4, IceType_f32, "<4 x float>") \
//#define X(tag, size, align, elts, elty, str)
#endif // SUBZERO_SRC_ICETYPES_DEF #endif // SUBZERO_SRC_ICETYPES_DEF
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
namespace Ice { namespace Ice {
enum Type { enum Type {
#define X(tag, size, align, str) tag, #define X(tag, size, align, elts, elty, str) tag,
ICETYPE_TABLE ICETYPE_TABLE
#undef X #undef X
IceType_NUM IceType_NUM
...@@ -43,6 +43,10 @@ enum OptLevel { ...@@ -43,6 +43,10 @@ enum OptLevel {
size_t typeWidthInBytes(Type Ty); size_t typeWidthInBytes(Type Ty);
size_t typeAlignInBytes(Type Ty); size_t typeAlignInBytes(Type Ty);
size_t typeNumElements(Type Ty);
Type typeElementType(Type Ty);
inline bool isVectorType(Type Ty) { return typeNumElements(Ty) > 1; }
template <> Ostream &operator<<(class Ostream &Str, const Type &Ty); template <> Ostream &operator<<(class Ostream &Str, const Type &Ty);
......
...@@ -7,31 +7,87 @@ ...@@ -7,31 +7,87 @@
; RUN: %llvm2iceinsts --pnacl %s | %szdiff %s \ ; RUN: %llvm2iceinsts --pnacl %s | %szdiff %s \
; RUN: | FileCheck --check-prefix=DUMP %s ; RUN: | FileCheck --check-prefix=DUMP %s
define i32 @undefi32() { define i32 @undef_i32() {
entry: entry:
; CHECK-LABEL: undefi32:
ret i32 undef ret i32 undef
; CHECK-LABEL: undef_i32:
; CHECK: mov eax, 0 ; CHECK: mov eax, 0
; CHECK: ret ; CHECK: ret
} }
define i64 @undefi64() { define i64 @undef_i64() {
entry: entry:
; CHECK-LABEL: undefi64:
ret i64 undef ret i64 undef
; CHECK-LABEL: undef_i64:
; CHECK-DAG: mov eax, 0 ; CHECK-DAG: mov eax, 0
; CHECK-DAG: mov edx, 0 ; CHECK-DAG: mov edx, 0
; CHECK: ret ; CHECK: ret
} }
define float @undeffloat() { define float @undef_float() {
entry: entry:
; CHECK-LABEL: undeffloat:
ret float undef ret float undef
; CHECK-LABEL: undef_float:
; CHECK-NOT: sub esp ; CHECK-NOT: sub esp
; CHECK: fld ; CHECK: fld
; CHECK: ret ; CHECK: ret
} }
define <4 x i1> @undef_v4i1() {
entry:
ret <4 x i1> undef
; CHECK-LABEL: undef_v4i1:
; CHECK: pxor
; CHECK: ret
}
define <8 x i1> @undef_v8i1() {
entry:
ret <8 x i1> undef
; CHECK-LABEL: undef_v8i1:
; CHECK: pxor
; CHECK: ret
}
define <16 x i1> @undef_v16i1() {
entry:
ret <16 x i1> undef
; CHECK-LABEL: undef_v16i1:
; CHECK: pxor
; CHECK: ret
}
define <16 x i8> @undef_v16i8() {
entry:
ret <16 x i8> undef
; CHECK-LABEL: undef_v16i8:
; CHECK: pxor
; CHECK: ret
}
define <8 x i16> @undef_v8i16() {
entry:
ret <8 x i16> undef
; CHECK-LABEL: undef_v8i16:
; CHECK: pxor
; CHECK: ret
}
define <4 x i32> @undef_v4i32() {
entry:
ret <4 x i32> undef
; CHECK-LABEL: undef_v4i32:
; CHECK: pxor
; CHECK: ret
}
define <4 x float> @undef_v4f32() {
entry:
ret <4 x float> undef
; CHECK-LABEL: undef_v4f32:
; CHECK: pxor
; CHECK: ret
}
; ERRORS-NOT: ICE translation error ; ERRORS-NOT: ICE translation error
; DUMP-NOT: SZ ; DUMP-NOT: SZ
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