summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/node/ShlNode.java
blob: f657cf516c4639a5652efd94a08b4e8b7b2e0505 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.seaofnodes.simple.node;

import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;

public class ShlNode extends ArithNode {
    public ShlNode(Parser.Lexer loc, Node lhs, Node rhs) { super(loc, lhs, rhs, (byte)1); }
    @Override public Tag serialTag() { return Tag.Shl; }

    @Override public String op() { return "<<"; }
    @Override long doOp( long x, long y ) { return x << y; }
    @Override TypeInteger doOp( TypeInteger x, TypeInteger y ) {
        if( x == TypeInteger.ZERO )
            return TypeInteger.ZERO;
        if( y.isConstant() ) {
            int shf = (int)y.value();
            // If no overflow, shift endpoints
            if( !(((x._min<<shf)>>shf) != x._min ||
                  ((x._max<<shf)>>shf) != x._max ) )
                    return TypeInteger.make(x._min<<shf,x._max<<shf);
        }
        return TypeInteger.BOT;
    }

    @Override
    public Node idealize() {
        Node lhs = in(1);
        Node rhs = in(2);

        if( rhs._type instanceof TypeInteger shl && shl.isConstant() ) {
            // Shl of 0.
            if( (shl.value()&63)==0 && forceInt(lhs) && lhs._type instanceof TypeInteger )
                return lhs;
            // (x + c) << i  =>  (x << i) + (c << i)
            if( lhs instanceof AddNode add && addDep(add).in(2)._type instanceof TypeInteger c && c.isConstant() ) {
                long sum = c.value() << shl.value();
                if( Integer.MIN_VALUE <= sum  && sum <= Integer.MAX_VALUE )
                    return new AddNode(new ShlNode(_loc,add.in(1),rhs).peephole(), CodeGen.CODE.con(sum) );
            }
        }

        // TODO: x << 3 << (y ? 1 : 2) ==> x << (y ? 4 : 5)

        return super.idealize();
    }
    @Override Node copy(Node lhs, Node rhs) { return new ShlNode(_loc,lhs,rhs); }
}