diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index 93739722cc44d0ad51f500beac5959dc14b2c9a0..c08c363c04f8db5a4189f4aa6462dcdec52df3c3 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -258,10 +258,16 @@ def so_imm_neg : return ARM_AM::getSOImmVal(-(uint32_t)N->getZExtValue()) != -1; }], so_imm_neg_XFORM>; +// Note: this pattern doesn't require an encoder method and such, as it's +// only used on aliases (Pat<> and InstAlias<>). The actual encoding +// is handled by the destination instructions, which use t2_so_imm. +def so_imm_not_asmoperand : AsmOperandClass { let Name = "ARMSOImmNot"; } def so_imm_not : - PatLeaf<(imm), [{ + Operand, PatLeaf<(imm), [{ return ARM_AM::getSOImmVal(~(uint32_t)N->getZExtValue()) != -1; - }], so_imm_not_XFORM>; + }], so_imm_not_XFORM> { + let ParserMatchClass = so_imm_not_asmoperand; +} // sext_16_node predicate - True if the SDNode is sign-extended 16 or more bits. def sext_16_node : PatLeaf<(i32 GPR:$a), [{ @@ -4988,3 +4994,9 @@ def : MnemonicAlias<"usubaddx", "usax">; // (LDRHTi GPR:$Rt, GPR:$Rt, addr_offset_none:$addr, 0, pred:$p)>; //def : InstAlias<"ldrsht${p} $Rt, $addr", // (LDRSHTi GPR:$Rt, GPR:$Rt, addr_offset_none:$addr, 0, pred:$p)>; + + +// "mov Rd, so_imm_not" can be handled via "mvn" in assembly, just like +// for isel. +def : ARMInstAlias<"mov${s}${p} $Rd, $imm", + (MVNi rGPR:$Rd, so_imm_not:$imm, pred:$p, cc_out:$s)>; diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index ad5f061eabae6931b44ba0224daca0255b6c98fb..03fba5aee98390bffd05ba24c2aca7e0d65eece6 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -657,6 +657,14 @@ public: int64_t Value = CE->getValue(); return ARM_AM::getSOImmVal(Value) != -1; } + bool isARMSOImmNot() const { + if (Kind != k_Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return ARM_AM::getSOImmVal(~Value) != -1; + } bool isT2SOImm() const { if (Kind != k_Immediate) return false; @@ -1257,6 +1265,14 @@ public: Inst.addOperand(MCOperand::CreateImm(~CE->getValue())); } + void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + // The operand is actually a so_imm, but we have its bitwise + // negation in the assembly source, so twiddle it here. + const MCConstantExpr *CE = dyn_cast(getImm()); + Inst.addOperand(MCOperand::CreateImm(~CE->getValue())); + } + void addSetEndImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); addExpr(Inst, getImm());