Skip to content

Commit 3203261

Browse files
author
Xiaohong Gong
committed
Apply trapping nullcheck to the uncompressed target for compressed pointer.
Trapping nullcheck might generate two uncompress instructions for the same compressed oop in Graal. One is inserted by the backend when it emits nullcheck. If the pointer is a compressed object, it should be uncompressed before the nullcheck is emitted. And another one is generated by the normal uncompressing operation. These two instructions are duplicated with each other. The generated codes on AArch64 like: ldr w0, [x0,oracle#112] lsl x2, x0, oracle#3 ; uncompressing (first) ldr xzr, [x2] ; implicit exception: deoptimizes ...... ; fixed operations lsl x0, x0, oracle#3 ; uncompressing (second) str w1, [x0,oracle#12] A simple way to avoid this is to apply the nullcheck to the uncompressed result if it exists instead of to the compressed pointer when generating the trapping nullcheck. With the modification, the codes above could be optimized to: ldr w0, [x0,oracle#112] lsl x0, x0, oracle#3 ; uncompressing ldr xzr, [x0] ; implicit exception: deoptimizes ...... ; fixed operations str w1, [x0,oracle#12] Change-Id: Iabfe47bbf984ed11c42555f84bdd0ccf2a5bdddb
1 parent 4520ef4 commit 3203261

File tree

1 file changed

+26
-3
lines changed

1 file changed

+26
-3
lines changed

compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -264,8 +264,13 @@ private static void replaceWithTrappingNullCheck(AbstractDeoptimizeNode deopt, I
264264
}
265265

266266
if (trappingNullCheck == null) {
267-
// Need to add a null check node.
268-
trappingNullCheck = deopt.graph().add(new NullCheckNode(value));
267+
// Need to add a null check node. Move the null check forward to the uncompressed object
268+
// if it exists.
269+
NullCheckNode nullCheck = tryUseUncompressedNullCheck(value, isNullNode);
270+
if (nullCheck == null) {
271+
nullCheck = new NullCheckNode(value);
272+
}
273+
trappingNullCheck = deopt.graph().add(nullCheck);
269274
deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
270275
deopt.getDebug().log("Inserted NullCheckNode %s", trappingNullCheck);
271276
}
@@ -287,4 +292,22 @@ private static void replaceWithTrappingNullCheck(AbstractDeoptimizeNode deopt, I
287292
GraphUtil.killCFG(trappingContinuation);
288293
GraphUtil.tryKillUnused(isNullNode);
289294
}
295+
296+
private static NullCheckNode tryUseUncompressedNullCheck(ValueNode value, IsNullNode isNullNode) {
297+
assert isNullNode.getValue().equals(value);
298+
CompressionNode uncompressed = null;
299+
for (Node usage : value.usages()) {
300+
if (usage instanceof CompressionNode) {
301+
if (((CompressionNode) usage).getOp() == CompressionNode.CompressionOp.Uncompress) {
302+
assert ((CompressionNode) usage).getValue().equals(value);
303+
uncompressed = (CompressionNode) usage;
304+
break;
305+
}
306+
}
307+
}
308+
if (uncompressed != null) {
309+
return new NullCheckNode(uncompressed);
310+
}
311+
return null;
312+
}
290313
}

0 commit comments

Comments
 (0)