Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(838)

Unified Diff: src/IceTargetLoweringX8632.cpp

Issue 353553004: Add support for vector types and vector constants. (Closed) Base URL: https://gerrit.chromium.org/gerrit/p/native_client/pnacl-subzero.git@master
Patch Set: 1) Fix alignment in type table. 2) Add VECT128_BYTES constant. 3) add _movp() function. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/IceTargetLoweringX8632.cpp
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index ef9bc22f525087d8ac85bd66b4824871ba58fbab..a358ad53bf8251be27c83a2869c7d4aa435cefad 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -85,6 +85,19 @@ InstX8632Br::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
return TableIcmp32[Index].Mapping;
}
+// Returns the type name as a valid assembly label.
+IceString typeAsmLabel(Type Ty) {
+ IceString Result;
+ llvm::raw_string_ostream BaseOS(Result);
Jim Stichnoth 2014/06/27 18:30:16 I'd like to avoid unnecessarily building LLVM stre
wala 2014/06/27 21:09:19 To avoid snprintf, this function could emit the va
Karl 2014/07/01 20:31:55 I find this statement about not using raw_string_o
+ Ostream OS(&BaseOS);
+ unsigned NumElements = typeNumElements(Ty);
+ if (NumElements > 1) {
+ OS << "v" << NumElements;
+ }
+ OS << typeElementType(Ty);
+ return BaseOS.str();
+}
+
// In some cases, there are x-macros tables for both high-level and
// low-level instructions/operands that use the same enum key value.
// The tables are kept separate to maintain a proper separation
@@ -160,7 +173,8 @@ void xMacroIntegrityCheck() {
_num
};
// 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;
#undef X
// Define a set of constants based on low-level table entries,
@@ -172,7 +186,8 @@ void xMacroIntegrityCheck() {
#undef X
// Repeat the static asserts with respect to the high-level
// 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;
#undef X
}
@@ -681,7 +696,7 @@ const char *PoolTypeConverter<double>::TypeName = "double";
const char *PoolTypeConverter<double>::AsmTag = ".quad";
const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
-template <typename T> void TargetX8632::emitConstantPool() const {
+template <typename T> void TargetX8632::emitScalarConstantPool() const {
Ostream &Str = Ctx->getStrEmit();
Type Ty = T::Ty;
SizeT Align = typeAlignInBytes(Ty);
@@ -710,9 +725,74 @@ template <typename T> void TargetX8632::emitConstantPool() const {
}
}
+void TargetX8632::emitVectorConstantPool() const {
+ Ostream &Str = Ctx->getStrEmit();
jvoung (off chromium) 2014/06/26 23:33:46 You could just make a local variable "Align = 16"
Jim Stichnoth 2014/06/27 18:30:16 Is it appropriate to reuse VECT128_BYTES for this
wala 2014/06/27 21:09:19 I'll do this, and then explain that we naturally a
+ Str << "\t.section\t.rodata.cst" << 16 << ",\"aM\",@progbits," << 16 << "\n";
+ Str << "\t.align\t" << 16 << "\n";
+
+ // Emit each (128 bit) vector.
+ ConstantList Vectors = Ctx->getConstantPool(IceType_v8i16);
jvoung (off chromium) 2014/06/26 23:33:46 Could add a comment that all non-i1 vectors are in
wala 2014/06/27 21:09:19 I will add the comment. I'm unsure how to avoid th
+ for (ConstantList::const_iterator I = Vectors.begin(), E = Vectors.end();
+ I != E; ++I) {
+ ConstantVector *Vector = llvm::cast<ConstantVector>(*I);
+ Vect128 Value = Vector->getValue();
+ assert(Value.size() == VECT128_BYTES);
+ const char *Data = Value.data();
+ Str << "L$" << typeAsmLabel(Vector->getType()) << "$"
+ << Vector->getPoolEntryID() << ":\n";
+ for (unsigned Element = 0; Element != 4; ++Element) {
+ uint32_t RawValue;
+ memcpy(&RawValue, &Data[4 * Element], 4);
+ char buf[30];
+ int CharsPrinted =
+ snprintf(buf, llvm::array_lengthof(buf), "0x%x", RawValue);
+ assert(CharsPrinted >= 0 &&
+ (size_t)CharsPrinted < llvm::array_lengthof(buf));
+ Str << "\t"
+ << ".long"
+ << "\t" << buf << "\t"
+ << "\n";
+ }
+ }
+
+ // Emit each I1 vector expanded to a 128 bit constant.
+ ConstantList BitVectors = Ctx->getConstantPool(IceType_v4i1);
+ for (ConstantList::const_iterator I = BitVectors.begin(),
+ E = BitVectors.end();
+ I != E; ++I) {
+ ConstantBitVector *BitVector = llvm::cast<ConstantBitVector>(*I);
+ BitVect Value = BitVector->getValue();
+ Str << "L$" << typeAsmLabel(BitVector->getType()) << "$"
+ << BitVector->getPoolEntryID() << ":\n";
+ const char *AsmString = NULL;
+ switch (BitVector->getType()) {
+ default:
+ llvm_unreachable("Unknown type");
+ case IceType_v4i1:
+ AsmString = ".long";
+ break;
+ case IceType_v8i1:
+ AsmString = ".short";
+ break;
+ case IceType_v16i1:
+ AsmString = ".byte";
+ break;
+ }
+ unsigned NumElements = Value.size();
+ for (unsigned Element = 0; Element != NumElements; ++Element) {
+ Str << "\t" << AsmString << "\t"
+ << "0x";
+ Str << (Value[Element] ? "1" : "0");
+ Str << "\t"
+ << "\n";
+ }
+ }
+}
+
void TargetX8632::emitConstants() const {
- emitConstantPool<PoolTypeConverter<float> >();
- emitConstantPool<PoolTypeConverter<double> >();
+ emitScalarConstantPool<PoolTypeConverter<float> >();
+ emitScalarConstantPool<PoolTypeConverter<double> >();
+ emitVectorConstantPool();
// No need to emit constants from the int pool since (for x86) they
// are embedded as immediates in the instructions.
@@ -1297,6 +1377,13 @@ void TargetX8632::lowerCall(const InstCall *Instr) {
Variable *edx = NULL;
if (Dest) {
switch (Dest->getType()) {
+ case IceType_v4i1:
+ case IceType_v8i1:
+ case IceType_v16i1:
+ case IceType_v16i8:
+ case IceType_v8i16:
+ case IceType_v4i32:
+ case IceType_v4f32:
case IceType_NUM:
llvm_unreachable("Invalid Call dest type");
break;
@@ -2271,6 +2358,8 @@ void TargetX8632::lowerRet(const InstRet *Inst) {
} else if (Src0->getType() == IceType_f32 ||
Src0->getType() == IceType_f64) {
_fld(Src0);
+ } else if (typeNumElements(Src0->getType()) > 1) {
+ Reg = legalizeToVar(Src0, false, Reg_xmm0);
} else {
_mov(Reg, Src0, Reg_eax);
}
@@ -2392,6 +2481,19 @@ void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) {
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 (typeNumElements(Ty) > 1) {
jvoung (off chromium) 2014/06/26 23:33:46 Maybe there should be some inlineable "isVectorTyp
wala 2014/06/27 21:09:19 I agree.
+ _movp(Reg, Src);
+ } else {
+ _mov(Reg, Src);
+ }
+ return Reg;
+}
+
Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
bool AllowOverlap, int32_t RegNum) {
// Assert that a physical register is allowed. To date, all calls
@@ -2424,9 +2526,7 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
}
if (!(Allowed & Legal_Mem)) {
- Variable *Reg = makeReg(From->getType(), RegNum);
- _mov(Reg, From, RegNum);
- From = Reg;
+ From = copyToReg(From, RegNum);
}
return From;
}
@@ -2447,13 +2547,13 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
}
bool NeedsReg =
!(Allowed & Legal_Imm) ||
- // ConstantFloat and ConstantDouble are actually memory operands.
+ // ConstantFloat, ConstantDouble, and vector constants are
+ // actually memory operands.
(!(Allowed & Legal_Mem) &&
- (From->getType() == IceType_f32 || From->getType() == IceType_f64));
+ (From->getType() == IceType_f32 || From->getType() == IceType_f64 ||
+ typeNumElements(From->getType()) > 1));
if (NeedsReg) {
- Variable *Reg = makeReg(From->getType(), RegNum);
- _mov(Reg, From);
- From = Reg;
+ From = copyToReg(From, RegNum);
}
return From;
}
@@ -2463,11 +2563,10 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
// RegNum is required and Var->getRegNum() doesn't match.
if ((!(Allowed & Legal_Mem) && !Var->hasReg()) ||
(RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
- Variable *Reg = makeReg(From->getType(), RegNum);
+ Variable *Reg = copyToReg(From, RegNum);
if (RegNum == Variable::NoRegister) {
Reg->setPreferredRegister(Var, AllowOverlap);
}
- _mov(Reg, From);
From = Reg;
}
return From;
@@ -2569,6 +2668,11 @@ void TargetX8632::postLower() {
}
}
+template <> void ConstantInteger::emit(GlobalContext *Ctx) const {
+ Ostream &Str = Ctx->getStrEmit();
+ Str << getValue();
+}
+
template <> void ConstantFloat::emit(GlobalContext *Ctx) const {
Ostream &Str = Ctx->getStrEmit();
// It would be better to prefix with ".L$" instead of "L$", but
@@ -2581,4 +2685,16 @@ template <> void ConstantDouble::emit(GlobalContext *Ctx) const {
Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]";
}
+template <> void ConstantVector::emit(GlobalContext *Ctx) const {
+ Ostream &Str = Ctx->getStrEmit();
+ Str << "xmmword ptr [L$" << typeAsmLabel(getType()) << "$" << getPoolEntryID()
+ << "]";
+}
+
+template <> void ConstantBitVector::emit(GlobalContext *Ctx) const {
+ Ostream &Str = Ctx->getStrEmit();
+ Str << "xmmword ptr [L$" << typeAsmLabel(getType()) << "$" << getPoolEntryID()
+ << "]";
+}
+
} // end of namespace Ice

Powered by Google App Engine
This is Rietveld 408576698