1// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include %s -o %t
2// RUN: FileCheck --check-prefix=ADD %s < %t
3// RUN: FileCheck --check-prefix=ADDINT %s < %t
4// RUN: FileCheck --check-prefix=SUB %s < %t
5// RUN: FileCheck --check-prefix=MULINT %s < %t
6
7include "llvm/Target/Target.td"
8
9def TestInstrInfo : InstrInfo;
10def TestTarget : Target {
11    let InstructionSet = TestInstrInfo;
12}
13
14class TestEncoding : Instruction {
15  field bits<32> Inst;
16}
17
18class TestReg<int index> : Register<"R"#index, []> {
19    let HWEncoding{15...4} = 0;
20    let HWEncoding{3...0} = !cast<bits<4>>(index);
21}
22foreach i = 0...15 in
23  def "R"#i : TestReg<i>;
24
25def Reg : RegisterClass<"TestTarget", [i32], 32, (sequence "R%d", 0, 15)>;
26
27def IntOperand: Operand<i32>;
28def OptionalIntOperand: OperandWithDefaultOps<i32, (ops (i32 0))>;
29
30class RRI<string Mnemonic, bits<4> Opcode> : TestEncoding {
31  dag OutOperandList = (outs Reg:$dest);
32  dag InOperandList = (ins Reg:$src1, Reg:$src2, OptionalIntOperand:$imm);
33  string AsmString = Mnemonic # " $dest1, $src1, $src2, #$imm";
34  string AsmVariantName = "";
35  field bits<4> dest;
36  field bits<4> src1;
37  field bits<4> src2;
38  field bits<16> imm;
39  let Inst{31...28} = Opcode;
40  let Inst{27...24} = dest;
41  let Inst{23...20} = src1;
42  let Inst{19...16} = src2;
43  let Inst{15...0} = imm;
44}
45
46def AddRRI : RRI<"add", 0b0001>;
47
48// I define one of these intrinsics with IntrNoMem and the other
49// without it, so that they'll match different top-level DAG opcodes
50// (INTRINSIC_WO_CHAIN and INTRINSIC_W_CHAIN), which makes the
51// FileCheck-herding easier, because every case I want to detect
52// should show up as a separate top-level switch element.
53def int_addplus1 : Intrinsic<
54    [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
55def int_mul3 : Intrinsic<
56    [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>;
57
58def AddPat  : Pat<(add i32:$x, i32:$y),
59                  (AddRRI Reg:$x, Reg:$y)>;
60def Add1Pat : Pat<(int_addplus1 i32:$x, i32:$y),
61                  (AddRRI Reg:$x, Reg:$y, (i32 1))>;
62
63def SubRRI : RRI<"sub", 0b0010> {
64  let Pattern = [(set Reg:$dest, (sub Reg:$src1, Reg:$src2))];
65}
66
67def MulRRI : RRI<"mul", 0b0011> {
68  let Pattern = [(set Reg:$dest, (int_mul3 Reg:$src1, Reg:$src2, i32:$imm))];
69}
70
71def MulIRR : RRI<"mul2", 0b0100> {
72  let InOperandList = (ins OptionalIntOperand:$imm, Reg:$src1, Reg:$src2);
73}
74def MulIRRPat : Pat<(mul i32:$x, i32:$y), (MulIRR Reg:$x, Reg:$y)>;
75
76// ADD: SwitchOpcode{{.*}}TARGET_VAL(ISD::ADD)
77// ADD-NEXT: OPC_RecordChild0
78// ADD-NEXT: OPC_RecordChild1
79// ADD-NEXT: OPC_EmitInteger, MVT::i32, 0
80// ADD-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::AddRRI)
81
82// ADDINT: SwitchOpcode{{.*}}TARGET_VAL(ISD::INTRINSIC_WO_CHAIN)
83// ADDINT-NEXT: OPC_CheckChild0Integer
84// ADDINT-NEXT: OPC_RecordChild1
85// ADDINT-NEXT: OPC_RecordChild2
86// ADDINT-NEXT: OPC_EmitInteger, MVT::i32, 1
87// ADDINT-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::AddRRI)
88
89// SUB: SwitchOpcode{{.*}}TARGET_VAL(ISD::SUB)
90// SUB-NEXT: OPC_RecordChild0
91// SUB-NEXT: OPC_RecordChild1
92// SUB-NEXT: OPC_EmitInteger, MVT::i32, 0
93// SUB-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::SubRRI)
94
95// MULINT: SwitchOpcode{{.*}}TARGET_VAL(ISD::INTRINSIC_W_CHAIN)
96// MULINT-NEXT: OPC_RecordNode
97// MULINT-NEXT: OPC_CheckChild1Integer
98// MULINT-NEXT: OPC_RecordChild2
99// MULINT-NEXT: OPC_RecordChild3
100// MULINT-NEXT: OPC_RecordChild4
101// MULINT-NEXT: OPC_EmitMergeInputChains
102// MULINT-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::MulRRI)
103
104// MUL: SwitchOpcode{{.*}}TARGET_VAL(ISD::MUL)
105// MUL-NEXT: OPC_EmitInteger, MVT::i32, 0
106// MUL-NEXT: OPC_RecordChild0
107// MUL-NEXT: OPC_RecordChild1
108// MUL-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::MulRRI)
109