diff --git a/ctx.cpp b/ctx.cpp index 0f01debe..d7219ee2 100644 --- a/ctx.cpp +++ b/ctx.cpp @@ -1107,6 +1107,33 @@ FunctionEmitContext::CmpInst(llvm::Instruction::OtherOps inst, } +llvm::Value * +FunctionEmitContext::SmearScalar(llvm::Value *value, const char *name) { + if (value == NULL) { + assert(m->errorCount > 0); + return NULL; + } + + llvm::Value *ret = NULL; + LLVM_TYPE_CONST llvm::Type *eltType = value->getType(); + LLVM_TYPE_CONST llvm::PointerType *pt = + llvm::dyn_cast(eltType); + if (pt != NULL) + ret = llvm::UndefValue::get(llvm::ArrayType::get(eltType, + g->target.vectorWidth)); + else + ret = llvm::UndefValue::get(llvm::VectorType::get(eltType, + g->target.vectorWidth)); + + for (int i = 0; i < g->target.vectorWidth; ++i) { + llvm::Twine n = llvm::Twine("smear.") + llvm::Twine(name ? name : "") + + llvm::Twine(i); + ret = InsertInst(ret, value, i, n.str().c_str()); + } + return ret; +} + + llvm::Value * FunctionEmitContext::BitCastInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type, const char *name) { diff --git a/ctx.h b/ctx.h index b1e6887a..e41bad90 100644 --- a/ctx.h +++ b/ctx.h @@ -312,12 +312,23 @@ public: llvm::CmpInst::Predicate pred, llvm::Value *v0, llvm::Value *v1, const char *name = NULL); + /** Given a scalar value, return a vector of the same type (or an + array, for pointer types). */ + llvm::Value *SmearScalar(llvm::Value *value, const char *name = NULL); + llvm::Value *BitCastInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type, const char *name = NULL); llvm::Value *PtrToIntInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type, const char *name = NULL); llvm::Value *IntToPtrInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type, const char *name = NULL); + /** Given a value of some array type, return the corresponding value of + vector type. */ + llvm::Value *ArrayToVectorInst(llvm::Value *value); + /** Given a value of some vector type, return the corresponding value of + array type. */ + llvm::Value *VectorToArrayInst(llvm::Value *value); + llvm::Instruction *TruncInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type, const char *name = NULL); llvm::Instruction *CastInst(llvm::Instruction::CastOps op, llvm::Value *value, diff --git a/expr.cpp b/expr.cpp index 41d4ae4f..613563f9 100644 --- a/expr.cpp +++ b/expr.cpp @@ -4590,13 +4590,8 @@ lTypeConvAtomic(FunctionEmitContext *ctx, llvm::Value *exprVal, // If we also want to go from uniform to varying, replicate out the // value across the vector elements.. - if (toType->IsVaryingType() && fromType->IsUniformType()) { - LLVM_TYPE_CONST llvm::Type *vtype = toType->LLVMType(g->ctx); - llvm::Value *castVec = llvm::UndefValue::get(vtype); - for (int i = 0; i < g->target.vectorWidth; ++i) - castVec = ctx->InsertInst(castVec, cast, i, "smearinsert"); - return castVec; - } + if (toType->IsVaryingType() && fromType->IsUniformType()) + return ctx->SmearScalar(cast); else return cast; } @@ -4631,9 +4626,7 @@ lUniformValueToVarying(FunctionEmitContext *ctx, llvm::Value *value, // Otherwise we must have a uniform AtomicType, so smear its value // across the vector lanes. assert(dynamic_cast(type) != NULL); - for (int i = 0; i < g->target.vectorWidth; ++i) - retValue = ctx->InsertInst(retValue, value, i, "smearinsert"); - return retValue; + return ctx->SmearScalar(value); }