diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td index 9bbcb6f3aedf5..5901bd8184c67 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -3028,8 +3028,12 @@ class BaseAddSubEReg64 + RegisterClass src1Regtype, dag src2> + : InstAlias; +class AddSubRegAlias64 : InstAlias; @@ -3097,22 +3101,22 @@ multiclass AddSub(NAME#"Wrs"), - GPR32, GPR32, GPR32, 0>; + GPR32, GPR32, (arith_shifted_reg32 GPR32:$src2, 0)>; def : AddSubRegAlias(NAME#"Xrs"), - GPR64, GPR64, GPR64, 0>; + GPR64, GPR64, (arith_shifted_reg64 GPR64:$src2, 0)>; // Register/register aliases with no shift when either the destination or // first source register is SP. def : AddSubRegAlias(NAME#"Wrx"), - GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0 + GPR32sponly, GPR32sp, + (arith_extended_reg32_i32 GPR32:$src2, 16)>; // UXTW #0 def : AddSubRegAlias(NAME#"Wrx"), - GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0 - def : AddSubRegAlias(NAME#"Xrx64"), - GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0 - def : AddSubRegAlias(NAME#"Xrx64"), - GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0 + GPR32sp, GPR32sponly, + (arith_extended_reg32_i32 GPR32:$src2, 16)>; // UXTW #0 + def : AddSubRegAlias64(NAME#"Xrx64"), + GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0 + def : AddSubRegAlias64(NAME#"Xrx64"), + GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0 } multiclass AddSubS(NAME#"Xri") XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>; def : InstAlias(NAME#"Wrx") - WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>; + WZR, GPR32sp:$src1, + (arith_extended_reg32_i32 GPR32:$src2, arith_extend:$sh)), 4>; def : InstAlias(NAME#"Xrx") - XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>; + XZR, GPR64sp:$src1, + (arith_extended_reg32_i64 GPR32:$src2, arith_extend:$sh)), 4>; def : InstAlias(NAME#"Xrx64") XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>; def : InstAlias(NAME#"Wrs") - WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>; + WZR, GPR32:$src1, + (arith_shifted_reg32 GPR32:$src2, arith_shift32:$sh)), 4>; def : InstAlias(NAME#"Xrs") - XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>; + XZR, GPR64:$src1, + (arith_shifted_reg64 GPR64:$src2, arith_shift64:$sh)), 4>; // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm def : InstSubst(NAME#"Wri") @@ -3194,27 +3202,28 @@ multiclass AddSubS(NAME#"Wrs") - WZR, GPR32:$src1, GPR32:$src2, 0), 5>; + WZR, GPR32:$src1, (arith_shifted_reg32 GPR32:$src2, 0)), 5>; def : InstAlias(NAME#"Xrs") - XZR, GPR64:$src1, GPR64:$src2, 0), 5>; + XZR, GPR64:$src1, (arith_shifted_reg64 GPR64:$src2, 0)), 5>; def : InstAlias(NAME#"Wrx") - WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>; + WZR, GPR32sponly:$src1, + (arith_extended_reg32_i32 GPR32:$src2, 16)), 5>; def : InstAlias(NAME#"Xrx64") XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>; // Register/register aliases with no shift when SP is not used. def : AddSubRegAlias(NAME#"Wrs"), - GPR32, GPR32, GPR32, 0>; + GPR32, GPR32, (arith_shifted_reg32 GPR32:$src2, 0)>; def : AddSubRegAlias(NAME#"Xrs"), - GPR64, GPR64, GPR64, 0>; + GPR64, GPR64, (arith_shifted_reg64 GPR64:$src2, 0)>; // Register/register aliases with no shift when the first source register // is SP. def : AddSubRegAlias(NAME#"Wrx"), - GPR32, GPR32sponly, GPR32, 16>; // UXTW #0 - def : AddSubRegAlias(NAME#"Xrx64"), - GPR64, GPR64sponly, GPR64, 24>; // UXTX #0 + GPR32, GPR32sponly, + (arith_extended_reg32_i32 GPR32:$src2, 16)>; // UXTW #0 + def : AddSubRegAlias64(NAME#"Xrx64"), + GPR64, GPR64sponly, GPR64, 24>; // UXTX #0 } class AddSubG @@ -3399,9 +3408,10 @@ class BaseLogicalSReg opc, bit N, RegisterClass regtype, } // Aliases for register+register logical instructions. -class LogicalRegAlias +class LogicalRegAlias : InstAlias; + (inst regtype:$dst, regtype:$src1, op2)>; multiclass LogicalImm opc, string mnemonic, SDNode OpNode, string Alias> { @@ -3473,10 +3483,10 @@ multiclass LogicalReg opc, bit N, string mnemonic, let Inst{31} = 1; } - def : LogicalRegAlias(NAME#"Wrs"), GPR32>; - def : LogicalRegAlias(NAME#"Xrs"), GPR64>; + def : LogicalRegAlias(NAME#"Wrs"), + GPR32, (logical_shifted_reg32 GPR32:$src2, 0)>; + def : LogicalRegAlias(NAME#"Xrs"), + GPR64, (logical_shifted_reg64 GPR64:$src2, 0)>; } // Split from LogicalReg to allow setting NZCV Defs @@ -3496,10 +3506,10 @@ multiclass LogicalRegS opc, bit N, string mnemonic, } } // Defs = [NZCV] - def : LogicalRegAlias(NAME#"Wrs"), GPR32>; - def : LogicalRegAlias(NAME#"Xrs"), GPR64>; + def : LogicalRegAlias(NAME#"Wrs"), + GPR32, (logical_shifted_reg32 GPR32:$src2, 0)>; + def : LogicalRegAlias(NAME#"Xrs"), + GPR64, (logical_shifted_reg64 GPR64:$src2, 0)>; } //--- @@ -3987,9 +3997,10 @@ class LoadStore8RO sz, bit V, bits<2> opc, string asm, dag ins, let Inst{4-0} = Rt; } -class ROInstAlias +class ROInstAlias : InstAlias; + (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, (ext 0, 0))>; multiclass Load8RO sz, bit V, bits<2> opc, DAGOperand regtype, string asm, ValueType Ty, SDPatternOperator loadop> { @@ -4015,7 +4026,7 @@ multiclass Load8RO sz, bit V, bits<2> opc, DAGOperand regtype, let Inst{13} = 0b1; } - def : ROInstAlias(NAME # "roX")>; + def : ROInstAlias(NAME # "roX"), ro_Xextend8>; } multiclass Store8RO sz, bit V, bits<2> opc, DAGOperand regtype, @@ -4040,7 +4051,7 @@ multiclass Store8RO sz, bit V, bits<2> opc, DAGOperand regtype, let Inst{13} = 0b1; } - def : ROInstAlias(NAME # "roX")>; + def : ROInstAlias(NAME # "roX"), ro_Xextend8>; } class LoadStore16RO sz, bit V, bits<2> opc, string asm, dag ins, @@ -4087,7 +4098,7 @@ multiclass Load16RO sz, bit V, bits<2> opc, DAGOperand regtype, let Inst{13} = 0b1; } - def : ROInstAlias(NAME # "roX")>; + def : ROInstAlias(NAME # "roX"), ro_Xextend16>; } multiclass Store16RO sz, bit V, bits<2> opc, DAGOperand regtype, @@ -4112,7 +4123,7 @@ multiclass Store16RO sz, bit V, bits<2> opc, DAGOperand regtype, let Inst{13} = 0b1; } - def : ROInstAlias(NAME # "roX")>; + def : ROInstAlias(NAME # "roX"), ro_Xextend16>; } class LoadStore32RO sz, bit V, bits<2> opc, string asm, dag ins, @@ -4159,7 +4170,7 @@ multiclass Load32RO sz, bit V, bits<2> opc, DAGOperand regtype, let Inst{13} = 0b1; } - def : ROInstAlias(NAME # "roX")>; + def : ROInstAlias(NAME # "roX"), ro_Xextend32>; } multiclass Store32RO sz, bit V, bits<2> opc, DAGOperand regtype, @@ -4184,7 +4195,7 @@ multiclass Store32RO sz, bit V, bits<2> opc, DAGOperand regtype, let Inst{13} = 0b1; } - def : ROInstAlias(NAME # "roX")>; + def : ROInstAlias(NAME # "roX"), ro_Xextend32>; } class LoadStore64RO sz, bit V, bits<2> opc, string asm, dag ins, @@ -4231,7 +4242,7 @@ multiclass Load64RO sz, bit V, bits<2> opc, DAGOperand regtype, let Inst{13} = 0b1; } - def : ROInstAlias(NAME # "roX")>; + def : ROInstAlias(NAME # "roX"), ro_Xextend64>; } multiclass Store64RO sz, bit V, bits<2> opc, DAGOperand regtype, @@ -4256,7 +4267,7 @@ multiclass Store64RO sz, bit V, bits<2> opc, DAGOperand regtype, let Inst{13} = 0b1; } - def : ROInstAlias(NAME # "roX")>; + def : ROInstAlias(NAME # "roX"), ro_Xextend64>; } class LoadStore128RO sz, bit V, bits<2> opc, string asm, dag ins, @@ -4303,7 +4314,7 @@ multiclass Load128RO sz, bit V, bits<2> opc, DAGOperand regtype, let Inst{13} = 0b1; } - def : ROInstAlias(NAME # "roX")>; + def : ROInstAlias(NAME # "roX"), ro_Xextend128>; } multiclass Store128RO sz, bit V, bits<2> opc, DAGOperand regtype, @@ -4324,7 +4335,7 @@ multiclass Store128RO sz, bit V, bits<2> opc, DAGOperand regtype, let Inst{13} = 0b1; } - def : ROInstAlias(NAME # "roX")>; + def : ROInstAlias(NAME # "roX"), ro_Xextend128>; } let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in @@ -4373,9 +4384,7 @@ multiclass PrefetchRO sz, bit V, bits<2> opc, string asm> { let Inst{13} = 0b1; } - def : InstAlias<"prfm $Rt, [$Rn, $Rm]", - (!cast(NAME # "roX") prfop:$Rt, - GPR64sp:$Rn, GPR64:$Rm, 0, 0)>; + def : ROInstAlias<"prfm", prfop, !cast(NAME # "roX"), ro_Xextend64>; } //--- diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index a060a2f597ccd..8596f7adeec4f 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2416,13 +2416,17 @@ defm ADD : AddSub<0, "add", "sub", add>; defm SUB : AddSub<1, "sub", "add">; def : InstAlias<"mov $dst, $src", - (ADDWri GPR32sponly:$dst, GPR32sp:$src, 0, 0)>; + (ADDWri GPR32sponly:$dst, GPR32sp:$src, + (addsub_shifted_imm32 0, 0))>; def : InstAlias<"mov $dst, $src", - (ADDWri GPR32sp:$dst, GPR32sponly:$src, 0, 0)>; + (ADDWri GPR32sp:$dst, GPR32sponly:$src, + (addsub_shifted_imm32 0, 0))>; def : InstAlias<"mov $dst, $src", - (ADDXri GPR64sponly:$dst, GPR64sp:$src, 0, 0)>; + (ADDXri GPR64sponly:$dst, GPR64sp:$src, + (addsub_shifted_imm64 0, 0))>; def : InstAlias<"mov $dst, $src", - (ADDXri GPR64sp:$dst, GPR64sponly:$src, 0, 0)>; + (ADDXri GPR64sp:$dst, GPR64sponly:$src, + (addsub_shifted_imm64 0, 0))>; defm ADDS : AddSubS<0, "adds", AArch64add_flag, "cmn", "subs", "cmp">; defm SUBS : AddSubS<1, "subs", AArch64sub_flag, "cmp", "adds", "cmn">; @@ -2482,19 +2486,31 @@ def : Pat<(AArch64sub_flag GPR64:$Rn, neg_addsub_shifted_imm64:$imm), (ADDSXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>; } -def : InstAlias<"neg $dst, $src", (SUBWrs GPR32:$dst, WZR, GPR32:$src, 0), 3>; -def : InstAlias<"neg $dst, $src", (SUBXrs GPR64:$dst, XZR, GPR64:$src, 0), 3>; +def : InstAlias<"neg $dst, $src", + (SUBWrs GPR32:$dst, WZR, + (arith_shifted_reg32 GPR32:$src, 0)), 3>; +def : InstAlias<"neg $dst, $src", + (SUBXrs GPR64:$dst, XZR, + (arith_shifted_reg64 GPR64:$src, 0)), 3>; def : InstAlias<"neg $dst, $src$shift", - (SUBWrs GPR32:$dst, WZR, GPR32:$src, arith_shift32:$shift), 2>; + (SUBWrs GPR32:$dst, WZR, + (arith_shifted_reg32 GPR32:$src, arith_shift32:$shift)), 2>; def : InstAlias<"neg $dst, $src$shift", - (SUBXrs GPR64:$dst, XZR, GPR64:$src, arith_shift64:$shift), 2>; - -def : InstAlias<"negs $dst, $src", (SUBSWrs GPR32:$dst, WZR, GPR32:$src, 0), 3>; -def : InstAlias<"negs $dst, $src", (SUBSXrs GPR64:$dst, XZR, GPR64:$src, 0), 3>; + (SUBXrs GPR64:$dst, XZR, + (arith_shifted_reg64 GPR64:$src, arith_shift64:$shift)), 2>; + +def : InstAlias<"negs $dst, $src", + (SUBSWrs GPR32:$dst, WZR, + (arith_shifted_reg32 GPR32:$src, 0)), 3>; +def : InstAlias<"negs $dst, $src", + (SUBSXrs GPR64:$dst, XZR, + (arith_shifted_reg64 GPR64:$src, 0)), 3>; def : InstAlias<"negs $dst, $src$shift", - (SUBSWrs GPR32:$dst, WZR, GPR32:$src, arith_shift32:$shift), 2>; + (SUBSWrs GPR32:$dst, WZR, + (arith_shifted_reg32 GPR32:$src, arith_shift32:$shift)), 2>; def : InstAlias<"negs $dst, $src$shift", - (SUBSXrs GPR64:$dst, XZR, GPR64:$src, arith_shift64:$shift), 2>; + (SUBSXrs GPR64:$dst, XZR, + (arith_shifted_reg64 GPR64:$src, arith_shift64:$shift)), 2>; // Unsigned/Signed divide @@ -2921,16 +2937,26 @@ defm ORN : LogicalReg<0b01, 1, "orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>; defm ORR : LogicalReg<0b01, 0, "orr", or>; -def : InstAlias<"mov $dst, $src", (ORRWrs GPR32:$dst, WZR, GPR32:$src, 0), 2>; -def : InstAlias<"mov $dst, $src", (ORRXrs GPR64:$dst, XZR, GPR64:$src, 0), 2>; - -def : InstAlias<"mvn $Wd, $Wm", (ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, 0), 3>; -def : InstAlias<"mvn $Xd, $Xm", (ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, 0), 3>; +def : InstAlias<"mov $dst, $src", + (ORRWrs GPR32:$dst, WZR, + (logical_shifted_reg32 GPR32:$src, 0)), 2>; +def : InstAlias<"mov $dst, $src", + (ORRXrs GPR64:$dst, XZR, + (logical_shifted_reg64 GPR64:$src, 0)), 2>; + +def : InstAlias<"mvn $Wd, $Wm", + (ORNWrs GPR32:$Wd, WZR, + (logical_shifted_reg32 GPR32:$Wm, 0)), 3>; +def : InstAlias<"mvn $Xd, $Xm", + (ORNXrs GPR64:$Xd, XZR, + (logical_shifted_reg64 GPR64:$Xm, 0)), 3>; def : InstAlias<"mvn $Wd, $Wm$sh", - (ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, logical_shift32:$sh), 2>; + (ORNWrs GPR32:$Wd, WZR, + (logical_shifted_reg32 GPR32:$Wm, logical_shift32:$sh)), 2>; def : InstAlias<"mvn $Xd, $Xm$sh", - (ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, logical_shift64:$sh), 2>; + (ORNXrs GPR64:$Xd, XZR, + (logical_shifted_reg64 GPR64:$Xm, logical_shift64:$sh)), 2>; def : InstAlias<"tst $src1, $src2", (ANDSWri WZR, GPR32:$src1, logical_imm32:$src2), 2>; @@ -2938,14 +2964,18 @@ def : InstAlias<"tst $src1, $src2", (ANDSXri XZR, GPR64:$src1, logical_imm64:$src2), 2>; def : InstAlias<"tst $src1, $src2", - (ANDSWrs WZR, GPR32:$src1, GPR32:$src2, 0), 3>; + (ANDSWrs WZR, GPR32:$src1, + (logical_shifted_reg32 GPR32:$src2, 0)), 3>; def : InstAlias<"tst $src1, $src2", - (ANDSXrs XZR, GPR64:$src1, GPR64:$src2, 0), 3>; + (ANDSXrs XZR, GPR64:$src1, + (logical_shifted_reg64 GPR64:$src2, 0)), 3>; def : InstAlias<"tst $src1, $src2$sh", - (ANDSWrs WZR, GPR32:$src1, GPR32:$src2, logical_shift32:$sh), 2>; + (ANDSWrs WZR, GPR32:$src1, + (logical_shifted_reg32 GPR32:$src2, logical_shift32:$sh)), 2>; def : InstAlias<"tst $src1, $src2$sh", - (ANDSXrs XZR, GPR64:$src1, GPR64:$src2, logical_shift64:$sh), 2>; + (ANDSXrs XZR, GPR64:$src1, + (logical_shifted_reg64 GPR64:$src2, logical_shift64:$sh)), 2>; def : Pat<(not GPR32:$Wm), (ORNWrr WZR, GPR32:$Wm)>; diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index c56713783289e..3e5ad17d9b5a9 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -5140,11 +5140,14 @@ multiclass sve_int_dup_imm { (!cast(NAME # _D) ZPR64:$Zd, cpy_imm8_opt_lsl_i64:$imm), 1>; def : InstAlias<"fmov $Zd, #0.0", - (!cast(NAME # _H) ZPR16:$Zd, 0, 0), 1>; + (!cast(NAME # _H) ZPR16:$Zd, + (cpy_imm8_opt_lsl_i16 0, 0)), 1>; def : InstAlias<"fmov $Zd, #0.0", - (!cast(NAME # _S) ZPR32:$Zd, 0, 0), 1>; + (!cast(NAME # _S) ZPR32:$Zd, + (cpy_imm8_opt_lsl_i32 0, 0)), 1>; def : InstAlias<"fmov $Zd, #0.0", - (!cast(NAME # _D) ZPR64:$Zd, 0, 0), 1>; + (!cast(NAME # _D) ZPR64:$Zd, + (cpy_imm8_opt_lsl_i64 0, 0)), 1>; } class sve_int_dup_fpimm sz8_64, Operand fpimmtype, @@ -5522,11 +5525,14 @@ multiclass sve_int_dup_imm_pred_merge { nxv2i64, nxv2i1, i64, SVECpyDupImm64Pat>; def : InstAlias<"fmov $Zd, $Pg/m, #0.0", - (!cast(NAME # _H) ZPR16:$Zd, PPRAny:$Pg, 0, 0), 0>; + (!cast(NAME # _H) ZPR16:$Zd, PPRAny:$Pg, + (cpy_imm8_opt_lsl_i16 0, 0)), 0>; def : InstAlias<"fmov $Zd, $Pg/m, #0.0", - (!cast(NAME # _S) ZPR32:$Zd, PPRAny:$Pg, 0, 0), 0>; + (!cast(NAME # _S) ZPR32:$Zd, PPRAny:$Pg, + (cpy_imm8_opt_lsl_i32 0, 0)), 0>; def : InstAlias<"fmov $Zd, $Pg/m, #0.0", - (!cast(NAME # _D) ZPR64:$Zd, PPRAny:$Pg, 0, 0), 0>; + (!cast(NAME # _D) ZPR64:$Zd, PPRAny:$Pg, + (cpy_imm8_opt_lsl_i64 0, 0)), 0>; def : Pat<(vselect PPRAny:$Pg, (SVEDup0), (nxv8f16 ZPR:$Zd)), (!cast(NAME # _H) $Zd, $Pg, 0, 0)>; diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 9eb9114069143..e50740f7d57c5 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -160,7 +160,7 @@ def CondCodeOperand : AsmOperandClass { let DefaultMethod = "defaultCondCodeOp"; let IsOptional = true; } -def pred : PredicateOperand { let PrintMethod = "printPredicateOperand"; let ParserMatchClass = CondCodeOperand; diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index d6387ff848593..356aba914e221 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -6469,7 +6469,7 @@ def : ARMInstAlias<"neg${s}${p} $Rd, $Rm", (RSBri GPR:$Rd, GPR:$Rm, 0, pred:$p, cc_out:$s)>; // Pre-v6, 'mov r0, r0' was used as a NOP encoding. -def : InstAlias<"nop${p}", (MOVr R0, R0, pred:$p, zero_reg), 0>, +def : InstAlias<"nop${p}", (MOVr R0, R0, pred:$p, (cc_out zero_reg)), 0>, Requires<[IsARM, NoV6]>; // MUL/UMLAL/SMLAL/UMULL/SMULL are available on all arches, but diff --git a/llvm/lib/Target/ARM/ARMInstrNEON.td b/llvm/lib/Target/ARM/ARMInstrNEON.td index 3335f52f15555..63d2e4e0a535e 100644 --- a/llvm/lib/Target/ARM/ARMInstrNEON.td +++ b/llvm/lib/Target/ARM/ARMInstrNEON.td @@ -95,28 +95,24 @@ def VectorIndex8 : Operand, ImmLeaf { let ParserMatchClass = VectorIndex8Operand; let PrintMethod = "printVectorIndex"; - let MIOperandInfo = (ops i32imm); } def VectorIndex16 : Operand, ImmLeaf { let ParserMatchClass = VectorIndex16Operand; let PrintMethod = "printVectorIndex"; - let MIOperandInfo = (ops i32imm); } def VectorIndex32 : Operand, ImmLeaf { let ParserMatchClass = VectorIndex32Operand; let PrintMethod = "printVectorIndex"; - let MIOperandInfo = (ops i32imm); } def VectorIndex64 : Operand, ImmLeaf { let ParserMatchClass = VectorIndex64Operand; let PrintMethod = "printVectorIndex"; - let MIOperandInfo = (ops i32imm); } // Register list of one D register. diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index b69bc601a0cdc..46746dde384af 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -1209,8 +1209,9 @@ def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255_expr:$imm8), IIC_iMOVi, } // Because we have an explicit tMOVSr below, we need an alias to handle // the immediate "movs" form here. Blech. -def : tInstAlias <"movs $Rdn, $imm8", - (tMOVi8 tGPR:$Rdn, CPSR, imm0_255_expr:$imm8, 14, zero_reg)>; +def : tInstAlias<"movs $Rdn, $imm8", + (tMOVi8 tGPR:$Rdn, (s_cc_out CPSR), + imm0_255_expr:$imm8, (pred 14, zero_reg))>; // A7-73: MOV(2) - mov setting flag. @@ -1764,7 +1765,8 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { // In Thumb1, "nop" is encoded as a "mov r8, r8". Technically, the bf00 // encoding is available on ARMv6K, but we don't differentiate that finely. -def : InstAlias<"nop", (tMOVr R8, R8, 14, zero_reg), 0>, Requires<[IsThumb, IsThumb1Only]>; +def : InstAlias<"nop", (tMOVr R8, R8, (pred 14, zero_reg)), 0>, + Requires<[IsThumb, IsThumb1Only]>; // "neg" is and alias for "rsb rd, rn, #0" diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td index 9f80af07df0fc..ed24e9ddd8f4e 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -2222,11 +2222,11 @@ def t2MOVr : T2sTwoReg<(outs GPRnopc:$Rd), (ins GPRnopc:$Rm), IIC_iMOVr, let Inst{7-4} = 0b0000; } def : t2InstAlias<"mov${p}.w $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPRnopc:$Rm, - pred:$p, zero_reg)>; + pred:$p, (cc_out zero_reg))>; def : t2InstAlias<"movs${p}.w $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPRnopc:$Rm, - pred:$p, CPSR)>; + pred:$p, (cc_out CPSR))>; def : t2InstAlias<"movs${p} $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPRnopc:$Rm, - pred:$p, CPSR)>; + pred:$p, (cc_out CPSR))>; // AddedComplexity to ensure isel tries t2MOVi before t2MOVi16. let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1, @@ -2244,14 +2244,14 @@ def t2MOVi : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), IIC_iMOVi, // cc_out is handled as part of the explicit mnemonic in the parser for 'mov'. // Use aliases to get that to play nice here. def : t2InstAlias<"movs${p}.w $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm, - pred:$p, CPSR)>; + pred:$p, (cc_out CPSR))>; def : t2InstAlias<"movs${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm, - pred:$p, CPSR)>; + pred:$p, (cc_out CPSR))>; def : t2InstAlias<"mov${p}.w $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm, - pred:$p, zero_reg)>; + pred:$p, (cc_out zero_reg))>; def : t2InstAlias<"mov${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm, - pred:$p, zero_reg)>; + pred:$p, (cc_out zero_reg))>; let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins imm0_65535_expr:$imm), IIC_iMOVi, @@ -5122,8 +5122,10 @@ def : InstAlias<"isb${p}.w", (t2ISB 0xf, pred:$p), 0>, Requires<[HasDB]>; // Non-predicable aliases of a predicable DSB: the predicate is (14, zero_reg) where // 14 = AL (always execute) and zero_reg = "instruction doesn't read the CPSR". -def : InstAlias<"ssbb", (t2DSB 0x0, 14, zero_reg), 1>, Requires<[HasDB, IsThumb2]>; -def : InstAlias<"pssbb", (t2DSB 0x4, 14, zero_reg), 1>, Requires<[HasDB, IsThumb2]>; +def : InstAlias<"ssbb", (t2DSB 0x0, (pred 14, zero_reg)), 1>, + Requires<[HasDB, IsThumb2]>; +def : InstAlias<"pssbb", (t2DSB 0x4, (pred 14, zero_reg)), 1>, + Requires<[HasDB, IsThumb2]>; // Armv8-R 'Data Full Barrier' def : InstAlias<"dfb${p}", (t2DSB 0xc, pred:$p), 1>, Requires<[HasDFB]>; @@ -5340,7 +5342,8 @@ def : t2InstAlias<"sxth${p} $Rd, $Rm$rot", // "mov Rd, t2_so_imm_not" can be handled via "mvn" in assembly, just like // for isel. def : t2InstSubst<"mov${p} $Rd, $imm", - (t2MVNi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, zero_reg)>; + (t2MVNi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, + (cc_out zero_reg))>; def : t2InstSubst<"mvn${s}${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, s_cc_out:$s)>; // Same for AND <--> BIC diff --git a/llvm/lib/Target/Lanai/LanaiInstrInfo.td b/llvm/lib/Target/Lanai/LanaiInstrInfo.td index 6feed27b7047b..8950cb85715d9 100644 --- a/llvm/lib/Target/Lanai/LanaiInstrInfo.td +++ b/llvm/lib/Target/Lanai/LanaiInstrInfo.td @@ -402,7 +402,7 @@ def : Pat<(LanaiSubbF GPR:$Rs1, i32lo16z:$imm), def : Pat<(LanaiSubbF GPR:$Rs1, i32hi16:$imm), (SUBB_F_I_HI GPR:$Rs1, i32hi16:$imm)>; -def : InstAlias<"mov $src, $dst", (ADD_R GPR:$dst, GPR:$src, R0, 0)>; +def : InstAlias<"mov $src, $dst", (ADD_R GPR:$dst, GPR:$src, R0, (pred 0))>; let isAsCheapAsAMove = 1, Rs1 = R0.Num, isCodeGenOnly = 1, H = 1, F = 0, isReMaterializable = 1 in diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index e2864c2405967..d4853d5f61b6a 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -4984,44 +4984,44 @@ defm : BranchSimpleMnemonic1<"dzf", "", 2>; multiclass BranchExtendedMnemonicPM { def : InstAlias<"b"#name#pm#" $cc, $dst", - (BCC bibo, crrc:$cc, condbrtarget:$dst)>; + (BCC (pred bibo, crrc:$cc), condbrtarget:$dst)>; def : InstAlias<"b"#name#pm#" $dst", - (BCC bibo, CR0, condbrtarget:$dst)>; + (BCC (pred bibo, CR0), condbrtarget:$dst)>; def : InstAlias<"b"#name#"a"#pm#" $cc, $dst", - (BCCA bibo, crrc:$cc, abscondbrtarget:$dst)>; + (BCCA (pred bibo, crrc:$cc), abscondbrtarget:$dst)>; def : InstAlias<"b"#name#"a"#pm#" $dst", - (BCCA bibo, CR0, abscondbrtarget:$dst)>; + (BCCA (pred bibo, CR0), abscondbrtarget:$dst)>; def : InstAlias<"b"#name#"lr"#pm#" $cc", - (BCCLR bibo, crrc:$cc)>; + (BCCLR (pred bibo, crrc:$cc))>; def : InstAlias<"b"#name#"lr"#pm, - (BCCLR bibo, CR0)>; + (BCCLR (pred bibo, CR0))>; def : InstAlias<"b"#name#"ctr"#pm#" $cc", - (BCCCTR bibo, crrc:$cc)>; + (BCCCTR (pred bibo, crrc:$cc))>; def : InstAlias<"b"#name#"ctr"#pm, - (BCCCTR bibo, CR0)>; + (BCCCTR (pred bibo, CR0))>; def : InstAlias<"b"#name#"l"#pm#" $cc, $dst", - (BCCL bibo, crrc:$cc, condbrtarget:$dst)>; + (BCCL (pred bibo, crrc:$cc), condbrtarget:$dst)>; def : InstAlias<"b"#name#"l"#pm#" $dst", - (BCCL bibo, CR0, condbrtarget:$dst)>; + (BCCL (pred bibo, CR0), condbrtarget:$dst)>; def : InstAlias<"b"#name#"la"#pm#" $cc, $dst", - (BCCLA bibo, crrc:$cc, abscondbrtarget:$dst)>; + (BCCLA (pred bibo, crrc:$cc), abscondbrtarget:$dst)>; def : InstAlias<"b"#name#"la"#pm#" $dst", - (BCCLA bibo, CR0, abscondbrtarget:$dst)>; + (BCCLA (pred bibo, CR0), abscondbrtarget:$dst)>; def : InstAlias<"b"#name#"lrl"#pm#" $cc", - (BCCLRL bibo, crrc:$cc)>; + (BCCLRL (pred bibo, crrc:$cc))>; def : InstAlias<"b"#name#"lrl"#pm, - (BCCLRL bibo, CR0)>; + (BCCLRL (pred bibo, CR0))>; def : InstAlias<"b"#name#"ctrl"#pm#" $cc", - (BCCCTRL bibo, crrc:$cc)>; + (BCCCTRL (pred bibo, crrc:$cc))>; def : InstAlias<"b"#name#"ctrl"#pm, - (BCCCTRL bibo, CR0)>; + (BCCCTRL (pred bibo, CR0))>; } multiclass BranchExtendedMnemonic { defm : BranchExtendedMnemonicPM; diff --git a/llvm/utils/TableGen/Common/CodeGenInstAlias.cpp b/llvm/utils/TableGen/Common/CodeGenInstAlias.cpp index 94c0d51faf2e9..366ba69037c77 100644 --- a/llvm/utils/TableGen/Common/CodeGenInstAlias.cpp +++ b/llvm/utils/TableGen/Common/CodeGenInstAlias.cpp @@ -15,155 +15,125 @@ #include "CodeGenRegisters.h" #include "CodeGenTarget.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/Error.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" using namespace llvm; -/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias -/// constructor. It checks if an argument in an InstAlias pattern matches -/// the corresponding operand of the instruction. It returns true on a -/// successful match, with ResOp set to the result operand to be used. -bool CodeGenInstAlias::tryAliasOpMatch(const DagInit *Result, - unsigned AliasOpNo, - const Record *InstOpRec, bool hasSubOps, - ArrayRef Loc, - const CodeGenTarget &T, - ResultOperand &ResOp) { - const Init *Arg = Result->getArg(AliasOpNo); - const DefInit *ADI = dyn_cast(Arg); - const Record *ResultRecord = ADI ? ADI->getDef() : nullptr; - - if (ADI && ADI->getDef() == InstOpRec) { - // If the operand is a record, it must have a name, and the record type - // must match up with the instruction's argument type. - if (!Result->getArgName(AliasOpNo)) - PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) + - " must have a name!"); - ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)), - ResultRecord); - return true; - } - - // For register operands, the source register class can be a subclass - // of the instruction register class, not just an exact match. - if (InstOpRec->isSubClassOf("RegisterOperand")) - InstOpRec = InstOpRec->getValueAsDef("RegClass"); +unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const { + if (!isRecord()) + return 1; - if (ADI && ADI->getDef()->isSubClassOf("RegisterOperand")) - ADI = ADI->getDef()->getValueAsDef("RegClass")->getDefInit(); + const Record *Rec = getRecord(); + if (!Rec->isSubClassOf("Operand")) + return 1; - if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) { - if (!InstOpRec->isSubClassOf("RegisterClass")) - return false; - if (!T.getRegisterClass(InstOpRec).hasSubClass( - &T.getRegisterClass(ADI->getDef()))) - return false; - ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)), - ResultRecord); - return true; + const DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); + if (MIOpInfo->getNumArgs() == 0) { + // Unspecified, so it defaults to 1 + return 1; } - // Handle explicit registers. - if (ADI && ADI->getDef()->isSubClassOf("Register")) { - if (InstOpRec->isSubClassOf("OptionalDefOperand")) { - const DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo"); - // The operand info should only have a single (register) entry. We - // want the register class of it. - InstOpRec = cast(DI->getArg(0))->getDef(); - } - - if (!InstOpRec->isSubClassOf("RegisterClass")) - return false; - - if (!T.getRegisterClass(InstOpRec).contains( - T.getRegBank().getReg(ADI->getDef()))) - PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() + - " is not a member of the " + - InstOpRec->getName() + " register class!"); - - if (Result->getArgName(AliasOpNo)) - PrintFatalError(Loc, "result fixed register argument must " - "not have a name!"); + return MIOpInfo->getNumArgs(); +} - ResOp = ResultOperand(ResultRecord); - return true; +static const Record *getInitValueAsRegClass(const Init *V) { + if (const DefInit *VDefInit = dyn_cast(V)) { + const Record *R = VDefInit->getDef(); + if (R->isSubClassOf("RegisterClass")) + return R; + if (R->isSubClassOf("RegisterOperand")) + return R->getValueAsDef("RegClass"); } + return nullptr; +} + +using ResultOperand = CodeGenInstAlias::ResultOperand; + +static Expected matchSimpleOperand(const Init *Arg, + const StringInit *ArgName, + const Record *Op, + const CodeGenTarget &T) { + if (Op->isSubClassOf("RegisterClass") || + Op->isSubClassOf("RegisterOperand")) { + const Record *OpRC = + Op->isSubClassOf("RegisterClass") ? Op : Op->getValueAsDef("RegClass"); + + if (const auto *ArgDef = dyn_cast(Arg)) { + const Record *ArgRec = ArgDef->getDef(); + + // Match 'RegClass:$name' or 'RegOp:$name'. + if (const Record *ArgRC = getInitValueAsRegClass(Arg)) { + if (!T.getRegisterClass(OpRC).hasSubClass(&T.getRegisterClass(ArgRC))) + return createStringError( + "argument register class" + ArgRC->getName() + + " is not a subclass of operand register class " + + OpRC->getName()); + if (!ArgName) + return createStringError("register class argument must have a name"); + return ResultOperand::createRecord(ArgName->getAsUnquotedString(), + ArgRec); + } - // Handle "zero_reg" for optional def operands. - if (ADI && ADI->getDef()->getName() == "zero_reg") { + // Match 'Reg'. + if (ArgRec->isSubClassOf("Register")) { + if (!T.getRegisterClass(OpRC).contains(T.getRegBank().getReg(ArgRec))) + return createStringError( + "register argument " + ArgRec->getName() + + " is not a member of operand register class " + OpRC->getName()); + if (ArgName) + return createStringError("register argument must not have a name"); + return ResultOperand::createRegister(ArgRec); + } - // Check if this is an optional def. - // Tied operands where the source is a sub-operand of a complex operand - // need to represent both operands in the alias destination instruction. - // Allow zero_reg for the tied portion. This can and should go away once - // the MC representation of things doesn't use tied operands at all. - // if (!InstOpRec->isSubClassOf("OptionalDefOperand")) - // throw TGError(Loc, "reg0 used for result that is not an " - // "OptionalDefOperand!"); + // Match 'zero_reg'. + if (ArgRec->getName() == "zero_reg") { + if (ArgName) + return createStringError("register argument must not have a name"); + return ResultOperand::createRegister(nullptr); + } + } - ResOp = ResultOperand(nullptr); - return true; + return createStringError("argument must be a subclass of RegisterClass, " + "RegisterOperand, or zero_reg"); } - // Literal integers. - if (const IntInit *II = dyn_cast(Arg)) { - if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) - return false; - // Integer arguments can't have names. - if (Result->getArgName(AliasOpNo)) - PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) + - " must not have a name!"); - ResOp = ResultOperand(II->getValue()); - return true; - } + if (Op->isSubClassOf("Operand")) { + // Match integer or bits. + if (const IntInit *ArgInt = dyn_cast_or_null( + Arg->convertInitializerTo(IntRecTy::get(Arg->getRecordKeeper())))) { + if (ArgName) + return createStringError("integer argument must not have a name"); + return ResultOperand::createImmediate(ArgInt->getValue()); + } - // Bits (also used for 0bxx literals) - if (const BitsInit *BI = dyn_cast(Arg)) { - if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) - return false; - if (!BI->isComplete()) - return false; - // Convert the bits init to an integer and use that for the result. - std::optional Value = BI->convertInitializerToInt(); - if (!Value) - return false; - ResOp = ResultOperand(*Value); - return true; - } + // Match a subclass of Operand. + if (const auto *ArgDef = dyn_cast(Arg); + ArgDef && ArgDef->getDef()->isSubClassOf("Operand")) { + if (!ArgName) + return createStringError("argument must have a name"); + return ResultOperand::createRecord(ArgName->getAsUnquotedString(), + ArgDef->getDef()); + } - // If both are Operands with the same MVT, allow the conversion. It's - // up to the user to make sure the values are appropriate, just like - // for isel Pat's. - if (InstOpRec->isSubClassOf("Operand") && ADI && - ADI->getDef()->isSubClassOf("Operand")) { - // FIXME: What other attributes should we check here? Identical - // MIOperandInfo perhaps? - if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type")) - return false; - ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)), - ADI->getDef()); - return true; + return createStringError("argument must be a subclass of Operand"); } - return false; + llvm_unreachable("Unknown operand kind"); } -unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const { - if (!isRecord()) - return 1; - - const Record *Rec = getRecord(); - if (!Rec->isSubClassOf("Operand")) - return 1; - - const DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); - if (MIOpInfo->getNumArgs() == 0) { - // Unspecified, so it defaults to 1 - return 1; - } - - return MIOpInfo->getNumArgs(); +static Expected matchComplexOperand(const Init *Arg, + const StringInit *ArgName, + const Record *Op) { + assert(Op->isSubClassOf("Operand")); + const auto *ArgDef = dyn_cast(Arg); + if (!ArgDef || !ArgDef->getDef()->isSubClassOf("Operand")) + return createStringError("argument must be a subclass of Operand"); + if (!ArgName) + return createStringError("argument must have a name"); + return ResultOperand::createRecord(ArgName->getAsUnquotedString(), + ArgDef->getDef()); } CodeGenInstAlias::CodeGenInstAlias(const Record *R, const CodeGenTarget &T) @@ -199,7 +169,7 @@ CodeGenInstAlias::CodeGenInstAlias(const Record *R, const CodeGenTarget &T) } // Decode and validate the arguments of the result. - unsigned AliasOpNo = 0; + unsigned ArgIdx = 0; for (auto [OpIdx, OpInfo] : enumerate(ResultInst->Operands)) { // Tied registers don't have an entry in the result dag unless they're part // of a complex operand, in which case we include them anyways, as we @@ -213,71 +183,64 @@ CodeGenInstAlias::CodeGenInstAlias(const Record *R, const CodeGenTarget &T) continue; } - if (AliasOpNo >= Result->getNumArgs()) + if (ArgIdx >= Result->getNumArgs()) PrintFatalError(R->getLoc(), "not enough arguments for instruction!"); - const Record *InstOpRec = OpInfo.Rec; - unsigned NumSubOps = OpInfo.MINumOperands; - ResultOperand ResOp(static_cast(0)); - if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1), - R->getLoc(), T, ResOp)) { - // If this is a simple operand, or a complex operand with a custom match - // class, then we can match is verbatim. - if (NumSubOps == 1 || (InstOpRec->getValue("ParserMatchClass") && - InstOpRec->getValueAsDef("ParserMatchClass") - ->getValueAsString("Name") != "Imm")) { - ResultOperands.push_back(std::move(ResOp)); - ResultInstOperandIndex.emplace_back(OpIdx, -1); - ++AliasOpNo; - - // Otherwise, we need to match each of the suboperands individually. - } else { - const DagInit *MIOI = OpInfo.MIOperandInfo; - for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { - const Record *SubRec = cast(MIOI->getArg(SubOp))->getDef(); - - // Take care to instantiate each of the suboperands with the correct - // nomenclature: $foo.bar - ResultOperands.emplace_back( - Result->getArgName(AliasOpNo)->getAsUnquotedString() + "." + - MIOI->getArgName(SubOp)->getAsUnquotedString(), - SubRec); - ResultInstOperandIndex.emplace_back(OpIdx, SubOp); - } - ++AliasOpNo; - } - continue; - } - - // If the argument did not match the instruction operand, and the operand - // is composed of multiple suboperands, try matching the suboperands. - if (NumSubOps > 1) { - const DagInit *MIOI = OpInfo.MIOperandInfo; - for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { - if (AliasOpNo >= Result->getNumArgs()) - PrintFatalError(R->getLoc(), "not enough arguments for instruction!"); - const Record *SubRec = cast(MIOI->getArg(SubOp))->getDef(); - if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, R->getLoc(), T, - ResOp)) { - ResultOperands.push_back(ResOp); - ResultInstOperandIndex.emplace_back(OpIdx, SubOp); - ++AliasOpNo; - } else { - PrintFatalError( - R->getLoc(), - "result argument #" + Twine(AliasOpNo) + - " does not match instruction operand class " + - (SubOp == 0 ? InstOpRec->getName() : SubRec->getName())); + const Record *Op = OpInfo.Rec; + if (Op->isSubClassOf("Operand") && !OpInfo.MIOperandInfo->arg_empty()) { + // Complex operand (a subclass of Operand with non-empty MIOperandInfo). + // The argument can be a DAG or a subclass of Operand. + if (auto *ArgDag = dyn_cast(Result->getArg(ArgIdx))) { + // The argument is a DAG. The operator must be the name of the operand. + if (auto *Operator = dyn_cast(ArgDag->getOperator()); + !Operator || Operator->getDef()->getName() != Op->getName()) + PrintFatalError(R, "argument #" + Twine(ArgIdx) + + " operator must be " + Op->getName()); + // The number of sub-arguments and the number of sub-operands + // must match exactly. + unsigned NumSubOps = OpInfo.MIOperandInfo->getNumArgs(); + unsigned NumSubArgs = ArgDag->getNumArgs(); + if (NumSubArgs != NumSubOps) + PrintFatalError(R, "argument #" + Twine(ArgIdx) + + " must have exactly " + Twine(NumSubOps) + + " sub-arguments"); + // Match sub-operands individually. + for (unsigned SubOpIdx = 0; SubOpIdx != NumSubOps; ++SubOpIdx) { + const Record *SubOp = + cast(OpInfo.MIOperandInfo->getArg(SubOpIdx))->getDef(); + Expected ResOpOrErr = matchSimpleOperand( + ArgDag->getArg(SubOpIdx), ArgDag->getArgName(SubOpIdx), SubOp, T); + if (!ResOpOrErr) + PrintFatalError(R, "in argument #" + Twine(ArgIdx) + "." + + Twine(SubOpIdx) + ": " + + toString(ResOpOrErr.takeError())); + ResultOperands.push_back(*ResOpOrErr); + ResultInstOperandIndex.emplace_back(OpIdx, SubOpIdx); } + } else { + // Match complex operand as a whole. + Expected ResOpOrErr = matchComplexOperand( + Result->getArg(ArgIdx), Result->getArgName(ArgIdx), Op); + if (!ResOpOrErr) + PrintFatalError(R, "in argument #" + Twine(ArgIdx) + ": " + + toString(ResOpOrErr.takeError())); + ResultOperands.push_back(*ResOpOrErr); + ResultInstOperandIndex.emplace_back(OpIdx, -1); } - continue; + } else { + // Simple operand (RegisterClass, RegisterOperand or Operand with empty + // MIOperandInfo). + Expected ResOpOrErr = matchSimpleOperand( + Result->getArg(ArgIdx), Result->getArgName(ArgIdx), Op, T); + if (!ResOpOrErr) + PrintFatalError(R, "in argument #" + Twine(ArgIdx) + ": " + + toString(ResOpOrErr.takeError())); + ResultOperands.push_back(*ResOpOrErr); + ResultInstOperandIndex.emplace_back(OpIdx, -1); } - PrintFatalError(R->getLoc(), - "result argument #" + Twine(AliasOpNo) + - " does not match instruction operand class " + - InstOpRec->getName()); + ArgIdx++; } - if (AliasOpNo != Result->getNumArgs()) + if (ArgIdx != Result->getNumArgs()) PrintFatalError(R->getLoc(), "too many operands for instruction!"); } diff --git a/llvm/utils/TableGen/Common/CodeGenInstAlias.h b/llvm/utils/TableGen/Common/CodeGenInstAlias.h index f045b9f6c1990..e9f603125d678 100644 --- a/llvm/utils/TableGen/Common/CodeGenInstAlias.h +++ b/llvm/utils/TableGen/Common/CodeGenInstAlias.h @@ -22,11 +22,9 @@ namespace llvm { -template class ArrayRef; class CodeGenInstruction; class CodeGenTarget; class DagInit; -class SMLoc; class Record; /// CodeGenInstAlias - This represents an InstAlias definition. @@ -45,20 +43,29 @@ class CodeGenInstAlias { /// Result). CodeGenInstruction *ResultInst; - struct ResultOperand { - private: + class ResultOperand { std::string Name; const Record *R = nullptr; int64_t Imm = 0; - public: - enum { K_Record, K_Imm, K_Reg } Kind; - ResultOperand(std::string N, const Record *R) : Name(std::move(N)), R(R), Kind(K_Record) {} - ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {} + ResultOperand(int64_t Imm) : Imm(Imm), Kind(K_Imm) {} ResultOperand(const Record *R) : R(R), Kind(K_Reg) {} + public: + enum { K_Record, K_Imm, K_Reg } Kind; + + static ResultOperand createRecord(std::string N, const Record *R) { + return ResultOperand(std::move(N), R); + } + static ResultOperand createImmediate(int64_t Imm) { + return ResultOperand(Imm); + } + static ResultOperand createRegister(const Record *R) { + return ResultOperand(R); + } + bool isRecord() const { return Kind == K_Record; } bool isImm() const { return Kind == K_Imm; } bool isReg() const { return Kind == K_Reg; } @@ -94,11 +101,6 @@ class CodeGenInstAlias { std::vector> ResultInstOperandIndex; CodeGenInstAlias(const Record *R, const CodeGenTarget &T); - - bool tryAliasOpMatch(const DagInit *Result, unsigned AliasOpNo, - const Record *InstOpRec, bool hasSubOps, - ArrayRef Loc, const CodeGenTarget &T, - ResultOperand &ResOp); }; } // namespace llvm