Add vector insert/extract instructions to Subzero bitcode reader. BUG= //code.google.com/p/nativeclient/issues/detail?id=3894 R=jvoung@chromium.org Review URL: https://codereview.chromium.org/529113002
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp index 8f157a6..12727e1 100644 --- a/src/PNaClTranslator.cpp +++ b/src/PNaClTranslator.cpp
@@ -909,6 +909,12 @@ return LocalOperands[LocalIndex]; } + // Returns the relative operand (wrt to next instruction) referenced by + // the given value index. + Ice::Operand *getRelativeOperand(uint32_t Index) { + return getOperand(convertRelativeToAbsIndex(Index)); + } + // Generates type error message for binary operator Op // operating on Type OpTy. void ReportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op, Ice::Type OpTy); @@ -1143,8 +1149,8 @@ // BINOP: [opval, opval, opcode] if (!isValidRecordSize(3, "function block binop")) return; - Ice::Operand *Op1 = getOperand(convertRelativeToAbsIndex(Values[0])); - Ice::Operand *Op2 = getOperand(convertRelativeToAbsIndex(Values[1])); + Ice::Operand *Op1 = getRelativeOperand(Values[0]); + Ice::Operand *Op2 = getRelativeOperand(Values[1]); Ice::Type Type1 = Op1->getType(); Ice::Type Type2 = Op2->getType(); if (Type1 != Type2) { @@ -1167,7 +1173,7 @@ // CAST: [opval, destty, castopc] if (!isValidRecordSize(3, "function block cast")) return; - Ice::Operand *Src = getOperand(convertRelativeToAbsIndex(Values[0])); + Ice::Operand *Src = getRelativeOperand(Values[0]); Type *CastType = Context->getTypeByID(Values[1]); Instruction::CastOps LLVMCastOp; Ice::InstCast::OpKind CastKind; @@ -1192,6 +1198,61 @@ Inst = Ice::InstCast::create(Func, CastKind, Dest, Src); break; } + case naclbitc::FUNC_CODE_INST_EXTRACTELT: { + // EXTRACTELT: [opval, opval] + Ice::Operand *Vec = getRelativeOperand(Values[0]); + Ice::Type VecType = Vec->getType(); + if (!Ice::isVectorType(VecType)) { + std::string Buffer; + raw_string_ostream StrBuf(Buffer); + StrBuf << "Extractelement not on vector. Found: " << Vec; + Error(StrBuf.str()); + } + Ice::Operand *Index = getRelativeOperand(Values[1]); + if (Index->getType() != Ice::IceType_i32) { + std::string Buffer; + raw_string_ostream StrBuf(Buffer); + StrBuf << "Extractelement index not i32. Found: " << Index; + Error(StrBuf.str()); + } + // TODO(kschimpf): Restrict index to a legal constant index (once + // constants can be defined). + Ice::Variable *Dest = NextInstVar(typeElementType(VecType)); + Inst = Ice::InstExtractElement::create(Func, Dest, Vec, Index); + break; + } + case naclbitc::FUNC_CODE_INST_INSERTELT: { + // INSERTELT: [opval, opval, opval] + Ice::Operand *Vec = getRelativeOperand(Values[0]); + Ice::Type VecType = Vec->getType(); + if (!Ice::isVectorType(VecType)) { + std::string Buffer; + raw_string_ostream StrBuf(Buffer); + StrBuf << "Insertelement not on vector. Found: " << Vec; + Error(StrBuf.str()); + } + Ice::Operand *Elt = getRelativeOperand(Values[1]); + Ice::Type EltType = Elt->getType(); + if (EltType != typeElementType(VecType)) { + std::string Buffer; + raw_string_ostream StrBuf(Buffer); + StrBuf << "Insertelement element not " << typeElementType(VecType) + << ". Found: " << Elt; + Error(StrBuf.str()); + } + Ice::Operand *Index = getRelativeOperand(Values[2]); + if (Index->getType() != Ice::IceType_i32) { + std::string Buffer; + raw_string_ostream StrBuf(Buffer); + StrBuf << "Insertelement index not i32. Found: " << Index; + Error(StrBuf.str()); + } + // TODO(kschimpf): Restrict index to a legal constant index (once + // constants can be defined). + Ice::Variable *Dest = NextInstVar(EltType); + Inst = Ice::InstInsertElement::create(Func, Dest, Vec, Elt, Index); + break; + } case naclbitc::FUNC_CODE_INST_RET: { // RET: [opval?] InstIsTerminating = true; @@ -1200,8 +1261,7 @@ if (Values.size() == 0) { Inst = Ice::InstRet::create(Func); } else { - Inst = Ice::InstRet::create( - Func, getOperand(convertRelativeToAbsIndex(Values[0]))); + Inst = Ice::InstRet::create(Func, getRelativeOperand(Values[0])); } break; }
diff --git a/tests_lit/reader_tests/insertextract.ll b/tests_lit/reader_tests/insertextract.ll new file mode 100644 index 0000000..51f54b9 --- /dev/null +++ b/tests_lit/reader_tests/insertextract.ll
@@ -0,0 +1,174 @@ +; Tests insertelement and extractelement vector instructions. + + +; RUN: llvm-as < %s | pnacl-freeze \ +; RUN: | %llvm2ice -notranslate -verbose=inst -build-on-read \ +; RUN: -allow-pnacl-reader-error-recovery \ +; RUN: | FileCheck %s + +; TODO(kschimpf): Change index arguments to valid constant indices once +; we can handle constants. + +define void @ExtractV4xi1(<4 x i1> %v, i32 %i) { + %e = extractelement <4 x i1> %v, i32 %i + ret void +} + +; CHECK: define void @ExtractV4xi1(<4 x i1> %__0, i32 %__1) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__2 = extractelement <4 x i1> %__0, i32 %__1 +; CHECK-NEXT: ret void +; CHECK-NEXT: } + +define void @ExtractV8xi1(<8 x i1> %v, i32 %i) { + %e = extractelement <8 x i1> %v, i32 %i + ret void +} + +; CHECK-NEXT: define void @ExtractV8xi1(<8 x i1> %__0, i32 %__1) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__2 = extractelement <8 x i1> %__0, i32 %__1 +; CHECK-NEXT: ret void +; CHECK-NEXT: } + +define void @ExtractV16xi1(<16 x i1> %v, i32 %i) { + %e = extractelement <16 x i1> %v, i32 %i + ret void +} + +; CHECK-NEXT: define void @ExtractV16xi1(<16 x i1> %__0, i32 %__1) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__2 = extractelement <16 x i1> %__0, i32 %__1 +; CHECK-NEXT: ret void +; CHECK-NEXT: } + +define void @ExtractV16xi8(<16 x i8> %v, i32 %i) { + %e = extractelement <16 x i8> %v, i32 %i + ret void +} + +; CHECK-NEXT: define void @ExtractV16xi8(<16 x i8> %__0, i32 %__1) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__2 = extractelement <16 x i8> %__0, i32 %__1 +; CHECK-NEXT: ret void +; CHECK-NEXT: } + +define void @ExtractV8xi16(<8 x i16> %v, i32 %i) { + %e = extractelement <8 x i16> %v, i32 %i + ret void +} + +; CHECK-NEXT: define void @ExtractV8xi16(<8 x i16> %__0, i32 %__1) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__2 = extractelement <8 x i16> %__0, i32 %__1 +; CHECK-NEXT: ret void +; CHECK-NEXT: } + +define i32 @ExtractV4xi32(<4 x i32> %v, i32 %i) { + %e = extractelement <4 x i32> %v, i32 %i + ret i32 %e +} + +; CHECK-NEXT: define i32 @ExtractV4xi32(<4 x i32> %__0, i32 %__1) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__2 = extractelement <4 x i32> %__0, i32 %__1 +; CHECK-NEXT: ret i32 %__2 +; CHECK-NEXT: } + +define float @ExtractV4xfloat(<4 x float> %v, i32 %i) { + %e = extractelement <4 x float> %v, i32 %i + ret float %e +} + +; CHECK-NEXT: define float @ExtractV4xfloat(<4 x float> %__0, i32 %__1) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__2 = extractelement <4 x float> %__0, i32 %__1 +; CHECK-NEXT: ret float %__2 +; CHECK-NEXT: } + +define <4 x i1> @InsertV4xi1(<4 x i1> %v, i32 %pe, i32 %i) { + %e = trunc i32 %pe to i1 + %r = insertelement <4 x i1> %v, i1 %e, i32 %i + ret <4 x i1> %r +} + +; CHECK-NEXT: define <4 x i1> @InsertV4xi1(<4 x i1> %__0, i32 %__1, i32 %__2) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__3 = trunc i32 %__1 to i1 +; CHECK-NEXT: %__4 = insertelement <4 x i1> %__0, i1 %__3, i32 %__2 +; CHECK-NEXT: ret i1 %__4 +; CHECK-NEXT: } + +define <8 x i1> @InsertV8xi1(<8 x i1> %v, i32 %pe, i32 %i) { + %e = trunc i32 %pe to i1 + %r = insertelement <8 x i1> %v, i1 %e, i32 %i + ret <8 x i1> %r +} + +; CHECK-NEXT: define <8 x i1> @InsertV8xi1(<8 x i1> %__0, i32 %__1, i32 %__2) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__3 = trunc i32 %__1 to i1 +; CHECK-NEXT: %__4 = insertelement <8 x i1> %__0, i1 %__3, i32 %__2 +; CHECK-NEXT: ret i1 %__4 +; CHECK-NEXT: } + +define <16 x i1> @InsertV16xi1(<16 x i1> %v, i32 %pe, i32 %i) { + %e = trunc i32 %pe to i1 + %r = insertelement <16 x i1> %v, i1 %e, i32 %i + ret <16 x i1> %r +} + +; CHECK-NEXT: define <16 x i1> @InsertV16xi1(<16 x i1> %__0, i32 %__1, i32 %__2) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__3 = trunc i32 %__1 to i1 +; CHECK-NEXT: %__4 = insertelement <16 x i1> %__0, i1 %__3, i32 %__2 +; CHECK-NEXT: ret i1 %__4 +; CHECK-NEXT: } + +define <16 x i8> @InsertV16xi8(<16 x i8> %v, i32 %pe, i32 %i) { + %e = trunc i32 %pe to i8 + %r = insertelement <16 x i8> %v, i8 %e, i32 %i + ret <16 x i8> %r +} + +; CHECK-NEXT: define <16 x i8> @InsertV16xi8(<16 x i8> %__0, i32 %__1, i32 %__2) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__3 = trunc i32 %__1 to i8 +; CHECK-NEXT: %__4 = insertelement <16 x i8> %__0, i8 %__3, i32 %__2 +; CHECK-NEXT: ret i8 %__4 +; CHECK-NEXT: } + +define <8 x i16> @InsertV8xi16(<8 x i16> %v, i32 %pe, i32 %i) { + %e = trunc i32 %pe to i16 + %r = insertelement <8 x i16> %v, i16 %e, i32 %i + ret <8 x i16> %r +} + +; CHECK-NEXT: define <8 x i16> @InsertV8xi16(<8 x i16> %__0, i32 %__1, i32 %__2) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__3 = trunc i32 %__1 to i16 +; CHECK-NEXT: %__4 = insertelement <8 x i16> %__0, i16 %__3, i32 %__2 +; CHECK-NEXT: ret i16 %__4 +; CHECK-NEXT: } + +define <4 x i32> @InsertV16xi32(<4 x i32> %v, i32 %e, i32 %i) { + %r = insertelement <4 x i32> %v, i32 %e, i32 %i + ret <4 x i32> %r +} + +; CHECK-NEXT: define <4 x i32> @InsertV16xi32(<4 x i32> %__0, i32 %__1, i32 %__2) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__3 = insertelement <4 x i32> %__0, i32 %__1, i32 %__2 +; CHECK-NEXT: ret i32 %__3 +; CHECK-NEXT: } + +define <4 x float> @InsertV16xfloat(<4 x float> %v, float %e, i32 %i) { + %r = insertelement <4 x float> %v, float %e, i32 %i + ret <4 x float> %r +} + +; CHECK-NEXT: define <4 x float> @InsertV16xfloat(<4 x float> %__0, float %__1, i32 %__2) { +; CHECK-NEXT: __0: +; CHECK-NEXT: %__3 = insertelement <4 x float> %__0, float %__1, i32 %__2 +; CHECK-NEXT: ret float %__3 +; CHECK-NEXT: }