Skip to content

Commit 8402891

Browse files
committed
8373355: C2: CompileCommand PrintIdealPhase should also print nodes that are not "reachable from below"
Reviewed-by: rcastanedalo, mchevalier, bmaillard
1 parent 78c2d57 commit 8402891

File tree

5 files changed

+210
-55
lines changed

5 files changed

+210
-55
lines changed

src/hotspot/share/opto/compile.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,9 @@ void Compile::print_ideal_ir(const char* phase_name) {
595595
if (_output == nullptr) {
596596
ss.print_cr("AFTER: %s", phase_name);
597597
// Print out all nodes in ascending order of index.
598-
root()->dump_bfs(MaxNodeLimit, nullptr, "+S$", &ss);
598+
// It is important that we traverse both inputs and outputs of nodes,
599+
// so that we reach all nodes that are connected to Root.
600+
root()->dump_bfs(MaxNodeLimit, nullptr, "-+S$", &ss);
599601
} else {
600602
// Dump the node blockwise if we have a scheduling
601603
_output->print_scheduling(&ss);

test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,29 @@ public void runMethod() {
6363
Asserts.assertEQ(unusedResultAfterLoopOpt3(1.1d, 2.2d), 0.d);
6464
}
6565

66+
// Note: we used to check for ConD nodes in the IR. But that is a bit brittle:
67+
// Constant nodes can appear during IR transformations, and then lose their outputs.
68+
// During IGNV, the constants stay in the graph even if they lose the inputs. But
69+
// CCP cleans them out because they are not in the useful set. So for now, we do not
70+
// rely on any constant counting, just on counting the operation nodes.
71+
6672
@Test
67-
@IR(failOn = {"drem"}, phase = CompilePhase.BEFORE_MATCHING)
68-
@IR(counts = {IRNode.CON_D, "1"})
73+
@IR(counts = {IRNode.MOD_D, "2"},
74+
phase = CompilePhase.AFTER_PARSING)
75+
@IR(counts = {".*CallLeaf.*drem.*", "0"},
76+
phase = CompilePhase.BEFORE_MATCHING)
6977
public double constant() {
7078
// All constants available during parsing
7179
return q % 72.0d % 30.0d;
7280
}
7381

7482
@Test
75-
@IR(failOn = {"drem"}, phase = CompilePhase.BEFORE_MATCHING)
76-
@IR(counts = {IRNode.CON_D, "1"})
83+
@IR(counts = {IRNode.MOD_D, "1"},
84+
phase = CompilePhase.AFTER_PARSING)
85+
@IR(counts = {IRNode.MOD_D, "1"},
86+
phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts
87+
@IR(counts = {".*CallLeaf.*drem.*", "0"},
88+
phase = CompilePhase.BEFORE_MATCHING)
7789
public double alsoConstant() {
7890
// Make sure value is only available after second loop opts round
7991
double val = 0;
@@ -86,8 +98,12 @@ public double alsoConstant() {
8698
}
8799

88100
@Test
89-
@IR(failOn = {"drem"}, phase = CompilePhase.BEFORE_MATCHING)
90-
@IR(counts = {IRNode.CON_D, "1"})
101+
@IR(counts = {IRNode.MOD_D, "2"},
102+
phase = CompilePhase.AFTER_PARSING)
103+
@IR(counts = {IRNode.MOD_D, "2"},
104+
phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts
105+
@IR(counts = {".*CallLeaf.*drem.*", "0"},
106+
phase = CompilePhase.BEFORE_MATCHING)
91107
public double nanLeftConstant() {
92108
// Make sure value is only available after second loop opts round
93109
double val = 134.18d;
@@ -100,8 +116,12 @@ public double nanLeftConstant() {
100116
}
101117

102118
@Test
103-
@IR(failOn = {"drem"}, phase = CompilePhase.BEFORE_MATCHING)
104-
@IR(counts = {IRNode.CON_D, "1"})
119+
@IR(counts = {IRNode.MOD_D, "2"},
120+
phase = CompilePhase.AFTER_PARSING)
121+
@IR(counts = {IRNode.MOD_D, "2"},
122+
phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts
123+
@IR(counts = {".*CallLeaf.*drem.*", "0"},
124+
phase = CompilePhase.BEFORE_MATCHING)
105125
public double nanRightConstant() {
106126
// Make sure value is only available after second loop opts round
107127
double val = 134.18d;
@@ -114,29 +134,41 @@ public double nanRightConstant() {
114134
}
115135

116136
@Test
117-
@IR(counts = {"drem", "1"}, phase = CompilePhase.BEFORE_MATCHING)
118-
@IR(counts = {IRNode.CON_D, "1"})
137+
@IR(counts = {IRNode.MOD_D, "1"},
138+
phase = CompilePhase.AFTER_PARSING)
139+
@IR(counts = {".*CallLeaf.*drem.*", "1"},
140+
phase = CompilePhase.BEFORE_MATCHING) // no constant folding
119141
public double notConstant(double x) {
120142
return x % 32.0d;
121143
}
122144

123145
@Test
124-
@IR(counts = {"drem", "2"}, phase = CompilePhase.BEFORE_MATCHING)
125-
@IR(counts = {IRNode.CON_D, "1"})
146+
@IR(counts = {IRNode.MOD_D, "2"},
147+
phase = CompilePhase.AFTER_PARSING)
148+
@IR(counts = {".*CallLeaf.*drem.*", "2"},
149+
phase = CompilePhase.BEFORE_MATCHING) // no constant folding
126150
public double veryNotConstant(double x, double y) {
127151
return x % 32.0d % y;
128152
}
129153

130154
@Test
131-
@IR(failOn = IRNode.MOD_D, phase = CompilePhase.ITER_GVN1)
132-
@IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.AFTER_PARSING)
155+
@IR(counts = {IRNode.MOD_D, "1"},
156+
phase = CompilePhase.AFTER_PARSING)
157+
@IR(counts = {IRNode.MOD_D, "0"},
158+
phase = CompilePhase.ITER_GVN1) // IGVN removes unused nodes
159+
@IR(counts = {".*CallLeaf.*drem.*", "0"},
160+
phase = CompilePhase.BEFORE_MATCHING)
133161
public void unusedResult(double x, double y) {
134162
double unused = x % y;
135163
}
136164

137165
@Test
138-
@IR(failOn = IRNode.MOD_D, phase = CompilePhase.ITER_GVN1)
139-
@IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.AFTER_PARSING)
166+
@IR(counts = {IRNode.MOD_D, "1"},
167+
phase = CompilePhase.AFTER_PARSING)
168+
@IR(counts = {IRNode.MOD_D, "0"},
169+
phase = CompilePhase.ITER_GVN1) // IGVN removes unused nodes
170+
@IR(counts = {".*CallLeaf.*drem.*", "0"},
171+
phase = CompilePhase.BEFORE_MATCHING)
140172
public void repeatedlyUnused(double x, double y) {
141173
double unused = 1.d;
142174
for (int i = 0; i < 100_000; i++) {
@@ -149,8 +181,14 @@ public void repeatedlyUnused(double x, double y) {
149181
// and thus a different execution path. In unusedResultAfterLoopOpt1 the modulo is
150182
// used in the traps of the parse predicates. In unusedResultAfterLoopOpt2, it is not.
151183
@Test
152-
@IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.ITER_GVN2)
153-
@IR(failOn = IRNode.MOD_D, phase = CompilePhase.BEFORE_MACRO_EXPANSION)
184+
@IR(counts = {IRNode.MOD_D, "1"},
185+
phase = CompilePhase.AFTER_PARSING)
186+
@IR(counts = {IRNode.MOD_D, "1"},
187+
phase = CompilePhase.ITER_GVN2)
188+
@IR(counts = {IRNode.MOD_D, "0"},
189+
phase = CompilePhase.BEFORE_MACRO_EXPANSION)
190+
@IR(counts = {".*CallLeaf.*drem.*", "0"},
191+
phase = CompilePhase.BEFORE_MATCHING)
154192
public double unusedResultAfterLoopOpt1(double x, double y) {
155193
double unused = x % y;
156194

@@ -168,8 +206,14 @@ public double unusedResultAfterLoopOpt1(double x, double y) {
168206
}
169207

170208
@Test
171-
@IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.AFTER_CLOOPS)
172-
@IR(failOn = IRNode.MOD_D, phase = CompilePhase.PHASEIDEALLOOP1)
209+
@IR(counts = {IRNode.MOD_D, "1"},
210+
phase = CompilePhase.AFTER_PARSING)
211+
@IR(counts = {IRNode.MOD_D, "1"},
212+
phase = CompilePhase.AFTER_CLOOPS)
213+
@IR(counts = {IRNode.MOD_D, "0"},
214+
phase = CompilePhase.PHASEIDEALLOOP1)
215+
@IR(counts = {".*CallLeaf.*drem.*", "0"},
216+
phase = CompilePhase.BEFORE_MATCHING)
173217
public double unusedResultAfterLoopOpt2(double x, double y) {
174218
int a = 77;
175219
int b = 0;
@@ -187,8 +231,14 @@ public double unusedResultAfterLoopOpt2(double x, double y) {
187231
}
188232

189233
@Test
190-
@IR(counts = {IRNode.MOD_D, "2"}, phase = CompilePhase.AFTER_CLOOPS)
191-
@IR(failOn = IRNode.MOD_D, phase = CompilePhase.PHASEIDEALLOOP1)
234+
@IR(counts = {IRNode.MOD_D, "3"},
235+
phase = CompilePhase.AFTER_PARSING)
236+
@IR(counts = {IRNode.MOD_D, "2"},
237+
phase = CompilePhase.AFTER_CLOOPS) // drop the useless one
238+
@IR(counts = {IRNode.MOD_D, "0"},
239+
phase = CompilePhase.PHASEIDEALLOOP1) // drop the rest
240+
@IR(counts = {".*CallLeaf.*drem.*", "0"},
241+
phase = CompilePhase.BEFORE_MATCHING)
192242
public double unusedResultAfterLoopOpt3(double x, double y) {
193243
double unused = x % y;
194244

test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,29 @@ public void runMethod() {
6363
Asserts.assertEQ(unusedResultAfterLoopOpt3(1.1f, 2.2f), 0.f);
6464
}
6565

66+
// Note: we used to check for ConF nodes in the IR. But that is a bit brittle:
67+
// Constant nodes can appear during IR transformations, and then lose their outputs.
68+
// During IGNV, the constants stay in the graph even if they lose the inputs. But
69+
// CCP cleans them out because they are not in the useful set. So for now, we do not
70+
// rely on any constant counting, just on counting the operation nodes.
71+
6672
@Test
67-
@IR(failOn = {"frem"}, phase = CompilePhase.BEFORE_MATCHING)
68-
@IR(counts = {IRNode.CON_F, "1"})
73+
@IR(counts = {IRNode.MOD_F, "2"},
74+
phase = CompilePhase.AFTER_PARSING)
75+
@IR(counts = {".*CallLeaf.*frem.*", "0"},
76+
phase = CompilePhase.BEFORE_MATCHING)
6977
public float constant() {
7078
// All constants available during parsing
7179
return q % 72.0f % 30.0f;
7280
}
7381

7482
@Test
75-
@IR(failOn = {"frem"}, phase = CompilePhase.BEFORE_MATCHING)
76-
@IR(counts = {IRNode.CON_F, "1"})
83+
@IR(counts = {IRNode.MOD_F, "1"},
84+
phase = CompilePhase.AFTER_PARSING)
85+
@IR(counts = {IRNode.MOD_F, "1"},
86+
phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts
87+
@IR(counts = {".*CallLeaf.*frem.*", "0"},
88+
phase = CompilePhase.BEFORE_MATCHING)
7789
public float alsoConstant() {
7890
// Make sure value is only available after second loop opts round
7991
float val = 0;
@@ -86,8 +98,12 @@ public float alsoConstant() {
8698
}
8799

88100
@Test
89-
@IR(failOn = {"frem"}, phase = CompilePhase.BEFORE_MATCHING)
90-
@IR(counts = {IRNode.CON_F, "1"})
101+
@IR(counts = {IRNode.MOD_F, "2"},
102+
phase = CompilePhase.AFTER_PARSING)
103+
@IR(counts = {IRNode.MOD_F, "2"},
104+
phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts
105+
@IR(counts = {".*CallLeaf.*frem.*", "0"},
106+
phase = CompilePhase.BEFORE_MATCHING)
91107
public float nanLeftConstant() {
92108
// Make sure value is only available after second loop opts round
93109
float val = 134.18f;
@@ -100,8 +116,12 @@ public float nanLeftConstant() {
100116
}
101117

102118
@Test
103-
@IR(failOn = {"frem"}, phase = CompilePhase.BEFORE_MATCHING)
104-
@IR(counts = {IRNode.CON_F, "1"})
119+
@IR(counts = {IRNode.MOD_F, "2"},
120+
phase = CompilePhase.AFTER_PARSING)
121+
@IR(counts = {IRNode.MOD_F, "2"},
122+
phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts
123+
@IR(counts = {".*CallLeaf.*frem.*", "0"},
124+
phase = CompilePhase.BEFORE_MATCHING)
105125
public float nanRightConstant() {
106126
// Make sure value is only available after second loop opts round
107127
float val = 134.18f;
@@ -114,29 +134,41 @@ public float nanRightConstant() {
114134
}
115135

116136
@Test
117-
@IR(counts = {"frem", "1"}, phase = CompilePhase.BEFORE_MATCHING)
118-
@IR(counts = {IRNode.CON_F, "1"})
137+
@IR(counts = {IRNode.MOD_F, "1"},
138+
phase = CompilePhase.AFTER_PARSING)
139+
@IR(counts = {".*CallLeaf.*frem.*", "1"},
140+
phase = CompilePhase.BEFORE_MATCHING) // no constant folding
119141
public float notConstant(float x) {
120142
return x % 32.0f;
121143
}
122144

123145
@Test
124-
@IR(counts = {"frem", "2"}, phase = CompilePhase.BEFORE_MATCHING)
125-
@IR(counts = {IRNode.CON_F, "1"})
146+
@IR(counts = {IRNode.MOD_F, "2"},
147+
phase = CompilePhase.AFTER_PARSING)
148+
@IR(counts = {".*CallLeaf.*frem.*", "2"},
149+
phase = CompilePhase.BEFORE_MATCHING) // no constant folding
126150
public float veryNotConstant(float x, float y) {
127151
return x % 32.0f % y;
128152
}
129153

130154
@Test
131-
@IR(failOn = IRNode.MOD_F, phase = CompilePhase.ITER_GVN1)
132-
@IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.AFTER_PARSING)
155+
@IR(counts = {IRNode.MOD_F, "1"},
156+
phase = CompilePhase.AFTER_PARSING)
157+
@IR(counts = {IRNode.MOD_F, "0"},
158+
phase = CompilePhase.ITER_GVN1) // IGVN removes unused nodes
159+
@IR(counts = {".*CallLeaf.*frem.*", "0"},
160+
phase = CompilePhase.BEFORE_MATCHING)
133161
public void unusedResult(float x, float y) {
134162
float unused = x % y;
135163
}
136164

137165
@Test
138-
@IR(failOn = IRNode.MOD_F, phase = CompilePhase.ITER_GVN1)
139-
@IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.AFTER_PARSING)
166+
@IR(counts = {IRNode.MOD_F, "1"},
167+
phase = CompilePhase.AFTER_PARSING)
168+
@IR(counts = {IRNode.MOD_F, "0"},
169+
phase = CompilePhase.ITER_GVN1) // IGVN removes unused nodes
170+
@IR(counts = {".*CallLeaf.*frem.*", "0"},
171+
phase = CompilePhase.BEFORE_MATCHING)
140172
public void repeatedlyUnused(float x, float y) {
141173
float unused = 1.f;
142174
for (int i = 0; i < 100_000; i++) {
@@ -149,8 +181,14 @@ public void repeatedlyUnused(float x, float y) {
149181
// and thus a different execution path. In unusedResultAfterLoopOpt1 the modulo is
150182
// used in the traps of the parse predicates. In unusedResultAfterLoopOpt2, it is not.
151183
@Test
152-
@IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.ITER_GVN2)
153-
@IR(failOn = IRNode.MOD_F, phase = CompilePhase.BEFORE_MACRO_EXPANSION)
184+
@IR(counts = {IRNode.MOD_F, "1"},
185+
phase = CompilePhase.AFTER_PARSING)
186+
@IR(counts = {IRNode.MOD_F, "1"},
187+
phase = CompilePhase.ITER_GVN2)
188+
@IR(counts = {IRNode.MOD_F, "0"},
189+
phase = CompilePhase.BEFORE_MACRO_EXPANSION)
190+
@IR(counts = {".*CallLeaf.*frem.*", "0"},
191+
phase = CompilePhase.BEFORE_MATCHING)
154192
public float unusedResultAfterLoopOpt1(float x, float y) {
155193
float unused = x % y;
156194

@@ -168,8 +206,14 @@ public float unusedResultAfterLoopOpt1(float x, float y) {
168206
}
169207

170208
@Test
171-
@IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.AFTER_CLOOPS)
172-
@IR(failOn = IRNode.MOD_F, phase = CompilePhase.PHASEIDEALLOOP1)
209+
@IR(counts = {IRNode.MOD_F, "1"},
210+
phase = CompilePhase.AFTER_PARSING)
211+
@IR(counts = {IRNode.MOD_F, "1"},
212+
phase = CompilePhase.AFTER_CLOOPS)
213+
@IR(counts = {IRNode.MOD_F, "0"},
214+
phase = CompilePhase.PHASEIDEALLOOP1)
215+
@IR(counts = {".*CallLeaf.*frem.*", "0"},
216+
phase = CompilePhase.BEFORE_MATCHING)
173217
public float unusedResultAfterLoopOpt2(float x, float y) {
174218
int a = 77;
175219
int b = 0;
@@ -187,8 +231,14 @@ public float unusedResultAfterLoopOpt2(float x, float y) {
187231
}
188232

189233
@Test
190-
@IR(counts = {IRNode.MOD_F, "2"}, phase = CompilePhase.AFTER_CLOOPS)
191-
@IR(failOn = IRNode.MOD_F, phase = CompilePhase.PHASEIDEALLOOP1)
234+
@IR(counts = {IRNode.MOD_F, "3"},
235+
phase = CompilePhase.AFTER_PARSING)
236+
@IR(counts = {IRNode.MOD_F, "2"},
237+
phase = CompilePhase.AFTER_CLOOPS) // drop the useless one
238+
@IR(counts = {IRNode.MOD_F, "0"},
239+
phase = CompilePhase.PHASEIDEALLOOP1) // drop the rest
240+
@IR(counts = {".*CallLeaf.*frem.*", "0"},
241+
phase = CompilePhase.BEFORE_MATCHING)
192242
public float unusedResultAfterLoopOpt3(float x, float y) {
193243
float unused = x % y;
194244

test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -690,16 +690,6 @@ public class IRNode {
690690
beforeMatchingNameRegex(CON_L, "ConL");
691691
}
692692

693-
public static final String CON_D = PREFIX + "CON_D" + POSTFIX;
694-
static {
695-
beforeMatchingNameRegex(CON_D, "ConD");
696-
}
697-
698-
public static final String CON_F = PREFIX + "CON_F" + POSTFIX;
699-
static {
700-
beforeMatchingNameRegex(CON_F, "ConF");
701-
}
702-
703693
public static final String COUNTED_LOOP = PREFIX + "COUNTED_LOOP" + POSTFIX;
704694
static {
705695
String regex = START + "CountedLoop\\b" + MID + END;

0 commit comments

Comments
 (0)