I’m in the middle of implementing my original backend, about which I cannot describe in detail.
I would like to move analysis data of LLVM IR to my original backend. Because LLVM IR is SSA format and is easy to analyze program code. To move analysis data to backend, I thought it was a good idea to utilize LLVM IR metadata, but I’ve found it difficult to do it.
For example, we assume we find these instructions in LLVM IR.
%8 = load i16, i16* %7, align 2, !tbaa !4
%9 = add i64 %8, 1
store i16 %9, i16* %8, align 2, !tbaa !4
Then I want to unit these instructions and transform to a SLADDi
assembly instruction for my original backend.
If I try to implement it in MyBackendISelLowering.cpp by using custom action, I have to anarize Selection DAG. But Selection DAG is more complex than LLVM IR and it is more difficult to analize.
Here is an example. These are the same basic blocks. You can find it more difficult to analize SelectionDAG than IR.
IR
39: ; preds = %39, %.preheader
%40 = phi i64 [ 0, %.preheader ], [ %68, %39 ]
%41 = getelementptr inbounds [1000 x i16], [1000 x i16]* %1, i64 0, i64 %40
%42 = load i16, i16* %41, align 2, !tbaa !4
%43 = add i16 %42, 1
store i16 %43, i16* %41, align 2, !tbaa !4
%44 = getelementptr inbounds [1000 x i16], [1000 x i16]* %2, i64 0, i64 %40
%45 = load i16, i16* %44, align 2, !tbaa !4
%46 = add i16 %45, 1
store i16 %46, i16* %44, align 2, !tbaa !4
%47 = add nuw nsw i64 %40, 1
%48 = getelementptr inbounds [1000 x i16], [1000 x i16]* %1, i64 0, i64 %47
%49 = load i16, i16* %48, align 2, !tbaa !4
%50 = add i16 %49, 1
store i16 %50, i16* %48, align 2, !tbaa !4
%51 = getelementptr inbounds [1000 x i16], [1000 x i16]* %2, i64 0, i64 %47
%52 = load i16, i16* %51, align 2, !tbaa !4
%53 = add i16 %52, 1
store i16 %53, i16* %51, align 2, !tbaa !4
%54 = add nuw nsw i64 %47, 1
%55 = getelementptr inbounds [1000 x i16], [1000 x i16]* %1, i64 0, i64 %54
%56 = load i16, i16* %55, align 2, !tbaa !4
%57 = add i16 %56, 1
store i16 %57, i16* %55, align 2, !tbaa !4
%58 = getelementptr inbounds [1000 x i16], [1000 x i16]* %2, i64 0, i64 %54
%59 = load i16, i16* %58, align 2, !tbaa !4
%60 = add i16 %59, 1
store i16 %60, i16* %58, align 2, !tbaa !4
%61 = add nuw nsw i64 %54, 1
%62 = getelementptr inbounds [1000 x i16], [1000 x i16]* %1, i64 0, i64 %61
%63 = load i16, i16* %62, align 2, !tbaa !4
%64 = add i16 %63, 1
store i16 %64, i16* %62, align 2, !tbaa !4
%65 = getelementptr inbounds [1000 x i16], [1000 x i16]* %2, i64 0, i64 %61
%66 = load i16, i16* %65, align 2, !tbaa !4
%67 = add i16 %66, 1
store i16 %67, i16* %65, align 2, !tbaa !4
%68 = add nuw nsw i64 %61, 1
%69 = icmp eq i64 %68, 1000
br i1 %69, label %27, label %39, !llvm.loop !11
SelectionDAG
Optimized lowered selection DAG: %bb.4 'main:'
SelectionDAG has 59 nodes:
t0: ch = EntryToken
t7: i64,ch = CopyFromReg t0, Register:i64 %8
t8: i64 = add FrameIndex:i64<0>, t7
t11: i16,ch = load<(load 2 from %ir.33, !tbaa !4)> t0, t8, undef:i64
t16: i64 = add FrameIndex:i64<1>, t7
t2: i64,ch = CopyFromReg t0, Register:i64 %7
t20: i64 = add t2, t7
t22: i64 = add t20, Constant:i64<-4>
t18: i16 = add t59, Constant:i16<1>
t61: ch = store<(store 2 into %ir.37, !tbaa !4)> t59:1, t18, t16, undef:i64
t13: i16 = add t11, Constant:i16<1>
t14: ch = store<(store 2 into %ir.33, !tbaa !4)> t11:1, t13, t8, undef:i64
t63: ch = TokenFactor t61, t14
t23: i16,ch = load<(load 2 from %ir.scevgep21, !tbaa !4)> t63, t22, undef:i64
t4: i64,ch = CopyFromReg t0, Register:i64 %6
t26: i64 = add t4, t7
t28: i64 = add t26, Constant:i64<-2>
t24: i16 = add t23, Constant:i16<1>
t25: ch = store<(store 2 into %ir.scevgep21, !tbaa !4)> t23:1, t24, t22, undef:i64
t29: i16,ch = load<(load 2 from %ir.scevgep11, !tbaa !4)> t25, t28, undef:i64
t32: i64 = add t20, Constant:i64<-2>
t30: i16 = add t29, Constant:i16<1>
t31: ch = store<(store 2 into %ir.scevgep11, !tbaa !4)> t29:1, t30, t28, undef:i64
t33: i16,ch = load<(load 2 from %ir.scevgep24, !tbaa !4)> t31, t32, undef:i64
t34: i16 = add t33, Constant:i16<1>
t35: ch = store<(store 2 into %ir.scevgep24, !tbaa !4)> t33:1, t34, t32, undef:i64
t36: i16,ch = load<(load 2 from %ir.uglygep2, !tbaa !4)> t35, t26, undef:i64
t37: i16 = add t36, Constant:i16<1>
t38: ch = store<(store 2 into %ir.uglygep2, !tbaa !4)> t36:1, t37, t26, undef:i64
t39: i16,ch = load<(load 2 from %ir.uglygep1415, !tbaa !4)> t38, t20, undef:i64
t43: i64 = add t26, Constant:i64<2>
t40: i16 = add t39, Constant:i16<1>
t41: ch = store<(store 2 into %ir.uglygep1415, !tbaa !4)> t39:1, t40, t20, undef:i64
t44: i16,ch = load<(load 2 from %ir.scevgep8, !tbaa !4)> t41, t43, undef:i64
t48: i64 = add nuw nsw t7, Constant:i64<8>
t59: i16,ch = load<(load 2 from %ir.37, !tbaa !4)> t0, t16, undef:i64
t50: ch = CopyToReg t0, Register:i64 %9, t48
t45: i16 = add t44, Constant:i16<1>
t46: ch = store<(store 2 into %ir.scevgep8, !tbaa !4)> t44:1, t45, t43, undef:i64
t55: ch = TokenFactor t50, t46
t53: i1 = setcc t48, Constant:i64<2000>, seteq:ch
t56: ch = brcond t55, t53, BasicBlock:ch< 0x5584eea9d1f0>
t58: ch = br t56, BasicBlock:ch< 0x5584eea9d2c8>
So I want to know the way to utilize IR metadata for my original backend.