Fix bug in &&/|| short-circuiting.

Use full mask, not internal mask when checking "any lanes running"
before evaluating expressions.

Added some more tests to try to cover this case.
This commit is contained in:
Matt Pharr
2012-02-01 08:17:25 -08:00
parent 0432f97555
commit fdb4eaf437
5 changed files with 117 additions and 8 deletions

View File

@@ -1537,6 +1537,7 @@ lEmitLogicalOp(BinaryExpr::Op op, Expr *arg0, Expr *arg1,
// Otherwise, the first operand is varying... Save the current
// value of the mask so that we can restore it at the end.
llvm::Value *oldMask = ctx->GetInternalMask();
llvm::Value *oldFullMask = ctx->GetFullMask();
// Convert the second operand to be varying as well, so that we can
// perform logical vector ops with its value.
@@ -1551,11 +1552,11 @@ lEmitLogicalOp(BinaryExpr::Op op, Expr *arg0, Expr *arg1,
// lanes--i.e. if (value0 & mask) == mask. If so, we don't
// need to evaluate the second operand of the expression.
llvm::Value *value0AndMask =
ctx->BinaryOperator(llvm::Instruction::And, value0, oldMask,
"op&mask");
ctx->BinaryOperator(llvm::Instruction::And, value0,
oldFullMask, "op&mask");
llvm::Value *equalsMask =
ctx->CmpInst(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_EQ,
value0AndMask, oldMask, "value0&mask==mask");
value0AndMask, oldFullMask, "value0&mask==mask");
equalsMask = ctx->I1VecToBoolVec(equalsMask);
llvm::Value *allMatch = ctx->All(equalsMask);
ctx->BranchInst(bbSkipEvalValue1, bbEvalValue1, allMatch);
@@ -1602,11 +1603,11 @@ lEmitLogicalOp(BinaryExpr::Op op, Expr *arg0, Expr *arg1,
// if (mask & ~value0) == mask.
llvm::Value *notValue0 = ctx->NotOperator(value0, "not_value0");
llvm::Value *notValue0AndMask =
ctx->BinaryOperator(llvm::Instruction::And, notValue0, oldMask,
"not_value0&mask");
ctx->BinaryOperator(llvm::Instruction::And, notValue0,
oldFullMask, "not_value0&mask");
llvm::Value *equalsMask =
ctx->CmpInst(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_EQ,
notValue0AndMask, oldMask, "not_value0&mask==mask");
notValue0AndMask, oldFullMask, "not_value0&mask==mask");
equalsMask = ctx->I1VecToBoolVec(equalsMask);
llvm::Value *allMatch = ctx->All(equalsMask);
ctx->BranchInst(bbSkipEvalValue1, bbEvalValue1, allMatch);
@@ -1634,8 +1635,8 @@ lEmitLogicalOp(BinaryExpr::Op op, Expr *arg0, Expr *arg1,
// masking off the valid lanes before we AND them together:
// result = (value0 & old_mask) & (value1 & current_mask)
llvm::Value *value0AndMask =
ctx->BinaryOperator(llvm::Instruction::And, value0, oldMask,
"op&mask");
ctx->BinaryOperator(llvm::Instruction::And, value0,
oldFullMask, "op&mask");
llvm::Value *value1AndMask =
ctx->BinaryOperator(llvm::Instruction::And, value1,
ctx->GetInternalMask(), "value1&mask");

View File

@@ -0,0 +1,25 @@
export uniform int width() { return programCount; }
uniform int * uniform ptr;
float foo(uniform float a[]) {
int index = (programIndex & 1) * 10000;
if (a[programIndex] < 10000 && a[index] == 1)
return 1;
else
return 1234;
}
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float a = aFOO[programIndex];
float a0 = aFOO[0], a1 = aFOO[1];
if ((programIndex & 1) == 0)
RET[programIndex] = foo(aFOO);
else
RET[programIndex] = 2;
}
export void result(uniform float RET[]) {
RET[programIndex] = (programIndex & 1) ? 2 : 1;
}

View File

@@ -0,0 +1,25 @@
export uniform int width() { return programCount; }
uniform int * uniform ptr;
float foo(uniform float a[]) {
int index = (programIndex & 1) * 10000;
if (a[programIndex] < 10000 && a[index] == 1)
return 1;
else
return 1234;
}
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float a = aFOO[programIndex];
float a0 = aFOO[0], a1 = aFOO[1];
if ((programIndex & 1) == 0)
RET[programIndex] = foo(aFOO);
else
RET[programIndex] = 2;
}
export void result(uniform float RET[]) {
RET[programIndex] = (programIndex & 1) ? 2 : 1;
}

View File

@@ -0,0 +1,29 @@
export uniform int width() { return programCount; }
int * uniform ptr;
int crash() {
return *ptr;
}
float foo(uniform float a[]) {
int index = (programIndex & 1);
if (a[index] == 2 && crash())
return 1234;
else
return 1;
}
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float a = aFOO[programIndex];
float a0 = aFOO[0], a1 = aFOO[1];
if ((programIndex & 1) == 0)
RET[programIndex] = foo(aFOO);
else
RET[programIndex] = 2;
}
export void result(uniform float RET[]) {
RET[programIndex] = (programIndex & 1) ? 2 : 1;
}

View File

@@ -0,0 +1,29 @@
export uniform int width() { return programCount; }
uniform int * uniform ptr;
uniform int crash() {
return *ptr;
}
float foo(uniform float a[]) {
int index = (programIndex & 1);
if (a[index] == 2 && crash())
return 1234;
else
return 1;
}
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float a = aFOO[programIndex];
float a0 = aFOO[0], a1 = aFOO[1];
if ((programIndex & 1) == 0)
RET[programIndex] = foo(aFOO);
else
RET[programIndex] = 2;
}
export void result(uniform float RET[]) {
RET[programIndex] = (programIndex & 1) ? 2 : 1;
}