comparison src/share/vm/opto/compile.cpp @ 368:36ccc817fca4

6747051: Improve code and implicit null check generation for compressed oops Summary: Push DecodeN node below the Null check to the non-null path to use the mach node without 0 test. Reviewed-by: rasbold, never
author kvn
date Tue, 23 Sep 2008 12:29:06 -0700
parents 194b8e3a2fc4
children f4fe12e429a4
comparison
equal deleted inserted replaced
367:194b8e3a2fc4 368:36ccc817fca4
2073 #endif 2073 #endif
2074 break; 2074 break;
2075 } 2075 }
2076 2076
2077 #ifdef _LP64 2077 #ifdef _LP64
2078 case Op_CastPP:
2079 if (n->in(1)->is_DecodeN() && UseImplicitNullCheckForNarrowOop) {
2080 Compile* C = Compile::current();
2081 Node* in1 = n->in(1);
2082 const Type* t = n->bottom_type();
2083 Node* new_in1 = in1->clone();
2084 new_in1->as_DecodeN()->set_type(t);
2085
2086 if (!Matcher::clone_shift_expressions) {
2087 //
2088 // x86, ARM and friends can handle 2 adds in addressing mode
2089 // and Matcher can fold a DecodeN node into address by using
2090 // a narrow oop directly and do implicit NULL check in address:
2091 //
2092 // [R12 + narrow_oop_reg<<3 + offset]
2093 // NullCheck narrow_oop_reg
2094 //
2095 // On other platforms (Sparc) we have to keep new DecodeN node and
2096 // use it to do implicit NULL check in address:
2097 //
2098 // decode_not_null narrow_oop_reg, base_reg
2099 // [base_reg + offset]
2100 // NullCheck base_reg
2101 //
2102 // Pin the new DecodeN node to non-null path on these patforms (Sparc)
2103 // to keep the information to which NULL check the new DecodeN node
2104 // corresponds to use it as value in implicit_null_check().
2105 //
2106 new_in1->set_req(0, n->in(0));
2107 }
2108
2109 n->subsume_by(new_in1);
2110 if (in1->outcnt() == 0) {
2111 in1->disconnect_inputs(NULL);
2112 }
2113 }
2114 break;
2115
2078 case Op_CmpP: 2116 case Op_CmpP:
2079 // Do this transformation here to preserve CmpPNode::sub() and 2117 // Do this transformation here to preserve CmpPNode::sub() and
2080 // other TypePtr related Ideal optimizations (for example, ptr nullness). 2118 // other TypePtr related Ideal optimizations (for example, ptr nullness).
2081 if (n->in(1)->is_DecodeN() || n->in(2)->is_DecodeN()) { 2119 if (n->in(1)->is_DecodeN() || n->in(2)->is_DecodeN()) {
2082 Node* in1 = n->in(1); 2120 Node* in1 = n->in(1);
2092 if (in2->is_DecodeN()) { 2130 if (in2->is_DecodeN()) {
2093 new_in2 = in2->in(1); 2131 new_in2 = in2->in(1);
2094 } else if (in2->Opcode() == Op_ConP) { 2132 } else if (in2->Opcode() == Op_ConP) {
2095 const Type* t = in2->bottom_type(); 2133 const Type* t = in2->bottom_type();
2096 if (t == TypePtr::NULL_PTR && UseImplicitNullCheckForNarrowOop) { 2134 if (t == TypePtr::NULL_PTR && UseImplicitNullCheckForNarrowOop) {
2097 if (Matcher::clone_shift_expressions) { 2135 new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR);
2098 // x86, ARM and friends can handle 2 adds in addressing mode. 2136 //
2099 // Decode a narrow oop and do implicit NULL check in address 2137 // This transformation together with CastPP transformation above
2100 // [R12 + narrow_oop_reg<<3 + offset] 2138 // will generated code for implicit NULL checks for compressed oops.
2101 new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR); 2139 //
2102 } else { 2140 // The original code after Optimize()
2103 // Don't replace CmpP(o ,null) if 'o' is used in AddP 2141 //
2104 // to generate implicit NULL check on Sparc where 2142 // LoadN memory, narrow_oop_reg
2105 // narrow oops can't be used in address. 2143 // decode narrow_oop_reg, base_reg
2106 uint i = 0; 2144 // CmpP base_reg, NULL
2107 for (; i < in1->outcnt(); i++) { 2145 // CastPP base_reg // NotNull
2108 if (in1->raw_out(i)->is_AddP()) 2146 // Load [base_reg + offset], val_reg
2109 break; 2147 //
2110 } 2148 // after these transformations will be
2111 if (i >= in1->outcnt()) { 2149 //
2112 new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR); 2150 // LoadN memory, narrow_oop_reg
2113 } 2151 // CmpN narrow_oop_reg, NULL
2114 } 2152 // decode_not_null narrow_oop_reg, base_reg
2153 // Load [base_reg + offset], val_reg
2154 //
2155 // and the uncommon path (== NULL) will use narrow_oop_reg directly
2156 // since narrow oops can be used in debug info now (see the code in
2157 // final_graph_reshaping_walk()).
2158 //
2159 // At the end the code will be matched to
2160 // on x86:
2161 //
2162 // Load_narrow_oop memory, narrow_oop_reg
2163 // Load [R12 + narrow_oop_reg<<3 + offset], val_reg
2164 // NullCheck narrow_oop_reg
2165 //
2166 // and on sparc:
2167 //
2168 // Load_narrow_oop memory, narrow_oop_reg
2169 // decode_not_null narrow_oop_reg, base_reg
2170 // Load [base_reg + offset], val_reg
2171 // NullCheck base_reg
2172 //
2115 } else if (t->isa_oopptr()) { 2173 } else if (t->isa_oopptr()) {
2116 new_in2 = ConNode::make(C, t->make_narrowoop()); 2174 new_in2 = ConNode::make(C, t->make_narrowoop());
2117 } 2175 }
2118 } 2176 }
2119 if (new_in2 != NULL) { 2177 if (new_in2 != NULL) {
2126 in2->disconnect_inputs(NULL); 2184 in2->disconnect_inputs(NULL);
2127 } 2185 }
2128 } 2186 }
2129 } 2187 }
2130 break; 2188 break;
2189
2190 case Op_DecodeN:
2191 assert(!n->in(1)->is_EncodeP(), "should be optimized out");
2192 break;
2193
2194 case Op_EncodeP: {
2195 Node* in1 = n->in(1);
2196 if (in1->is_DecodeN()) {
2197 n->subsume_by(in1->in(1));
2198 } else if (in1->Opcode() == Op_ConP) {
2199 Compile* C = Compile::current();
2200 const Type* t = in1->bottom_type();
2201 if (t == TypePtr::NULL_PTR) {
2202 n->subsume_by(ConNode::make(C, TypeNarrowOop::NULL_PTR));
2203 } else if (t->isa_oopptr()) {
2204 n->subsume_by(ConNode::make(C, t->make_narrowoop()));
2205 }
2206 }
2207 if (in1->outcnt() == 0) {
2208 in1->disconnect_inputs(NULL);
2209 }
2210 break;
2211 }
2212
2213 case Op_Phi:
2214 if (n->as_Phi()->bottom_type()->isa_narrowoop()) {
2215 // The EncodeP optimization may create Phi with the same edges
2216 // for all paths. It is not handled well by Register Allocator.
2217 Node* unique_in = n->in(1);
2218 assert(unique_in != NULL, "");
2219 uint cnt = n->req();
2220 for (uint i = 2; i < cnt; i++) {
2221 Node* m = n->in(i);
2222 assert(m != NULL, "");
2223 if (unique_in != m)
2224 unique_in = NULL;
2225 }
2226 if (unique_in != NULL) {
2227 n->subsume_by(unique_in);
2228 }
2229 }
2230 break;
2231
2131 #endif 2232 #endif
2132 2233
2133 case Op_ModI: 2234 case Op_ModI:
2134 if (UseDivMod) { 2235 if (UseDivMod) {
2135 // Check if a%b and a/b both exist 2236 // Check if a%b and a/b both exist