Use logical shift right op for shifts of unsigned ints. Fixes issue #88.

This commit is contained in:
Matt Pharr
2011-08-29 10:32:26 -07:00
parent da76396c75
commit d0db46aac5
2 changed files with 23 additions and 4 deletions

View File

@@ -799,11 +799,17 @@ lOpString(BinaryExpr::Op op) {
*/ */
static llvm::Value * static llvm::Value *
lEmitBinaryBitOp(BinaryExpr::Op op, llvm::Value *arg0Val, lEmitBinaryBitOp(BinaryExpr::Op op, llvm::Value *arg0Val,
llvm::Value *arg1Val, FunctionEmitContext *ctx) { llvm::Value *arg1Val, bool isUnsigned,
FunctionEmitContext *ctx) {
llvm::Instruction::BinaryOps inst; llvm::Instruction::BinaryOps inst;
switch (op) { switch (op) {
case BinaryExpr::Shl: inst = llvm::Instruction::Shl; break; case BinaryExpr::Shl: inst = llvm::Instruction::Shl; break;
case BinaryExpr::Shr: inst = llvm::Instruction::AShr; break; case BinaryExpr::Shr:
if (isUnsigned)
inst = llvm::Instruction::LShr;
else
inst = llvm::Instruction::AShr;
break;
case BinaryExpr::BitAnd: inst = llvm::Instruction::And; break; case BinaryExpr::BitAnd: inst = llvm::Instruction::And; break;
case BinaryExpr::BitXor: inst = llvm::Instruction::Xor; break; case BinaryExpr::BitXor: inst = llvm::Instruction::Xor; break;
case BinaryExpr::BitOr: inst = llvm::Instruction::Or; break; case BinaryExpr::BitOr: inst = llvm::Instruction::Or; break;
@@ -949,7 +955,8 @@ BinaryExpr::GetValue(FunctionEmitContext *ctx) const {
dynamic_cast<ConstExpr *>(arg1) == NULL) dynamic_cast<ConstExpr *>(arg1) == NULL)
PerformanceWarning(pos, "Shift right is extremely inefficient for " PerformanceWarning(pos, "Shift right is extremely inefficient for "
"varying shift amounts."); "varying shift amounts.");
return lEmitBinaryBitOp(op, e0Val, e1Val, ctx); return lEmitBinaryBitOp(op, e0Val, e1Val,
arg0->GetType()->IsUnsignedType(), ctx);
} }
case LogicalAnd: case LogicalAnd:
return ctx->BinaryOperator(llvm::Instruction::And, e0Val, e1Val, return ctx->BinaryOperator(llvm::Instruction::And, e0Val, e1Val,
@@ -1533,7 +1540,8 @@ lEmitOpAssign(AssignExpr::Op op, Expr *arg0, Expr *arg1, const Type *type,
case AssignExpr::AndAssign: case AssignExpr::AndAssign:
case AssignExpr::XorAssign: case AssignExpr::XorAssign:
case AssignExpr::OrAssign: case AssignExpr::OrAssign:
newValue = lEmitBinaryBitOp(basicop, oldLHS, rvalue, ctx); newValue = lEmitBinaryBitOp(basicop, oldLHS, rvalue,
arg0->GetType()->IsUnsignedType(), ctx);
break; break;
default: default:
FATAL("logic error in lEmitOpAssign"); FATAL("logic error in lEmitOpAssign");

11
tests/uint-shift.ispc Normal file
View File

@@ -0,0 +1,11 @@
export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) {
unsigned int x = 0xffffffff;
RET[programIndex] = x >> 16;
}
export void result(uniform float RET[]) {
RET[programIndex] = 0xffff;
}