1 /*
   2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  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 package com.oracle.graal.lir.hsail;
  24 
  25 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
  26 
  27 import com.oracle.graal.api.meta.*;
  28 import com.oracle.graal.asm.hsail.*;
  29 import com.oracle.graal.graph.*;
  30 import com.oracle.graal.lir.*;
  31 import com.oracle.graal.lir.asm.*;
  32 import com.oracle.graal.nodes.calc.*;
  33 
  34 /**
  35  * Implementation of control flow instructions.
  36  */
  37 public class HSAILControlFlow {
  38 
  39     public static class ReturnOp extends HSAILLIRInstruction {
  40 
  41         @Use({REG, ILLEGAL}) protected Value x;
  42 
  43         public ReturnOp(Value x) {
  44             this.x = x;
  45         }
  46 
  47         @Override
  48         public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
  49             if (tasm.frameContext != null) {
  50                 tasm.frameContext.leave(tasm);
  51             }
  52             masm.exit();
  53         }
  54     }
  55 
  56 
  57     public static class ForeignCallNoOp0 extends HSAILLIRInstruction {
  58 
  59         @Def({REG}) protected Value out;
  60         String callName;
  61 
  62         public ForeignCallNoOp0(String callName, Value out) {
  63             this.out = out;
  64             this.callName = callName;
  65         }
  66 
  67         @Override
  68         public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
  69             masm.emitComment("//ForeignCall to " + callName + " would have gone here");
  70         }
  71     }
  72 
  73     public static class ForeignCallNoOp1 extends ForeignCallNoOp0 {
  74 
  75         @Use({REG, ILLEGAL}) protected Value arg1;
  76 
  77         public ForeignCallNoOp1(String callName, Value out, Value arg1) {
  78             super(callName, out);
  79             this.arg1 = arg1;
  80         }
  81     }
  82 
  83 
  84     public static class CompareBranchOp extends HSAILLIRInstruction implements StandardOp.BranchOp {
  85 
  86         @Opcode protected final HSAILCompare opcode;
  87         @Use({REG, CONST}) protected Value x;
  88         @Use({REG, CONST}) protected Value y;
  89         @Def({REG}) protected Value z;
  90         protected Condition condition;
  91         protected LabelRef destination;
  92         protected boolean unordered = false;
  93         @Def({REG}) protected Value result;
  94 
  95         public CompareBranchOp(HSAILCompare opcode, Condition condition, Value x, Value y, Value z, Value result, LabelRef destination) {
  96             this.condition = condition;
  97             this.opcode = opcode;
  98             this.x = x;
  99             this.y = y;
 100             this.z = z;
 101             this.result = result;
 102             this.destination = destination;
 103         }
 104 
 105         @Override
 106         public LabelRef destination() {
 107             return destination;
 108         }
 109 
 110         @Override
 111         public void negate(LabelRef newDestination) {
 112             destination = newDestination;
 113             condition = condition.negate();
 114         }
 115 
 116         @Override
 117         public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
 118             HSAILCompare.emit(tasm, masm, condition, x, y, z, unordered);
 119             masm.cbr(masm.nameOf(destination.label()));
 120         }
 121     }
 122 
 123     public static class FloatCompareBranchOp extends CompareBranchOp {
 124 
 125         public FloatCompareBranchOp(HSAILCompare opcode, Condition condition, Value x, Value y, Value z, Value result, LabelRef destination, boolean unordered) {
 126             super(opcode, condition, x, y, z, result, destination);
 127             this.unordered = unordered;
 128         }
 129 
 130         @Override
 131         public void negate(LabelRef newDestination) {
 132             destination = newDestination;
 133             condition = condition.negate();
 134             unordered = !unordered;
 135         }
 136 
 137         @Override
 138         public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
 139             HSAILCompare.emit(tasm, masm, condition, x, y, z, unordered);
 140             masm.cbr(masm.nameOf(destination.label()));
 141         }
 142     }
 143 
 144     public static class DoubleCompareBranchOp extends CompareBranchOp {
 145 
 146         public DoubleCompareBranchOp(HSAILCompare opcode, Condition condition, Value x, Value y, Value z, Value result, LabelRef destination, boolean unordered) {
 147             super(opcode, condition, x, y, z, result, destination);
 148             this.unordered = unordered;
 149         }
 150 
 151         @Override
 152         public void negate(LabelRef newDestination) {
 153             destination = newDestination;
 154             condition = condition.negate();
 155             unordered = !unordered;
 156         }
 157 
 158         @Override
 159         public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
 160             HSAILCompare.emit(tasm, masm, condition, x, y, z, unordered);
 161             masm.cbr(masm.nameOf(destination.label()));
 162         }
 163     }
 164 
 165     public static class BranchOp extends HSAILLIRInstruction implements StandardOp.BranchOp {
 166 
 167         protected Condition condition;
 168         protected LabelRef destination;
 169         @Def({REG}) protected Value result;
 170 
 171         public BranchOp(Condition condition, Value result, LabelRef destination) {
 172             this.condition = condition;
 173             this.destination = destination;
 174             this.result = result;
 175         }
 176 
 177         @Override
 178         public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
 179             masm.cbr(masm.nameOf(destination.label()));
 180         }
 181 
 182         @Override
 183         public LabelRef destination() {
 184             return destination;
 185         }
 186 
 187         @Override
 188         public void negate(LabelRef newDestination) {
 189             destination = newDestination;
 190             condition = condition.negate();
 191         }
 192     }
 193 
 194     public static class FloatBranchOp extends BranchOp {
 195 
 196         public FloatBranchOp(Condition condition, Value result, LabelRef destination) {
 197             super(condition, result, destination);
 198         }
 199 
 200         @Override
 201         public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
 202             masm.cbr(masm.nameOf(destination.label()));
 203         }
 204     }
 205 
 206     public static class CondMoveOp extends HSAILLIRInstruction {
 207 
 208         @Opcode protected final HSAILCompare opcode;
 209         @Def({REG, HINT}) protected Value result;
 210         @Alive({REG}) protected Value trueValue;
 211         @Use({REG, STACK, CONST}) protected Value falseValue;
 212         @Use({REG, STACK, CONST}) protected Value left;
 213         @Use({REG, STACK, CONST}) protected Value right;
 214         protected final Condition condition;
 215 
 216         public CondMoveOp(HSAILCompare opcode, Variable left, Variable right, Variable result, Condition condition, Variable trueValue, Value falseValue) {
 217             this.opcode = opcode;
 218             this.result = result;
 219             this.left = left;
 220             this.right = right;
 221             this.condition = condition;
 222             this.trueValue = trueValue;
 223             this.falseValue = falseValue;
 224         }
 225 
 226         @Override
 227         public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
 228             HSAILCompare.emit(tasm, masm, condition, left, right, right, false);
 229             cmove(tasm, masm, result, false, trueValue, falseValue);
 230         }
 231     }
 232 
 233     public static class FloatCondMoveOp extends CondMoveOp {
 234 
 235         private final boolean unorderedIsTrue;
 236 
 237         public FloatCondMoveOp(HSAILCompare opcode, Variable left, Variable right, Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Value falseValue) {
 238             super(opcode, left, right, result, condition, trueValue, falseValue);
 239             this.unorderedIsTrue = unorderedIsTrue;
 240         }
 241 
 242         @Override
 243         public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
 244             HSAILCompare.emit(tasm, masm, condition, left, right, right, unorderedIsTrue);
 245             cmove(tasm, masm, result, false, trueValue, falseValue);
 246         }
 247     }
 248 
 249     @SuppressWarnings("unused")
 250     private static void cmove(TargetMethodAssembler tasm, HSAILAssembler masm, Value result, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
 251         // Check that we don't overwrite an input operand before it is used.
 252         assert (result.getKind() == trueValue.getKind() && result.getKind() == falseValue.getKind());
 253         int width;
 254         switch (result.getKind()) {
 255         /**
 256          * We don't need to pass the cond to the assembler. We will always use $c0 as the control
 257          * register.
 258          */
 259             case Float:
 260             case Int:
 261                 width = 32;
 262                 break;
 263             case Double:
 264             case Long:
 265                 width = 64;
 266                 break;
 267             default:
 268                 throw GraalInternalError.shouldNotReachHere();
 269         }
 270         masm.cmovCommon(result, trueValue, falseValue, width);
 271     }
 272 }
--- EOF ---