graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java

Print this page
rev 8661 : Graal PTX enhancements
rev 8662 : [mq]: ptx_switch
rev 8663 : [mq]: ptx_table_switch


   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.ptx;
  24 



  25 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
  26 
  27 import com.oracle.graal.api.meta.*;
  28 import com.oracle.graal.asm.*;
  29 import com.oracle.graal.asm.ptx.*;
  30 import com.oracle.graal.lir.*;
  31 import com.oracle.graal.lir.asm.*;
  32 import com.oracle.graal.nodes.calc.*;











  33 
  34 public class PTXControlFlow {
  35 
  36     public static class ReturnOp extends PTXLIRInstruction {
  37 
  38         @Use({REG, ILLEGAL}) protected Value x;
  39 
  40         public ReturnOp(Value x) {
  41             this.x = x;
  42         }
  43 
  44         @Override
  45         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
  46             if (tasm.frameContext != null) {
  47                 tasm.frameContext.leave(tasm);
  48             }
  49             masm.exit();
  50         }
  51     }
  52 


  63         @Override
  64         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
  65             masm.at();
  66             Label l = destination.label();
  67             l.addPatchAt(tasm.asm.codeBuffer.position());
  68             String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
  69             masm.bra(target);
  70         }
  71 
  72         @Override
  73         public LabelRef destination() {
  74             return destination;
  75         }
  76 
  77         @Override
  78         public void negate(LabelRef newDestination) {
  79             destination = newDestination;
  80             condition = condition.negate();
  81         }
  82     }









































































































































































  83 }


   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.ptx;
  24 
  25 import static com.oracle.graal.api.code.ValueUtil.asIntReg;
  26 import static com.oracle.graal.api.code.ValueUtil.asLongReg;
  27 import static com.oracle.graal.api.code.ValueUtil.asObjectReg;
  28 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
  29 
  30 import com.oracle.graal.api.code.Register;
  31 import com.oracle.graal.api.code.CompilationResult.JumpTable;
  32 import com.oracle.graal.api.meta.Constant;
  33 import com.oracle.graal.api.meta.Kind;
  34 import com.oracle.graal.api.meta.Value;
  35 import com.oracle.graal.asm.Buffer;
  36 import com.oracle.graal.asm.Label;
  37 import com.oracle.graal.asm.NumUtil;
  38 import com.oracle.graal.asm.ptx.AbstractPTXAssembler;
  39 import com.oracle.graal.asm.ptx.PTXAssembler;
  40 import com.oracle.graal.graph.GraalInternalError;
  41 import com.oracle.graal.lir.LabelRef;
  42 import com.oracle.graal.lir.StandardOp;
  43 import com.oracle.graal.lir.StandardOp.FallThroughOp;
  44 import com.oracle.graal.lir.Variable;
  45 import com.oracle.graal.lir.asm.TargetMethodAssembler;
  46 import com.oracle.graal.nodes.calc.Condition;
  47 
  48 public class PTXControlFlow {
  49 
  50     public static class ReturnOp extends PTXLIRInstruction {
  51 
  52         @Use({REG, ILLEGAL}) protected Value x;
  53 
  54         public ReturnOp(Value x) {
  55             this.x = x;
  56         }
  57 
  58         @Override
  59         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
  60             if (tasm.frameContext != null) {
  61                 tasm.frameContext.leave(tasm);
  62             }
  63             masm.exit();
  64         }
  65     }
  66 


  77         @Override
  78         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
  79             masm.at();
  80             Label l = destination.label();
  81             l.addPatchAt(tasm.asm.codeBuffer.position());
  82             String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
  83             masm.bra(target);
  84         }
  85 
  86         @Override
  87         public LabelRef destination() {
  88             return destination;
  89         }
  90 
  91         @Override
  92         public void negate(LabelRef newDestination) {
  93             destination = newDestination;
  94             condition = condition.negate();
  95         }
  96     }
  97     
  98     public static class CondMoveOp extends PTXLIRInstruction {
  99         @Def({REG, HINT}) protected Value result;
 100         @Alive({REG}) protected Value trueValue;
 101         @Use({REG, STACK, CONST}) protected Value falseValue;
 102         private final Condition condition;
 103 
 104         public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
 105             this.result = result;
 106             this.condition = condition;
 107             this.trueValue = trueValue;
 108             this.falseValue = falseValue;
 109         }
 110 
 111         @Override
 112         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
 113             // cmove(tasm, masm, result, false, condition, false, trueValue, falseValue);
 114                 // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1
 115             throw new InternalError("NYI");
 116         }
 117     }
 118 
 119 
 120     public static class FloatCondMoveOp extends PTXLIRInstruction {
 121         @Def({REG}) protected Value result;
 122         @Alive({REG}) protected Value trueValue;
 123         @Alive({REG}) protected Value falseValue;
 124         private final Condition condition;
 125         private final boolean unorderedIsTrue;
 126 
 127         public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
 128             this.result = result;
 129             this.condition = condition;
 130             this.unorderedIsTrue = unorderedIsTrue;
 131             this.trueValue = trueValue;
 132             this.falseValue = falseValue;
 133         }
 134 
 135         @Override
 136         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
 137             // cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue);
 138             // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1
 139             throw new InternalError("NYI");
 140         }
 141     }
 142     
 143     public static class SequentialSwitchOp extends PTXLIRInstruction implements FallThroughOp {
 144         @Use({CONST}) protected Constant[] keyConstants;
 145         private final LabelRef[] keyTargets;
 146         private LabelRef defaultTarget;
 147         @Alive({REG}) protected Value key;
 148         @Temp({REG, ILLEGAL}) protected Value scratch;
 149 
 150         public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
 151             assert keyConstants.length == keyTargets.length;
 152             this.keyConstants = keyConstants;
 153             this.keyTargets = keyTargets;
 154             this.defaultTarget = defaultTarget;
 155             this.key = key;
 156             this.scratch = scratch;
 157         }
 158 
 159         @Override
 160         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
 161             if (key.getKind() == Kind.Int) {
 162                 Register intKey = asIntReg(key);
 163                 for (int i = 0; i < keyConstants.length; i++) {
 164                     if (tasm.runtime.needsDataPatch(keyConstants[i])) {
 165                         tasm.recordDataReferenceInCode(keyConstants[i], 0, true);
 166                     }
 167                     long lc = keyConstants[i].asLong();
 168                     assert NumUtil.isInt(lc);
 169                     masm.setp_eq_s32((int)lc, intKey);
 170                     masm.at();
 171                     Label l = keyTargets[i].label();
 172                     l.addPatchAt(tasm.asm.codeBuffer.position());
 173                     String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
 174                     masm.bra(target);
 175                 }
 176             } else if (key.getKind() == Kind.Long) {
 177                 Register longKey = asLongReg(key);
 178                 for (int i = 0; i < keyConstants.length; i++) {
 179                     masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]), longKey);
 180                     masm.at();
 181                     Label l = keyTargets[i].label();
 182                     l.addPatchAt(tasm.asm.codeBuffer.position());
 183                     String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
 184                     masm.bra(target);
 185                 }
 186             } else if (key.getKind() == Kind.Object) {
 187                 Register intKey = asObjectReg(key);
 188                 Register temp = asObjectReg(scratch);
 189                 for (int i = 0; i < keyConstants.length; i++) {
 190                     PTXMove.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]);
 191                     masm.setp_eq_u32(intKey, temp);
 192                     masm.at();
 193                     masm.bra(keyTargets[i].label().toString());
 194                 }
 195             } else {
 196                 throw new GraalInternalError("sequential switch only supported for int, long and object");
 197             }
 198             if (defaultTarget != null) {
 199                 masm.jmp(defaultTarget.label());
 200             } else {
 201                 // masm.hlt();
 202             }
 203         }
 204 
 205         @Override
 206         public LabelRef fallThroughTarget() {
 207             return defaultTarget;
 208         }
 209 
 210         @Override
 211         public void setFallThroughTarget(LabelRef target) {
 212             defaultTarget = target;
 213         }
 214     }
 215     
 216     public static class TableSwitchOp extends PTXLIRInstruction {
 217         private final int lowKey;
 218         private final LabelRef defaultTarget;
 219         private final LabelRef[] targets;
 220         @Alive protected Value index;
 221         @Temp protected Value scratch;
 222 
 223         public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, 
 224                                                  Variable index, Variable scratch) {
 225             this.lowKey = lowKey;
 226             this.defaultTarget = defaultTarget;
 227             this.targets = targets;
 228             this.index = index;
 229             this.scratch = scratch;
 230         }
 231 
 232         @Override
 233         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
 234             tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch));
 235         }
 236     }
 237 
 238     private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey, 
 239                                                                 LabelRef defaultTarget, LabelRef[] targets, 
 240                                                                 Register value, Register scratch) {
 241         Buffer buf = masm.codeBuffer;
 242         // Compare index against jump table bounds
 243         int highKey = lowKey + targets.length - 1;
 244         if (lowKey != 0) {
 245             // subtract the low value from the switch value
 246                 masm.sub_s32(value, value, lowKey);
 247                 masm.setp_gt_s32(value, highKey - lowKey);
 248         } else {
 249                 masm.setp_gt_s32(value, highKey);
 250         }
 251 
 252         // Jump to default target if index is not within the jump table
 253         if (defaultTarget != null) {
 254             masm.at();
 255             masm.bra(defaultTarget.label().toString());
 256         }
 257 
 258         // address of jump table
 259         int tablePos = buf.position();
 260         
 261         JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4);
 262         tasm.compilationResult.addAnnotation(jt);
 263         
 264         System.err.println("PTX: unimp: tableswitch");
 265     }
 266 }