Fix bug that led to incorrect code with return statements.

The conceptual error was the assumption that not being under varying
control flow implied that the mask was all on; this is not the case
if some of the instances have executed a return earlier in the function's
execution.  The error in practice would be that the mask would be
assumed to be all-on for things like memory writes, so there would
be unintended side-effects for the instances that had returned.
This commit is contained in:
Matt Pharr
2011-12-14 06:00:05 -08:00
parent 07f218137a
commit 9920b30318

26
ctx.cpp
View File

@@ -312,11 +312,7 @@ FunctionEmitContext::GetFunctionMask() {
llvm::Value *
FunctionEmitContext::GetInternalMask() {
if (VaryingCFDepth() == 0 &&
!g->opt.disableMaskAllOnOptimizations)
return LLVMMaskAllOn;
else
return LoadInst(internalMaskPointer, "load_mask");
return LoadInst(internalMaskPointer, "load_mask");
}
@@ -798,13 +794,19 @@ FunctionEmitContext::CurrentLanesReturned(Expr *expr, bool doCoherenceCheck) {
expr = TypeConvertExpr(expr, returnType, "return statement");
if (expr != NULL) {
llvm::Value *retVal = expr->GetValue(this);
if (retVal != NULL)
// Use a masked store to store the value of the expression
// in the return value memory; this preserves the return
// values from other lanes that may have executed return
// statements previously.
StoreInst(retVal, returnValuePtr, GetInternalMask(),
PointerType::GetUniform(returnType));
if (retVal != NULL) {
if (returnType->IsUniformType() ||
dynamic_cast<const ReferenceType *>(returnType) != NULL)
StoreInst(retVal, returnValuePtr);
else {
// Use a masked store to store the value of the expression
// in the return value memory; this preserves the return
// values from other lanes that may have executed return
// statements previously.
StoreInst(retVal, returnValuePtr, GetInternalMask(),
PointerType::GetUniform(returnType));
}
}
}
}