Skip to content

Commit a94f68a

Browse files
author
Erich Keane
committed
Implement some constexpr vector unary operators, fix boolean-ops
As requested in the review, this implements unary +,-,~, and ! for vector types. All of our boolean operations on vector types should be using something like vcmpeqd, which results in a mask of '-1' for the 'truth' type. We are currently instead using '1', which results in some incorrect calculations when used later (note that it does NOT result in a boolean vector, as that is not really a thing). This patch corrects that 1 to be a -1, and updates the affected tests. Differential Revision: https://reviews.llvm.org/D115670
1 parent b8c9ebf commit a94f68a

File tree

3 files changed

+210
-59
lines changed

3 files changed

+210
-59
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2931,6 +2931,11 @@ handleCompareOpForVectorHelper(const APTy &LHSValue, BinaryOperatorKind Opcode,
29312931
break;
29322932
}
29332933

2934+
// The boolean operations on these vector types use an instruction that
2935+
// results in a mask of '-1' for the 'truth' value. Ensure that we negate 1
2936+
// to -1 to make sure that we produce the correct value.
2937+
Result.negate();
2938+
29342939
return true;
29352940
}
29362941

@@ -10179,7 +10184,8 @@ namespace {
1017910184
bool VisitInitListExpr(const InitListExpr *E);
1018010185
bool VisitUnaryImag(const UnaryOperator *E);
1018110186
bool VisitBinaryOperator(const BinaryOperator *E);
10182-
// FIXME: Missing: unary -, unary ~, conditional operator (for GNU
10187+
bool VisitUnaryOperator(const UnaryOperator *E);
10188+
// FIXME: Missing: conditional operator (for GNU
1018310189
// conditional select), shufflevector, ExtVectorElementExpr
1018410190
};
1018510191
} // end anonymous namespace
@@ -10364,6 +10370,83 @@ bool VectorExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
1036410370
return Success(LHSValue, E);
1036510371
}
1036610372

10373+
static llvm::Optional<APValue> handleVectorUnaryOperator(ASTContext &Ctx,
10374+
QualType ResultTy,
10375+
UnaryOperatorKind Op,
10376+
APValue Elt) {
10377+
switch (Op) {
10378+
case UO_Plus:
10379+
// Nothing to do here.
10380+
return Elt;
10381+
case UO_Minus:
10382+
if (Elt.getKind() == APValue::Int) {
10383+
Elt.getInt().negate();
10384+
} else {
10385+
assert(Elt.getKind() == APValue::Float &&
10386+
"Vector can only be int or float type");
10387+
Elt.getFloat().changeSign();
10388+
}
10389+
return Elt;
10390+
case UO_Not:
10391+
// This is only valid for integral types anyway, so we don't have to handle
10392+
// float here.
10393+
assert(Elt.getKind() == APValue::Int &&
10394+
"Vector operator ~ can only be int");
10395+
Elt.getInt().flipAllBits();
10396+
return Elt;
10397+
case UO_LNot: {
10398+
if (Elt.getKind() == APValue::Int) {
10399+
Elt.getInt() = !Elt.getInt();
10400+
// operator ! on vectors returns -1 for 'truth', so negate it.
10401+
Elt.getInt().negate();
10402+
return Elt;
10403+
}
10404+
assert(Elt.getKind() == APValue::Float &&
10405+
"Vector can only be int or float type");
10406+
// Float types result in an int of the same size, but -1 for true, or 0 for
10407+
// false.
10408+
APSInt EltResult{Ctx.getIntWidth(ResultTy),
10409+
ResultTy->isUnsignedIntegerType()};
10410+
if (Elt.getFloat().isZero())
10411+
EltResult.setAllBits();
10412+
else
10413+
EltResult.clearAllBits();
10414+
10415+
return APValue{EltResult};
10416+
}
10417+
default:
10418+
// FIXME: Implement the rest of the unary operators.
10419+
return llvm::None;
10420+
}
10421+
}
10422+
10423+
bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
10424+
Expr *SubExpr = E->getSubExpr();
10425+
const auto *VD = SubExpr->getType()->castAs<VectorType>();
10426+
// This result element type differs in the case of negating a floating point
10427+
// vector, since the result type is the a vector of the equivilant sized
10428+
// integer.
10429+
const QualType ResultEltTy = VD->getElementType();
10430+
UnaryOperatorKind Op = E->getOpcode();
10431+
10432+
APValue SubExprValue;
10433+
if (!Evaluate(SubExprValue, Info, SubExpr))
10434+
return false;
10435+
10436+
assert(SubExprValue.getVectorLength() == VD->getNumElements() &&
10437+
"Vector length doesn't match type?");
10438+
10439+
SmallVector<APValue, 4> ResultElements;
10440+
for (unsigned EltNum = 0; EltNum < VD->getNumElements(); ++EltNum) {
10441+
llvm::Optional<APValue> Elt = handleVectorUnaryOperator(
10442+
Info.Ctx, ResultEltTy, Op, SubExprValue.getVectorElt(EltNum));
10443+
if (!Elt)
10444+
return false;
10445+
ResultElements.push_back(*Elt);
10446+
}
10447+
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
10448+
}
10449+
1036710450
//===----------------------------------------------------------------------===//
1036810451
// Array Evaluation
1036910452
//===----------------------------------------------------------------------===//

clang/lib/Sema/SemaExpr.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12261,27 +12261,32 @@ QualType Sema::GetSignedVectorType(QualType V) {
1226112261
if (isa<ExtVectorType>(VTy)) {
1226212262
if (TypeSize == Context.getTypeSize(Context.CharTy))
1226312263
return Context.getExtVectorType(Context.CharTy, VTy->getNumElements());
12264-
else if (TypeSize == Context.getTypeSize(Context.ShortTy))
12264+
if (TypeSize == Context.getTypeSize(Context.ShortTy))
1226512265
return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements());
12266-
else if (TypeSize == Context.getTypeSize(Context.IntTy))
12266+
if (TypeSize == Context.getTypeSize(Context.IntTy))
1226712267
return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
12268-
else if (TypeSize == Context.getTypeSize(Context.LongTy))
12268+
if (TypeSize == Context.getTypeSize(Context.Int128Ty))
12269+
return Context.getExtVectorType(Context.Int128Ty, VTy->getNumElements());
12270+
if (TypeSize == Context.getTypeSize(Context.LongTy))
1226912271
return Context.getExtVectorType(Context.LongTy, VTy->getNumElements());
1227012272
assert(TypeSize == Context.getTypeSize(Context.LongLongTy) &&
1227112273
"Unhandled vector element size in vector compare");
1227212274
return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
1227312275
}
1227412276

12277+
if (TypeSize == Context.getTypeSize(Context.Int128Ty))
12278+
return Context.getVectorType(Context.Int128Ty, VTy->getNumElements(),
12279+
VectorType::GenericVector);
1227512280
if (TypeSize == Context.getTypeSize(Context.LongLongTy))
1227612281
return Context.getVectorType(Context.LongLongTy, VTy->getNumElements(),
1227712282
VectorType::GenericVector);
12278-
else if (TypeSize == Context.getTypeSize(Context.LongTy))
12283+
if (TypeSize == Context.getTypeSize(Context.LongTy))
1227912284
return Context.getVectorType(Context.LongTy, VTy->getNumElements(),
1228012285
VectorType::GenericVector);
12281-
else if (TypeSize == Context.getTypeSize(Context.IntTy))
12286+
if (TypeSize == Context.getTypeSize(Context.IntTy))
1228212287
return Context.getVectorType(Context.IntTy, VTy->getNumElements(),
1228312288
VectorType::GenericVector);
12284-
else if (TypeSize == Context.getTypeSize(Context.ShortTy))
12289+
if (TypeSize == Context.getTypeSize(Context.ShortTy))
1228512290
return Context.getVectorType(Context.ShortTy, VTy->getNumElements(),
1228612291
VectorType::GenericVector);
1228712292
assert(TypeSize == Context.getTypeSize(Context.CharTy) &&

0 commit comments

Comments
 (0)