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