Skip to content

Commit d075466

Browse files
authored
Merge pull request #18941 from aschackmull/ssa/refactor4
Ssa: Extend consistency checks and reduce phi read nodes
2 parents cef8f7b + 3508ca8 commit d075466

File tree

6 files changed

+74
-15
lines changed

6 files changed

+74
-15
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import java
2+
import semmle.code.java.dataflow.internal.SsaImpl
3+
import Impl::Consistency

java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,15 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
168168
* Holds if the `i`th of basic block `bb` reads source variable `v`.
169169
*/
170170
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
171-
exists(VarRead use |
172-
v.getAnAccess() = use and bb.getNode(i) = use.getControlFlowNode() and certain = true
171+
hasDominanceInformation(bb) and
172+
(
173+
exists(VarRead use |
174+
v.getAnAccess() = use and bb.getNode(i) = use.getControlFlowNode() and certain = true
175+
)
176+
or
177+
variableCapture(v, _, bb, i) and
178+
certain = false
173179
)
174-
or
175-
variableCapture(v, _, bb, i) and
176-
certain = false
177180
}
178181
}
179182

java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,15 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
204204
* This includes implicit reads via calls.
205205
*/
206206
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
207-
exists(VarRead use |
208-
v.getAnAccess() = use and bb.getNode(i) = use.getControlFlowNode() and certain = true
207+
hasDominanceInformation(bb) and
208+
(
209+
exists(VarRead use |
210+
v.getAnAccess() = use and bb.getNode(i) = use.getControlFlowNode() and certain = true
211+
)
212+
or
213+
variableCapture(v, _, bb, i) and
214+
certain = false
209215
)
210-
or
211-
variableCapture(v, _, bb, i) and
212-
certain = false
213216
}
214217
}
215218

ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.expected

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ newStyleBarrierGuards
1212
| barrier-guards.rb:28:5:28:7 | foo |
1313
| barrier-guards.rb:37:21:38:19 | [input] SSA phi read(foo) |
1414
| barrier-guards.rb:38:5:38:7 | foo |
15-
| barrier-guards.rb:43:16:46:5 | [input] SSA phi read(foo) |
1615
| barrier-guards.rb:45:9:45:11 | foo |
1716
| barrier-guards.rb:70:22:71:19 | [input] SSA phi read(foo) |
1817
| barrier-guards.rb:71:5:71:7 | foo |
@@ -51,9 +50,7 @@ newStyleBarrierGuards
5150
| barrier-guards.rb:199:4:199:15 | [input] SSA phi read(foo) |
5251
| barrier-guards.rb:199:4:199:31 | [input] SSA phi read(foo) |
5352
| barrier-guards.rb:199:20:199:31 | [input] SSA phi read(foo) |
54-
| barrier-guards.rb:203:4:203:15 | [input] SSA phi read(foo) |
5553
| barrier-guards.rb:203:36:203:47 | [input] SSA phi read(foo) |
56-
| barrier-guards.rb:207:21:207:21 | [input] SSA phi read(foo) |
5754
| barrier-guards.rb:207:22:208:19 | [input] SSA phi read(foo) |
5855
| barrier-guards.rb:208:5:208:7 | foo |
5956
| barrier-guards.rb:211:22:212:19 | [input] SSA phi read(foo) |
@@ -64,8 +61,6 @@ newStyleBarrierGuards
6461
| barrier-guards.rb:219:21:219:32 | [input] SSA phi read(foo) |
6562
| barrier-guards.rb:219:95:220:19 | [input] SSA phi read(foo) |
6663
| barrier-guards.rb:220:5:220:7 | foo |
67-
| barrier-guards.rb:227:21:227:21 | [input] SSA phi read(foo) |
68-
| barrier-guards.rb:227:22:228:7 | [input] SSA phi read(foo) |
6964
| barrier-guards.rb:232:18:233:19 | [input] SSA phi read(foo) |
7065
| barrier-guards.rb:233:5:233:7 | foo |
7166
| barrier-guards.rb:237:19:237:38 | [input] SSA phi read(foo) |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
uselessPhiNode
2+
| sqlx.rs:155:5:157:5 | phi | 1 |
3+
phiWithoutTwoPriorRefs
4+
| sqlx.rs:155:5:157:5 | phi | 1 |

shared/ssa/codeql/ssa/Ssa.qll

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
307307
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
308308
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
309309
ssaDefReachesRead(v, _, readbb, _) and
310+
variableRead(readbb, _, v, true) and
310311
not variableWrite(readbb, _, v, _)
311312
or
312313
synthPhiRead(readbb, v) and
@@ -1379,6 +1380,56 @@ module Make<LocationSig Location, InputSig<Location> Input> {
13791380
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
13801381
)
13811382
}
1383+
1384+
/** Holds if the end of a basic block can be reached by multiple definitions. */
1385+
query predicate nonUniqueDefReachesEndOfBlock(Definition def, SourceVariable v, BasicBlock bb) {
1386+
ssaDefReachesEndOfBlock(bb, def, v) and
1387+
not exists(unique(Definition def0 | ssaDefReachesEndOfBlock(bb, def0, v)))
1388+
}
1389+
1390+
/** Holds if a phi node has less than two inputs. */
1391+
query predicate uselessPhiNode(PhiNode phi, int inputs) {
1392+
inputs = count(Definition inp | phiHasInputFromBlock(phi, inp, _)) and
1393+
inputs < 2
1394+
}
1395+
1396+
/** Holds if a certain read does not have a prior reference. */
1397+
query predicate readWithoutPriorRef(SourceVariable v, BasicBlock bb, int i) {
1398+
variableRead(bb, i, v, true) and
1399+
not AdjacentSsaRefs::adjacentRefRead(_, _, bb, i, v)
1400+
}
1401+
1402+
/**
1403+
* Holds if a certain read has multiple prior references. The introduction
1404+
* of phi reads should make the prior reference unique.
1405+
*/
1406+
query predicate readWithMultiplePriorRefs(
1407+
SourceVariable v, BasicBlock bb1, int i1, BasicBlock bb2, int i2
1408+
) {
1409+
AdjacentSsaRefs::adjacentRefRead(bb1, i1, bb2, i2, v) and
1410+
2 <=
1411+
strictcount(BasicBlock bb0, int i0 | AdjacentSsaRefs::adjacentRefRead(bb0, i0, bb1, i1, v))
1412+
}
1413+
1414+
/** Holds if `phi` has less than 2 immediately prior references. */
1415+
query predicate phiWithoutTwoPriorRefs(PhiNode phi, int inputRefs) {
1416+
exists(BasicBlock bbPhi, SourceVariable v |
1417+
phi.definesAt(v, bbPhi, _) and
1418+
inputRefs =
1419+
count(BasicBlock bb, int i | AdjacentSsaRefs::adjacentRefPhi(bb, i, _, bbPhi, v)) and
1420+
inputRefs < 2
1421+
)
1422+
}
1423+
1424+
/**
1425+
* Holds if the phi read for `v` at `bb` has less than 2 immediately prior
1426+
* references.
1427+
*/
1428+
query predicate phiReadWithoutTwoPriorRefs(BasicBlock bbPhi, SourceVariable v, int inputRefs) {
1429+
synthPhiRead(bbPhi, v) and
1430+
inputRefs = count(BasicBlock bb, int i | AdjacentSsaRefs::adjacentRefPhi(bb, i, _, bbPhi, v)) and
1431+
inputRefs < 2
1432+
}
13821433
}
13831434

13841435
/** Provides the input to `DataFlowIntegration`. */

0 commit comments

Comments
 (0)