changeset 11924:ba829878000c

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 07 Oct 2013 01:24:08 +0200
parents 88fb9cba8751 (current diff) 1f82cda83ced (diff)
children fe71a5ed24c2
files
diffstat 5 files changed, 298 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Mon Oct 07 01:23:54 2013 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Mon Oct 07 01:24:08 2013 +0200
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 
+import com.oracle.graal.asm.Label;
 import com.oracle.graal.api.code.Register;
 import com.oracle.graal.api.code.RegisterConfig;
 import com.oracle.graal.api.code.TargetDescription;
@@ -32,6 +33,7 @@
 import com.oracle.graal.api.meta.Value;
 import com.oracle.graal.nodes.calc.Condition;
 import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.lir.LabelRef;
 import com.oracle.graal.lir.Variable;
 
 public class PTXAssembler extends AbstractPTXAssembler {
@@ -511,12 +513,18 @@
 
     // Checkstyle: stop method name check
     public final void bra(String tgt, int pred) {
-        System.err.println("BRA: " + tgt + " pred: " + pred);
         assert pred >= 0;
 
+        if (tgt.equals("?")) {
+            Thread.dumpStack();
+        }
         emitString("@%p" + pred + " " + "bra" + " " + tgt + ";");
     }
 
+    public final void bra(String target) {
+        emitString("bra " + target + ";");
+    }
+
     public final void bra_uni(String tgt) {
         emitString("bra.uni" + " " + tgt + ";" + "");
     }
@@ -534,10 +542,16 @@
     
     public static class Mov extends SingleOperandFormat {
 
+        private int predicateRegisterNumber = -1;
+
         public Mov(Variable dst, Value src) {
             super(dst, src);
         }
 
+        public Mov(Variable dst, Value src, int predicate) {
+            super(dst, src);
+            this.predicateRegisterNumber = predicate;
+        }
         /*
         public Mov(Variable dst, AbstractAddress src) {
             throw GraalInternalError.unimplemented("AbstractAddress Mov");
@@ -545,10 +559,15 @@
         */
         
         public void emit(PTXAssembler asm) {
-            asm.emitString("mov." + super.emit());
+            if (predicateRegisterNumber >= 0) {
+                asm.emitString("@%p" + String.valueOf(predicateRegisterNumber)
+                               + " mov." + super.emit());
+            } else {
+                asm.emitString("mov." + super.emit());
+            }
         }
     }
-    
+
     public static class Neg extends SingleOperandFormat {
 
         public Neg(Variable dst, Variable src) {
@@ -597,6 +616,49 @@
         emitString("exit;" + " " + "");
     }
 
+    public static class Global {
+
+        private Kind kind;
+        private String name;
+        private LabelRef[] targets;
+
+        public Global(Value val, String name, LabelRef[] targets) {
+            this.kind = val.getKind();
+            this.name = name;
+            this.targets = targets;
+        }
+
+        private String valueForKind(Kind k) {
+            switch (k.getTypeChar()) {
+                case 'i':
+                    return "s32";
+                case 'j':
+                    return "s64";
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        private String emitTargets(PTXAssembler asm, LabelRef[] refs) {
+            StringBuffer sb = new StringBuffer();
+
+            for (int i = 0; i < refs.length; i++) {
+                sb.append(asm.nameOf(refs[i].label()));
+                if (i < (refs.length -1)) {
+                    sb.append(", ");
+                }
+            }
+
+            return sb.toString();
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString(".global ." + valueForKind(kind) +
+                           " " + name + "[" + targets.length + "] = " +
+                           "{ " + emitTargets(asm, targets) + " };");
+        }
+    }
+
     public static class Param extends SingleOperandFormat {
 
         private boolean lastParameter;
@@ -824,4 +886,15 @@
     public PTXAddress getPlaceholder() {
         return null;
     }
+
+    @Override
+    public void jmp(Label l) {
+        String str = nameOf(l);
+        if (l.equals("?")) {
+            Thread.dumpStack();
+        }
+        bra(str);
+    }
+
+
 }
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java	Mon Oct 07 01:23:54 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java	Mon Oct 07 01:24:08 2013 +0200
@@ -42,10 +42,27 @@
         } else {
             printReport("testSwitchDefault1I: no VALUE");
         }
+        ret = (Integer) invoke(compile("testSwitch1I"), 2);
+        if (ret != null) {
+            printReport("testSwitch1I: " + ret);
+        } else {
+            printReport("testSwitch1I: no VALUE");
+        }
+        ret = (Integer) invoke(compile("testIfElse1I"), 222);
+        if (ret != null) {
+            printReport("testIfElse1I: " + ret);
+        } else {
+            printReport("testIfElse1I: no VALUE");
+        }
+        ret = (Integer) invoke(compile("testIfElse2I"), 19, 64);
+        if (ret != null) {
+            printReport("testIfElse2I: " + (char) ret.intValue());
+        } else {
+            printReport("testIfElse2I: no VALUE");
+        }
         compile("testStatic");
         compile("testCall");
-        // compile("testSwitch1I");
-        // compile("testLookupSwitch1I");
+        compile("testLookupSwitch1I");
     }
 
     public static int testLoop(int n) {
@@ -57,6 +74,24 @@
         return sum;
     }
 
+    public static int testIfElse1I(int n) {
+        if (n > 22) {
+            return 42;
+        } else {
+            return -42;
+        }
+    }
+
+    public static int testIfElse2I(int c, int y) {
+        if  (c > 19) {
+            return (int) 'M';    // millenial
+        } else if (y > 84) {
+            return (int) 'Y';    // young
+        } else {
+            return (int) 'O';    // old
+        }
+    }
+
     public static int testSwitchDefault1I(int a) {
         switch (a) {
             default:
@@ -78,31 +113,31 @@
     public static int testLookupSwitch1I(int a) {
         switch (a) {
             case 0:
-                return 1;
+                return 10;
             case 1:
-                return 2;
+                return 11;
             case 2:
-                return 3;
+                return 12;
             case 3:
-                return 1;
+                return 13;
             case 4:
-                return 2;
+                return 14;
             case 5:
-                return 3;
+                return 15;
             case 6:
-                return 1;
+                return 16;
             case 7:
-                return 2;
+                return 17;
             case 8:
-                return 3;
+                return 18;
             case 9:
-                return 1;
+                return 19;
             case 10:
-                return 2;
+                return 20;
             case 11:
-                return 3;
+                return 21;
             default:
-                return -1;
+                return 42;
         }
     }
 
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Mon Oct 07 01:23:54 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Mon Oct 07 01:24:08 2013 +0200
@@ -109,8 +109,8 @@
         Buffer codeBuffer = tasm.asm.codeBuffer;
 
         // Emit initial boiler-plate directives.
-        codeBuffer.emitString(".version 1.4");
-        codeBuffer.emitString(".target sm_10");
+        codeBuffer.emitString(".version 2.1");
+        codeBuffer.emitString(".target sm_20");
         codeBuffer.emitString0(".entry " + name + " (");
         codeBuffer.emitString("");
 
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Oct 07 01:23:54 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Oct 07 01:24:08 2013 +0200
@@ -46,6 +46,8 @@
 import com.oracle.graal.lir.ptx.PTXArithmetic.Unary2Op;
 import com.oracle.graal.lir.ptx.PTXCompare.CompareOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.FloatCondMoveOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnNoValOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.SequentialSwitchOp;
@@ -86,7 +88,9 @@
         }
     }
 
-    public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) {
+    public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime,
+                           TargetDescription target, FrameMap frameMap,
+                           CallingConvention cc, LIR lir) {
         super(graph, runtime, target, frameMap, cc, lir);
         lir.spillMoveFactory = new PTXSpillMoveFactory();
         int callVariables = cc.getArgumentCount() + (cc.getReturn() == Value.ILLEGAL ? 0 : 1);
@@ -333,11 +337,79 @@
     }
 
     @Override
-    public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
-        // TODO: There is no conventional conditional move instruction in PTX.
-        // So, this method is changed to throw NYI exception.
-        // To be revisited if this needs to be really implemented.
-        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitConditionalMove()");
+    public Variable emitConditionalMove(Value left, Value right,
+                                        Condition cond, boolean unorderedIsTrue,
+                                        Value trueValue, Value falseValue) {
+
+        Condition finalCondition = LIRValueUtil.isVariable(right) ? cond.mirror() : cond;
+
+        boolean mirrored;
+        mirrored = emitCompare(finalCondition, left, right);
+
+        Variable result = newVariable(trueValue.getKind());
+        switch (left.getKind().getStackKind()) {
+            case Int:
+            case Long:
+            case Object:
+                append(new CondMoveOp(result, finalCondition,
+                                      load(trueValue), loadNonConst(falseValue),
+                                      nextPredRegNum));
+                nextPredRegNum++;
+                break;
+            case Float:
+            case Double:
+                append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue,
+                                           load(trueValue), load(falseValue),
+                                           nextPredRegNum));
+                nextPredRegNum++;
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("" + left.getKind());
+        }
+        return result;
+    }
+
+    /**
+     * This method emits the compare instruction, and may reorder the operands. 
+     * It returns true if it did so.
+     *
+     * @param a the left operand of the comparison
+     * @param b the right operand of the comparison
+     * @return true if the left and right operands were switched, false otherwise
+     */
+    private boolean emitCompare(Condition cond, Value a, Value b) {
+        Variable left;
+        Value right;
+        boolean mirrored;
+        if (LIRValueUtil.isVariable(b)) {
+            left = load(b);
+            right = loadNonConst(a);
+            mirrored = true;
+        } else {
+            left = load(a);
+            right = loadNonConst(b);
+            mirrored = false;
+        }
+        switch (left.getKind().getStackKind()) {
+            case Int:
+                append(new CompareOp(ICMP, cond, left, right, nextPredRegNum));
+                break;
+            case Long:
+                append(new CompareOp(LCMP, cond, left, right, nextPredRegNum));
+                break;
+            case Object:
+                append(new CompareOp(ACMP, cond, left, right, nextPredRegNum));
+                break;
+            case Float:
+                append(new CompareOp(FCMP, cond, left, right, nextPredRegNum));
+                break;
+            case Double:
+                append(new CompareOp(DCMP, cond, left, right, nextPredRegNum));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return mirrored;
     }
 
 
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Oct 07 01:23:54 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Oct 07 01:24:08 2013 +0200
@@ -22,8 +22,10 @@
  */
 package com.oracle.graal.lir.ptx;
 
+import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.asm.ptx.PTXAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.lir.LIRValueUtil.*;
 import static com.oracle.graal.nodes.calc.Condition.*;
 
 import com.oracle.graal.api.code.CompilationResult.JumpTable;
@@ -97,30 +99,31 @@
         }
     }
 
-    @SuppressWarnings("unused")
     public static class CondMoveOp extends PTXLIRInstruction {
 
         @Def({REG, HINT}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Use({REG, STACK, CONST}) protected Value falseValue;
         private final Condition condition;
+        private final int predicate;
 
-        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
+        public CondMoveOp(Variable result, Condition condition,
+                          Variable trueValue, Value falseValue,
+                          int predicateRegister) {
             this.result = result;
             this.condition = condition;
             this.trueValue = trueValue;
             this.falseValue = falseValue;
+            this.predicate = predicateRegister;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            // cmove(tasm, masm, result, false, condition, false, trueValue, falseValue);
-            // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1
-            throw new InternalError("NYI");
+            cmove(tasm, masm, result, false, condition, false,
+                  trueValue, falseValue, predicate);
         }
     }
 
-    @SuppressWarnings("unused")
     public static class FloatCondMoveOp extends PTXLIRInstruction {
 
         @Def({REG}) protected Value result;
@@ -128,20 +131,81 @@
         @Alive({REG}) protected Value falseValue;
         private final Condition condition;
         private final boolean unorderedIsTrue;
+        private final int predicate;
 
-        public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
+        public FloatCondMoveOp(Variable result, Condition condition,
+                               boolean unorderedIsTrue,
+                               Variable trueValue, Variable falseValue,
+                               int predicateRegister) {
             this.result = result;
             this.condition = condition;
             this.unorderedIsTrue = unorderedIsTrue;
             this.trueValue = trueValue;
             this.falseValue = falseValue;
+            this.predicate = predicateRegister;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            // cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue);
-            // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1
-            throw new InternalError("NYI");
+            cmove(tasm, masm, result, true, condition, unorderedIsTrue,
+                  trueValue, falseValue, predicate);
+        }
+    }
+
+    private static void cmove(TargetMethodAssembler tasm, PTXAssembler asm,
+                              Value result, boolean isFloat, Condition condition,
+                              boolean unorderedIsTrue,
+                              Value trueValue, Value falseValue,
+                              int predicateRegister) {
+        // check that we don't overwrite an input operand before it is used.
+        assert !result.equals(trueValue);
+
+        PTXMove.move(tasm, asm, result, falseValue);
+        cmove(tasm, asm, result, condition, trueValue, predicateRegister);
+
+        if (isFloat) {
+            if (unorderedIsTrue && !trueOnUnordered(condition)) {
+                // cmove(tasm, masm, result, ConditionFlag.Parity, trueValue);
+                throw GraalInternalError.unimplemented();
+            } else if (!unorderedIsTrue && trueOnUnordered(condition)) {
+                // cmove(tasm, masm, result, ConditionFlag.Parity, falseValue);
+                throw GraalInternalError.unimplemented();
+            }
+        }
+    }
+
+    private static boolean trueOnUnordered(Condition condition) {
+        switch (condition) {
+            case NE:
+            case EQ:
+                return false;
+            case LT:
+            case GE:
+                return true;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void cmove(TargetMethodAssembler tasm, PTXAssembler asm,
+                              Value result, Condition cond, Value other,
+                              int predicateRegister) {
+        if (isVariable(other)) {
+            assert !asVariable(other).equals(asVariable(result)) :
+                "other already overwritten by previous move";
+
+            switch (other.getKind()) {
+                case Int:
+                    new Mov(asVariable(result), other, predicateRegister).emit(asm);
+                    break;
+                case Long:
+                    new Mov(asVariable(result), other, predicateRegister).emit(asm);
+                    break;
+                default:
+                    throw new InternalError("unhandled: " + other.getKind());
+            }
+        } else {
+            throw GraalInternalError.shouldNotReachHere("cmove: not register");
         }
     }
 
@@ -155,7 +219,9 @@
         // Number of predicate register that would be set by this instruction.
         protected int predRegNum;
 
-        public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch, int predReg) {
+        public SequentialSwitchOp(Constant[] keyConstants,
+                                  LabelRef[] keyTargets, LabelRef defaultTarget,
+                                  Value key, Value scratch, int predReg) {
             assert keyConstants.length == keyTargets.length;
             this.keyConstants = keyConstants;
             this.keyTargets = keyTargets;
@@ -214,7 +280,9 @@
         // Number of predicate register that would be set by this instruction.
         protected int predRegNum;
 
-        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch, int predReg) {
+        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget,
+                             final LabelRef[] targets,
+                             Variable index, Variable scratch, int predReg) {
             this.lowKey = lowKey;
             this.defaultTarget = defaultTarget;
             this.targets = targets;
@@ -225,7 +293,8 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            tableswitch(tasm, masm, lowKey, defaultTarget, targets, index, scratch, predRegNum);
+            tableswitch(tasm, masm, lowKey, defaultTarget, targets,
+                        index, scratch, predRegNum);
         }
     }
 
@@ -234,7 +303,9 @@
                                     LabelRef defaultTarget, LabelRef[] targets,
                                     Value value, Value scratch, int predNum) {
         Buffer buf = masm.codeBuffer;
+
         // Compare index against jump table bounds
+
         int highKey = lowKey + targets.length - 1;
         if (lowKey != 0) {
             // subtract the low value from the switch value
@@ -246,15 +317,21 @@
 
         // Jump to default target if index is not within the jump table
         if (defaultTarget != null) {
-            masm.bra(defaultTarget.label().toString(), predNum);
+            masm.bra(masm.nameOf(defaultTarget.label()), predNum);
         }
 
         // address of jump table
         int tablePos = buf.position();
 
+
         JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4);
+        String name = "jumptable" + jt.position;
+
+        new Global(value, name, targets).emit(masm);
+
+        // bra(Value, name);
+
         tasm.compilationResult.addAnnotation(jt);
 
-        // PTX: unimp: tableswitch extract
     }
 }