Hi all,
I wish to describe a pattern in tablegen to pattern match G_STORE with base_address plus offset form. I am now implementing it in ${Target}InstructionSelector.cpp.
For example:
bb.1.entry:
liveins: $arg0, $arg1, $arg2
%2:argreg(s32) = COPY $arg0
%3:argreg(s32) = COPY $arg1
%0:argreg64r(p1) = G_MERGE_VALUES %2:argreg(s32), %3:argreg(s32)
%1:argreg(s32) = COPY $arg2
%8:vregr(s32) = G_CONSTANT i32 2
%5:vregr(s32) = G_SHL %1:argreg, %8:vregr(s32)
%6:argreg64r(p1) = G_PTR_ADD %0:argreg64r, %5:vregr(s32)
G_STORE %1:argreg(s32), %6:argreg64r(p1) :: (store (s32) into %ir.arrayidx, !tbaa !3, addrspace 1)
PseudoRET
When select ‘G_STORE’, my C++ code takes G_PTR_ADD’s 2nd and 3rd operands, which are ‘base_ptr’ and ‘offset’ respectively, and then create ${Target} Store Instruction with ‘base_ptr’ and ‘offset’ as its operands.
This is the result:
bb.1.entry:
liveins: $arg0, $arg1, $arg2
%2:argreg = COPY $arg0
%3:argreg = COPY $arg1
%0:argreg64 = PseudoMERGE %2:argreg, %3:argreg
%1:argreg = COPY $arg2
%5:vreg = MUL %1:argreg, 4
STORE %1:argreg, %0:argreg64, %5:vreg
PseudoRET
G_SHL with 2 (bits) is lowered to ${Target} MUL instruction, this is ‘offset’.
Can I describe this in tablegen instead of writing C++ code?
Thanks!
CY
1 Like
Found a way to pattern match it.
I was inspired by [GISel/DAG] Getting a TableGen pattern to match both `G_ADD` and `G_PTR_ADD` in GISel, and his patch ⚙ D131254 [AMDGPU][GISel] Enable Selection of ADD3 for G_PTR_ADD
My implementation in tablegen:
-
Store instruction:
def STORE : Instr<"st", [], (outs),
(ins Arg:$val, Arg64:$ptr, VReg:$offset)>;
-
Define ptradd
// iPTR:$out_ptr = ptradd iPTR:$ptr, int:$offset
def SDTPtrAddOp : SDTypeProfile<1, 2, [
SDTCisSameAs<0, 1>, SDTCisInt<2>, SDTCisPtrTy<1>
]>;
def ptradd : SDNode<"ISD::ADD", SDTPtrAddOp, []>;
def : GINodeEquiv<G_PTR_ADD, ptradd>;
-
Pattern matches: G_STORE %1:argreg(s32), G_PTR_ADD %0:argreg64r, %5:vregr(s32) :: (store (s32) into %ir.arrayidx, !tbaa !3, addrspace 1)
// matches (op2 ty2:$x, (op1 ty0:$y, ty1:$z))
class ThreeOpFrag<SDPatternOperator op1, SDPatternOperator op2>
: PatFrag<(ops node:$x, node:$y, node:$z),
(op2 node:$x, (op1 node:$y, node:$z))> {
}
def p1 : PtrValueType<i64, 1>;
// (ins Arg:$Rn, Arg64:$Rm, VReg:$Offset)>;
class StorePats<SDPatternOperator op1, SDPatternOperator op2, Instruction inst>
: Pat<(ThreeOpFrag<op1, op2> i32:$val, p1:$ptr, i32:$offset),
(inst Arg:$val, Arg64:$ptr, VReg:$offset)>;
def : StorePats<ptradd, st, STORE>;
I found I have to explicit use p1 for $ptr, iPTRAny didn’t work.
This pattern rule can replace my c++ code.
Thanks,
CY