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