Skip to content

Commit

Permalink
[Fixed Point Arithmetic] Fixed Point Comparisons
Browse files Browse the repository at this point in the history
This patch implements fixed point comparisons with other fixed point types and
integers. This also provides constant expression evaluation for them.

Differential Revision: https://reviews.llvm.org/D57219

llvm-svn: 354621
  • Loading branch information
PiJoules committed Feb 21, 2019
1 parent c265017 commit ce1d4f1
Show file tree
Hide file tree
Showing 3 changed files with 428 additions and 12 deletions.
16 changes: 16 additions & 0 deletions clang/lib/AST/ExprConstant.cpp
Expand Up @@ -9144,6 +9144,22 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
return Success(CCR::Equal, E);
}

if (LHSTy->isFixedPointType() || RHSTy->isFixedPointType()) {
APFixedPoint LHSFX(Info.Ctx.getFixedPointSemantics(LHSTy));
APFixedPoint RHSFX(Info.Ctx.getFixedPointSemantics(RHSTy));

bool LHSOK = EvaluateFixedPointOrInteger(E->getLHS(), LHSFX, Info);
if (!LHSOK && !Info.noteFailure())
return false;
if (!EvaluateFixedPointOrInteger(E->getRHS(), RHSFX, Info) || !LHSOK)
return false;
if (LHSFX < RHSFX)
return Success(CCR::Less, E);
if (LHSFX > RHSFX)
return Success(CCR::Greater, E);
return Success(CCR::Equal, E);
}

if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) {
ComplexValue LHS, RHS;
bool LHSOK;
Expand Down
46 changes: 34 additions & 12 deletions clang/lib/CodeGen/CGExprScalar.cpp
Expand Up @@ -125,11 +125,19 @@ struct BinOpInfo {
return true;
}

/// Check if either operand is a fixed point type, in which case, this
/// Check if either operand is a fixed point type or integer type, with at
/// least one being a fixed point type. In any case, this
/// operation did not follow usual arithmetic conversion and both operands may
/// not be the same.
bool isFixedPointBinOp() const {
return isa<BinaryOperator>(E) && Ty->isFixedPointType();
// We cannot simply check the result type since comparison operations return
// an int.
if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) {
QualType LHSType = BinOp->getLHS()->getType();
QualType RHSType = BinOp->getRHS()->getType();
return LHSType->isFixedPointType() || RHSType->isFixedPointType();
}
return false;
}
};

Expand Down Expand Up @@ -3372,8 +3380,6 @@ Value *ScalarExprEmitter::EmitFixedPointBinOp(const BinOpInfo &op) {
using llvm::ConstantInt;

const auto *BinOp = cast<BinaryOperator>(op.E);
assert((BinOp->getOpcode() == BO_Add || BinOp->getOpcode() == BO_Sub) &&
"Expected operation to be addition or subtraction");

// The result is a fixed point type and at least one of the operands is fixed
// point while the other is either fixed point or an int. This resulting type
Expand Down Expand Up @@ -3421,17 +3427,30 @@ Value *ScalarExprEmitter::EmitFixedPointBinOp(const BinOpInfo &op) {
}
break;
}
case BO_Mul:
case BO_Div:
case BO_Shl:
case BO_Shr:
case BO_Cmp:
case BO_LT:
return CommonFixedSema.isSigned() ? Builder.CreateICmpSLT(FullLHS, FullRHS)
: Builder.CreateICmpULT(FullLHS, FullRHS);
case BO_GT:
return CommonFixedSema.isSigned() ? Builder.CreateICmpSGT(FullLHS, FullRHS)
: Builder.CreateICmpUGT(FullLHS, FullRHS);
case BO_LE:
return CommonFixedSema.isSigned() ? Builder.CreateICmpSLE(FullLHS, FullRHS)
: Builder.CreateICmpULE(FullLHS, FullRHS);
case BO_GE:
return CommonFixedSema.isSigned() ? Builder.CreateICmpSGE(FullLHS, FullRHS)
: Builder.CreateICmpUGE(FullLHS, FullRHS);
case BO_EQ:
// For equality operations, we assume any padding bits on unsigned types are
// zero'd out. They could be overwritten through non-saturating operations
// that cause overflow, but this leads to undefined behavior.
return Builder.CreateICmpEQ(FullLHS, FullRHS);
case BO_NE:
return Builder.CreateICmpNE(FullLHS, FullRHS);
case BO_Mul:
case BO_Div:
case BO_Shl:
case BO_Shr:
case BO_Cmp:
case BO_LAnd:
case BO_LOr:
case BO_MulAssign:
Expand Down Expand Up @@ -3714,8 +3733,9 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,
Result = CGF.CGM.getCXXABI().EmitMemberPointerComparison(
CGF, LHS, RHS, MPT, E->getOpcode() == BO_NE);
} else if (!LHSTy->isAnyComplexType() && !RHSTy->isAnyComplexType()) {
Value *LHS = Visit(E->getLHS());
Value *RHS = Visit(E->getRHS());
BinOpInfo BOInfo = EmitBinOps(E);
Value *LHS = BOInfo.LHS;
Value *RHS = BOInfo.RHS;

// If AltiVec, the comparison results in a numeric type, so we use
// intrinsics comparing vectors and giving 0 or 1 as a result
Expand Down Expand Up @@ -3793,7 +3813,9 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,
E->getExprLoc());
}

if (LHS->getType()->isFPOrFPVectorTy()) {
if (BOInfo.isFixedPointBinOp()) {
Result = EmitFixedPointBinOp(BOInfo);
} else if (LHS->getType()->isFPOrFPVectorTy()) {
Result = Builder.CreateFCmp(FCmpOpc, LHS, RHS, "cmp");
} else if (LHSTy->hasSignedIntegerRepresentation()) {
Result = Builder.CreateICmp(SICmpOpc, LHS, RHS, "cmp");
Expand Down

0 comments on commit ce1d4f1

Please sign in to comment.