< prev index next >

src/cpu/aarch64/vm/aarch64.ad

Print this page
rev 8068 : fix volatile reads and writes on AArch64


 776   }
 777 };
 778 
 779 class HandlerImpl {
 780 
 781  public:
 782 
 783   static int emit_exception_handler(CodeBuffer &cbuf);
 784   static int emit_deopt_handler(CodeBuffer& cbuf);
 785 
 786   static uint size_exception_handler() {
 787     return MacroAssembler::far_branch_size();
 788   }
 789 
 790   static uint size_deopt_handler() {
 791     // count one adr and one far branch instruction
 792     return 4 * NativeInstruction::instruction_size;
 793   }
 794 };
 795 
 796   bool preceded_by_ordered_load(const Node *barrier);













 797 
 798   // Use barrier instructions rather than load acquire / store
 799   // release.
 800   const bool UseBarriersForVolatile = true;



 801 %}
 802 
 803 source %{
 804 
 805   // AArch64 has load acquire and store release instructions which we
 806   // use for ordered memory accesses, e.g. for volatiles.  The ideal
 807   // graph generator also inserts memory barriers around volatile
 808   // accesses, and we don't want to generate both barriers and acq/rel
 809   // instructions.  So, when we emit a MemBarAcquire we look back in
 810   // the ideal graph for an ordered load and only emit the barrier if
 811   // we don't find one.









































































































































 812 
 813 bool preceded_by_ordered_load(const Node *barrier) {
 814   Node *x = barrier->lookup(TypeFunc::Parms);
















 815 
 816   if (! x)


































































 817     return false;
 818 






























 819   if (x->is_DecodeNarrowPtr())
 820     x = x->in(1);
 821 
 822   if (x->is_Load())
 823     return ! x->as_Load()->is_unordered();







































































































































































































































































































































































































































































































































 824 




 825   return false;




 826 }
 827 


 828 #define __ _masm.
 829 
 830 // advance declarations for helper functions to convert register
 831 // indices to register objects
 832 
 833 // the ad file has to provide implementations of certain methods
 834 // expected by the generic code
 835 //
 836 // REQUIRED FUNCTIONALITY
 837 
 838 //=============================================================================
 839 
 840 // !!!!! Special hack to get all types of calls to specify the byte offset
 841 //       from the start of the call to the point where the return address
 842 //       will point.
 843 
 844 int MachCallStaticJavaNode::ret_addr_offset()
 845 {
 846   // call should be a simple bl
 847   // unless this is a method handle invoke in which case it is


5134 //               by referring to it with a '$' prefix.
5135 // opcode     -- Three instruction opcodes may be provided.  These are referred
5136 //               to within an encode class as $primary, $secondary, and $tertiary
5137 //               rrspectively.  The primary opcode is commonly used to
5138 //               indicate the type of machine instruction, while secondary
5139 //               and tertiary are often used for prefix options or addressing
5140 //               modes.
5141 // ins_encode -- A list of encode classes with parameters. The encode class
5142 //               name must have been defined in an 'enc_class' specification
5143 //               in the encode section of the architecture description.
5144 
5145 // ============================================================================
5146 // Memory (Load/Store) Instructions
5147 
5148 // Load Instructions
5149 
5150 // Load Byte (8 bit signed)
5151 instruct loadB(iRegINoSp dst, memory mem)
5152 %{
5153   match(Set dst (LoadB mem));
5154   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5155 
5156   ins_cost(4 * INSN_COST);
5157   format %{ "ldrsbw  $dst, $mem\t# byte" %}
5158 
5159   ins_encode(aarch64_enc_ldrsbw(dst, mem));
5160 
5161   ins_pipe(iload_reg_mem);
5162 %}
5163 
5164 // Load Byte (8 bit signed) into long
5165 instruct loadB2L(iRegLNoSp dst, memory mem)
5166 %{
5167   match(Set dst (ConvI2L (LoadB mem)));
5168   predicate(UseBarriersForVolatile || n->in(1)->as_Load()->is_unordered());
5169 
5170   ins_cost(4 * INSN_COST);
5171   format %{ "ldrsb  $dst, $mem\t# byte" %}
5172 
5173   ins_encode(aarch64_enc_ldrsb(dst, mem));
5174 
5175   ins_pipe(iload_reg_mem);
5176 %}
5177 
5178 // Load Byte (8 bit unsigned)
5179 instruct loadUB(iRegINoSp dst, memory mem)
5180 %{
5181   match(Set dst (LoadUB mem));
5182   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5183 
5184   ins_cost(4 * INSN_COST);
5185   format %{ "ldrbw  $dst, $mem\t# byte" %}
5186 
5187   ins_encode(aarch64_enc_ldrb(dst, mem));
5188 
5189   ins_pipe(iload_reg_mem);
5190 %}
5191 
5192 // Load Byte (8 bit unsigned) into long
5193 instruct loadUB2L(iRegLNoSp dst, memory mem)
5194 %{
5195   match(Set dst (ConvI2L (LoadUB mem)));
5196   predicate(UseBarriersForVolatile || n->in(1)->as_Load()->is_unordered());
5197 
5198   ins_cost(4 * INSN_COST);
5199   format %{ "ldrb  $dst, $mem\t# byte" %}
5200 
5201   ins_encode(aarch64_enc_ldrb(dst, mem));
5202 
5203   ins_pipe(iload_reg_mem);
5204 %}
5205 
5206 // Load Short (16 bit signed)
5207 instruct loadS(iRegINoSp dst, memory mem)
5208 %{
5209   match(Set dst (LoadS mem));
5210   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5211 
5212   ins_cost(4 * INSN_COST);
5213   format %{ "ldrshw  $dst, $mem\t# short" %}
5214 
5215   ins_encode(aarch64_enc_ldrshw(dst, mem));
5216 
5217   ins_pipe(iload_reg_mem);
5218 %}
5219 
5220 // Load Short (16 bit signed) into long
5221 instruct loadS2L(iRegLNoSp dst, memory mem)
5222 %{
5223   match(Set dst (ConvI2L (LoadS mem)));
5224   predicate(UseBarriersForVolatile || n->in(1)->as_Load()->is_unordered());
5225 
5226   ins_cost(4 * INSN_COST);
5227   format %{ "ldrsh  $dst, $mem\t# short" %}
5228 
5229   ins_encode(aarch64_enc_ldrsh(dst, mem));
5230 
5231   ins_pipe(iload_reg_mem);
5232 %}
5233 
5234 // Load Char (16 bit unsigned)
5235 instruct loadUS(iRegINoSp dst, memory mem)
5236 %{
5237   match(Set dst (LoadUS mem));
5238   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5239 
5240   ins_cost(4 * INSN_COST);
5241   format %{ "ldrh  $dst, $mem\t# short" %}
5242 
5243   ins_encode(aarch64_enc_ldrh(dst, mem));
5244 
5245   ins_pipe(iload_reg_mem);
5246 %}
5247 
5248 // Load Short/Char (16 bit unsigned) into long
5249 instruct loadUS2L(iRegLNoSp dst, memory mem)
5250 %{
5251   match(Set dst (ConvI2L (LoadUS mem)));
5252   predicate(UseBarriersForVolatile || n->in(1)->as_Load()->is_unordered());
5253 
5254   ins_cost(4 * INSN_COST);
5255   format %{ "ldrh  $dst, $mem\t# short" %}
5256 
5257   ins_encode(aarch64_enc_ldrh(dst, mem));
5258 
5259   ins_pipe(iload_reg_mem);
5260 %}
5261 
5262 // Load Integer (32 bit signed)
5263 instruct loadI(iRegINoSp dst, memory mem)
5264 %{
5265   match(Set dst (LoadI mem));
5266   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5267 
5268   ins_cost(4 * INSN_COST);
5269   format %{ "ldrw  $dst, $mem\t# int" %}
5270 
5271   ins_encode(aarch64_enc_ldrw(dst, mem));
5272 
5273   ins_pipe(iload_reg_mem);
5274 %}
5275 
5276 // Load Integer (32 bit signed) into long
5277 instruct loadI2L(iRegLNoSp dst, memory mem)
5278 %{
5279   match(Set dst (ConvI2L (LoadI mem)));
5280   predicate(UseBarriersForVolatile || n->in(1)->as_Load()->is_unordered());
5281 
5282   ins_cost(4 * INSN_COST);
5283   format %{ "ldrsw  $dst, $mem\t# int" %}
5284 
5285   ins_encode(aarch64_enc_ldrsw(dst, mem));
5286 
5287   ins_pipe(iload_reg_mem);
5288 %}
5289 
5290 // Load Integer (32 bit unsigned) into long
5291 instruct loadUI2L(iRegLNoSp dst, memory mem, immL_32bits mask)
5292 %{
5293   match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
5294   predicate(UseBarriersForVolatile || n->in(1)->in(1)->as_Load()->is_unordered());
5295 
5296   ins_cost(4 * INSN_COST);
5297   format %{ "ldrw  $dst, $mem\t# int" %}
5298 
5299   ins_encode(aarch64_enc_ldrw(dst, mem));
5300 
5301   ins_pipe(iload_reg_mem);
5302 %}
5303 
5304 // Load Long (64 bit signed)
5305 instruct loadL(iRegLNoSp dst, memory mem)
5306 %{
5307   match(Set dst (LoadL mem));
5308   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5309 
5310   ins_cost(4 * INSN_COST);
5311   format %{ "ldr  $dst, $mem\t# int" %}
5312 
5313   ins_encode(aarch64_enc_ldr(dst, mem));
5314 
5315   ins_pipe(iload_reg_mem);
5316 %}
5317 
5318 // Load Range
5319 instruct loadRange(iRegINoSp dst, memory mem)
5320 %{
5321   match(Set dst (LoadRange mem));
5322 
5323   ins_cost(4 * INSN_COST);
5324   format %{ "ldrw  $dst, $mem\t# range" %}
5325 
5326   ins_encode(aarch64_enc_ldrw(dst, mem));
5327 
5328   ins_pipe(iload_reg_mem);
5329 %}
5330 
5331 // Load Pointer
5332 instruct loadP(iRegPNoSp dst, memory mem)
5333 %{
5334   match(Set dst (LoadP mem));
5335   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5336 
5337   ins_cost(4 * INSN_COST);
5338   format %{ "ldr  $dst, $mem\t# ptr" %}
5339 
5340   ins_encode(aarch64_enc_ldr(dst, mem));
5341 
5342   ins_pipe(iload_reg_mem);
5343 %}
5344 
5345 // Load Compressed Pointer
5346 instruct loadN(iRegNNoSp dst, memory mem)
5347 %{
5348   match(Set dst (LoadN mem));
5349   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5350 
5351   ins_cost(4 * INSN_COST);
5352   format %{ "ldrw  $dst, $mem\t# compressed ptr" %}
5353 
5354   ins_encode(aarch64_enc_ldrw(dst, mem));
5355 
5356   ins_pipe(iload_reg_mem);
5357 %}
5358 
5359 // Load Klass Pointer
5360 instruct loadKlass(iRegPNoSp dst, memory mem)
5361 %{
5362   match(Set dst (LoadKlass mem));
5363   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5364 
5365   ins_cost(4 * INSN_COST);
5366   format %{ "ldr  $dst, $mem\t# class" %}
5367 
5368   ins_encode(aarch64_enc_ldr(dst, mem));
5369 
5370   ins_pipe(iload_reg_mem);
5371 %}
5372 
5373 // Load Narrow Klass Pointer
5374 instruct loadNKlass(iRegNNoSp dst, memory mem)
5375 %{
5376   match(Set dst (LoadNKlass mem));
5377   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5378 
5379   ins_cost(4 * INSN_COST);
5380   format %{ "ldrw  $dst, $mem\t# compressed class ptr" %}
5381 
5382   ins_encode(aarch64_enc_ldrw(dst, mem));
5383 
5384   ins_pipe(iload_reg_mem);
5385 %}
5386 
5387 // Load Float
5388 instruct loadF(vRegF dst, memory mem)
5389 %{
5390   match(Set dst (LoadF mem));
5391   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5392 
5393   ins_cost(4 * INSN_COST);
5394   format %{ "ldrs  $dst, $mem\t# float" %}
5395 
5396   ins_encode( aarch64_enc_ldrs(dst, mem) );
5397 
5398   ins_pipe(pipe_class_memory);
5399 %}
5400 
5401 // Load Double
5402 instruct loadD(vRegD dst, memory mem)
5403 %{
5404   match(Set dst (LoadD mem));
5405   predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5406 
5407   ins_cost(4 * INSN_COST);
5408   format %{ "ldrd  $dst, $mem\t# double" %}
5409 
5410   ins_encode( aarch64_enc_ldrd(dst, mem) );
5411 
5412   ins_pipe(pipe_class_memory);
5413 %}
5414 
5415 
5416 // Load Int Constant
5417 instruct loadConI(iRegINoSp dst, immI src)
5418 %{
5419   match(Set dst src);
5420 
5421   ins_cost(INSN_COST);
5422   format %{ "mov $dst, $src\t# int" %}
5423 
5424   ins_encode( aarch64_enc_movw_imm(dst, src) );
5425 


5616 
5617 // Store Instructions
5618 
5619 // Store CMS card-mark Immediate
5620 instruct storeimmCM0(immI0 zero, memory mem)
5621 %{
5622   match(Set mem (StoreCM mem zero));
5623 
5624   ins_cost(INSN_COST);
5625   format %{ "strb zr, $mem\t# byte" %}
5626 
5627   ins_encode(aarch64_enc_strb0(mem));
5628 
5629   ins_pipe(istore_mem);
5630 %}
5631 
5632 // Store Byte
5633 instruct storeB(iRegIorL2I src, memory mem)
5634 %{
5635   match(Set mem (StoreB mem src));
5636   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5637 
5638   ins_cost(INSN_COST);
5639   format %{ "strb  $src, $mem\t# byte" %}
5640 
5641   ins_encode(aarch64_enc_strb(src, mem));
5642 
5643   ins_pipe(istore_reg_mem);
5644 %}
5645 
5646 
5647 instruct storeimmB0(immI0 zero, memory mem)
5648 %{
5649   match(Set mem (StoreB mem zero));
5650   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5651 
5652   ins_cost(INSN_COST);
5653   format %{ "strb zr, $mem\t# byte" %}
5654 
5655   ins_encode(aarch64_enc_strb0(mem));
5656 
5657   ins_pipe(istore_mem);
5658 %}
5659 
5660 // Store Char/Short
5661 instruct storeC(iRegIorL2I src, memory mem)
5662 %{
5663   match(Set mem (StoreC mem src));
5664   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5665 
5666   ins_cost(INSN_COST);
5667   format %{ "strh  $src, $mem\t# short" %}
5668 
5669   ins_encode(aarch64_enc_strh(src, mem));
5670 
5671   ins_pipe(istore_reg_mem);
5672 %}
5673 
5674 instruct storeimmC0(immI0 zero, memory mem)
5675 %{
5676   match(Set mem (StoreC mem zero));
5677   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5678 
5679   ins_cost(INSN_COST);
5680   format %{ "strh  zr, $mem\t# short" %}
5681 
5682   ins_encode(aarch64_enc_strh0(mem));
5683 
5684   ins_pipe(istore_mem);
5685 %}
5686 
5687 // Store Integer
5688 
5689 instruct storeI(iRegIorL2I src, memory mem)
5690 %{
5691   match(Set mem(StoreI mem src));
5692   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5693 
5694   ins_cost(INSN_COST);
5695   format %{ "strw  $src, $mem\t# int" %}
5696 
5697   ins_encode(aarch64_enc_strw(src, mem));
5698 
5699   ins_pipe(istore_reg_mem);
5700 %}
5701 
5702 instruct storeimmI0(immI0 zero, memory mem)
5703 %{
5704   match(Set mem(StoreI mem zero));
5705   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5706 
5707   ins_cost(INSN_COST);
5708   format %{ "strw  zr, $mem\t# int" %}
5709 
5710   ins_encode(aarch64_enc_strw0(mem));
5711 
5712   ins_pipe(istore_mem);
5713 %}
5714 
5715 // Store Long (64 bit signed)
5716 instruct storeL(iRegL src, memory mem)
5717 %{
5718   match(Set mem (StoreL mem src));
5719   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5720 
5721   ins_cost(INSN_COST);
5722   format %{ "str  $src, $mem\t# int" %}
5723 
5724   ins_encode(aarch64_enc_str(src, mem));
5725 
5726   ins_pipe(istore_reg_mem);
5727 %}
5728 
5729 // Store Long (64 bit signed)
5730 instruct storeimmL0(immL0 zero, memory mem)
5731 %{
5732   match(Set mem (StoreL mem zero));
5733   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5734 
5735   ins_cost(INSN_COST);
5736   format %{ "str  zr, $mem\t# int" %}
5737 
5738   ins_encode(aarch64_enc_str0(mem));
5739 
5740   ins_pipe(istore_mem);
5741 %}
5742 
5743 // Store Pointer
5744 instruct storeP(iRegP src, memory mem)
5745 %{
5746   match(Set mem (StoreP mem src));
5747   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5748 
5749   ins_cost(INSN_COST);
5750   format %{ "str  $src, $mem\t# ptr" %}
5751 
5752   ins_encode(aarch64_enc_str(src, mem));
5753 
5754   ins_pipe(istore_reg_mem);
5755 %}
5756 
5757 // Store Pointer
5758 instruct storeimmP0(immP0 zero, memory mem)
5759 %{
5760   match(Set mem (StoreP mem zero));
5761   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5762 
5763   ins_cost(INSN_COST);
5764   format %{ "str zr, $mem\t# ptr" %}
5765 
5766   ins_encode(aarch64_enc_str0(mem));
5767 
5768   ins_pipe(istore_mem);
5769 %}
5770 
5771 // Store Compressed Pointer
5772 instruct storeN(iRegN src, memory mem)
5773 %{
5774   match(Set mem (StoreN mem src));
5775   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5776 
5777   ins_cost(INSN_COST);
5778   format %{ "strw  $src, $mem\t# compressed ptr" %}
5779 
5780   ins_encode(aarch64_enc_strw(src, mem));
5781 
5782   ins_pipe(istore_reg_mem);
5783 %}
5784 
5785 instruct storeImmN0(iRegIHeapbase heapbase, immN0 zero, memory mem)
5786 %{
5787   match(Set mem (StoreN mem zero));
5788   predicate(Universe::narrow_oop_base() == NULL &&
5789             Universe::narrow_klass_base() == NULL &&
5790             (UseBarriersForVolatile || n->as_Store()->is_unordered()));
5791 
5792   ins_cost(INSN_COST);
5793   format %{ "strw  rheapbase, $mem\t# compressed ptr (rheapbase==0)" %}
5794 
5795   ins_encode(aarch64_enc_strw(heapbase, mem));
5796 
5797   ins_pipe(istore_reg_mem);
5798 %}
5799 
5800 // Store Float
5801 instruct storeF(vRegF src, memory mem)
5802 %{
5803   match(Set mem (StoreF mem src));
5804   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5805 
5806   ins_cost(INSN_COST);
5807   format %{ "strs  $src, $mem\t# float" %}
5808 
5809   ins_encode( aarch64_enc_strs(src, mem) );
5810 
5811   ins_pipe(pipe_class_memory);
5812 %}
5813 
5814 // TODO
5815 // implement storeImmF0 and storeFImmPacked
5816 
5817 // Store Double
5818 instruct storeD(vRegD src, memory mem)
5819 %{
5820   match(Set mem (StoreD mem src));
5821   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5822 
5823   ins_cost(INSN_COST);
5824   format %{ "strd  $src, $mem\t# double" %}
5825 
5826   ins_encode( aarch64_enc_strd(src, mem) );
5827 
5828   ins_pipe(pipe_class_memory);
5829 %}
5830 
5831 // Store Compressed Klass Pointer
5832 instruct storeNKlass(iRegN src, memory mem)
5833 %{
5834   predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5835   match(Set mem (StoreNKlass mem src));
5836 
5837   ins_cost(INSN_COST);
5838   format %{ "strw  $src, $mem\t# compressed klass ptr" %}
5839 
5840   ins_encode(aarch64_enc_strw(src, mem));
5841 
5842   ins_pipe(istore_reg_mem);
5843 %}
5844 
5845 // TODO
5846 // implement storeImmD0 and storeDImmPacked
5847 
5848 // prefetch instructions
5849 // Must be safe to execute with invalid address (cannot fault).
5850 
5851 instruct prefetchalloc( memory mem ) %{
5852   match(PrefetchAllocation mem);
5853 
5854   ins_cost(INSN_COST);


6276 
6277   ins_pipe(ialu_reg);
6278 %}
6279 
6280 // ============================================================================
6281 // MemBar Instruction
6282 
6283 instruct load_fence() %{
6284   match(LoadFence);
6285   ins_cost(VOLATILE_REF_COST);
6286 
6287   format %{ "load_fence" %}
6288 
6289   ins_encode %{
6290     __ membar(Assembler::LoadLoad|Assembler::LoadStore);
6291   %}
6292   ins_pipe(pipe_serial);
6293 %}
6294 
6295 instruct unnecessary_membar_acquire() %{
6296   predicate(! UseBarriersForVolatile && preceded_by_ordered_load(n));
6297   match(MemBarAcquire);
6298   ins_cost(0);
6299 
6300   format %{ "membar_acquire (elided)" %}
6301 
6302   ins_encode %{
6303     __ block_comment("membar_acquire (elided)");
6304   %}
6305 
6306   ins_pipe(pipe_class_empty);
6307 %}
6308 
6309 instruct membar_acquire() %{
6310   match(MemBarAcquire);
6311   ins_cost(VOLATILE_REF_COST);
6312 
6313   format %{ "membar_acquire" %}
6314 
6315   ins_encode %{
6316     __ membar(Assembler::LoadLoad|Assembler::LoadStore);


6328 
6329   ins_encode %{
6330     __ membar(Assembler::LoadLoad|Assembler::LoadStore);
6331   %}
6332 
6333   ins_pipe(pipe_serial);
6334 %}
6335 
6336 instruct store_fence() %{
6337   match(StoreFence);
6338   ins_cost(VOLATILE_REF_COST);
6339 
6340   format %{ "store_fence" %}
6341 
6342   ins_encode %{
6343     __ membar(Assembler::LoadStore|Assembler::StoreStore);
6344   %}
6345   ins_pipe(pipe_serial);
6346 %}
6347 













6348 instruct membar_release() %{
6349   match(MemBarRelease);
6350   ins_cost(VOLATILE_REF_COST);
6351 
6352   format %{ "membar_release" %}
6353 
6354   ins_encode %{
6355     __ membar(Assembler::LoadStore|Assembler::StoreStore);
6356   %}
6357   ins_pipe(pipe_serial);
6358 %}
6359 
6360 instruct membar_storestore() %{
6361   match(MemBarStoreStore);
6362   ins_cost(VOLATILE_REF_COST);
6363 
6364   format %{ "MEMBAR-store-store" %}
6365 
6366   ins_encode %{
6367     __ membar(Assembler::StoreStore);
6368   %}
6369   ins_pipe(pipe_serial);
6370 %}
6371 
6372 instruct membar_release_lock() %{
6373   match(MemBarReleaseLock);
6374   ins_cost(VOLATILE_REF_COST);
6375 
6376   format %{ "membar_release_lock" %}
6377 
6378   ins_encode %{
6379     __ membar(Assembler::LoadStore|Assembler::StoreStore);














6380   %}
6381 
6382   ins_pipe(pipe_serial);
6383 %}
6384 
6385 instruct membar_volatile() %{
6386   match(MemBarVolatile);
6387   ins_cost(VOLATILE_REF_COST*100);
6388 
6389   format %{ "membar_volatile" %}
6390 
6391   ins_encode %{
6392     __ membar(Assembler::StoreLoad);
6393   %}
6394 
6395   ins_pipe(pipe_serial);
6396 %}
6397 
6398 // ============================================================================
6399 // Cast/Convert Instructions




 776   }
 777 };
 778 
 779 class HandlerImpl {
 780 
 781  public:
 782 
 783   static int emit_exception_handler(CodeBuffer &cbuf);
 784   static int emit_deopt_handler(CodeBuffer& cbuf);
 785 
 786   static uint size_exception_handler() {
 787     return MacroAssembler::far_branch_size();
 788   }
 789 
 790   static uint size_deopt_handler() {
 791     // count one adr and one far branch instruction
 792     return 4 * NativeInstruction::instruction_size;
 793   }
 794 };
 795 
 796   // graph traversal helpers
 797   MemBarNode *has_parent_membar(const Node *n,
 798                                 ProjNode *&ctl, ProjNode *&mem);
 799   MemBarNode *has_child_membar(const MemBarNode *n,
 800                                ProjNode *&ctl, ProjNode *&mem);
 801 
 802   // predicates controlling emit of ldr<x>/ldar<x> and associated dmb
 803   bool unnecessary_acquire(const Node *barrier);
 804   bool needs_acquiring_load(const Node *load);
 805 
 806   // predicates controlling emit of str<x>/stlr<x> and associated dmbs
 807   bool unnecessary_release(const Node *barrier);
 808   bool unnecessary_volatile(const Node *barrier);
 809   bool needs_releasing_store(const Node *store);
 810 
 811   // Use barrier instructions rather than load acquire / store
 812   // release.
 813   const bool UseBarriersForVolatile = false;
 814   // Use barrier instructions for unsafe volatile gets rather than
 815   // trying to identify an exact signature for them
 816   const bool UseBarriersForUnsafeVolatileGet = false;
 817 %}
 818 
 819 source %{
 820 
 821   // AArch64 has ldar<x> and stlr<x> instructions which we can safely
 822   // use to implement volatile reads and writes. For a volatile read
 823   // we simply need
 824   //
 825   //   ldar<x>
 826   //
 827   // and for a volatile write we need
 828   //
 829   //   stlr<x>
 830   // 
 831   // Alternatively, we can implement them by pairing a normal
 832   // load/store with a memory barrier. For a volatile read we need
 833   // 
 834   //   ldr<x>
 835   //   dmb ishld
 836   //
 837   // for a volatile write
 838   //
 839   //   dmb ish
 840   //   str<x>
 841   //   dmb ish
 842   //
 843   // In order to generate the desired instruction sequence we need to
 844   // be able to identify specific 'signature' ideal graph node
 845   // sequences which i) occur as a translation of a volatile reads or
 846   // writes and ii) do not occur through any other translation or
 847   // graph transformation. We can then provide alternative aldc
 848   // matching rules which translate these node sequences to the
 849   // desired machine code sequences. Selection of the alternative
 850   // rules can be implemented by predicates which identify the
 851   // relevant node sequences.
 852   //
 853   // The ideal graph generator translates a volatile read to the node
 854   // sequence
 855   //
 856   //   LoadX[mo_acquire]
 857   //   MemBarAcquire
 858   //
 859   // As a special case when using the compressed oops optimization we
 860   // may also see this variant
 861   //
 862   //   LoadN[mo_acquire]
 863   //   DecodeN
 864   //   MemBarAcquire
 865   //
 866   // A volatile write is translated to the node sequence
 867   //
 868   //   MemBarRelease
 869   //   StoreX[mo_release]
 870   //   MemBarVolatile
 871   //
 872   // n.b. the above node patterns are generated with a strict
 873   // 'signature' configuration of input and output dependencies (see
 874   // the predicates below for exact details). The two signatures are
 875   // unique to translated volatile reads/stores -- they will not
 876   // appear as a result of any other bytecode translation or inlining
 877   // nor as a consequence of optimizing transforms.
 878   //
 879   // We also want to catch inlined unsafe volatile gets and puts and
 880   // be able to implement them using either ldar<x>/stlr<x> or some
 881   // combination of ldr<x>/stlr<x> and dmb instructions.
 882   //
 883   // Inlined unsafe volatiles puts manifest as a minor variant of the
 884   // normal volatile put node sequence containing an extra cpuorder
 885   // membar
 886   //
 887   //   MemBarRelease
 888   //   MemBarCPUOrder
 889   //   StoreX[mo_release]
 890   //   MemBarVolatile
 891   //
 892   // n.b. as an aside, the cpuorder membar is not itself subject to
 893   // matching and translation by adlc rules.  However, the rule
 894   // predicates need to detect its presence in order to correctly
 895   // select the desired adlc rules.
 896   //
 897   // Inlined unsafe volatiles gets manifest as a somewhat different
 898   // node sequence to a normal volatile get
 899   //
 900   //   MemBarCPUOrder
 901   //        ||       \\
 902   //   MemBarAcquire LoadX[mo_acquire]
 903   //        ||
 904   //   MemBarCPUOrder
 905   //
 906   // In this case the acquire membar does not directly depend on the
 907   // load. However, we can be sure that the load is generated from an
 908   // inlined unsafe volatile get if we see it dependent on this unique
 909   // sequence of membar nodes. Similarly, given an acquire membar we
 910   // can know that it was added because of an inlined unsafe volatile
 911   // get if it is fed and feeds a cpuorder membar and if its feed
 912   // membar also feeds an acquiring load.
 913   //
 914   // So, where we can identify these volatile read and write
 915   // signatures we can choose to plant either of the above two code
 916   // sequences. For a volatile read we can simply plant a normal
 917   // ldr<x> and translate the MemBarAcquire to a dmb. However, we can
 918   // also choose to inhibit translation of the MemBarAcquire and
 919   // inhibit planting of the ldr<x>, instead planting an ldar<x>.
 920   //
 921   // When we recognise a volatile store signature we can choose to
 922   // plant at a dmb ish as a translation for the MemBarRelease, a
 923   // normal str<x> and then a dmb ish for the MemBarVolatile.
 924   // Alternatively, we can inhibit translation of the MemBarRelease
 925   // and MemBarVolatile and instead plant a simple stlr<x>
 926   // instruction.
 927   //
 928   // Of course, the above only applies when we see these signature
 929   // configurations. We still want to plant dmb instructions in any
 930   // other cases where we may see a MemBarAcquire, MemBarRelease or
 931   // MemBarVolatile. For example, at the end of a constructor which
 932   // writes final/volatile fields we will see a MemBarRelease
 933   // instruction and this needs a 'dmb ish' lest we risk the
 934   // constructed object being visible without making the
 935   // final/volatile field writes visible.
 936   //
 937   // n.b. the translation rules below which rely on detection of the
 938   // volatile signatures and insert ldar<x> or stlr<x> are failsafe.
 939   // If we see anything other than the signature configurations we
 940   // always just translate the loads and stors to ldr<x> and str<x>
 941   // and translate acquire, release and volatile membars to the
 942   // relevant dmb instructions.
 943   //
 944   // n.b.b as a case in point for the above comment, the current
 945   // predicates don't detect the precise signature for certain types
 946   // of volatile object stores (where the heap_base input type is not
 947   // known at compile-time to be non-NULL). In those cases the
 948   // MemBarRelease and MemBarVolatile bracket an if-then-else sequence
 949   // with a store in each branch (we need a different store depending
 950   // on whether heap_base is actually NULL). In such a case we will
 951   // just plant a dmb both before and after the branch/merge. The
 952   // predicate could (and probably should) be fixed later to also
 953   // detect this case.
 954 
 955   // graph traversal helpers
 956 
 957   // if node n is linked to a parent MemBarNode by an intervening
 958   // Control or Memory ProjNode return the MemBarNode otherwise return
 959   // NULL.
 960   //
 961   // n may only be a Load or a MemBar.
 962   //
 963   // The ProjNode* references c and m are used to return the relevant
 964   // nodes.
 965 
 966   MemBarNode *has_parent_membar(const Node *n, ProjNode *&c, ProjNode *&m)
 967   {
 968     Node *ctl = NULL;
 969     Node *mem = NULL;
 970     Node *membar = NULL;
 971 
 972     if (n->is_Load()) {
 973       ctl = n->lookup(LoadNode::Control);
 974       mem = n->lookup(LoadNode::Memory);
 975     } else if (n->is_MemBar()) {
 976       ctl = n->lookup(TypeFunc::Control);
 977       mem = n->lookup(TypeFunc::Memory);
 978     } else {
 979         return NULL;
 980     }
 981 
 982     if (!ctl || !mem || !ctl->is_Proj() || !mem->is_Proj())
 983       return NULL;
 984 
 985     c = ctl->as_Proj();
 986 
 987     membar = ctl->lookup(0);
 988 
 989     if (!membar || !membar->is_MemBar())
 990       return NULL;
 991 
 992     m = mem->as_Proj();
 993 
 994     if (mem->lookup(0) != membar)
 995       return NULL;
 996 
 997     return membar->as_MemBar();
 998   }
 999 
1000   // if n is linked to a child MemBarNode by intervening Control and
1001   // Memory ProjNodes return the MemBarNode otherwise return NULL.
1002   //
1003   // The ProjNode** arguments c and m are used to return pointers to
1004   // the relevant nodes. A null argument means don't don't return a
1005   // value.
1006 
1007   MemBarNode *has_child_membar(const MemBarNode *n, ProjNode *&c, ProjNode *&m)
1008   {
1009     ProjNode *ctl = n->proj_out(TypeFunc::Control);
1010     ProjNode *mem = n->proj_out(TypeFunc::Memory);
1011 
1012     // MemBar needs to have both a Ctl and Mem projection
1013     if (! ctl || ! mem)
1014       return NULL;
1015 
1016     c = ctl;
1017     m = mem;
1018 
1019     MemBarNode *child = NULL;
1020     Node *x;
1021 
1022     for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
1023       x = ctl->fast_out(i);
1024       // if we see a membar we keep hold of it. we may also see a new
1025       // arena copy of the original but it will appear later
1026       if (x->is_MemBar()) {
1027           child = x->as_MemBar();
1028           break;
1029       }
1030     }
1031 
1032     if (child == NULL)
1033       return NULL;
1034 
1035     for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
1036       x = mem->fast_out(i);
1037       // if we see a membar we keep hold of it. we may also see a new
1038       // arena copy of the original but it will appear later
1039       if (x == child) {
1040         return child;
1041       }
1042     }
1043     return NULL;
1044   }
1045 
1046   // predicates controlling emit of ldr<x>/ldar<x> and associated dmb
1047 
1048 bool unnecessary_acquire(const Node *barrier) {
1049   // assert barrier->is_MemBar();
1050   if (UseBarriersForVolatile)
1051     // we need to plant a dmb
1052     return false;
1053 
1054   // a volatile read derived from bytecode (or also from an inlined
1055   // SHA field read via LibraryCallKit::load_field_from_object)
1056   // manifests as a LoadX[mo_acquire] followed by an acquire membar
1057   // with a bogus read dependency on it's preceding load. so in those
1058   // cases we will find the load node at the PARMS offset of the
1059   // acquire membar.  n.b. there may be an intervening DecodeN node.
1060   //
1061   // a volatile load derived from an inlined unsafe field access
1062   // manifests as a cpuorder membar with Ctl and Mem projections
1063   // feeding both an acquire membar and a LoadX[mo_acquire]. The
1064   // acquire then feeds another cpuorder membar via Ctl and Mem
1065   // projections. The load has no output dependency on these trailing
1066   // membars because subsequent nodes inserted into the graph take
1067   // their control feed from the final membar cpuorder meaning they
1068   // are all ordered after the load.
1069 
1070   Node *x = barrier->lookup(TypeFunc::Parms);
1071   if (x) {
1072     // we are starting from an acquire and it has a fake dependency
1073     //
1074     // need to check for
1075     //
1076     //   LoadX[mo_acquire]
1077     //   {  |1   }
1078     //   {DecodeN}
1079     //      |Parms
1080     //   MemBarAcquire*
1081     //
1082     // where * tags node we were passed
1083     // and |k means input k
1084     if (x->is_DecodeNarrowPtr())
1085       x = x->in(1);
1086 
1087     return (x->is_Load() && x->as_Load()->is_acquire());
1088   }
1089   
1090   // only continue if we want to try to match unsafe volatile gets
1091   if (UseBarriersForUnsafeVolatileGet)
1092     return false;
1093 
1094   // need to check for
1095   //
1096   //     MemBarCPUOrder
1097   //        ||       \\
1098   //   MemBarAcquire* LoadX[mo_acquire]
1099   //        ||
1100   //   MemBarCPUOrder
1101   //
1102   // where * tags node we were passed
1103   // and || or \\ are Ctl+Mem feeds via intermediate Proj Nodes
1104 
1105   // check for a parent MemBarCPUOrder
1106   ProjNode *ctl;
1107   ProjNode *mem;
1108   MemBarNode *parent = has_parent_membar(barrier, ctl, mem);
1109   if (!parent || parent->Opcode() != Op_MemBarCPUOrder)
1110     return false;
1111   // ensure the proj nodes both feed a LoadX[mo_acquire]
1112   LoadNode *ld = NULL;
1113   for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
1114     x = ctl->fast_out(i);
1115     // if we see a load we keep hold of it and stop searching
1116     if (x->is_Load()) {
1117       ld = x->as_Load();
1118       break;
1119     }
1120   }
1121   // it must be an acquiring load
1122   if (! ld || ! ld->is_acquire())
1123     return false;
1124   for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
1125     x = mem->fast_out(i);
1126     // if we see the same load we drop it and stop searching
1127     if (x == ld) {
1128       ld = NULL;
1129       break;
1130     }
1131   }
1132   // we must have dropped the load
1133   if (ld)
1134     return false;
1135   // check for a child cpuorder membar
1136   MemBarNode *child  = has_child_membar(barrier->as_MemBar(), ctl, mem);
1137   if (!child || child->Opcode() != Op_MemBarCPUOrder)
1138     return false;
1139 
1140   return true;
1141 }
1142 
1143 bool needs_acquiring_load(const Node *n)
1144 {
1145   // assert n->is_Load();
1146   if (UseBarriersForVolatile)
1147     // we use a normal load and a dmb
1148     return false;
1149 
1150   LoadNode *ld = n->as_Load();
1151 
1152   if (!ld->is_acquire())
1153     return false;
1154 
1155   // check if this load is feeding an acquire membar
1156   //
1157   //   LoadX[mo_acquire]
1158   //   {  |1   }
1159   //   {DecodeN}
1160   //      |Parms
1161   //   MemBarAcquire*
1162   //
1163   // where * tags node we were passed
1164   // and |k means input k
1165 
1166   Node *start = ld;
1167   Node *mbacq = NULL;
1168 
1169   // if we hit a DecodeNarrowPtr we reset the start node and restart
1170   // the search through the outputs
1171  restart:
1172 
1173   for (DUIterator_Fast imax, i = start->fast_outs(imax); i < imax; i++) {
1174     Node *x = start->fast_out(i);
1175     if (x->is_MemBar() && x->Opcode() == Op_MemBarAcquire) {
1176       mbacq = x;
1177     } else if (!mbacq &&
1178                (x->is_DecodeNarrowPtr() ||
1179                 (x->is_Mach() && x->Opcode() == Op_DecodeN))) {
1180       start = x;
1181       goto restart;
1182     }
1183   }
1184 
1185   if (mbacq) {
1186     return true;
1187   }
1188 
1189   // only continue if we want to try to match unsafe volatile gets
1190   if (UseBarriersForUnsafeVolatileGet)
1191     return false;
1192 
1193   // check if Ctl and Proj feed comes from a MemBarCPUOrder
1194   //
1195   //     MemBarCPUOrder
1196   //        ||       \\
1197   //   MemBarAcquire* LoadX[mo_acquire]
1198   //        ||
1199   //   MemBarCPUOrder
1200 
1201   MemBarNode *membar;
1202   ProjNode *ctl;
1203   ProjNode *mem;
1204 
1205   membar = has_parent_membar(ld, ctl, mem);
1206 
1207   if (!membar || !membar->Opcode() == Op_MemBarCPUOrder)
1208     return false;
1209 
1210   // ensure that there is a CPUOrder->Acquire->CPUOrder membar chain
1211 
1212   membar = has_child_membar(membar, ctl, mem);
1213 
1214   if (!membar || !membar->Opcode() == Op_MemBarAcquire)
1215     return false;
1216 
1217   membar = has_child_membar(membar, ctl, mem);
1218   
1219   if (!membar || !membar->Opcode() == Op_MemBarCPUOrder)
1220     return false;
1221 
1222   return true;
1223 }
1224 
1225 bool unnecessary_release(const Node *n) {
1226   // assert n->is_MemBar();
1227   if (UseBarriersForVolatile)
1228     // we need to plant a dmb
1229     return false;
1230 
1231   // ok, so we can omit this release barrier if it has been inserted
1232   // as part of a volatile store sequence
1233   //
1234   //   MemBarRelease
1235   //  {      ||      }
1236   //  {MemBarCPUOrder} -- optional
1237   //         ||     \\
1238   //         ||     StoreX[mo_release]
1239   //         | \     /
1240   //         | MergeMem
1241   //         | /
1242   //   MemBarVolatile
1243   //
1244   // where
1245   //  || and \\ represent Ctl and Mem feeds via Proj nodes
1246   //  | \ and / indicate further routing of the Ctl and Mem feeds
1247   // 
1248   // so we need to check that
1249   //
1250   // ia) the release membar (or its dependent cpuorder membar) feeds
1251   // control to a store node (via a Control project node)
1252   //
1253   // ii) the store is ordered release
1254   //
1255   // iii) the release membar (or its dependent cpuorder membar) feeds
1256   // control to a volatile membar (via the same Control project node)
1257   //
1258   // iv) the release membar feeds memory to a merge mem and to the
1259   // same store (both via a single Memory proj node)
1260   //
1261   // v) the store outputs to the merge mem
1262   //
1263   // vi) the merge mem outputs to the same volatile membar
1264   //
1265   // n.b. if this is an inlined unsafe node then the release membar
1266   // may feed its control and memory links via an intervening cpuorder
1267   // membar. this case can be dealt with when we check the release
1268   // membar projections. if they both feed a single cpuorder membar
1269   // node continue to make the same checks as above but with the
1270   // cpuorder membar substituted for the release membar. if they don't
1271   // both feed a cpuorder membar then the check fails.
1272   //
1273   // n.b.b. for an inlined unsafe store of an object in the case where
1274   // !TypePtr::NULL_PTR->higher_equal(type(heap_base_oop)) we may see
1275   // an embedded if then else where we expect the store. this is
1276   // needed to do the right type of store depending on whether
1277   // heap_base is NULL. We could check for that but for now we can
1278   // just take the hit of on inserting a redundant dmb for this
1279   // redundant volatile membar
1280 
1281   MemBarNode *barrier = n->as_MemBar();
1282   ProjNode *ctl;
1283   ProjNode *mem;
1284   // check for an intervening cpuorder membar
1285   MemBarNode *b = has_child_membar(barrier, ctl, mem);
1286   if (b && b->Opcode() == Op_MemBarCPUOrder) {
1287     // ok, so start form the dependent cpuorder barrier
1288     barrier = b;
1289   }
1290   // check the ctl and mem flow
1291   ctl = barrier->proj_out(TypeFunc::Control);
1292   mem = barrier->proj_out(TypeFunc::Memory);
1293 
1294   // the barrier needs to have both a Ctl and Mem projection
1295   if (! ctl || ! mem)
1296     return false;
1297 
1298   Node *x = NULL;
1299   Node *mbvol = NULL;
1300   StoreNode * st = NULL;
1301 
1302   // For a normal volatile write the Ctl ProjNode should have output
1303   // to a MemBarVolatile and a Store marked as releasing
1304   //
1305   // n.b. for an inlined unsafe store of an object in the case where
1306   // !TypePtr::NULL_PTR->higher_equal(type(heap_base_oop)) we may see
1307   // an embedded if then else where we expect the store. this is
1308   // needed to do the right type of store depending on whether
1309   // heap_base is NULL. We could check for that case too but for now
1310   // we can just take the hit of inserting a dmb and a non-volatile
1311   // store to implement the volatile store
1312 
1313   for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
1314     x = ctl->fast_out(i);
1315     if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
1316       if (mbvol) {
1317         return false;
1318       }
1319       mbvol = x;
1320     } else if (x->is_Store()) {
1321       st = x->as_Store();
1322       if (! st->is_release()) {
1323         return false;
1324       }
1325     } else if (!x->is_Mach()) {
1326       // we may see mach nodes added during matching but nothing else
1327       return false;
1328     }
1329   }
1330 
1331   if (!mbvol || !st)
1332     return false;
1333 
1334   // the Mem ProjNode should output to a MergeMem and the same Store
1335   Node *mm = NULL;
1336   for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
1337     x = mem->fast_out(i);
1338     if (!mm && x->is_MergeMem()) {
1339       mm = x;
1340     } else if (x != st && !x->is_Mach()) {
1341       // we may see mach nodes added during matching but nothing else
1342       return false;
1343     }
1344   }
1345 
1346   if (!mm)
1347     return false;
1348 
1349   // the MergeMem should output to the MemBarVolatile
1350   for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
1351     x = mm->fast_out(i);
1352     if (x != mbvol && !x->is_Mach()) {
1353       // we may see mach nodes added during matching but nothing else
1354       return false;
1355     }
1356   }
1357 
1358   return true;
1359 }
1360 
1361 bool unnecessary_volatile(const Node *n) {
1362   // assert n->is_MemBar();
1363   if (UseBarriersForVolatile)
1364     // we need to plant a dmb
1365     return false;
1366 
1367   // ok, so we can omit this volatile barrier if it has been inserted
1368   // as part of a volatile store sequence
1369   //
1370   //   MemBarRelease
1371   //  {      ||      }
1372   //  {MemBarCPUOrder} -- optional
1373   //         ||     \\
1374   //         ||     StoreX[mo_release]
1375   //         | \     /
1376   //         | MergeMem
1377   //         | /
1378   //   MemBarVolatile
1379   //
1380   // where
1381   //  || and \\ represent Ctl and Mem feeds via Proj nodes
1382   //  | \ and / indicate further routing of the Ctl and Mem feeds
1383   // 
1384   // we need to check that
1385   //
1386   // i) the volatile membar gets its control feed from a release
1387   // membar (or its dependent cpuorder membar) via a Control project
1388   // node
1389   //
1390   // ii) the release membar (or its dependent cpuorder membar) also
1391   // feeds control to a store node via the same proj node
1392   //
1393   // iii) the store is ordered release
1394   //
1395   // iv) the release membar (or its dependent cpuorder membar) feeds
1396   // memory to a merge mem and to the same store (both via a single
1397   // Memory proj node)
1398   //
1399   // v) the store outputs to the merge mem
1400   //
1401   // vi) the merge mem outputs to the volatile membar
1402   //
1403   // n.b. for an inlined unsafe store of an object in the case where
1404   // !TypePtr::NULL_PTR->higher_equal(type(heap_base_oop)) we may see
1405   // an embedded if then else where we expect the store. this is
1406   // needed to do the right type of store depending on whether
1407   // heap_base is NULL. We could check for that but for now we can
1408   // just take the hit of on inserting a redundant dmb for this
1409   // redundant volatile membar
1410 
1411   MemBarNode *mbvol = n->as_MemBar();
1412   Node *x = n->lookup(TypeFunc::Control);
1413 
1414   if (! x || !x->is_Proj())
1415     return false;
1416 
1417   ProjNode *proj = x->as_Proj();
1418 
1419   x = proj->lookup(0);
1420 
1421   if (!x || !x->is_MemBar())
1422     return false;
1423 
1424   MemBarNode *barrier = x->as_MemBar();
1425 
1426   // if the barrier is a release membar we have what we want. if it is
1427   // a cpuorder membar then we need to ensure that it is fed by a
1428   // release membar in which case we proceed to check the graph below
1429   // this cpuorder membar as the feed
1430 
1431   if (x->Opcode() != Op_MemBarRelease) {
1432     if (x->Opcode() != Op_MemBarCPUOrder)
1433       return false;
1434     ProjNode *ctl;
1435     ProjNode *mem;
1436     MemBarNode *b = has_parent_membar(x, ctl, mem);
1437     if (!b || !b->Opcode() == Op_MemBarRelease)
1438       return false;
1439   }
1440 
1441   ProjNode *ctl = barrier->proj_out(TypeFunc::Control);
1442   ProjNode *mem = barrier->proj_out(TypeFunc::Memory);
1443 
1444   // barrier needs to have both a Ctl and Mem projection
1445   // and we need to have reached it via the Ctl projection
1446   if (! ctl || ! mem || ctl != proj)
1447     return false;
1448 
1449   StoreNode * st = NULL;
1450 
1451   // The Ctl ProjNode should have output to a MemBarVolatile and
1452   // a Store marked as releasing
1453   for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
1454     x = ctl->fast_out(i);
1455     if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
1456       if (x != mbvol) {
1457         return false;
1458       }
1459     } else if (x->is_Store()) {
1460       st = x->as_Store();
1461       if (! st->is_release()) {
1462         return false;
1463       }
1464     } else if (!x->is_Mach()){
1465       // we may see mach nodes added during matching but nothing else
1466       return false;
1467     }
1468   }
1469 
1470   if (!st)
1471     return false;
1472 
1473   // the Mem ProjNode should output to a MergeMem and the same Store
1474   Node *mm = NULL;
1475   for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
1476     x = mem->fast_out(i);
1477     if (!mm && x->is_MergeMem()) {
1478       mm = x;
1479     } else if (x != st && !x->is_Mach()) {
1480       // we may see mach nodes added during matching but nothing else
1481       return false;
1482     }
1483   }
1484 
1485   if (!mm)
1486     return false;
1487 
1488   // the MergeMem should output to the MemBarVolatile
1489   for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
1490     x = mm->fast_out(i);
1491     if (x != mbvol && !x->is_Mach()) {
1492       // we may see mach nodes added during matching but nothing else
1493       return false;
1494     }
1495   }
1496 
1497   return true;
1498 }
1499 
1500 
1501 
1502 bool needs_releasing_store(const Node *n)
1503 {
1504   // assert n->is_Store();
1505   if (UseBarriersForVolatile)
1506     // we use a normal store and dmb combination
1507     return false;
1508 
1509   StoreNode *st = n->as_Store();
1510 
1511   if (!st->is_release())
1512     return false;
1513 
1514   // check if this store is bracketed by a release (or its dependent
1515   // cpuorder membar) and a volatile membar
1516   //
1517   //   MemBarRelease
1518   //  {      ||      }
1519   //  {MemBarCPUOrder} -- optional
1520   //         ||     \\
1521   //         ||     StoreX[mo_release]
1522   //         | \     /
1523   //         | MergeMem
1524   //         | /
1525   //   MemBarVolatile
1526   //
1527   // where
1528   //  || and \\ represent Ctl and Mem feeds via Proj nodes
1529   //  | \ and / indicate further routing of the Ctl and Mem feeds
1530   // 
1531 
1532 
1533   Node *x = st->lookup(TypeFunc::Control);
1534 
1535   if (! x || !x->is_Proj())
1536     return false;
1537 
1538   ProjNode *proj = x->as_Proj();
1539 
1540   x = proj->lookup(0);
1541 
1542   if (!x || !x->is_MemBar())
1543     return false;
1544 
1545   MemBarNode *barrier = x->as_MemBar();
1546 
1547   // if the barrier is a release membar we have what we want. if it is
1548   // a cpuorder membar then we need to ensure that it is fed by a
1549   // release membar in which case we proceed to check the graph below
1550   // this cpuorder membar as the feed
1551 
1552   if (x->Opcode() != Op_MemBarRelease) {
1553     if (x->Opcode() != Op_MemBarCPUOrder)
1554       return false;
1555     Node *ctl = x->lookup(TypeFunc::Control);
1556     Node *mem = x->lookup(TypeFunc::Memory);
1557     if (!ctl || !ctl->is_Proj() || !mem || !mem->is_Proj())
1558       return false;
1559     x = ctl->lookup(0);
1560     if (!x || !x->is_MemBar() || !x->Opcode() == Op_MemBarRelease)
1561       return false;
1562     Node *y = mem->lookup(0);
1563     if (!y || y != x)
1564       return false;
1565   }
1566 
1567   ProjNode *ctl = barrier->proj_out(TypeFunc::Control);
1568   ProjNode *mem = barrier->proj_out(TypeFunc::Memory);
1569 
1570   // MemBarRelease needs to have both a Ctl and Mem projection
1571   // and we need to have reached it via the Ctl projection
1572   if (! ctl || ! mem || ctl != proj)
1573     return false;
1574 
1575   MemBarNode *mbvol = NULL;
1576 
1577   // The Ctl ProjNode should have output to a MemBarVolatile and
1578   // a Store marked as releasing
1579   for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
1580     x = ctl->fast_out(i);
1581     if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
1582       mbvol = x->as_MemBar();
1583     } else if (x->is_Store()) {
1584       if (x != st) {
1585         return false;
1586       }
1587     } else if (!x->is_Mach()){
1588       return false;
1589     }
1590   }
1591 
1592   if (!mbvol)
1593     return false;
1594 
1595   // the Mem ProjNode should output to a MergeMem and the same Store
1596   Node *mm = NULL;
1597   for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
1598     x = mem->fast_out(i);
1599     if (!mm && x->is_MergeMem()) {
1600       mm = x;
1601     } else if (x != st && !x->is_Mach()) {
1602       return false;
1603     }
1604   }
1605 
1606   if (!mm)
1607     return false;
1608 
1609   // the MergeMem should output to the MemBarVolatile
1610   for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
1611     x = mm->fast_out(i);
1612     if (x != mbvol && !x->is_Mach()) {
1613       return false;
1614     }
1615   }
1616 
1617   return true;
1618 }
1619 
1620 
1621 
1622 #define __ _masm.
1623 
1624 // advance declarations for helper functions to convert register
1625 // indices to register objects
1626 
1627 // the ad file has to provide implementations of certain methods
1628 // expected by the generic code
1629 //
1630 // REQUIRED FUNCTIONALITY
1631 
1632 //=============================================================================
1633 
1634 // !!!!! Special hack to get all types of calls to specify the byte offset
1635 //       from the start of the call to the point where the return address
1636 //       will point.
1637 
1638 int MachCallStaticJavaNode::ret_addr_offset()
1639 {
1640   // call should be a simple bl
1641   // unless this is a method handle invoke in which case it is


5928 //               by referring to it with a '$' prefix.
5929 // opcode     -- Three instruction opcodes may be provided.  These are referred
5930 //               to within an encode class as $primary, $secondary, and $tertiary
5931 //               rrspectively.  The primary opcode is commonly used to
5932 //               indicate the type of machine instruction, while secondary
5933 //               and tertiary are often used for prefix options or addressing
5934 //               modes.
5935 // ins_encode -- A list of encode classes with parameters. The encode class
5936 //               name must have been defined in an 'enc_class' specification
5937 //               in the encode section of the architecture description.
5938 
5939 // ============================================================================
5940 // Memory (Load/Store) Instructions
5941 
5942 // Load Instructions
5943 
5944 // Load Byte (8 bit signed)
5945 instruct loadB(iRegINoSp dst, memory mem)
5946 %{
5947   match(Set dst (LoadB mem));
5948   predicate(!needs_acquiring_load(n));
5949 
5950   ins_cost(4 * INSN_COST);
5951   format %{ "ldrsbw  $dst, $mem\t# byte" %}
5952 
5953   ins_encode(aarch64_enc_ldrsbw(dst, mem));
5954 
5955   ins_pipe(iload_reg_mem);
5956 %}
5957 
5958 // Load Byte (8 bit signed) into long
5959 instruct loadB2L(iRegLNoSp dst, memory mem)
5960 %{
5961   match(Set dst (ConvI2L (LoadB mem)));
5962   predicate(!needs_acquiring_load(n->in(1)));
5963 
5964   ins_cost(4 * INSN_COST);
5965   format %{ "ldrsb  $dst, $mem\t# byte" %}
5966 
5967   ins_encode(aarch64_enc_ldrsb(dst, mem));
5968 
5969   ins_pipe(iload_reg_mem);
5970 %}
5971 
5972 // Load Byte (8 bit unsigned)
5973 instruct loadUB(iRegINoSp dst, memory mem)
5974 %{
5975   match(Set dst (LoadUB mem));
5976   predicate(!needs_acquiring_load(n));
5977 
5978   ins_cost(4 * INSN_COST);
5979   format %{ "ldrbw  $dst, $mem\t# byte" %}
5980 
5981   ins_encode(aarch64_enc_ldrb(dst, mem));
5982 
5983   ins_pipe(iload_reg_mem);
5984 %}
5985 
5986 // Load Byte (8 bit unsigned) into long
5987 instruct loadUB2L(iRegLNoSp dst, memory mem)
5988 %{
5989   match(Set dst (ConvI2L (LoadUB mem)));
5990   predicate(!needs_acquiring_load(n->in(1)));
5991 
5992   ins_cost(4 * INSN_COST);
5993   format %{ "ldrb  $dst, $mem\t# byte" %}
5994 
5995   ins_encode(aarch64_enc_ldrb(dst, mem));
5996 
5997   ins_pipe(iload_reg_mem);
5998 %}
5999 
6000 // Load Short (16 bit signed)
6001 instruct loadS(iRegINoSp dst, memory mem)
6002 %{
6003   match(Set dst (LoadS mem));
6004   predicate(!needs_acquiring_load(n));
6005 
6006   ins_cost(4 * INSN_COST);
6007   format %{ "ldrshw  $dst, $mem\t# short" %}
6008 
6009   ins_encode(aarch64_enc_ldrshw(dst, mem));
6010 
6011   ins_pipe(iload_reg_mem);
6012 %}
6013 
6014 // Load Short (16 bit signed) into long
6015 instruct loadS2L(iRegLNoSp dst, memory mem)
6016 %{
6017   match(Set dst (ConvI2L (LoadS mem)));
6018   predicate(!needs_acquiring_load(n->in(1)));
6019 
6020   ins_cost(4 * INSN_COST);
6021   format %{ "ldrsh  $dst, $mem\t# short" %}
6022 
6023   ins_encode(aarch64_enc_ldrsh(dst, mem));
6024 
6025   ins_pipe(iload_reg_mem);
6026 %}
6027 
6028 // Load Char (16 bit unsigned)
6029 instruct loadUS(iRegINoSp dst, memory mem)
6030 %{
6031   match(Set dst (LoadUS mem));
6032   predicate(!needs_acquiring_load(n));
6033 
6034   ins_cost(4 * INSN_COST);
6035   format %{ "ldrh  $dst, $mem\t# short" %}
6036 
6037   ins_encode(aarch64_enc_ldrh(dst, mem));
6038 
6039   ins_pipe(iload_reg_mem);
6040 %}
6041 
6042 // Load Short/Char (16 bit unsigned) into long
6043 instruct loadUS2L(iRegLNoSp dst, memory mem)
6044 %{
6045   match(Set dst (ConvI2L (LoadUS mem)));
6046   predicate(!needs_acquiring_load(n->in(1)));
6047 
6048   ins_cost(4 * INSN_COST);
6049   format %{ "ldrh  $dst, $mem\t# short" %}
6050 
6051   ins_encode(aarch64_enc_ldrh(dst, mem));
6052 
6053   ins_pipe(iload_reg_mem);
6054 %}
6055 
6056 // Load Integer (32 bit signed)
6057 instruct loadI(iRegINoSp dst, memory mem)
6058 %{
6059   match(Set dst (LoadI mem));
6060   predicate(!needs_acquiring_load(n));
6061 
6062   ins_cost(4 * INSN_COST);
6063   format %{ "ldrw  $dst, $mem\t# int" %}
6064 
6065   ins_encode(aarch64_enc_ldrw(dst, mem));
6066 
6067   ins_pipe(iload_reg_mem);
6068 %}
6069 
6070 // Load Integer (32 bit signed) into long
6071 instruct loadI2L(iRegLNoSp dst, memory mem)
6072 %{
6073   match(Set dst (ConvI2L (LoadI mem)));
6074   predicate(!needs_acquiring_load(n->in(1)));
6075 
6076   ins_cost(4 * INSN_COST);
6077   format %{ "ldrsw  $dst, $mem\t# int" %}
6078 
6079   ins_encode(aarch64_enc_ldrsw(dst, mem));
6080 
6081   ins_pipe(iload_reg_mem);
6082 %}
6083 
6084 // Load Integer (32 bit unsigned) into long
6085 instruct loadUI2L(iRegLNoSp dst, memory mem, immL_32bits mask)
6086 %{
6087   match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
6088   predicate(!needs_acquiring_load(n->in(1)->in(1)->as_Load()));
6089 
6090   ins_cost(4 * INSN_COST);
6091   format %{ "ldrw  $dst, $mem\t# int" %}
6092 
6093   ins_encode(aarch64_enc_ldrw(dst, mem));
6094 
6095   ins_pipe(iload_reg_mem);
6096 %}
6097 
6098 // Load Long (64 bit signed)
6099 instruct loadL(iRegLNoSp dst, memory mem)
6100 %{
6101   match(Set dst (LoadL mem));
6102   predicate(!needs_acquiring_load(n));
6103 
6104   ins_cost(4 * INSN_COST);
6105   format %{ "ldr  $dst, $mem\t# int" %}
6106 
6107   ins_encode(aarch64_enc_ldr(dst, mem));
6108 
6109   ins_pipe(iload_reg_mem);
6110 %}
6111 
6112 // Load Range
6113 instruct loadRange(iRegINoSp dst, memory mem)
6114 %{
6115   match(Set dst (LoadRange mem));
6116 
6117   ins_cost(4 * INSN_COST);
6118   format %{ "ldrw  $dst, $mem\t# range" %}
6119 
6120   ins_encode(aarch64_enc_ldrw(dst, mem));
6121 
6122   ins_pipe(iload_reg_mem);
6123 %}
6124 
6125 // Load Pointer
6126 instruct loadP(iRegPNoSp dst, memory mem)
6127 %{
6128   match(Set dst (LoadP mem));
6129   predicate(!needs_acquiring_load(n));
6130 
6131   ins_cost(4 * INSN_COST);
6132   format %{ "ldr  $dst, $mem\t# ptr" %}
6133 
6134   ins_encode(aarch64_enc_ldr(dst, mem));
6135 
6136   ins_pipe(iload_reg_mem);
6137 %}
6138 
6139 // Load Compressed Pointer
6140 instruct loadN(iRegNNoSp dst, memory mem)
6141 %{
6142   match(Set dst (LoadN mem));
6143   predicate(!needs_acquiring_load(n));
6144 
6145   ins_cost(4 * INSN_COST);
6146   format %{ "ldrw  $dst, $mem\t# compressed ptr" %}
6147 
6148   ins_encode(aarch64_enc_ldrw(dst, mem));
6149 
6150   ins_pipe(iload_reg_mem);
6151 %}
6152 
6153 // Load Klass Pointer
6154 instruct loadKlass(iRegPNoSp dst, memory mem)
6155 %{
6156   match(Set dst (LoadKlass mem));
6157   predicate(!needs_acquiring_load(n));
6158 
6159   ins_cost(4 * INSN_COST);
6160   format %{ "ldr  $dst, $mem\t# class" %}
6161 
6162   ins_encode(aarch64_enc_ldr(dst, mem));
6163 
6164   ins_pipe(iload_reg_mem);
6165 %}
6166 
6167 // Load Narrow Klass Pointer
6168 instruct loadNKlass(iRegNNoSp dst, memory mem)
6169 %{
6170   match(Set dst (LoadNKlass mem));
6171   predicate(!needs_acquiring_load(n));
6172 
6173   ins_cost(4 * INSN_COST);
6174   format %{ "ldrw  $dst, $mem\t# compressed class ptr" %}
6175 
6176   ins_encode(aarch64_enc_ldrw(dst, mem));
6177 
6178   ins_pipe(iload_reg_mem);
6179 %}
6180 
6181 // Load Float
6182 instruct loadF(vRegF dst, memory mem)
6183 %{
6184   match(Set dst (LoadF mem));
6185   predicate(!needs_acquiring_load(n));
6186 
6187   ins_cost(4 * INSN_COST);
6188   format %{ "ldrs  $dst, $mem\t# float" %}
6189 
6190   ins_encode( aarch64_enc_ldrs(dst, mem) );
6191 
6192   ins_pipe(pipe_class_memory);
6193 %}
6194 
6195 // Load Double
6196 instruct loadD(vRegD dst, memory mem)
6197 %{
6198   match(Set dst (LoadD mem));
6199   predicate(!needs_acquiring_load(n));
6200 
6201   ins_cost(4 * INSN_COST);
6202   format %{ "ldrd  $dst, $mem\t# double" %}
6203 
6204   ins_encode( aarch64_enc_ldrd(dst, mem) );
6205 
6206   ins_pipe(pipe_class_memory);
6207 %}
6208 
6209 
6210 // Load Int Constant
6211 instruct loadConI(iRegINoSp dst, immI src)
6212 %{
6213   match(Set dst src);
6214 
6215   ins_cost(INSN_COST);
6216   format %{ "mov $dst, $src\t# int" %}
6217 
6218   ins_encode( aarch64_enc_movw_imm(dst, src) );
6219 


6410 
6411 // Store Instructions
6412 
6413 // Store CMS card-mark Immediate
6414 instruct storeimmCM0(immI0 zero, memory mem)
6415 %{
6416   match(Set mem (StoreCM mem zero));
6417 
6418   ins_cost(INSN_COST);
6419   format %{ "strb zr, $mem\t# byte" %}
6420 
6421   ins_encode(aarch64_enc_strb0(mem));
6422 
6423   ins_pipe(istore_mem);
6424 %}
6425 
6426 // Store Byte
6427 instruct storeB(iRegIorL2I src, memory mem)
6428 %{
6429   match(Set mem (StoreB mem src));
6430   predicate(!needs_releasing_store(n));
6431 
6432   ins_cost(INSN_COST);
6433   format %{ "strb  $src, $mem\t# byte" %}
6434 
6435   ins_encode(aarch64_enc_strb(src, mem));
6436 
6437   ins_pipe(istore_reg_mem);
6438 %}
6439 
6440 
6441 instruct storeimmB0(immI0 zero, memory mem)
6442 %{
6443   match(Set mem (StoreB mem zero));
6444   predicate(!needs_releasing_store(n));
6445 
6446   ins_cost(INSN_COST);
6447   format %{ "strb zr, $mem\t# byte" %}
6448 
6449   ins_encode(aarch64_enc_strb0(mem));
6450 
6451   ins_pipe(istore_mem);
6452 %}
6453 
6454 // Store Char/Short
6455 instruct storeC(iRegIorL2I src, memory mem)
6456 %{
6457   match(Set mem (StoreC mem src));
6458   predicate(!needs_releasing_store(n));
6459 
6460   ins_cost(INSN_COST);
6461   format %{ "strh  $src, $mem\t# short" %}
6462 
6463   ins_encode(aarch64_enc_strh(src, mem));
6464 
6465   ins_pipe(istore_reg_mem);
6466 %}
6467 
6468 instruct storeimmC0(immI0 zero, memory mem)
6469 %{
6470   match(Set mem (StoreC mem zero));
6471   predicate(!needs_releasing_store(n));
6472 
6473   ins_cost(INSN_COST);
6474   format %{ "strh  zr, $mem\t# short" %}
6475 
6476   ins_encode(aarch64_enc_strh0(mem));
6477 
6478   ins_pipe(istore_mem);
6479 %}
6480 
6481 // Store Integer
6482 
6483 instruct storeI(iRegIorL2I src, memory mem)
6484 %{
6485   match(Set mem(StoreI mem src));
6486   predicate(!needs_releasing_store(n));
6487 
6488   ins_cost(INSN_COST);
6489   format %{ "strw  $src, $mem\t# int" %}
6490 
6491   ins_encode(aarch64_enc_strw(src, mem));
6492 
6493   ins_pipe(istore_reg_mem);
6494 %}
6495 
6496 instruct storeimmI0(immI0 zero, memory mem)
6497 %{
6498   match(Set mem(StoreI mem zero));
6499   predicate(!needs_releasing_store(n));
6500 
6501   ins_cost(INSN_COST);
6502   format %{ "strw  zr, $mem\t# int" %}
6503 
6504   ins_encode(aarch64_enc_strw0(mem));
6505 
6506   ins_pipe(istore_mem);
6507 %}
6508 
6509 // Store Long (64 bit signed)
6510 instruct storeL(iRegL src, memory mem)
6511 %{
6512   match(Set mem (StoreL mem src));
6513   predicate(!needs_releasing_store(n));
6514 
6515   ins_cost(INSN_COST);
6516   format %{ "str  $src, $mem\t# int" %}
6517 
6518   ins_encode(aarch64_enc_str(src, mem));
6519 
6520   ins_pipe(istore_reg_mem);
6521 %}
6522 
6523 // Store Long (64 bit signed)
6524 instruct storeimmL0(immL0 zero, memory mem)
6525 %{
6526   match(Set mem (StoreL mem zero));
6527   predicate(!needs_releasing_store(n));
6528 
6529   ins_cost(INSN_COST);
6530   format %{ "str  zr, $mem\t# int" %}
6531 
6532   ins_encode(aarch64_enc_str0(mem));
6533 
6534   ins_pipe(istore_mem);
6535 %}
6536 
6537 // Store Pointer
6538 instruct storeP(iRegP src, memory mem)
6539 %{
6540   match(Set mem (StoreP mem src));
6541   predicate(!needs_releasing_store(n));
6542 
6543   ins_cost(INSN_COST);
6544   format %{ "str  $src, $mem\t# ptr" %}
6545 
6546   ins_encode(aarch64_enc_str(src, mem));
6547 
6548   ins_pipe(istore_reg_mem);
6549 %}
6550 
6551 // Store Pointer
6552 instruct storeimmP0(immP0 zero, memory mem)
6553 %{
6554   match(Set mem (StoreP mem zero));
6555   predicate(!needs_releasing_store(n));
6556 
6557   ins_cost(INSN_COST);
6558   format %{ "str zr, $mem\t# ptr" %}
6559 
6560   ins_encode(aarch64_enc_str0(mem));
6561 
6562   ins_pipe(istore_mem);
6563 %}
6564 
6565 // Store Compressed Pointer
6566 instruct storeN(iRegN src, memory mem)
6567 %{
6568   match(Set mem (StoreN mem src));
6569   predicate(!needs_releasing_store(n));
6570 
6571   ins_cost(INSN_COST);
6572   format %{ "strw  $src, $mem\t# compressed ptr" %}
6573 
6574   ins_encode(aarch64_enc_strw(src, mem));
6575 
6576   ins_pipe(istore_reg_mem);
6577 %}
6578 
6579 instruct storeImmN0(iRegIHeapbase heapbase, immN0 zero, memory mem)
6580 %{
6581   match(Set mem (StoreN mem zero));
6582   predicate(Universe::narrow_oop_base() == NULL &&
6583             Universe::narrow_klass_base() == NULL &&
6584             (!needs_releasing_store(n)));
6585 
6586   ins_cost(INSN_COST);
6587   format %{ "strw  rheapbase, $mem\t# compressed ptr (rheapbase==0)" %}
6588 
6589   ins_encode(aarch64_enc_strw(heapbase, mem));
6590 
6591   ins_pipe(istore_reg_mem);
6592 %}
6593 
6594 // Store Float
6595 instruct storeF(vRegF src, memory mem)
6596 %{
6597   match(Set mem (StoreF mem src));
6598   predicate(!needs_releasing_store(n));
6599 
6600   ins_cost(INSN_COST);
6601   format %{ "strs  $src, $mem\t# float" %}
6602 
6603   ins_encode( aarch64_enc_strs(src, mem) );
6604 
6605   ins_pipe(pipe_class_memory);
6606 %}
6607 
6608 // TODO
6609 // implement storeImmF0 and storeFImmPacked
6610 
6611 // Store Double
6612 instruct storeD(vRegD src, memory mem)
6613 %{
6614   match(Set mem (StoreD mem src));
6615   predicate(!needs_releasing_store(n));
6616 
6617   ins_cost(INSN_COST);
6618   format %{ "strd  $src, $mem\t# double" %}
6619 
6620   ins_encode( aarch64_enc_strd(src, mem) );
6621 
6622   ins_pipe(pipe_class_memory);
6623 %}
6624 
6625 // Store Compressed Klass Pointer
6626 instruct storeNKlass(iRegN src, memory mem)
6627 %{
6628   predicate(!needs_releasing_store(n));
6629   match(Set mem (StoreNKlass mem src));
6630 
6631   ins_cost(INSN_COST);
6632   format %{ "strw  $src, $mem\t# compressed klass ptr" %}
6633 
6634   ins_encode(aarch64_enc_strw(src, mem));
6635 
6636   ins_pipe(istore_reg_mem);
6637 %}
6638 
6639 // TODO
6640 // implement storeImmD0 and storeDImmPacked
6641 
6642 // prefetch instructions
6643 // Must be safe to execute with invalid address (cannot fault).
6644 
6645 instruct prefetchalloc( memory mem ) %{
6646   match(PrefetchAllocation mem);
6647 
6648   ins_cost(INSN_COST);


7070 
7071   ins_pipe(ialu_reg);
7072 %}
7073 
7074 // ============================================================================
7075 // MemBar Instruction
7076 
7077 instruct load_fence() %{
7078   match(LoadFence);
7079   ins_cost(VOLATILE_REF_COST);
7080 
7081   format %{ "load_fence" %}
7082 
7083   ins_encode %{
7084     __ membar(Assembler::LoadLoad|Assembler::LoadStore);
7085   %}
7086   ins_pipe(pipe_serial);
7087 %}
7088 
7089 instruct unnecessary_membar_acquire() %{
7090   predicate(unnecessary_acquire(n));
7091   match(MemBarAcquire);
7092   ins_cost(0);
7093 
7094   format %{ "membar_acquire (elided)" %}
7095 
7096   ins_encode %{
7097     __ block_comment("membar_acquire (elided)");
7098   %}
7099 
7100   ins_pipe(pipe_class_empty);
7101 %}
7102 
7103 instruct membar_acquire() %{
7104   match(MemBarAcquire);
7105   ins_cost(VOLATILE_REF_COST);
7106 
7107   format %{ "membar_acquire" %}
7108 
7109   ins_encode %{
7110     __ membar(Assembler::LoadLoad|Assembler::LoadStore);


7122 
7123   ins_encode %{
7124     __ membar(Assembler::LoadLoad|Assembler::LoadStore);
7125   %}
7126 
7127   ins_pipe(pipe_serial);
7128 %}
7129 
7130 instruct store_fence() %{
7131   match(StoreFence);
7132   ins_cost(VOLATILE_REF_COST);
7133 
7134   format %{ "store_fence" %}
7135 
7136   ins_encode %{
7137     __ membar(Assembler::LoadStore|Assembler::StoreStore);
7138   %}
7139   ins_pipe(pipe_serial);
7140 %}
7141 
7142 instruct unnecessary_membar_release() %{
7143   predicate(unnecessary_release(n));
7144   match(MemBarRelease);
7145   ins_cost(0);
7146 
7147   format %{ "membar_release (elided)" %}
7148 
7149   ins_encode %{
7150     __ block_comment("membar_release (elided)");
7151   %}
7152   ins_pipe(pipe_serial);
7153 %}
7154 
7155 instruct membar_release() %{
7156   match(MemBarRelease);
7157   ins_cost(VOLATILE_REF_COST);
7158 
7159   format %{ "membar_release" %}
7160 
7161   ins_encode %{
7162     __ membar(Assembler::LoadStore|Assembler::StoreStore);
7163   %}
7164   ins_pipe(pipe_serial);
7165 %}
7166 
7167 instruct membar_storestore() %{
7168   match(MemBarStoreStore);
7169   ins_cost(VOLATILE_REF_COST);
7170 
7171   format %{ "MEMBAR-store-store" %}
7172 
7173   ins_encode %{
7174     __ membar(Assembler::StoreStore);
7175   %}
7176   ins_pipe(pipe_serial);
7177 %}
7178 
7179 instruct membar_release_lock() %{
7180   match(MemBarReleaseLock);
7181   ins_cost(VOLATILE_REF_COST);
7182 
7183   format %{ "membar_release_lock" %}
7184 
7185   ins_encode %{
7186     __ membar(Assembler::LoadStore|Assembler::StoreStore);
7187   %}
7188 
7189   ins_pipe(pipe_serial);
7190 %}
7191 
7192 instruct unnecessary_membar_volatile() %{
7193   predicate(unnecessary_volatile(n));
7194   match(MemBarVolatile);
7195   ins_cost(0);
7196 
7197   format %{ "membar_volatile (elided)" %}
7198 
7199   ins_encode %{
7200     __ block_comment("membar_volatile (elided)");
7201   %}
7202 
7203   ins_pipe(pipe_serial);
7204 %}
7205 
7206 instruct membar_volatile() %{
7207   match(MemBarVolatile);
7208   ins_cost(VOLATILE_REF_COST*100);
7209 
7210   format %{ "membar_volatile" %}
7211 
7212   ins_encode %{
7213     __ membar(Assembler::StoreLoad);
7214   %}
7215 
7216   ins_pipe(pipe_serial);
7217 %}
7218 
7219 // ============================================================================
7220 // Cast/Convert Instructions


< prev index next >