aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGExprScalar.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp90
1 files changed, 64 insertions, 26 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index ef3e27ecec99..603d9a6e7e84 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -348,6 +348,9 @@ public:
EmitImplicitIntegerSignChangeChecks(
SanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {}
};
+ Value *EmitScalarCast(Value *Src, QualType SrcType, QualType DstType,
+ llvm::Type *SrcTy, llvm::Type *DstTy,
+ ScalarConversionOpts Opts);
Value *
EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
SourceLocation Loc,
@@ -1191,6 +1194,58 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
{Src, Dst});
}
+Value *ScalarExprEmitter::EmitScalarCast(Value *Src, QualType SrcType,
+ QualType DstType, llvm::Type *SrcTy,
+ llvm::Type *DstTy,
+ ScalarConversionOpts Opts) {
+ // The Element types determine the type of cast to perform.
+ llvm::Type *SrcElementTy;
+ llvm::Type *DstElementTy;
+ QualType SrcElementType;
+ QualType DstElementType;
+ if (SrcType->isMatrixType() && DstType->isMatrixType()) {
+ // Allow bitcast between matrixes of the same size.
+ if (SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits())
+ return Builder.CreateBitCast(Src, DstTy, "conv");
+
+ SrcElementTy = cast<llvm::VectorType>(SrcTy)->getElementType();
+ DstElementTy = cast<llvm::VectorType>(DstTy)->getElementType();
+ SrcElementType = SrcType->castAs<MatrixType>()->getElementType();
+ DstElementType = DstType->castAs<MatrixType>()->getElementType();
+ } else {
+ assert(!SrcType->isMatrixType() && !DstType->isMatrixType() &&
+ "cannot cast between matrix and non-matrix types");
+ SrcElementTy = SrcTy;
+ DstElementTy = DstTy;
+ SrcElementType = SrcType;
+ DstElementType = DstType;
+ }
+
+ if (isa<llvm::IntegerType>(SrcElementTy)) {
+ bool InputSigned = SrcElementType->isSignedIntegerOrEnumerationType();
+ if (SrcElementType->isBooleanType() && Opts.TreatBooleanAsSigned) {
+ InputSigned = true;
+ }
+
+ if (isa<llvm::IntegerType>(DstElementTy))
+ return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
+ if (InputSigned)
+ return Builder.CreateSIToFP(Src, DstTy, "conv");
+ return Builder.CreateUIToFP(Src, DstTy, "conv");
+ }
+
+ if (isa<llvm::IntegerType>(DstElementTy)) {
+ assert(SrcElementTy->isFloatingPointTy() && "Unknown real conversion");
+ if (DstElementType->isSignedIntegerOrEnumerationType())
+ return Builder.CreateFPToSI(Src, DstTy, "conv");
+ return Builder.CreateFPToUI(Src, DstTy, "conv");
+ }
+
+ if (DstElementTy->getTypeID() < SrcElementTy->getTypeID())
+ return Builder.CreateFPTrunc(Src, DstTy, "conv");
+ return Builder.CreateFPExt(Src, DstTy, "conv");
+}
+
/// Emit a conversion from the specified type to the specified destination type,
/// both of which are LLVM scalar types.
Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
@@ -1318,6 +1373,9 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
return Builder.CreateVectorSplat(NumElements, Src, "splat");
}
+ if (SrcType->isMatrixType() && DstType->isMatrixType())
+ return EmitScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts);
+
if (isa<llvm::VectorType>(SrcTy) || isa<llvm::VectorType>(DstTy)) {
// Allow bitcast from vector to integer/fp of the same size.
unsigned SrcSize = SrcTy->getPrimitiveSizeInBits();
@@ -1384,31 +1442,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
DstTy = CGF.FloatTy;
}
- if (isa<llvm::IntegerType>(SrcTy)) {
- bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
- if (SrcType->isBooleanType() && Opts.TreatBooleanAsSigned) {
- InputSigned = true;
- }
- if (isa<llvm::IntegerType>(DstTy))
- Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
- else if (InputSigned)
- Res = Builder.CreateSIToFP(Src, DstTy, "conv");
- else
- Res = Builder.CreateUIToFP(Src, DstTy, "conv");
- } else if (isa<llvm::IntegerType>(DstTy)) {
- assert(SrcTy->isFloatingPointTy() && "Unknown real conversion");
- if (DstType->isSignedIntegerOrEnumerationType())
- Res = Builder.CreateFPToSI(Src, DstTy, "conv");
- else
- Res = Builder.CreateFPToUI(Src, DstTy, "conv");
- } else {
- assert(SrcTy->isFloatingPointTy() && DstTy->isFloatingPointTy() &&
- "Unknown real conversion");
- if (DstTy->getTypeID() < SrcTy->getTypeID())
- Res = Builder.CreateFPTrunc(Src, DstTy, "conv");
- else
- Res = Builder.CreateFPExt(Src, DstTy, "conv");
- }
+ Res = EmitScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts);
if (DstTy != ResTy) {
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
@@ -1729,7 +1763,7 @@ Value *ScalarExprEmitter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *E) {
llvm::MatrixBuilder<CGBuilderTy> MB(Builder);
return MB.CreateExtractElement(
Matrix, RowIdx, ColumnIdx,
- E->getBase()->getType()->getAs<ConstantMatrixType>()->getNumRows());
+ E->getBase()->getType()->castAs<ConstantMatrixType>()->getNumRows());
}
static int getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx,
@@ -2230,6 +2264,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
CGF.EmitIgnoredExpr(E);
return nullptr;
}
+ case CK_MatrixCast: {
+ return EmitScalarConversion(Visit(E), E->getType(), DestTy,
+ CE->getExprLoc());
+ }
case CK_VectorSplat: {
llvm::Type *DstTy = ConvertType(DestTy);
Value *Elt = Visit(const_cast<Expr*>(E));