Skip to content

Commit 6600436

Browse files
committed
C++: handle degenerate phi nodes
1 parent 7930c4a commit 6600436

File tree

5 files changed

+23
-20
lines changed

5 files changed

+23
-20
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,25 @@ private module Cached {
4343
class TStageInstruction =
4444
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction;
4545

46+
/**
47+
* If `oldInstruction` is a `Phi` instruction that has exactly one reachable predecessor block,
48+
* this predicate returns the `PhiInputOperand` corresponding to that predecessor block.
49+
* Otherwise, this predicate does not hold.
50+
*/
51+
private OldIR::PhiInputOperand getDegeneratePhiOperand(OldInstruction oldInstruction) {
52+
result =
53+
unique(OldIR::PhiInputOperand operand |
54+
operand = oldInstruction.(OldIR::PhiInstruction).getAnInputOperand() and
55+
operand.getPredecessorBlock() instanceof OldBlock
56+
)
57+
}
58+
4659
cached
4760
predicate hasInstruction(TStageInstruction instr) {
4861
instr instanceof TRawInstruction and instr instanceof OldInstruction
4962
or
50-
instr instanceof TPhiInstruction
63+
instr instanceof TPhiInstruction and
64+
not exists(getDegeneratePhiOperand(instr))
5165
or
5266
instr instanceof TChiInstruction
5367
or
@@ -150,16 +164,13 @@ private module Cached {
150164
(
151165
result = getNewInstruction(oldOperand.getAnyDef()) and
152166
overlap = originalOverlap
153-
/*
154-
* or
155-
* exists(OldIR::PhiInputOperand phiOperand, Overlap phiOperandOverlap |
156-
* phiOperand = getDegeneratePhiOperand(oldOperand.getAnyDef()) and
157-
* result = getNewDefinitionFromOldSSA(phiOperand, phiOperandOverlap) and
158-
* overlap = combineOverlap(phiOperandOverlap, originalOverlap)
159-
* )
160-
*/
161-
167+
or
168+
exists(OldIR::PhiInputOperand phiOperand, Overlap phiOperandOverlap |
169+
phiOperand = getDegeneratePhiOperand(oldOperand.getAnyDef()) and
170+
result = getNewDefinitionFromOldSSA(phiOperand, phiOperandOverlap) and
171+
overlap = combineOverlap(phiOperandOverlap, originalOverlap)
162172
)
173+
)
163174
)
164175
}
165176

cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency.expected

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,9 @@ instructionWithoutSuccessor
1010
ambiguousSuccessors
1111
unexplainedLoop
1212
unnecessaryPhiInstruction
13-
| ssa.cpp:345:3:345:13 | Phi: return ... | Instruction 'Phi: return ...' is in a block with only 0 predecessors in function '$@'. | ssa.cpp:335:5:335:25 | int UnreachablePhiOperand(int, int) | int UnreachablePhiOperand(int, int) |
14-
| ssa.cpp:395:5:395:5 | Phi: ; | Instruction 'Phi: ;' is in a block with only 0 predecessors in function '$@'. | ssa.cpp:383:5:383:24 | int FusedBlockPhiOperand(int, int, int, bool) | int FusedBlockPhiOperand(int, int, int, bool) |
1513
memoryOperandDefinitionIsUnmodeled
1614
operandAcrossFunctions
1715
instructionWithoutUniqueBlock
18-
| ssa.cpp:345:3:345:13 | Phi: return ... | Instruction 'Phi: return ...' is a member of 0 blocks in function '$@'. | ssa.cpp:335:5:335:25 | int UnreachablePhiOperand(int, int) | int UnreachablePhiOperand(int, int) |
19-
| ssa.cpp:395:5:395:5 | Phi: ; | Instruction 'Phi: ;' is a member of 0 blocks in function '$@'. | ssa.cpp:383:5:383:24 | int FusedBlockPhiOperand(int, int, int, bool) | int FusedBlockPhiOperand(int, int, int, bool) |
2016
containsLoopOfForwardEdges
2117
lostReachability
2218
backEdgeCountMismatch

cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency_unsound.expected

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,9 @@ instructionWithoutSuccessor
1010
ambiguousSuccessors
1111
unexplainedLoop
1212
unnecessaryPhiInstruction
13-
| ssa.cpp:345:3:345:13 | Phi: return ... | Instruction 'Phi: return ...' is in a block with only 0 predecessors in function '$@'. | ssa.cpp:335:5:335:25 | int UnreachablePhiOperand(int, int) | int UnreachablePhiOperand(int, int) |
14-
| ssa.cpp:395:5:395:5 | Phi: ; | Instruction 'Phi: ;' is in a block with only 0 predecessors in function '$@'. | ssa.cpp:383:5:383:24 | int FusedBlockPhiOperand(int, int, int, bool) | int FusedBlockPhiOperand(int, int, int, bool) |
1513
memoryOperandDefinitionIsUnmodeled
1614
operandAcrossFunctions
1715
instructionWithoutUniqueBlock
18-
| ssa.cpp:345:3:345:13 | Phi: return ... | Instruction 'Phi: return ...' is a member of 0 blocks in function '$@'. | ssa.cpp:335:5:335:25 | int UnreachablePhiOperand(int, int) | int UnreachablePhiOperand(int, int) |
19-
| ssa.cpp:395:5:395:5 | Phi: ; | Instruction 'Phi: ;' is a member of 0 blocks in function '$@'. | ssa.cpp:383:5:383:24 | int FusedBlockPhiOperand(int, int, int, bool) | int FusedBlockPhiOperand(int, int, int, bool) |
2016
containsLoopOfForwardEdges
2117
lostReachability
2218
backEdgeCountMismatch

cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1618,7 +1618,7 @@ ssa.cpp:
16181618
# 340| m340_4(int) = Store[ret] : &:r340_3, r340_2
16191619
# 345| r345_1(glval<int>) = VariableAddress[#return] :
16201620
# 345| r345_2(glval<int>) = VariableAddress[ret] :
1621-
# 345| r345_3(int) = Load[ret] : &:r345_2
1621+
# 345| r345_3(int) = Load[ret] : &:r345_2, m340_4
16221622
# 345| m345_4(int) = Store[#return] : &:r345_1, r345_3
16231623
# 335| r335_9(glval<int>) = VariableAddress[#return] :
16241624
# 335| v335_10(void) = ReturnValue : &:r335_9, m345_4

cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1608,7 +1608,7 @@ ssa.cpp:
16081608
# 340| m340_4(int) = Store[ret] : &:r340_3, r340_2
16091609
# 345| r345_1(glval<int>) = VariableAddress[#return] :
16101610
# 345| r345_2(glval<int>) = VariableAddress[ret] :
1611-
# 345| r345_3(int) = Load[ret] : &:r345_2
1611+
# 345| r345_3(int) = Load[ret] : &:r345_2, m340_4
16121612
# 345| m345_4(int) = Store[#return] : &:r345_1, r345_3
16131613
# 335| r335_9(glval<int>) = VariableAddress[#return] :
16141614
# 335| v335_10(void) = ReturnValue : &:r335_9, m345_4

0 commit comments

Comments
 (0)