Index: src/IceTargetLowering.h |
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h |
index 55597ca14e7d212c5ee38c3bbf68f8f97c9252f3..678dd3d87d1300610bac3dc0e17356de6939fa82 100644 |
--- a/src/IceTargetLowering.h |
+++ b/src/IceTargetLowering.h |
@@ -467,6 +467,83 @@ protected: |
void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest, |
Operand *Src0, Operand *Src1); |
+ /// Generalizes scalarizeArithmetic to support other instruction types. |
+ /// |
+ /// MakeInstruction is a function-like object with signature |
+ /// (Variable *Dest, Variable *Src0, Variable *Src1) -> Instr *. |
+ template<typename F> |
+ void scalarizeInstruction(Variable *Dest, Operand *Src0, Operand *Src1, |
+ F &&MakeInstruction) { |
+ assert(isVectorType(Dest->getType())); |
Jim Stichnoth
2016/02/10 19:08:11
I would "assert(isVectorType(DestTy));" and move i
Eric Holk
2016/02/10 21:07:20
Done.
|
+ const Type DestTy = Dest->getType(); |
+ const Type DestElementTy = typeElementType(DestTy); |
+ const SizeT NumElements = typeNumElements(DestTy); |
+ const Type Src0ElementTy = typeElementType(Src0->getType()); |
+ const Type Src1ElementTy = typeElementType(Src1->getType()); |
+ |
+ assert(NumElements == typeNumElements(Src0->getType())); |
+ assert(NumElements == typeNumElements(Src1->getType())); |
+ |
+ Variable *T = Func->makeVariable(DestTy); |
+ Context.insert<InstFakeDef>(T); |
+ for (SizeT I = 0; I < NumElements; ++I) { |
+ Constant *Index = Ctx->getConstantInt32(I); |
+ |
+ // Extract the next two inputs. |
+ Variable *Op0 = Func->makeVariable(Src0ElementTy); |
+ Context.insert<InstExtractElement>(Op0, Src0, Index); |
+ Variable *Op1 = Func->makeVariable(Src1ElementTy); |
+ Context.insert<InstExtractElement>(Op1, Src1, Index); |
+ |
+ // Perform the arithmetic as a scalar operation. |
Jim Stichnoth
2016/02/10 19:08:12
You probably want change "arithmetic" to be more g
Eric Holk
2016/02/10 21:07:20
Done.
|
+ Variable *Res = Func->makeVariable(DestElementTy); |
+ auto Arith = MakeInstruction(Res, Op0, Op1); |
+ // We might have created an operation that needed a helper call. |
+ genTargetHelperCallFor(Arith); |
+ |
+ // Insert the result into position. |
+ Variable *DestT = Func->makeVariable(DestTy); |
+ Context.insert<InstInsertElement>(DestT, T, Res, Index); |
+ T = DestT; |
+ } |
+ Context.insert<InstAssign>(Dest, T); |
+ } |
+ |
+ template<typename F> |
+ void scalarizeUnaryInstruction(Variable *Dest, Operand *Src0, |
+ F &&MakeInstruction) { |
+ assert(isVectorType(Dest->getType())); |
+ const Type DestTy = Dest->getType(); |
+ const Type DestElementTy = typeElementType(DestTy); |
+ const SizeT NumElements = typeNumElements(DestTy); |
+ const Type Src0ElementTy = typeElementType(Src0->getType()); |
+ |
+ assert(NumElements == typeNumElements(Src0->getType())); |
+ |
+ Variable *T = Func->makeVariable(DestTy); |
+ Context.insert<InstFakeDef>(T); |
+ for (SizeT I = 0; I < NumElements; ++I) { |
+ Constant *Index = Ctx->getConstantInt32(I); |
+ |
+ // Extract the next two inputs. |
+ Variable *Op0 = Func->makeVariable(Src0ElementTy); |
+ Context.insert<InstExtractElement>(Op0, Src0, Index); |
+ |
+ // Perform the arithmetic as a scalar operation. |
+ Variable *Res = Func->makeVariable(DestElementTy); |
+ auto Arith = MakeInstruction(Res, Op0); |
+ // We might have created an operation that needed a helper call. |
+ genTargetHelperCallFor(Arith); |
+ |
+ // Insert the result into position. |
+ Variable *DestT = Func->makeVariable(DestTy); |
+ Context.insert<InstInsertElement>(DestT, T, Res, Index); |
+ T = DestT; |
+ } |
+ Context.insert<InstAssign>(Dest, T); |
+ } |
+ |
+ |
/// SandboxType enumerates all possible sandboxing strategies that |
enum SandboxType { |
ST_None, |