// RUN: llvm-tblgen -gen-compress-inst-emitter -I %p/../../../include %s 2>&1 | FileCheck %s include "llvm/Target/Target.td" def ArchInstrInfo : InstrInfo { } def ArchAsmWriter : AsmWriter { int PassSubtarget = 1; } def Arch : Target { let InstructionSet = ArchInstrInfo; let AssemblyWriters = [ArchAsmWriter]; } def Reg0 : Register<"reg0"> { let HWEncoding{4-0} = 0; } def Reg1 : Register<"reg1"> { let HWEncoding{4-0} = 1; } def Regs : RegisterClass<"Arch", [i32], 32, (add Reg0, Reg1)>; def RegsC : RegisterClass<"Arch", [i32], 32, (sub Regs, Reg0)>; def simm6 : Operand, ImmLeaf(Imm);}]> { let MCOperandPredicate = [{ int64_t Imm; if (!MCOp.evaluateAsConstantImm(Imm)) return false; return isInt<6>(Imm); }]; } def simm12 : Operand, ImmLeaf(Imm);}]> { let MCOperandPredicate = [{ int64_t Imm; if (!MCOp.evaluateAsConstantImm(Imm)) return false; return isInt<12>(Imm); }]; } def MemOpnd : Operand { let MIOperandInfo = (ops Regs, simm12); } def MemOpndC : Operand { let MIOperandInfo = (ops RegsC, simm6); } def BigInst : Instruction { let Namespace = "MyNS"; let OutOperandList = (outs Regs:$dst); let InOperandList = (ins MemOpnd:$addr); let Size = 4; let AsmString = "big $dst, $addr"; } def SmallInst : Instruction { let Namespace = "MyNS"; let OutOperandList = (outs RegsC:$dst); let InOperandList = (ins MemOpndC:$addr); let Size = 2; let AsmString = "small $dst, $addr"; } def : CompressPat<(BigInst RegsC:$dst, RegsC:$src, simm6:$imm), (SmallInst RegsC:$dst, RegsC:$src, simm6:$imm)>; def BigInst2 : Instruction { let Namespace = "MyNS"; let OutOperandList = (outs Regs:$dst); let InOperandList = (ins MemOpnd:$addr); let Size = 4; let AsmString = "big $dst, $addr"; } def SmallInst2 : Instruction { let Namespace = "MyNS"; let OutOperandList = (outs RegsC:$dst); let InOperandList = (ins RegsC:$src, simm6:$imm); let Size = 2; let AsmString = "small $dst, $src, $imm"; } def : CompressPat<(BigInst2 RegsC:$dst, RegsC:$src, simm6:$imm), (SmallInst2 RegsC:$dst, RegsC:$src, simm6:$imm)>; def BigInst3 : Instruction { let Namespace = "MyNS"; let OutOperandList = (outs Regs:$dst); let InOperandList = (ins Regs:$src, simm12:$imm); let Size = 4; let AsmString = "big $dst, $src, $imm"; } def SmallInst3 : Instruction { let Namespace = "MyNS"; let OutOperandList = (outs RegsC:$dst); let InOperandList = (ins MemOpndC:$addr); let Size = 2; let AsmString = "small $dst, $addr"; } def : CompressPat<(BigInst3 RegsC:$dst, RegsC:$src, simm6:$imm), (SmallInst3 RegsC:$dst, RegsC:$src, simm6:$imm)>; // CHECK-LABEL: ArchValidateMCOperandForCompress // CHECK: // simm6 // CHECK: return isInt<6>(Imm); // CHECK-LABEL: compressInst // CHECK: case Arch::BigInst // CHECK-NEXT: if (MI.getOperand(0).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) && // CHECK-NEXT: MI.getOperand(1).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) && // CHECK-NEXT: ArchValidateMCOperandForCompress(MI.getOperand(2), STI, 1 /* simm6 */)) { // CHECK-NEXT: // small $dst, $addr // CHECK-NEXT: OutInst.setOpcode(Arch::SmallInst); // CHECK-NEXT: // Operand: dst // CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); // CHECK-NEXT: // Operand: addr // CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); // CHECK-NEXT: OutInst.addOperand(MI.getOperand(2)); // CHECK-NEXT: OutInst.setLoc(MI.getLoc()); // CHECK-NEXT: return true; // CHECK-NEXT: } // if // CHECK: case Arch::BigInst2 // CHECK-NEXT: if (MI.getOperand(0).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) && // CHECK-NEXT: MI.getOperand(1).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) && // CHECK-NEXT: ArchValidateMCOperandForCompress(MI.getOperand(2), STI, 1 /* simm6 */)) { // CHECK-NEXT: // small $dst, $src, $imm // CHECK-NEXT: OutInst.setOpcode(Arch::SmallInst2); // CHECK-NEXT: // Operand: dst // CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); // CHECK-NEXT: // Operand: src // CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); // CHECK-NEXT: // Operand: imm // CHECK-NEXT: OutInst.addOperand(MI.getOperand(2)); // CHECK-NEXT: OutInst.setLoc(MI.getLoc()); // CHECK-NEXT: return true; // CHECK-NEXT: } // if // CHECK: case Arch::BigInst3 // CHECK-NEXT: if (MI.getOperand(0).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) && // CHECK-NEXT: MI.getOperand(1).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) && // CHECK-NEXT: ArchValidateMCOperandForCompress(MI.getOperand(2), STI, 1 /* simm6 */)) { // CHECK-NEXT: // small $dst, $addr // CHECK-NEXT: OutInst.setOpcode(Arch::SmallInst3); // CHECK-NEXT: // Operand: dst // CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); // CHECK-NEXT: // Operand: addr // CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); // CHECK-NEXT: OutInst.addOperand(MI.getOperand(2)); // CHECK-NEXT: OutInst.setLoc(MI.getLoc()); // CHECK-NEXT: return true; // CHECK-NEXT: } // if // CHECK-LABEL: ArchValidateMCOperandForUncompress // CHECK: // simm6 // CHECK: return isInt<6>(Imm); // CHECK-LABEL: uncompressInst // CHECK: case Arch::SmallInst: // CHECK-NEXT: if (MI.getOperand(0).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) && // CHECK-NEXT: MI.getOperand(1).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) && // CHECK-NEXT: ArchValidateMCOperandForUncompress(MI.getOperand(2), STI, 1 /* simm6 */) && // CHECK-NEXT: ArchValidateMCOperandForUncompress(MI.getOperand(2), STI, 2 /* simm12 */)) // CHECK-NEXT: // big $dst, $addr // CHECK-NEXT: OutInst.setOpcode(Arch::BigInst); // CHECK-NEXT: // Operand: dst // CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); // CHECK-NEXT: // Operand: addr // CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); // CHECK-NEXT: OutInst.addOperand(MI.getOperand(2)); // CHECK-NEXT: OutInst.setLoc(MI.getLoc()); // CHECK-NEXT: return true; // CHECK-NEXT: } // if // CHECK: case Arch::SmallInst2: // CHECK-NEXT: if (MI.getOperand(0).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) && // CHECK-NEXT: MI.getOperand(1).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) && // CHECK-NEXT: ArchValidateMCOperandForUncompress(MI.getOperand(2), STI, 1 /* simm6 */) && // CHECK-NEXT: ArchValidateMCOperandForUncompress(MI.getOperand(2), STI, 2 /* simm12 */)) { // CHECK-NEXT: // big $dst, $addr // CHECK-NEXT: OutInst.setOpcode(Arch::BigInst2); // CHECK-NEXT: // Operand: dst // CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); // CHECK-NEXT: // Operand: addr // CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); // CHECK-NEXT: OutInst.addOperand(MI.getOperand(2)); // CHECK-NEXT: OutInst.setLoc(MI.getLoc()); // CHECK-NEXT: return true; // CHECK-NEXT: } // if // CHECK: case Arch::SmallInst3: // CHECK-NEXT: if (MI.getOperand(0).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) && // CHECK-NEXT: MI.getOperand(1).isReg() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) && // CHECK-NEXT: ArchValidateMCOperandForUncompress(MI.getOperand(2), STI, 1 /* simm6 */) && // CHECK-NEXT: ArchValidateMCOperandForUncompress(MI.getOperand(2), STI, 2 /* simm12 */)) { // CHECK-NEXT: // big $dst, $src, $imm // CHECK-NEXT: OutInst.setOpcode(Arch::BigInst3); // CHECK-NEXT: // Operand: dst // CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); // CHECK-NEXT: // Operand: src // CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); // CHECK-NEXT: // Operand: imm // CHECK-NEXT: OutInst.addOperand(MI.getOperand(2)); // CHECK-NEXT: OutInst.setLoc(MI.getLoc()); // CHECK-NEXT: return true; // CHECK-NEXT: } // if // CHECK-LABEL: ArchValidateMachineOperand // CHECK: // simm6 // CHECK: return isInt<6>(Imm); // CHECK-LABEL: isCompressibleInst // CHECK: case Arch::BigInst: { // CHECK-NEXT: if (MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) && // CHECK-NEXT: MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) && // CHECK-NEXT: MI.getOperand(2).isImm() && // CHECK-NEXT: ArchValidateMachineOperand(MI.getOperand(2), &STI, 1 /* simm6 */)) { // CHECK-NEXT: // small $dst, $addr // CHECK-NEXT: // Operand: dst // CHECK-NEXT: // Operand: addr // CHECK-NEXT: return true; // CHECK-NEXT: } // if // CHECK: case Arch::BigInst2: { // CHECK-NEXT: if (MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) && // CHECK-NEXT: MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) && // CHECK-NEXT: MI.getOperand(2).isImm() && // CHECK-NEXT: ArchValidateMachineOperand(MI.getOperand(2), &STI, 1 /* simm6 */)) { // CHECK-NEXT: // small $dst, $src, $imm // CHECK-NEXT: // Operand: dst // CHECK-NEXT: // Operand: src // CHECK-NEXT: // Operand: imm // CHECK-NEXT: return true; // CHECK-NEXT: } // if // CHECK: case Arch::BigInst3: { // CHECK-NEXT: if (MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) && // CHECK-NEXT: MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() && // CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) && // CHECK-NEXT: MI.getOperand(2).isImm() && // CHECK-NEXT: ArchValidateMachineOperand(MI.getOperand(2), &STI, 1 /* simm6 */)) { // CHECK-NEXT: // small $dst, $addr // CHECK-NEXT: // Operand: dst // CHECK-NEXT: // Operand: addr // CHECK-NEXT: return true; // CHECK-NEXT: } // if