summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExprScalar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGExprScalar.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp46
1 files changed, 34 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 0ea59d14e31..bdc07f17769 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -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;
}
};
@@ -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
@@ -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:
@@ -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
@@ -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");
OpenPOWER on IntegriCloud