diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-01-07 17:37:58 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-01-07 17:38:09 -0800 |
commit | 1f526e71d9eda3515d0d80f0589424eb193f3283 (patch) | |
tree | 69d8db5e892ad9b88c8f1a45ee167db653e69ddd /lib/Target/JSBackend/JSBackend.cpp | |
parent | a04e87629b6548d2be2a99fab4644ccad6ee6fc8 (diff) |
initial work to support SIMD vector types and operations
Diffstat (limited to 'lib/Target/JSBackend/JSBackend.cpp')
-rw-r--r-- | lib/Target/JSBackend/JSBackend.cpp | 123 |
1 files changed, 119 insertions, 4 deletions
diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp index 0f1b0d6625..cef52e313d 100644 --- a/lib/Target/JSBackend/JSBackend.cpp +++ b/lib/Target/JSBackend/JSBackend.cpp @@ -69,6 +69,9 @@ namespace { ASM_NONSPECIFIC = 2 // nonspecific means to not differentiate ints. |0 for all, regardless of size and sign }; + const char *SIMDLane = "XYZW"; + const char *simdLane = "xyzw"; + typedef std::map<const Value*,std::string> ValueMap; typedef std::set<std::string> NameSet; typedef std::vector<unsigned char> HeapData; @@ -275,6 +278,7 @@ namespace { std::string getStore(const Value *P, const Type *T, const std::string& VS, unsigned Alignment, char sep=';'); void printFunctionBody(const Function *F); + bool generateSIMDInstruction(const std::string &iName, const Instruction *I, raw_string_ostream& Code); void generateInstruction(const Instruction *I, raw_string_ostream& Code); std::string getOpName(const Value*); @@ -397,7 +401,10 @@ std::string JSWriter::getAssign(const StringRef &s, const Type *t) { std::string JSWriter::getCast(const StringRef &s, const Type *t, AsmCast sign) { switch (t->getTypeID()) { - default: assert(false && "Unsupported type"); + default: { + // some types we cannot cast, like vectors - ignore + if (!t->isVectorTy()) assert(false && "Unsupported type"); + } case Type::FloatTyID: // TODO return ("Math_fround(" + s + ")").str(); case Type::DoubleTyID: return ("+" + s).str(); case Type::IntegerTyID: { @@ -733,6 +740,26 @@ std::string JSWriter::getConstant(const Constant* CV, AsmCast sign) { return CI->getValue().toString(10, sign != ASM_UNSIGNED); } else if (isa<UndefValue>(CV)) { return CV->getType()->isIntegerTy() ? "0" : "+0"; // XXX fround, refactor this + } else if (isa<ConstantAggregateZero>(CV)) { + const VectorType *VT = cast<VectorType>(CV->getType()); + if (VT->getElementType()->isIntegerTy()) { + return "int32x4.splat(0)"; + } else { + return "float32x4.splat(0)"; + } + } else if (const ConstantDataVector *DV = dyn_cast<ConstantDataVector>(CV)) { + const VectorType *VT = cast<VectorType>(CV->getType()); + if (VT->getElementType()->isIntegerTy()) { + return "int32x4(" + getConstant(DV->getElementAsConstant(0)) + ',' + + getConstant(DV->getElementAsConstant(1)) + ',' + + getConstant(DV->getElementAsConstant(2)) + ',' + + getConstant(DV->getElementAsConstant(3)) + ')'; + } else { + return "float32x4(" + getConstant(DV->getElementAsConstant(0)) + ',' + + getConstant(DV->getElementAsConstant(1)) + ',' + + getConstant(DV->getElementAsConstant(2)) + ',' + + getConstant(DV->getElementAsConstant(3)) + ')'; + } } else { dumpIR(CV); assert(false); @@ -772,6 +799,90 @@ std::string JSWriter::getValueAsCastParenStr(const Value* V, AsmCast sign) { } } +bool JSWriter::generateSIMDInstruction(const std::string &iName, const Instruction *I, raw_string_ostream& Code) { + #define CHECK_VECTOR(VT) \ + assert(VT->getElementType()->getPrimitiveSizeInBits() == 32); \ + assert(VT->getNumElements() == 4); + + if (VectorType *VT = dyn_cast<VectorType>(I->getType())) { + // vector-producing instructions + CHECK_VECTOR(VT); + + Code << getAssign(iName, I->getType()); + + switch (I->getOpcode()) { + default: dumpIR(I); error("invalid vector instr"); break; + case Instruction::FAdd: Code << "SIMD.float32x4.add(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break; + case Instruction::FSub: Code << "SIMD.float32x4.sub(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break; + case Instruction::FMul: Code << "SIMD.float32x4.mul(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break; + case Instruction::FDiv: Code << "SIMD.float32x4.div(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break; + case Instruction::Add: Code << "SIMD.int32x4.add(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break; + case Instruction::Sub: Code << "SIMD.int32x4.sub(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break; + case Instruction::Mul: Code << "SIMD.int32x4.mul(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break; + case Instruction::And: Code << "SIMD.int32x4.and(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break; + case Instruction::Or: Code << "SIMD.int32x4.or(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break; + case Instruction::Xor: Code << "SIMD.int32x4.xor(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break; + case Instruction::BitCast: { + if (cast<VectorType>(I->getType())->getElementType()->isIntegerTy()) { + Code << "SIMD.float32x4.bitsToInt32x4(" + getValueAsStr(I->getOperand(0)) + ')'; + } else { + Code << "SIMD.int32x4.bitsToInt32x4(" + getValueAsStr(I->getOperand(0)) + ')'; + } + break; + } + case Instruction::Load: { + std::string PS = getOpName(I->getOperand(0)); + if (VT->getElementType()->isIntegerTy()) { + Code << "int32x4(HEAPU32[" + PS + ">>2],HEAPU32[" + PS + "+4>>2],HEAPU32[" + PS + "+8>>2],HEAPU32[" + PS + "+12>>2])"; + } else { + Code << "float32x4(HEAPF32[" + PS + ">>2],HEAPF32[" + PS + "+4>>2],HEAPF32[" + PS + "+8>>2],HEAPF32[" + PS + "+12>>2])"; + } + break; + } + case Instruction::InsertElement: { + const InsertElementInst *III = cast<InsertElementInst>(I); + const ConstantInt *IndexInt = cast<const ConstantInt>(III->getOperand(2)); + unsigned Index = IndexInt->getZExtValue(); + assert(Index <= 3); + if (VT->getElementType()->isIntegerTy()) { + Code << "SIMD.int32x4.with"; + } else { + Code << "SIMD.float32x4.with"; + } + Code << SIMDLane[Index]; + Code << "(" + getValueAsStr(III->getOperand(0)) + ',' + getValueAsStr(III->getOperand(1)) + ')'; + break; + } + } + return true; + } else { + // vector-consuming instructions + VectorType *VT; + if (I->getOpcode() == Instruction::Store && (VT = dyn_cast<VectorType>(I->getOperand(0)->getType())) && VT->isVectorTy()) { + CHECK_VECTOR(VT); + std::string PS = getOpName(I->getOperand(1)); + std::string VS = getValueAsStr(I->getOperand(0)); + if (VT->getElementType()->isIntegerTy()) { + Code << "HEAPU32[" + PS + ">>2]=" + VS + ".x;HEAPU32[" + PS + "+4>>2]=" + VS + ".y;HEAPU32[" + PS + "+8>>2]=" + VS + ".z;HEAPU32[" + PS + "+12>>2]=" + VS + ".w"; + } else { + Code << "HEAPF32[" + PS + ">>2]=" + VS + ".x;HEAPF32[" + PS + "+4>>2]=" + VS + ".y;HEAPF32[" + PS + "+8>>2]=" + VS + ".z;HEAPF32[" + PS + "+12>>2]=" + VS + ".w"; + } + return true; + } else if (I->getOpcode() == Instruction::ExtractElement) { + const ExtractElementInst *EEI = cast<ExtractElementInst>(I); + VT = cast<VectorType>(EEI->getVectorOperand()->getType()); + CHECK_VECTOR(VT); + const ConstantInt *IndexInt = cast<const ConstantInt>(EEI->getIndexOperand()); + unsigned Index = IndexInt->getZExtValue(); + assert(Index <= 3); + Code << getAssign(iName, I->getType()); + Code << getValueAsStr(EEI->getVectorOperand()) + '.' + simdLane[Index]; + return true; + } + } + return false; +} + // generateInstruction - This member is called for each Instruction in a function. void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Code) { std::string iName(getJSName(I)); @@ -782,11 +893,12 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod assert(0 && "FIXME: finish legalization"); // FIXME } - switch (I->getOpcode()) { - default: + if (!generateSIMDInstruction(iName, I, Code)) switch (I->getOpcode()) { + default: { + dumpIR(I); error("Invalid instruction"); break; - + } case Instruction::Ret: { const ReturnInst* ret = cast<ReturnInst>(I); Value *RV = ret->getReturnValue(); @@ -1250,6 +1362,9 @@ void JSWriter::printFunctionBody(const Function *F) { case Type::DoubleTyID: Out << "+0"; // FIXME break; + case Type::VectorTyID: + Out << "null"; // best we can do for now + break; } } Out << ";"; |