Improve warnings for right shift by varying amounts.
Fixes: - Don't issue a warning when the shift is a by the same amount in all vector lanes. - Do issue a warning when it's a compile-time constant but the values are different in different lanes. Previously, we warned iff the shift amount wasn't a compile-time constant.
This commit is contained in:
39
expr.cpp
39
expr.cpp
@@ -1911,6 +1911,40 @@ lEmitLogicalOp(BinaryExpr::Op op, Expr *arg0, Expr *arg1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Returns true if shifting right by the given amount will lead to
|
||||||
|
inefficient code. (Assumes x86 target. May also warn inaccurately if
|
||||||
|
later optimization simplify the shift amount more than we are able to
|
||||||
|
see at this point.) */
|
||||||
|
static bool
|
||||||
|
lIsDifficultShiftAmount(Expr *expr) {
|
||||||
|
// Uniform shifts (of uniform values) are no problem.
|
||||||
|
if (expr->GetType()->IsVaryingType() == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ConstExpr *ce = dynamic_cast<ConstExpr *>(expr);
|
||||||
|
if (ce) {
|
||||||
|
// If the shift is by a constant amount, *and* it's the same amount
|
||||||
|
// in all vector lanes, we're in good shape.
|
||||||
|
uint32_t amount[ISPC_MAX_NVEC];
|
||||||
|
int count = ce->GetValues(amount);
|
||||||
|
for (int i = 1; i < count; ++i)
|
||||||
|
if (amount[i] != amount[0])
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeCastExpr *tce = dynamic_cast<TypeCastExpr *>(expr);
|
||||||
|
if (tce && tce->expr) {
|
||||||
|
// Finally, if the shift amount is given by a uniform value that's
|
||||||
|
// been smeared out into a varying, we have the same shift for all
|
||||||
|
// lanes and are also in good shape.
|
||||||
|
return (tce->expr->GetType()->IsUniformType() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
llvm::Value *
|
llvm::Value *
|
||||||
BinaryExpr::GetValue(FunctionEmitContext *ctx) const {
|
BinaryExpr::GetValue(FunctionEmitContext *ctx) const {
|
||||||
if (!arg0 || !arg1) {
|
if (!arg0 || !arg1) {
|
||||||
@@ -1951,9 +1985,8 @@ BinaryExpr::GetValue(FunctionEmitContext *ctx) const {
|
|||||||
case BitAnd:
|
case BitAnd:
|
||||||
case BitXor:
|
case BitXor:
|
||||||
case BitOr: {
|
case BitOr: {
|
||||||
if (op == Shr && arg1->GetType()->IsVaryingType() &&
|
if (op == Shr && lIsDifficultShiftAmount(arg1))
|
||||||
dynamic_cast<ConstExpr *>(arg1) == NULL)
|
PerformanceWarning(pos, "Shift right is inefficient for "
|
||||||
PerformanceWarning(pos, "Shift right is extremely inefficient for "
|
|
||||||
"varying shift amounts.");
|
"varying shift amounts.");
|
||||||
return lEmitBinaryBitOp(op, value0, value1,
|
return lEmitBinaryBitOp(op, value0, value1,
|
||||||
arg0->GetType()->IsUnsignedType(), ctx);
|
arg0->GetType()->IsUnsignedType(), ctx);
|
||||||
|
|||||||
Reference in New Issue
Block a user