diff options
-rw-r--r-- | lib/Target/AArch64/AArch64InstrInfo.td | 995 |
1 files changed, 492 insertions, 503 deletions
diff --git a/lib/Target/AArch64/AArch64InstrInfo.td b/lib/Target/AArch64/AArch64InstrInfo.td index 319ec97cfc..37be5e4892 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.td +++ b/lib/Target/AArch64/AArch64InstrInfo.td @@ -162,13 +162,13 @@ let Defs = [XSP], Uses = [XSP] in { let usesCustomInserter = 1 in { multiclass AtomicSizes<string opname> { def _I8 : PseudoInst<(outs GPR32:$dst), (ins GPR64:$ptr, GPR32:$incr), - [(set GPR32:$dst, (!cast<SDNode>(opname # "_8") GPR64:$ptr, GPR32:$incr))]>; + [(set i32:$dst, (!cast<SDNode>(opname # "_8") i64:$ptr, i32:$incr))]>; def _I16 : PseudoInst<(outs GPR32:$dst), (ins GPR64:$ptr, GPR32:$incr), - [(set GPR32:$dst, (!cast<SDNode>(opname # "_16") GPR64:$ptr, GPR32:$incr))]>; + [(set i32:$dst, (!cast<SDNode>(opname # "_16") i64:$ptr, i32:$incr))]>; def _I32 : PseudoInst<(outs GPR32:$dst), (ins GPR64:$ptr, GPR32:$incr), - [(set GPR32:$dst, (!cast<SDNode>(opname # "_32") GPR64:$ptr, GPR32:$incr))]>; + [(set i32:$dst, (!cast<SDNode>(opname # "_32") i64:$ptr, i32:$incr))]>; def _I64 : PseudoInst<(outs GPR64:$dst), (ins GPR64:$ptr, GPR64:$incr), - [(set GPR64:$dst, (!cast<SDNode>(opname # "_64") GPR64:$ptr, GPR64:$incr))]>; + [(set i64:$dst, (!cast<SDNode>(opname # "_64") i64:$ptr, i64:$incr))]>; } } @@ -190,20 +190,16 @@ let Defs = [NZCV] in { let usesCustomInserter = 1, Defs = [NZCV] in { def ATOMIC_CMP_SWAP_I8 : PseudoInst<(outs GPR32:$dst), (ins GPR64:$ptr, GPR32:$old, GPR32:$new), - [(set GPR32:$dst, - (atomic_cmp_swap_8 GPR64:$ptr, GPR32:$old, GPR32:$new))]>; + [(set i32:$dst, (atomic_cmp_swap_8 i64:$ptr, i32:$old, i32:$new))]>; def ATOMIC_CMP_SWAP_I16 : PseudoInst<(outs GPR32:$dst), (ins GPR64:$ptr, GPR32:$old, GPR32:$new), - [(set GPR32:$dst, - (atomic_cmp_swap_16 GPR64:$ptr, GPR32:$old, GPR32:$new))]>; + [(set i32:$dst, (atomic_cmp_swap_16 i64:$ptr, i32:$old, i32:$new))]>; def ATOMIC_CMP_SWAP_I32 : PseudoInst<(outs GPR32:$dst), (ins GPR64:$ptr, GPR32:$old, GPR32:$new), - [(set GPR32:$dst, - (atomic_cmp_swap_32 GPR64:$ptr, GPR32:$old, GPR32:$new))]>; + [(set i32:$dst, (atomic_cmp_swap_32 i64:$ptr, i32:$old, i32:$new))]>; def ATOMIC_CMP_SWAP_I64 : PseudoInst<(outs GPR64:$dst), (ins GPR64:$ptr, GPR64:$old, GPR64:$new), - [(set GPR64:$dst, - (atomic_cmp_swap_64 GPR64:$ptr, GPR64:$old, GPR64:$new))]>; + [(set i64:$dst, (atomic_cmp_swap_64 i64:$ptr, i64:$old, i64:$new))]>; } //===----------------------------------------------------------------------===// @@ -264,31 +260,39 @@ def LSL_extoperand : Operand<i64> { class extend_types { dag uxtb; dag uxth; dag uxtw; dag uxtx; dag sxtb; dag sxth; dag sxtw; dag sxtx; + ValueType ty; + RegisterClass GPR; } def extends_to_i64 : extend_types { - let uxtb = (and (anyext GPR32:$Rm), 255); - let uxth = (and (anyext GPR32:$Rm), 65535); - let uxtw = (zext GPR32:$Rm); - let uxtx = (i64 GPR64:$Rm); + let uxtb = (and (anyext i32:$Rm), 255); + let uxth = (and (anyext i32:$Rm), 65535); + let uxtw = (zext i32:$Rm); + let uxtx = (i64 $Rm); - let sxtb = (sext_inreg (anyext GPR32:$Rm), i8); - let sxth = (sext_inreg (anyext GPR32:$Rm), i16); - let sxtw = (sext GPR32:$Rm); - let sxtx = (i64 GPR64:$Rm); + let sxtb = (sext_inreg (anyext i32:$Rm), i8); + let sxth = (sext_inreg (anyext i32:$Rm), i16); + let sxtw = (sext i32:$Rm); + let sxtx = (i64 $Rm); + + let ty = i64; + let GPR = GPR64xsp; } def extends_to_i32 : extend_types { - let uxtb = (and GPR32:$Rm, 255); - let uxth = (and GPR32:$Rm, 65535); - let uxtw = (i32 GPR32:$Rm); - let uxtx = (i32 GPR32:$Rm); + let uxtb = (and i32:$Rm, 255); + let uxth = (and i32:$Rm, 65535); + let uxtw = (i32 i32:$Rm); + let uxtx = (i32 i32:$Rm); + + let sxtb = (sext_inreg i32:$Rm, i8); + let sxth = (sext_inreg i32:$Rm, i16); + let sxtw = (i32 i32:$Rm); + let sxtx = (i32 i32:$Rm); - let sxtb = (sext_inreg GPR32:$Rm, i8); - let sxth = (sext_inreg GPR32:$Rm, i16); - let sxtw = (i32 GPR32:$Rm); - let sxtx = (i32 GPR32:$Rm); + let ty = i32; + let GPR = GPR32wsp; } // Now, six of the extensions supported are easy and uniform: if the source size @@ -303,44 +307,38 @@ def extends_to_i32 : extend_types { // would probably be the best option). multiclass addsub_exts<bit sf, bit op, bit S, string asmop, SDPatternOperator opfrag, - dag outs, extend_types exts, RegisterClass GPRsp> { + dag outs, extend_types exts> { def w_uxtb : A64I_addsubext<sf, op, S, 0b00, 0b000, - outs, - (ins GPRsp:$Rn, GPR32:$Rm, UXTB_operand:$Imm3), - !strconcat(asmop, "$Rn, $Rm, $Imm3"), - [(opfrag GPRsp:$Rn, (shl exts.uxtb, UXTB_operand:$Imm3))], - NoItinerary>; + outs, (ins exts.GPR:$Rn, GPR32:$Rm, UXTB_operand:$Imm3), + !strconcat(asmop, "$Rn, $Rm, $Imm3"), + [(opfrag exts.ty:$Rn, (shl exts.uxtb, UXTB_operand:$Imm3))], + NoItinerary>; def w_uxth : A64I_addsubext<sf, op, S, 0b00, 0b001, - outs, - (ins GPRsp:$Rn, GPR32:$Rm, UXTH_operand:$Imm3), - !strconcat(asmop, "$Rn, $Rm, $Imm3"), - [(opfrag GPRsp:$Rn, (shl exts.uxth, UXTH_operand:$Imm3))], - NoItinerary>; + outs, (ins exts.GPR:$Rn, GPR32:$Rm, UXTH_operand:$Imm3), + !strconcat(asmop, "$Rn, $Rm, $Imm3"), + [(opfrag exts.ty:$Rn, (shl exts.uxth, UXTH_operand:$Imm3))], + NoItinerary>; def w_uxtw : A64I_addsubext<sf, op, S, 0b00, 0b010, - outs, - (ins GPRsp:$Rn, GPR32:$Rm, UXTW_operand:$Imm3), - !strconcat(asmop, "$Rn, $Rm, $Imm3"), - [(opfrag GPRsp:$Rn, (shl exts.uxtw, UXTW_operand:$Imm3))], - NoItinerary>; + outs, (ins exts.GPR:$Rn, GPR32:$Rm, UXTW_operand:$Imm3), + !strconcat(asmop, "$Rn, $Rm, $Imm3"), + [(opfrag exts.ty:$Rn, (shl exts.uxtw, UXTW_operand:$Imm3))], + NoItinerary>; def w_sxtb : A64I_addsubext<sf, op, S, 0b00, 0b100, - outs, - (ins GPRsp:$Rn, GPR32:$Rm, SXTB_operand:$Imm3), - !strconcat(asmop, "$Rn, $Rm, $Imm3"), - [(opfrag GPRsp:$Rn, (shl exts.sxtb, SXTB_operand:$Imm3))], - NoItinerary>; + outs, (ins exts.GPR:$Rn, GPR32:$Rm, SXTB_operand:$Imm3), + !strconcat(asmop, "$Rn, $Rm, $Imm3"), + [(opfrag exts.ty:$Rn, (shl exts.sxtb, SXTB_operand:$Imm3))], + NoItinerary>; def w_sxth : A64I_addsubext<sf, op, S, 0b00, 0b101, - outs, - (ins GPRsp:$Rn, GPR32:$Rm, SXTH_operand:$Imm3), - !strconcat(asmop, "$Rn, $Rm, $Imm3"), - [(opfrag GPRsp:$Rn, (shl exts.sxth, SXTH_operand:$Imm3))], - NoItinerary>; + outs, (ins exts.GPR:$Rn, GPR32:$Rm, SXTH_operand:$Imm3), + !strconcat(asmop, "$Rn, $Rm, $Imm3"), + [(opfrag exts.ty:$Rn, (shl exts.sxth, SXTH_operand:$Imm3))], + NoItinerary>; def w_sxtw : A64I_addsubext<sf, op, S, 0b00, 0b110, - outs, - (ins GPRsp:$Rn, GPR32:$Rm, SXTW_operand:$Imm3), - !strconcat(asmop, "$Rn, $Rm, $Imm3"), - [(opfrag GPRsp:$Rn, (shl exts.sxtw, SXTW_operand:$Imm3))], - NoItinerary>; + outs, (ins exts.GPR:$Rn, GPR32:$Rm, SXTW_operand:$Imm3), + !strconcat(asmop, "$Rn, $Rm, $Imm3"), + [(opfrag exts.ty:$Rn, (shl exts.sxtw, SXTW_operand:$Imm3))], + NoItinerary>; } // These two could be merge in with the above, but their patterns aren't really @@ -351,7 +349,7 @@ multiclass addsub_xxtx<bit op, bit S, string asmop, SDPatternOperator opfrag, outs, (ins GPR64xsp:$Rn, GPR64:$Rm, UXTX_operand:$Imm3), !strconcat(asmop, "$Rn, $Rm, $Imm3"), - [(opfrag GPR64xsp:$Rn, (shl GPR64:$Rm, UXTX_operand:$Imm3))], + [(opfrag i64:$Rn, (shl i64:$Rm, UXTX_operand:$Imm3))], NoItinerary>; def x_sxtx : A64I_addsubext<0b1, op, S, 0b00, 0b111, @@ -384,53 +382,53 @@ class SetNZCV<SDPatternOperator op> : PatFrag<(ops node:$lhs, node:$rhs), (set NZCV, (op node:$lhs, node:$rhs))>; defm ADDxx :addsub_exts<0b1, 0b0, 0b0, "add\t$Rd, ", SetRD<GPR64xsp, add>, - (outs GPR64xsp:$Rd), extends_to_i64, GPR64xsp>, + (outs GPR64xsp:$Rd), extends_to_i64>, addsub_xxtx< 0b0, 0b0, "add\t$Rd, ", SetRD<GPR64xsp, add>, (outs GPR64xsp:$Rd)>; defm ADDww :addsub_exts<0b0, 0b0, 0b0, "add\t$Rd, ", SetRD<GPR32wsp, add>, - (outs GPR32wsp:$Rd), extends_to_i32, GPR32wsp>, + (outs GPR32wsp:$Rd), extends_to_i32>, addsub_wxtx< 0b0, 0b0, "add\t$Rd, ", (outs GPR32wsp:$Rd)>; defm SUBxx :addsub_exts<0b1, 0b1, 0b0, "sub\t$Rd, ", SetRD<GPR64xsp, sub>, - (outs GPR64xsp:$Rd), extends_to_i64, GPR64xsp>, + (outs GPR64xsp:$Rd), extends_to_i64>, addsub_xxtx< 0b1, 0b0, "sub\t$Rd, ", SetRD<GPR64xsp, sub>, (outs GPR64xsp:$Rd)>; defm SUBww :addsub_exts<0b0, 0b1, 0b0, "sub\t$Rd, ", SetRD<GPR32wsp, sub>, - (outs GPR32wsp:$Rd), extends_to_i32, GPR32wsp>, + (outs GPR32wsp:$Rd), extends_to_i32>, addsub_wxtx< 0b1, 0b0, "sub\t$Rd, ", (outs GPR32wsp:$Rd)>; let Defs = [NZCV] in { defm ADDSxx :addsub_exts<0b1, 0b0, 0b1, "adds\t$Rd, ", SetRD<GPR64, addc>, - (outs GPR64:$Rd), extends_to_i64, GPR64xsp>, + (outs GPR64:$Rd), extends_to_i64>, addsub_xxtx< 0b0, 0b1, "adds\t$Rd, ", SetRD<GPR64, addc>, (outs GPR64:$Rd)>; defm ADDSww :addsub_exts<0b0, 0b0, 0b1, "adds\t$Rd, ", SetRD<GPR32, addc>, - (outs GPR32:$Rd), extends_to_i32, GPR32wsp>, + (outs GPR32:$Rd), extends_to_i32>, addsub_wxtx< 0b0, 0b1, "adds\t$Rd, ", (outs GPR32:$Rd)>; defm SUBSxx :addsub_exts<0b1, 0b1, 0b1, "subs\t$Rd, ", SetRD<GPR64, subc>, - (outs GPR64:$Rd), extends_to_i64, GPR64xsp>, + (outs GPR64:$Rd), extends_to_i64>, addsub_xxtx< 0b1, 0b1, "subs\t$Rd, ", SetRD<GPR64, subc>, (outs GPR64:$Rd)>; defm SUBSww :addsub_exts<0b0, 0b1, 0b1, "subs\t$Rd, ", SetRD<GPR32, subc>, - (outs GPR32:$Rd), extends_to_i32, GPR32wsp>, + (outs GPR32:$Rd), extends_to_i32>, addsub_wxtx< 0b1, 0b1, "subs\t$Rd, ", (outs GPR32:$Rd)>; let Rd = 0b11111, isCompare = 1 in { defm CMNx : addsub_exts<0b1, 0b0, 0b1, "cmn\t", SetNZCV<A64cmn>, - (outs), extends_to_i64, GPR64xsp>, + (outs), extends_to_i64>, addsub_xxtx< 0b0, 0b1, "cmn\t", SetNZCV<A64cmn>, (outs)>; defm CMNw : addsub_exts<0b0, 0b0, 0b1, "cmn\t", SetNZCV<A64cmn>, - (outs), extends_to_i32, GPR32wsp>, + (outs), extends_to_i32>, addsub_wxtx< 0b0, 0b1, "cmn\t", (outs)>; defm CMPx : addsub_exts<0b1, 0b1, 0b1, "cmp\t", SetNZCV<A64cmp>, - (outs), extends_to_i64, GPR64xsp>, + (outs), extends_to_i64>, addsub_xxtx< 0b1, 0b1, "cmp\t", SetNZCV<A64cmp>, (outs)>; defm CMPw : addsub_exts<0b0, 0b1, 0b1, "cmp\t", SetNZCV<A64cmp>, - (outs), extends_to_i32, GPR32wsp>, + (outs), extends_to_i32>, addsub_wxtx< 0b1, 0b1, "cmp\t", (outs)>; } } @@ -439,31 +437,31 @@ defm CMPw : addsub_exts<0b0, 0b1, 0b1, "cmp\t", SetNZCV<A64cmp>, // created for uxtx/sxtx since they're non-uniform and it's expected that // add/sub (shifted register) will handle those cases anyway. multiclass addsubext_noshift_patterns<string prefix, SDPatternOperator nodeop, - RegisterClass GPRsp, extend_types exts> { - def : Pat<(nodeop GPRsp:$Rn, exts.uxtb), - (!cast<Instruction>(prefix # "w_uxtb") GPRsp:$Rn, GPR32:$Rm, 0)>; - def : Pat<(nodeop GPRsp:$Rn, exts.uxth), - (!cast<Instruction>(prefix # "w_uxth") GPRsp:$Rn, GPR32:$Rm, 0)>; - def : Pat<(nodeop GPRsp:$Rn, exts.uxtw), - (!cast<Instruction>(prefix # "w_uxtw") GPRsp:$Rn, GPR32:$Rm, 0)>; - - def : Pat<(nodeop GPRsp:$Rn, exts.sxtb), - (!cast<Instruction>(prefix # "w_sxtb") GPRsp:$Rn, GPR32:$Rm, 0)>; - def : Pat<(nodeop GPRsp:$Rn, exts.sxth), - (!cast<Instruction>(prefix # "w_sxth") GPRsp:$Rn, GPR32:$Rm, 0)>; - def : Pat<(nodeop GPRsp:$Rn, exts.sxtw), - (!cast<Instruction>(prefix # "w_sxtw") GPRsp:$Rn, GPR32:$Rm, 0)>; -} - -defm : addsubext_noshift_patterns<"ADDxx", add, GPR64xsp, extends_to_i64>; -defm : addsubext_noshift_patterns<"ADDww", add, GPR32wsp, extends_to_i32>; -defm : addsubext_noshift_patterns<"SUBxx", sub, GPR64xsp, extends_to_i64>; -defm : addsubext_noshift_patterns<"SUBww", sub, GPR32wsp, extends_to_i32>; - -defm : addsubext_noshift_patterns<"CMNx", A64cmn, GPR64xsp, extends_to_i64>; -defm : addsubext_noshift_patterns<"CMNw", A64cmn, GPR32wsp, extends_to_i32>; -defm : addsubext_noshift_patterns<"CMPx", A64cmp, GPR64xsp, extends_to_i64>; -defm : addsubext_noshift_patterns<"CMPw", A64cmp, GPR32wsp, extends_to_i32>; + extend_types exts> { + def : Pat<(nodeop exts.ty:$Rn, exts.uxtb), + (!cast<Instruction>(prefix # "w_uxtb") $Rn, $Rm, 0)>; + def : Pat<(nodeop exts.ty:$Rn, exts.uxth), + (!cast<Instruction>(prefix # "w_uxth") $Rn, $Rm, 0)>; + def : Pat<(nodeop exts.ty:$Rn, exts.uxtw), + (!cast<Instruction>(prefix # "w_uxtw") $Rn, $Rm, 0)>; + + def : Pat<(nodeop exts.ty:$Rn, exts.sxtb), + (!cast<Instruction>(prefix # "w_sxtb") $Rn, $Rm, 0)>; + def : Pat<(nodeop exts.ty:$Rn, exts.sxth), + (!cast<Instruction>(prefix # "w_sxth") $Rn, $Rm, 0)>; + def : Pat<(nodeop exts.ty:$Rn, exts.sxtw), + (!cast<Instruction>(prefix # "w_sxtw") $Rn, $Rm, 0)>; +} + +defm : addsubext_noshift_patterns<"ADDxx", add, extends_to_i64>; +defm : addsubext_noshift_patterns<"ADDww", add, extends_to_i32>; +defm : addsubext_noshift_patterns<"SUBxx", sub, extends_to_i64>; +defm : addsubext_noshift_patterns<"SUBww", sub, extends_to_i32>; + +defm : addsubext_noshift_patterns<"CMNx", A64cmn, extends_to_i64>; +defm : addsubext_noshift_patterns<"CMNw", A64cmn, extends_to_i32>; +defm : addsubext_noshift_patterns<"CMPx", A64cmp, extends_to_i64>; +defm : addsubext_noshift_patterns<"CMPw", A64cmp, extends_to_i32>; // An extend of "lsl #imm" is valid if and only if one of Rn and Rd is // sp/wsp. It is synonymous with uxtx/uxtw depending on the size of the @@ -614,14 +612,13 @@ multiclass addsubimm_varieties<string prefix, bit sf, bit op, bits<2> shift, string asmop, string cmpasmop, Operand imm_operand, Operand cmp_imm_operand, RegisterClass GPR, RegisterClass GPRsp, - AArch64Reg ZR> { + AArch64Reg ZR, ValueType Ty> { // All registers for non-S variants allow SP def _s : A64I_addsubimm<sf, op, 0b0, shift, (outs GPRsp:$Rd), (ins GPRsp:$Rn, imm_operand:$Imm12), !strconcat(asmop, "\t$Rd, $Rn, $Imm12"), - [(set GPRsp:$Rd, - (add GPRsp:$Rn, imm_operand:$Imm12))], + [(set Ty:$Rd, (add Ty:$Rn, imm_operand:$Imm12))], NoItinerary>; @@ -630,7 +627,7 @@ multiclass addsubimm_varieties<string prefix, bit sf, bit op, bits<2> shift, (outs GPR:$Rd), (ins GPRsp:$Rn, imm_operand:$Imm12), !strconcat(asmop, "s\t$Rd, $Rn, $Imm12"), - [(set GPR:$Rd, (addc GPRsp:$Rn, imm_operand:$Imm12))], + [(set Ty:$Rd, (addc Ty:$Rn, imm_operand:$Imm12))], NoItinerary> { let Defs = [NZCV]; } @@ -642,7 +639,7 @@ multiclass addsubimm_varieties<string prefix, bit sf, bit op, bits<2> shift, (outs), (ins GPRsp:$Rn, imm_operand:$Imm12), !strconcat(cmpasmop, " $Rn, $Imm12"), [(set NZCV, - (A64cmp GPRsp:$Rn, cmp_imm_operand:$Imm12))], + (A64cmp Ty:$Rn, cmp_imm_operand:$Imm12))], NoItinerary> { let Rd = 0b11111; let Defs = [NZCV]; @@ -653,36 +650,37 @@ multiclass addsubimm_varieties<string prefix, bit sf, bit op, bits<2> shift, multiclass addsubimm_shifts<string prefix, bit sf, bit op, string asmop, string cmpasmop, string operand, string cmpoperand, - RegisterClass GPR, RegisterClass GPRsp, AArch64Reg ZR> { + RegisterClass GPR, RegisterClass GPRsp, AArch64Reg ZR, + ValueType Ty> { defm _lsl0 : addsubimm_varieties<prefix # "_lsl0", sf, op, 0b00, asmop, cmpasmop, !cast<Operand>(operand # "_lsl0"), !cast<Operand>(cmpoperand # "_lsl0"), - GPR, GPRsp, ZR>; + GPR, GPRsp, ZR, Ty>; defm _lsl12 : addsubimm_varieties<prefix # "_lsl12", sf, op, 0b01, asmop, cmpasmop, !cast<Operand>(operand # "_lsl12"), !cast<Operand>(cmpoperand # "_lsl12"), - GPR, GPRsp, ZR>; + GPR, GPRsp, ZR, Ty>; } defm ADDwwi : addsubimm_shifts<"ADDwi", 0b0, 0b0, "add", "cmn", "addsubimm_operand_i32_posimm", "addsubimm_operand_i32_negimm", - GPR32, GPR32wsp, WZR>; + GPR32, GPR32wsp, WZR, i32>; defm ADDxxi : addsubimm_shifts<"ADDxi", 0b1, 0b0, "add", "cmn", "addsubimm_operand_i64_posimm", "addsubimm_operand_i64_negimm", - GPR64, GPR64xsp, XZR>; + GPR64, GPR64xsp, XZR, i64>; defm SUBwwi : addsubimm_shifts<"SUBwi", 0b0, 0b1, "sub", "cmp", "addsubimm_operand_i32_negimm", "addsubimm_operand_i32_posimm", - GPR32, GPR32wsp, WZR>; + GPR32, GPR32wsp, WZR, i32>; defm SUBxxi : addsubimm_shifts<"SUBxi", 0b1, 0b1, "sub", "cmp", "addsubimm_operand_i64_negimm", "addsubimm_operand_i64_posimm", - GPR64, GPR64xsp, XZR>; + GPR64, GPR64xsp, XZR, i64>; multiclass MOVsp<RegisterClass GPRsp, RegisterClass SP, Instruction addop> { def _fromsp : InstAlias<"mov $Rd, $Rn", @@ -753,36 +751,36 @@ defm ror_operand : shift_operands<"ror_operand", "ROR">; // N.b. the commutable parameter is just !N. It will be first against the wall // when the revolution comes. multiclass addsub_shifts<string prefix, bit sf, bit op, bit s, bit commutable, - string asmop, SDPatternOperator opfrag, string sty, + string asmop, SDPatternOperator opfrag, ValueType ty, RegisterClass GPR, list<Register> defs> { let isCommutable = commutable, Defs = defs in { def _lsl : A64I_addsubshift<sf, op, s, 0b00, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, - !cast<Operand>("lsl_operand_" # sty):$Imm6), + !cast<Operand>("lsl_operand_" # ty):$Imm6), !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Imm6"), - [(set GPR:$Rd, (opfrag GPR:$Rn, (shl GPR:$Rm, - !cast<Operand>("lsl_operand_" # sty):$Imm6)) + [(set GPR:$Rd, (opfrag ty:$Rn, (shl ty:$Rm, + !cast<Operand>("lsl_operand_" # ty):$Imm6)) )], NoItinerary>; def _lsr : A64I_addsubshift<sf, op, s, 0b01, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, - !cast<Operand>("lsr_operand_" # sty):$Imm6), + !cast<Operand>("lsr_operand_" # ty):$Imm6), !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Imm6"), - [(set GPR:$Rd, (opfrag GPR:$Rn, (srl GPR:$Rm, - !cast<Operand>("lsr_operand_" # sty):$Imm6)) + [(set ty:$Rd, (opfrag ty:$Rn, (srl ty:$Rm, + !cast<Operand>("lsr_operand_" # ty):$Imm6)) )], NoItinerary>; def _asr : A64I_addsubshift<sf, op, s, 0b10, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, - !cast<Operand>("asr_operand_" # sty):$Imm6), + !cast<Operand>("asr_operand_" # ty):$Imm6), !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Imm6"), - [(set GPR:$Rd, (opfrag GPR:$Rn, (sra GPR:$Rm, - !cast<Operand>("asr_operand_" # sty):$Imm6)) + [(set ty:$Rd, (opfrag ty:$Rn, (sra ty:$Rm, + !cast<Operand>("asr_operand_" # ty):$Imm6)) )], NoItinerary>; } @@ -792,17 +790,17 @@ multiclass addsub_shifts<string prefix, bit sf, bit op, bit s, bit commutable, (!cast<Instruction>(prefix # "_lsl") GPR:$Rd, GPR:$Rn, GPR:$Rm, 0)>; - def : Pat<(opfrag GPR:$Rn, GPR:$Rm), - (!cast<Instruction>(prefix # "_lsl") GPR:$Rn, GPR:$Rm, 0)>; + def : Pat<(opfrag ty:$Rn, ty:$Rm), + (!cast<Instruction>(prefix # "_lsl") $Rn, $Rm, 0)>; } multiclass addsub_sizes<string prefix, bit op, bit s, bit commutable, string asmop, SDPatternOperator opfrag, list<Register> defs> { defm xxx : addsub_shifts<prefix # "xxx", 0b1, op, s, - commutable, asmop, opfrag, "i64", GPR64, defs>; + commutable, asmop, opfrag, i64, GPR64, defs>; defm www : addsub_shifts<prefix # "www", 0b0, op, s, - commutable, asmop, opfrag, "i32", GPR32, defs>; + commutable, asmop, opfrag, i32, GPR32, defs>; } @@ -816,26 +814,26 @@ defm SUBS : addsub_sizes<"SUBS", 0b1, 0b1, 0b0, "subs", subc, [NZCV]>; // 1. The NEG/NEGS aliases //===------------------------------- -multiclass neg_alias<Instruction INST, RegisterClass GPR, - Register ZR, Operand shift_operand, SDNode shiftop> { +multiclass neg_alias<Instruction INST, RegisterClass GPR, Register ZR, + ValueType ty, Operand shift_operand, SDNode shiftop> { def : InstAlias<"neg $Rd, $Rm, $Imm6", (INST GPR:$Rd, ZR, GPR:$Rm, shift_operand:$Imm6)>; - def : Pat<(sub 0, (shiftop GPR:$Rm, shift_operand:$Imm6)), - (INST ZR, GPR:$Rm, shift_operand:$Imm6)>; + def : Pat<(sub 0, (shiftop ty:$Rm, shift_operand:$Imm6)), + (INST ZR, $Rm, shift_operand:$Imm6)>; } -defm : neg_alias<SUBwww_lsl, GPR32, WZR, lsl_operand_i32, shl>; -defm : neg_alias<SUBwww_lsr, GPR32, WZR, lsr_operand_i32, srl>; -defm : neg_alias<SUBwww_asr, GPR32, WZR, asr_operand_i32, sra>; +defm : neg_alias<SUBwww_lsl, GPR32, WZR, i32, lsl_operand_i32, shl>; +defm : neg_alias<SUBwww_lsr, GPR32, WZR, i32, lsr_operand_i32, srl>; +defm : neg_alias<SUBwww_asr, GPR32, WZR, i32, asr_operand_i32, sra>; def : InstAlias<"neg $Rd, $Rm", (SUBwww_lsl GPR32:$Rd, WZR, GPR32:$Rm, 0)>; -def : Pat<(sub 0, GPR32:$Rm), (SUBwww_lsl WZR, GPR32:$Rm, 0)>; +def : Pat<(sub 0, i32:$Rm), (SUBwww_lsl WZR, $Rm, 0)>; -defm : neg_alias<SUBxxx_lsl, GPR64, XZR, lsl_operand_i64, shl>; -defm : neg_alias<SUBxxx_lsr, GPR64, XZR, lsr_operand_i64, srl>; -defm : neg_alias<SUBxxx_asr, GPR64, XZR, asr_operand_i64, sra>; +defm : neg_alias<SUBxxx_lsl, GPR64, XZR, i64, lsl_operand_i64, shl>; +defm : neg_alias<SUBxxx_lsr, GPR64, XZR, i64, lsr_operand_i64, srl>; +defm : neg_alias<SUBxxx_asr, GPR64, XZR, i64, asr_operand_i64, sra>; def : InstAlias<"neg $Rd, $Rm", (SUBxxx_lsl GPR64:$Rd, XZR, GPR64:$Rm, 0)>; -def : Pat<(sub 0, GPR64:$Rm), (SUBxxx_lsl XZR, GPR64:$Rm, 0)>; +def : Pat<(sub 0, i64:$Rm), (SUBxxx_lsl XZR, $Rm, 0)>; // NEGS doesn't get any patterns yet: defining multiple outputs means C++ has to // be involved. @@ -859,36 +857,36 @@ def : InstAlias<"negs $Rd, $Rm", (SUBSxxx_lsl GPR64:$Rd, XZR, GPR64:$Rm, 0)>; //===------------------------------- multiclass cmp_shifts<string prefix, bit sf, bit op, bit commutable, - string asmop, SDPatternOperator opfrag, string sty, + string asmop, SDPatternOperator opfrag, ValueType ty, RegisterClass GPR> { let isCommutable = commutable, Rd = 0b11111, Defs = [NZCV] in { def _lsl : A64I_addsubshift<sf, op, 0b1, 0b00, (outs), (ins GPR:$Rn, GPR:$Rm, - !cast<Operand>("lsl_operand_" # sty):$Imm6), + !cast<Operand>("lsl_operand_" # ty):$Imm6), !strconcat(asmop, "\t$Rn, $Rm, $Imm6"), - [(set NZCV, (opfrag GPR:$Rn, (shl GPR:$Rm, - !cast<Operand>("lsl_operand_" # sty):$Imm6)) + [(set NZCV, (opfrag ty:$Rn, (shl ty:$Rm, + !cast<Operand>("lsl_operand_" # ty):$Imm6)) )], NoItinerary>; def _lsr : A64I_addsubshift<sf, op, 0b1, 0b01, (outs), (ins GPR:$Rn, GPR:$Rm, - !cast<Operand>("lsr_operand_" # sty):$Imm6), + !cast<Operand>("lsr_operand_" # ty):$Imm6), !strconcat(asmop, "\t$Rn, $Rm, $Imm6"), - [(set NZCV, (opfrag GPR:$Rn, (srl GPR:$Rm, - !cast<Operand>("lsr_operand_" # sty):$Imm6)) + [(set NZCV, (opfrag ty:$Rn, (srl ty:$Rm, + !cast<Operand>("lsr_operand_" # ty):$Imm6)) )], NoItinerary>; def _asr : A64I_addsubshift<sf, op, 0b1, 0b10, (outs), (ins GPR:$Rn, GPR:$Rm, - !cast<Operand>("asr_operand_" # sty):$Imm6), + !cast<Operand>("asr_operand_" # ty):$Imm6), !strconcat(asmop, "\t$Rn, $Rm, $Imm6"), - [(set NZCV, (opfrag GPR:$Rn, (sra GPR:$Rm, - !cast<Operand>("asr_operand_" # sty):$Imm6)) + [(set NZCV, (opfrag ty:$Rn, (sra ty:$Rm, + !cast<Operand>("asr_operand_" # ty):$Imm6)) )], NoItinerary>; } @@ -897,15 +895,15 @@ multiclass cmp_shifts<string prefix, bit sf, bit op, bit commutable, : InstAlias<!strconcat(asmop, " $Rn, $Rm"), (!cast<Instruction>(prefix # "_lsl") GPR:$Rn, GPR:$Rm, 0)>; - def : Pat<(opfrag GPR:$Rn, GPR:$Rm), - (!cast<Instruction>(prefix # "_lsl") GPR:$Rn, GPR:$Rm, 0)>; + def : Pat<(opfrag ty:$Rn, ty:$Rm), + (!cast<Instruction>(prefix # "_lsl") $Rn, $Rm, 0)>; } -defm CMPww : cmp_shifts<"CMPww", 0b0, 0b1, 0b0, "cmp", A64cmp, "i32", GPR32>; -defm CMPxx : cmp_shifts<"CMPxx", 0b1, 0b1, 0b0, "cmp", A64cmp, "i64", GPR64>; +defm CMPww : cmp_shifts<"CMPww", 0b0, 0b1, 0b0, "cmp", A64cmp, i32, GPR32>; +defm CMPxx : cmp_shifts<"CMPxx", 0b1, 0b1, 0b0, "cmp", A64cmp, i64, GPR64>; -defm CMNww : cmp_shifts<"CMNww", 0b0, 0b0, 0b1, "cmn", A64cmn, "i32", GPR32>; -defm CMNxx : cmp_shifts<"CMNxx", 0b1, 0b0, 0b1, "cmn", A64cmn, "i64", GPR64>; +defm CMNww : cmp_shifts<"CMNww", 0b0, 0b0, 0b1, "cmn", A64cmn, i32, GPR32>; +defm CMNxx : cmp_shifts<"CMNxx", 0b1, 0b0, 0b1, "cmn", A64cmn, i64, GPR64>; //===----------------------------------------------------------------------===// // Add-subtract (with carry) instructions @@ -947,10 +945,10 @@ def : InstAlias<"ngcs $Rd, $Rm", (SBCSxxx GPR64:$Rd, XZR, GPR64:$Rm)>; // Note that adde and sube can form a chain longer than two (e.g. for 256-bit // addition). So the flag-setting instructions are appropriate. -def : Pat<(adde GPR32:$Rn, GPR32:$Rm), (ADCSwww GPR32:$Rn, GPR32:$Rm)>; -def : Pat<(adde GPR64:$Rn, GPR64:$Rm), (ADCSxxx GPR64:$Rn, GPR64:$Rm)>; -def : Pat<(sube GPR32:$Rn, GPR32:$Rm), (SBCSwww GPR32:$Rn, GPR32:$Rm)>; -def : Pat<(sube GPR64:$Rn, GPR64:$Rm), (SBCSxxx GPR64:$Rn, GPR64:$Rm)>; +def : Pat<(adde i32:$Rn, i32:$Rm), (ADCSwww $Rn, $Rm)>; +def : Pat<(adde i64:$Rn, i64:$Rm), (ADCSxxx $Rn, $Rm)>; +def : Pat<(sube i32:$Rn, i32:$Rm), (SBCSwww $Rn, $Rm)>; +def : Pat<(sube i64:$Rn, i64:$Rm), (SBCSxxx $Rn, $Rm)>; //===----------------------------------------------------------------------===// // Bitfield @@ -1053,52 +1051,52 @@ def BFMxxii : // Note that these instructions are strictly more specific than the // BFM ones (in ImmR) so they can handle their own decoding. -class A64I_bf_ext<bit sf, bits<2> opc, RegisterClass GPRDest, string asmop, - bits<6> imms, dag pattern> +class A64I_bf_ext<bit sf, bits<2> opc, RegisterClass GPRDest, ValueType dty, + string asmop, bits<6> imms, dag pattern> : A64I_bitfield<sf, opc, sf, (outs GPRDest:$Rd), (ins GPR32:$Rn), !strconcat(asmop, "\t$Rd, $Rn"), - [(set GPRDest:$Rd, pattern)], NoItinerary> { + [(set dty:$Rd, pattern)], NoItinerary> { let ImmR = 0b000000; let ImmS = imms; } // Signed extensions -def SXTBxw : A64I_bf_ext<0b1, 0b00, GPR64, "sxtb", 7, - (sext_inreg (anyext GPR32:$Rn), i8)>; -def SXTBww : A64I_bf_ext<0b0, 0b00, GPR32, "sxtb", 7, - (sext_inreg GPR32:$Rn, i8)>; -def SXTHxw : A64I_bf_ext<0b1, 0b00, GPR64, "sxth", 15, - (sext_inreg (anyext GPR32:$Rn), i16)>; -def SXTHww : A64I_bf_ext<0b0, 0b00, GPR32, "sxth", 15, - (sext_inreg GPR32:$Rn, i16)>; -def SXTWxw : A64I_bf_ext<0b1, 0b00, GPR64, "sxtw", 31, (sext GPR32:$Rn)>; +def SXTBxw : A64I_bf_ext<0b1, 0b00, GPR64, i64, "sxtb", 7, + (sext_inreg (anyext i32:$Rn), i8)>; +def SXTBww : A64I_bf_ext<0b0, 0b00, GPR32, i32, "sxtb", 7, + (sext_inreg i32:$Rn, i8)>; +def SXTHxw : A64I_bf_ext<0b1, 0b00, GPR64, i64, "sxth", 15, + (sext_inreg (anyext i32:$Rn), i16)>; +def SXTHww : A64I_bf_ext<0b0, 0b00, GPR32, i32, "sxth", 15, + (sext_inreg i32:$Rn, i16)>; +def SXTWxw : A64I_bf_ext<0b1, 0b00, GPR64, i64, "sxtw", 31, (sext i32:$Rn)>; // Unsigned extensions -def UXTBww : A64I_bf_ext<0b0, 0b10, GPR32, "uxtb", 7, - (and GPR32:$Rn, 255)>; -def UXTHww : A64I_bf_ext<0b0, 0b10, GPR32, "uxth", 15, - (and GPR32:$Rn, 65535)>; +def UXTBww : A64I_bf_ext<0b0, 0b10, GPR32, i32, "uxtb", 7, + (and i32:$Rn, 255)>; +def UXTHww : A64I_bf_ext<0b0, 0b10, GPR32, i32, "uxth", 15, + (and i32:$Rn, 65535)>; // The 64-bit unsigned variants are not strictly architectural but recommended // for consistency. let isAsmParserOnly = 1 in { - def UXTBxw : A64I_bf_ext<0b0, 0b10, GPR64, "uxtb", 7, - (and (anyext GPR32:$Rn), 255)>; - def UXTHxw : A64I_bf_ext<0b0, 0b10, GPR64, "uxth", 15, - (and (anyext GPR32:$Rn), 65535)>; + def UXTBxw : A64I_bf_ext<0b0, 0b10, GPR64, i64, "uxtb", 7, + (and (anyext i32:$Rn), 255)>; + def UXTHxw : A64I_bf_ext<0b0, 0b10, GPR64, i64, "uxth", 15, + (and (anyext i32:$Rn), 65535)>; } // Extra patterns for when the source register is actually 64-bits // too. There's no architectural difference here, it's just LLVM // shinanigans. There's no need for equivalent zero-extension patterns // because they'll already be caught by logical (immediate) matching. -def : Pat<(sext_inreg GPR64:$Rn, i8), - (SXTBxw (EXTRACT_SUBREG GPR64:$Rn, sub_32))>; -def : Pat<(sext_inreg GPR64:$Rn, i16), - (SXTHxw (EXTRACT_SUBREG GPR64:$Rn, sub_32))>; -def : Pat<(sext_inreg GPR64:$Rn, i32), - (SXTWxw (EXTRACT_SUBREG GPR64:$Rn, sub_32))>; +def : Pat<(sext_inreg i64:$Rn, i8), + (SXTBxw (EXTRACT_SUBREG $Rn, sub_32))>; +def : Pat<(sext_inreg i64:$Rn, i16), + (SXTHxw (EXTRACT_SUBREG $Rn, sub_32))>; +def : Pat<(sext_inreg i64:$Rn, i32), + (SXTWxw (EXTRACT_SUBREG $Rn, sub_32))>; //===------------------------------- @@ -1111,7 +1109,7 @@ multiclass A64I_shift<bits<2> opc, string asmop, SDNode opnode> { def wwi : A64I_bitfield<0b0, opc, 0b0, (outs GPR32:$Rd), (ins GPR32:$Rn, bitfield32_imm:$ImmR), !strconcat(asmop, "\t$Rd, $Rn, $ImmR"), - [(set GPR32:$Rd, (opnode GPR32:$Rn, bitfield32_imm:$ImmR))], + [(set i32:$Rd, (opnode i32:$Rn, bitfield32_imm:$ImmR))], NoItinerary> { let ImmS = 31; } @@ -1119,7 +1117,7 @@ multiclass A64I_shift<bits<2> opc, string asmop, SDNode opnode> { def xxi : A64I_bitfield<0b1, opc, 0b1, (outs GPR64:$Rd), (ins GPR64:$Rn, bitfield64_imm:$ImmR), !strconcat(asmop, "\t$Rd, $Rn, $ImmR"), - [(set GPR64:$Rd, (opnode GPR64:$Rn, bitfield64_imm:$ImmR))], + [(set i64:$Rd, (opnode i64:$Rn, bitfield64_imm:$ImmR))], NoItinerary> { let ImmS = 63; } @@ -1156,10 +1154,11 @@ def bitfield64_lsl_imm : Operand<i64>, let EncoderMethod = "getBitfield64LSLOpValue"; } -class A64I_bitfield_lsl<bit sf, RegisterClass GPR, Operand operand> +class A64I_bitfield_lsl<bit sf, RegisterClass GPR, ValueType ty, + Operand operand> : A64I_bitfield<sf, 0b10, sf, (outs GPR:$Rd), (ins GPR:$Rn, operand:$FullImm), "lsl\t$Rd, $Rn, $FullImm", - [(set GPR:$Rd, (shl GPR:$Rn, operand:$FullImm))], + [(set ty:$Rd, (shl ty:$Rn, operand:$FullImm))], NoItinerary> { bits<12> FullImm; let ImmR = FullImm{5-0}; @@ -1170,8 +1169,8 @@ class A64I_bitfield_lsl<bit sf, RegisterClass GPR, Operand operand> let isAsmParserOnly = 1; } -def LSLwwi : A64I_bitfield_lsl<0b0, GPR32, bitfield32_lsl_imm>; -def LSLxxi : A64I_bitfield_lsl<0b1, GPR64, bitfield64_lsl_imm>; +def LSLwwi : A64I_bitfield_lsl<0b0, GPR32, i32, bitfield32_lsl_imm>; +def LSLxxi : A64I_bitfield_lsl<0b1, GPR64, i64, bitfield64_lsl_imm>; //===------------------------------- // 5. Aliases for bitfield extract instructions @@ -1206,7 +1205,7 @@ multiclass A64I_bitfield_extract<bits<2> opc, string asmop, SDNode op> { def wwii : A64I_bitfield<0b0, opc, 0b0, (outs GPR32:$Rd), (ins GPR32:$Rn, bitfield32_imm:$ImmR, bfx32_width:$ImmS), !strconcat(asmop, "\t$Rd, $Rn, $ImmR, $ImmS"), - [(set GPR32:$Rd, (op GPR32:$Rn, imm:$ImmR, imm:$ImmS))], + [(set i32:$Rd, (op i32:$Rn, imm:$ImmR, imm:$ImmS))], NoItinerary> { // As above, no disassembler allowed. let isAsmParserOnly = 1; @@ -1215,7 +1214,7 @@ multiclass A64I_bitfield_extract<bits<2> opc, string asmop, SDNode op> { def xxii : A64I_bitfield<0b1, opc, 0b1, (outs GPR64:$Rd), (ins GPR64:$Rn, bitfield64_imm:$ImmR, bfx64_width:$ImmS), !strconcat(asmop, "\t$Rd, $Rn, $ImmR, $ImmS"), - [(set GPR64:$Rd, (op GPR64:$Rn, imm:$ImmR, imm:$ImmS))], + [(set i64:$Rd, (op i64:$Rn, imm:$ImmR, imm:$ImmS))], NoItinerary> { // As above, no disassembler allowed. let isAsmParserOnly = 1; @@ -1243,15 +1242,15 @@ def BFXILxxii : A64I_bitfield<0b1, 0b01, 0b1, (outs GPR64:$Rd), } // SBFX instructions can do a 1-instruction sign-extension of boolean values. -def : Pat<(sext_inreg GPR64:$Rn, i1), (SBFXxxii GPR64:$Rn, 0, 0)>; -def : Pat<(sext_inreg GPR32:$Rn, i1), (SBFXwwii GPR32:$Rn, 0, 0)>; -def : Pat<(i64 (sext_inreg (anyext GPR32:$Rn), i1)), - (SBFXxxii (SUBREG_TO_REG (i64 0), GPR32:$Rn, sub_32), 0, 0)>; +def : Pat<(sext_inreg i64:$Rn, i1), (SBFXxxii $Rn, 0, 0)>; +def : Pat<(sext_inreg i32:$Rn, i1), (SBFXwwii $Rn, 0, 0)>; +def : Pat<(i64 (sext_inreg (anyext i32:$Rn), i1)), + (SBFXxxii (SUBREG_TO_REG (i64 0), $Rn, sub_32), 0, 0)>; // UBFX makes sense as an implementation of a 64-bit zero-extension too. Could // use either 64-bit or 32-bit variant, but 32-bit might be more efficient. -def : Pat<(zext GPR32:$Rn), (SUBREG_TO_REG (i64 0), (UBFXwwii GPR32:$Rn, 0, 31), - sub_32)>; +def : Pat<(zext i32:$Rn), (SUBREG_TO_REG (i64 0), (UBFXwwii $Rn, 0, 31), + sub_32)>; //===------------------------------- // 6. Aliases for bitfield insert instructions @@ -1380,14 +1379,14 @@ multiclass cmpbr_sizes<bit op, string asmop, ImmLeaf SETOP> { (outs), (ins GPR64:$Rt, bcc_target:$Label), !strconcat(asmop,"\t$Rt, $Label"), - [(A64br_cc (A64cmp GPR64:$Rt, 0), SETOP, bb:$Label)], + [(A64br_cc (A64cmp i64:$Rt, 0), SETOP, bb:$Label)], NoItinerary>; def w : A64I_cmpbr<0b0, op, (outs), (ins GPR32:$Rt, bcc_target:$Label), !strconcat(asmop,"\t$Rt, $Label"), - [(A64br_cc (A64cmp GPR32:$Rt, 0), SETOP, bb:$Label)], + [(A64br_cc (A64cmp i32:$Rt, 0), SETOP, bb:$Label)], NoItinerary>; } } @@ -1530,7 +1529,7 @@ multiclass A64I_condselSizes<bit op, bits<2> op2, string asmop, (outs GPR32:$Rd), (ins GPR32:$Rn, GPR32:$Rm, cond_code_op:$Cond), !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Cond"), - [(set GPR32:$Rd, (select GPR32:$Rn, GPR32:$Rm))], + [(set i32:$Rd, (select i32:$Rn, i32:$Rm))], NoItinerary>; @@ -1538,7 +1537,7 @@ multiclass A64I_condselSizes<bit op, bits<2> op2, string asmop, (outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm, cond_code_op:$Cond), !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Cond"), - |