11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package org.graalvm.compiler.replacements.aarch64; 25 26 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; 27 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; 28 29 import org.graalvm.compiler.api.replacements.Snippet; 30 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 31 import org.graalvm.compiler.graph.Node.NodeIntrinsic; 32 import org.graalvm.compiler.graph.NodeClass; 33 import org.graalvm.compiler.nodeinfo.NodeInfo; 34 import org.graalvm.compiler.nodes.StructuredGraph; 35 import org.graalvm.compiler.nodes.ValueNode; 36 import org.graalvm.compiler.nodes.calc.RemNode; 37 import org.graalvm.compiler.nodes.spi.LoweringTool; 38 import org.graalvm.compiler.options.OptionValues; 39 import org.graalvm.compiler.phases.util.Providers; 40 import org.graalvm.compiler.replacements.SnippetTemplate; 41 import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; 42 import org.graalvm.compiler.replacements.Snippets; 43 44 import jdk.vm.ci.code.TargetDescription; 45 import jdk.vm.ci.meta.JavaKind; 46 47 /** 48 * AArch64 does not have a remainder operation. We use <code>n % d == n - Truncate(n / d) * d</code> 49 * for it instead. This is not correct for some edge cases, so we have to fix it up using these 50 * snippets. 51 */ 52 public class AArch64FloatArithmeticSnippets extends SnippetTemplate.AbstractTemplates implements Snippets { 53 54 private final SnippetTemplate.SnippetInfo drem; 55 private final SnippetTemplate.SnippetInfo frem; 56 57 public AArch64FloatArithmeticSnippets(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { 58 super(options, providers, snippetReflection, target); 59 drem = snippet(AArch64FloatArithmeticSnippets.class, "dremSnippet"); 60 frem = snippet(AArch64FloatArithmeticSnippets.class, "fremSnippet"); 61 } 62 63 public void lower(RemNode node, LoweringTool tool) { 64 JavaKind kind = node.stamp().getStackKind(); 65 assert kind == JavaKind.Float || kind == JavaKind.Double; 66 if (node instanceof SafeNode) { 67 // We already introduced the necessary checks, nothing to do. 68 return; 69 } 70 SnippetTemplate.SnippetInfo snippet = kind == JavaKind.Float ? frem : drem; 71 StructuredGraph graph = node.graph(); 72 Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); 73 args.add("x", node.getX()); 74 args.add("y", node.getY()); 75 template(args).instantiate(providers.getMetaAccess(), node, SnippetTemplate.DEFAULT_REPLACER, tool, args); 76 } 77 78 @Snippet 79 public static float fremSnippet(float x, float y) { 80 // JVMS: If either value1' or value2' is NaN, the result is NaN. 81 // JVMS: If the dividend is an infinity or the divisor is a zero or both, the result is NaN. 82 if (Float.isInfinite(x) || y == 0.0f || Float.isNaN(y)) { 83 return Float.NaN; 84 } 85 // JVMS: If the dividend is finite and the divisor is an infinity, the result equals the 86 // dividend. 87 // JVMS: If the dividend is a zero and the divisor is finite, the result equals the 88 // dividend. 89 if (x == 0.0f || Float.isInfinite(y)) { 90 return x; 91 } 92 93 float result = safeRem(x, y); 94 95 // JVMS: If neither value1' nor value2' is NaN, the sign of the result equals the sign of | 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package org.graalvm.compiler.replacements.aarch64; 25 26 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; 27 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; 28 29 import org.graalvm.compiler.api.replacements.Snippet; 30 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 31 import org.graalvm.compiler.debug.DebugHandlersFactory; 32 import org.graalvm.compiler.graph.Node.NodeIntrinsic; 33 import org.graalvm.compiler.graph.NodeClass; 34 import org.graalvm.compiler.nodeinfo.NodeInfo; 35 import org.graalvm.compiler.nodes.StructuredGraph; 36 import org.graalvm.compiler.nodes.ValueNode; 37 import org.graalvm.compiler.nodes.calc.RemNode; 38 import org.graalvm.compiler.nodes.spi.LoweringTool; 39 import org.graalvm.compiler.options.OptionValues; 40 import org.graalvm.compiler.phases.util.Providers; 41 import org.graalvm.compiler.replacements.SnippetTemplate; 42 import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; 43 import org.graalvm.compiler.replacements.Snippets; 44 45 import jdk.vm.ci.code.TargetDescription; 46 import jdk.vm.ci.meta.JavaKind; 47 48 /** 49 * AArch64 does not have a remainder operation. We use <code>n % d == n - Truncate(n / d) * d</code> 50 * for it instead. This is not correct for some edge cases, so we have to fix it up using these 51 * snippets. 52 */ 53 public class AArch64FloatArithmeticSnippets extends SnippetTemplate.AbstractTemplates implements Snippets { 54 55 private final SnippetTemplate.SnippetInfo drem; 56 private final SnippetTemplate.SnippetInfo frem; 57 58 public AArch64FloatArithmeticSnippets(OptionValues options, Iterable<DebugHandlersFactory> factories, Providers providers, SnippetReflectionProvider snippetReflection, 59 TargetDescription target) { 60 super(options, factories, providers, snippetReflection, target); 61 drem = snippet(AArch64FloatArithmeticSnippets.class, "dremSnippet"); 62 frem = snippet(AArch64FloatArithmeticSnippets.class, "fremSnippet"); 63 } 64 65 public void lower(RemNode node, LoweringTool tool) { 66 JavaKind kind = node.stamp().getStackKind(); 67 assert kind == JavaKind.Float || kind == JavaKind.Double; 68 if (node instanceof SafeNode) { 69 // We already introduced the necessary checks, nothing to do. 70 return; 71 } 72 SnippetTemplate.SnippetInfo snippet = kind == JavaKind.Float ? frem : drem; 73 StructuredGraph graph = node.graph(); 74 Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); 75 args.add("x", node.getX()); 76 args.add("y", node.getY()); 77 template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), node, SnippetTemplate.DEFAULT_REPLACER, tool, args); 78 } 79 80 @Snippet 81 public static float fremSnippet(float x, float y) { 82 // JVMS: If either value1' or value2' is NaN, the result is NaN. 83 // JVMS: If the dividend is an infinity or the divisor is a zero or both, the result is NaN. 84 if (Float.isInfinite(x) || y == 0.0f || Float.isNaN(y)) { 85 return Float.NaN; 86 } 87 // JVMS: If the dividend is finite and the divisor is an infinity, the result equals the 88 // dividend. 89 // JVMS: If the dividend is a zero and the divisor is finite, the result equals the 90 // dividend. 91 if (x == 0.0f || Float.isInfinite(y)) { 92 return x; 93 } 94 95 float result = safeRem(x, y); 96 97 // JVMS: If neither value1' nor value2' is NaN, the sign of the result equals the sign of |