@@ -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
0 commit comments