001/* 002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023 024package com.oracle.graal.compiler.amd64; 025 026import jdk.internal.jvmci.code.*; 027import jdk.internal.jvmci.meta.*; 028 029import com.oracle.graal.asm.*; 030import com.oracle.graal.asm.amd64.AMD64Address.Scale; 031import com.oracle.graal.compiler.common.type.*; 032import com.oracle.graal.nodes.*; 033import com.oracle.graal.nodes.calc.*; 034import com.oracle.graal.nodes.memory.address.*; 035import com.oracle.graal.phases.common.AddressLoweringPhase.AddressLowering; 036 037public class AMD64AddressLowering extends AddressLowering { 038 039 private final CodeCacheProvider codeCache; 040 041 public AMD64AddressLowering(CodeCacheProvider codeCache) { 042 this.codeCache = codeCache; 043 } 044 045 @Override 046 public AddressNode lower(ValueNode address) { 047 return lower(address, null); 048 } 049 050 @Override 051 public AddressNode lower(ValueNode base, ValueNode offset) { 052 AMD64AddressNode ret = new AMD64AddressNode(base, offset); 053 boolean changed; 054 do { 055 changed = improve(ret); 056 } while (changed); 057 return base.graph().unique(ret); 058 } 059 060 protected boolean improve(AMD64AddressNode ret) { 061 ValueNode newBase = improveInput(ret, ret.getBase(), 0); 062 if (newBase != ret.getBase()) { 063 ret.setBase(newBase); 064 return true; 065 } 066 067 ValueNode newIdx = improveInput(ret, ret.getIndex(), ret.getScale().log2); 068 if (newIdx != ret.getIndex()) { 069 ret.setIndex(newIdx); 070 return true; 071 } 072 073 if (ret.getIndex() instanceof LeftShiftNode) { 074 LeftShiftNode shift = (LeftShiftNode) ret.getIndex(); 075 if (shift.getY().isConstant()) { 076 int amount = ret.getScale().log2 + shift.getY().asJavaConstant().asInt(); 077 Scale scale = Scale.fromShift(amount); 078 if (scale != null) { 079 ret.setIndex(shift.getX()); 080 ret.setScale(scale); 081 return true; 082 } 083 } 084 } 085 086 if (ret.getScale() == Scale.Times1) { 087 if (ret.getBase() == null || ret.getIndex() == null) { 088 if (ret.getBase() instanceof AddNode) { 089 AddNode add = (AddNode) ret.getBase(); 090 ret.setBase(add.getX()); 091 ret.setIndex(add.getY()); 092 return true; 093 } else if (ret.getIndex() instanceof AddNode) { 094 AddNode add = (AddNode) ret.getIndex(); 095 ret.setBase(add.getX()); 096 ret.setIndex(add.getY()); 097 return true; 098 } 099 } 100 101 if (ret.getBase() instanceof LeftShiftNode && !(ret.getIndex() instanceof LeftShiftNode)) { 102 ValueNode tmp = ret.getBase(); 103 ret.setBase(ret.getIndex()); 104 ret.setIndex(tmp); 105 return true; 106 } 107 } 108 109 return false; 110 } 111 112 private ValueNode improveInput(AMD64AddressNode address, ValueNode node, int shift) { 113 if (node == null) { 114 return null; 115 } 116 117 if (node.isConstant()) { 118 return improveConstDisp(address, node, node.asJavaConstant(), null, shift); 119 } else { 120 if (node.stamp() instanceof IntegerStamp && ((IntegerStamp) node.stamp()).getBits() == 64) { 121 if (node instanceof ZeroExtendNode) { 122 if (((ZeroExtendNode) node).getInputBits() == 32) { 123 /* 124 * We can just swallow a zero-extend from 32 bit to 64 bit because the upper 125 * half of the register will always be zero. 126 */ 127 return ((ZeroExtendNode) node).getValue(); 128 } 129 } else if (node instanceof AddNode) { 130 AddNode add = (AddNode) node; 131 if (add.getX().isConstant()) { 132 return improveConstDisp(address, node, add.getX().asJavaConstant(), add.getY(), shift); 133 } else if (add.getY().isConstant()) { 134 return improveConstDisp(address, node, add.getY().asJavaConstant(), add.getX(), shift); 135 } 136 } 137 } 138 } 139 140 return node; 141 } 142 143 private ValueNode improveConstDisp(AMD64AddressNode address, ValueNode original, JavaConstant c, ValueNode other, int shift) { 144 if (c.getKind().isNumericInteger() && !codeCache.needsDataPatch(c)) { 145 long disp = address.getDisplacement(); 146 disp += c.asLong() << shift; 147 if (NumUtil.isInt(disp)) { 148 address.setDisplacement((int) disp); 149 return other; 150 } 151 } 152 return original; 153 } 154}