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 }