|
| 1 | +#include "mlir/Dialect/Arith/IR/ArithOps.td" |
| 2 | + |
| 3 | +Constraint IsPowerOfTwo(attr: Attr) [{ |
| 4 | + int64_t value = cast<::mlir::IntegerAttr>(attr).getValue().getSExtValue(); |
| 5 | + return success((value & (value - 1)) == 0); |
| 6 | +}]; |
| 7 | + |
| 8 | +// Currently, constraints that return values must be defined in C++ |
| 9 | +Constraint Halve(atttr: Attr) -> Attr; |
| 10 | +Constraint MinusOne(attr: Attr) -> Attr; |
| 11 | + |
| 12 | +// Replace y = C*x with y = C/2*x + C/2*x, when C is a power of 2, otherwise do |
| 13 | +// nothing. |
| 14 | +Pattern PowerOfTwoExpandRhs with benefit(2) { |
| 15 | + let root = op<arith.muli>(op<arith.constant> {value = const: Attr}, rhs: Value); |
| 16 | + IsPowerOfTwo(const); |
| 17 | + let halved: Attr = Halve(const); |
| 18 | + |
| 19 | + rewrite root with { |
| 20 | + let newConst = op<arith.constant> {value = halved}; |
| 21 | + let newMul = op<arith.muli>(newConst, rhs); |
| 22 | + let newAdd = op<arith.addi>(newMul, newMul); |
| 23 | + replace root with newAdd; |
| 24 | + }; |
| 25 | +} |
| 26 | + |
| 27 | +Pattern PowerOfTwoExpandLhs with benefit(2) { |
| 28 | + let root = op<arith.muli>(lhs: Value, op<arith.constant> {value = const: Attr}); |
| 29 | + IsPowerOfTwo(const); |
| 30 | + let halved: Attr = Halve(const); |
| 31 | + |
| 32 | + rewrite root with { |
| 33 | + let newConst = op<arith.constant> {value = halved}; |
| 34 | + let newMul = op<arith.muli>(lhs, newConst); |
| 35 | + let newAdd = op<arith.addi>(newMul, newMul); |
| 36 | + replace root with newAdd; |
| 37 | + }; |
| 38 | +} |
| 39 | + |
| 40 | +// Replace y = 9*x with y = 8*x + x |
| 41 | +Pattern PeelFromMulRhs with benefit(1) { |
| 42 | + let root = op<arith.muli>(lhs: Value, op<arith.constant> {value = const: Attr}); |
| 43 | + |
| 44 | + // We are guaranteed `value` is not a power of two, because the greedy |
| 45 | + // rewrite engine ensures the PowerOfTwoExpand pattern is run first, since |
| 46 | + // it has higher benefit. |
| 47 | + let minusOne: Attr = MinusOne(const); |
| 48 | + |
| 49 | + rewrite root with { |
| 50 | + let newConst = op<arith.constant> {value = minusOne}; |
| 51 | + let newMul = op<arith.muli>(lhs, newConst); |
| 52 | + let newAdd = op<arith.addi>(newMul, lhs); |
| 53 | + replace root with newAdd; |
| 54 | + }; |
| 55 | +} |
| 56 | + |
| 57 | +Pattern PeelFromMulLhs with benefit(1) { |
| 58 | + let root = op<arith.muli>(op<arith.constant> {value = const: Attr}, rhs: Value); |
| 59 | + let minusOne: Attr = MinusOne(const); |
| 60 | + |
| 61 | + rewrite root with { |
| 62 | + let newConst = op<arith.constant> {value = minusOne}; |
| 63 | + let newMul = op<arith.muli>(newConst, rhs); |
| 64 | + let newAdd = op<arith.addi>(newMul, rhs); |
| 65 | + replace root with newAdd; |
| 66 | + }; |
| 67 | +} |
0 commit comments