Fixed structurized return when there are phi's from shortcircuiting. (#3981)

This commit is contained in:
Adam Yang 2021-10-02 13:55:47 -07:00 коммит произвёл GitHub
Родитель b44b76d1ad
Коммит 9b281d0de6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 73 добавлений и 3 удалений

Просмотреть файл

@ -3494,6 +3494,14 @@ void InitRetValue(BasicBlock *exitBB) {
}
}
static void ChangePredBranch(BasicBlock *BB, BasicBlock *NewBB) {
for (auto predIt = pred_begin(BB); predIt != pred_end(BB);) {
BasicBlock *Pred = *(predIt++);
TerminatorInst *TI = Pred->getTerminator();
TI->replaceUsesOfWith(BB, NewBB);
}
}
// For functions has multiple returns like
// float foo(float a, float b, float c) {
// float r = c;
@ -3529,6 +3537,7 @@ void InitRetValue(BasicBlock *exitBB) {
void StructurizeMultiRetFunction(Function *F, ScopeInfo &ScopeInfo,
bool bWaveEnabledStage,
SmallVector<BranchInst *, 16> &DxBreaks) {
if (ScopeInfo.CanSkipStructurize())
return;
// Get bbWithRets.
@ -3621,8 +3630,10 @@ void StructurizeMultiRetFunction(Function *F, ScopeInfo &ScopeInfo,
BasicBlock *CmpBB = BasicBlock::Create(BB->getContext(),
"bReturned.cmp.false", F, BB);
// Make BB preds go to cmpBB.
BB->replaceAllUsesWith(CmpBB);
// Make BB preds go to cmpBB. Do this instead of replaceAllUsesWith
// because BB could have PHI nodes that reference it.
ChangePredBranch(BB, CmpBB);
// Update endscopeBB to CmpBB for scopes which has BB as endscope.
updateEndScope(ScopeInfo, EndBBToScopeIndexMap, BB, CmpBB);
@ -3641,7 +3652,8 @@ void StructurizeMultiRetFunction(Function *F, ScopeInfo &ScopeInfo,
BasicBlock::Create(BB->getContext(), "bReturned.cmp.true", F, BB);
BasicBlock *BreakBB =
BasicBlock::Create(BB->getContext(), "bReturned.break", F, BB);
BB->replaceAllUsesWith(CmpBB);
ChangePredBranch(BB, CmpBB);
// Update endscopeBB to CmpBB for scopes which has BB as endscope.
updateEndScope(ScopeInfo, EndBBToScopeIndexMap, BB, CmpBB);

Просмотреть файл

@ -0,0 +1,58 @@
// RUN: %dxc -E main -fcgl -opt-enable structurize-returns -T ps_6_0 -enable-short-circuit %s | FileCheck %s
// RUN: %dxc -E main -opt-enable structurize-returns -T ps_6_0 -enable-short-circuit %s | FileCheck %s -check-prefix=FULL
// FULL: @main
float main(uint x : X, uint y : Y, uint z : Z) : SV_Target {
// CHECK: %[[bReturned:.*]] = alloca i1
// CHECK: store i1 false, i1* %[[bReturned]]
// CHECK-NOT: ret float
// CHECK: [[label:.+]] ; preds =
if (x) {
// CHECK: [[label2:.+]] ; preds =
if (y) {
// CHECK: store float 1.000000e+00
// CHECK: store i1 true, i1* %[[bReturned]]
// CHECK: br
return 1;
// CHECK: [[label_bRet_cmp_false:.+]]: ; preds =
// CHECK: %[[RET:.*]] = load i1, i1* %[[bReturned]]
// CHECK: %[[NRET:.*]] = icmp ne i1 %[[RET]], false
// CHECK: br i1 %[[NRET]],
}
// CHECK: [[if_end:.+]] ; preds =
// CHECK: load i32
// CHECK: %[[x_to_bool:.+]] = icmp
// CHECK: br i1 %[[x_to_bool]],
// CHECK: [[land_rhs:.+]] ; preds =
// CHECK: load i32
// CHECK: icmp
// CHECK: br
bool cond = x && y;
// CHECK: [[land_end:.+]] ; preds =
// CHECK-NOT: phi.+ %[[label_bRet_cmp_false]]
// CHECK: phi
// CHECK: icmp
// CHECK: br i1
if (cond) {
// CHECK: [[then2:.+]] ; preds =
// store float 2.000000e+00
// CHECK: store i1 true, i1* %[[bReturned]]
return 2;
// CHECK: [[label_bRet_cmp_false_2:.+]]: ; preds =
// CHECK: %[[RET2:.*]] = load i1, i1* %[[bReturned]]
// CHECK: %[[NRET2:.*]] = icmp ne i1 %[[RET2]], false
// CHECK: br i1 %[[NRET2]],
}
}
return 0;
}