ARM assembler aliases for "add Rd, #-imm" to "sub Rd, #imm".

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146111 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2011-12-08 00:31:07 +00:00
parent 7bf7fecd8d
commit 3bc8a3d3af
4 changed files with 62 additions and 11 deletions

View File

@ -243,17 +243,18 @@ def imm16_31 : ImmLeaf<i32, [{
return (int32_t)Imm >= 16 && (int32_t)Imm < 32; return (int32_t)Imm >= 16 && (int32_t)Imm < 32;
}]>; }]>;
def so_imm_neg : def so_imm_neg_asmoperand : AsmOperandClass { let Name = "ARMSOImmNeg"; }
PatLeaf<(imm), [{ def so_imm_neg : Operand<i32>, PatLeaf<(imm), [{
return ARM_AM::getSOImmVal(-(uint32_t)N->getZExtValue()) != -1; return ARM_AM::getSOImmVal(-(uint32_t)N->getZExtValue()) != -1;
}], so_imm_neg_XFORM>; }], so_imm_neg_XFORM> {
let ParserMatchClass = so_imm_neg_asmoperand;
}
// Note: this pattern doesn't require an encoder method and such, as it's // Note: this pattern doesn't require an encoder method and such, as it's
// only used on aliases (Pat<> and InstAlias<>). The actual encoding // only used on aliases (Pat<> and InstAlias<>). The actual encoding
// is handled by the destination instructions, which use t2_so_imm. // is handled by the destination instructions, which use t2_so_imm.
def so_imm_not_asmoperand : AsmOperandClass { let Name = "ARMSOImmNot"; } def so_imm_not_asmoperand : AsmOperandClass { let Name = "ARMSOImmNot"; }
def so_imm_not : def so_imm_not : Operand<i32>, PatLeaf<(imm), [{
Operand<i32>, PatLeaf<(imm), [{
return ARM_AM::getSOImmVal(~(uint32_t)N->getZExtValue()) != -1; return ARM_AM::getSOImmVal(~(uint32_t)N->getZExtValue()) != -1;
}], so_imm_not_XFORM> { }], so_imm_not_XFORM> {
let ParserMatchClass = so_imm_not_asmoperand; let ParserMatchClass = so_imm_not_asmoperand;
@ -5041,6 +5042,11 @@ def : MnemonicAlias<"usubaddx", "usax">;
// for isel. // for isel.
def : ARMInstAlias<"mov${s}${p} $Rd, $imm", def : ARMInstAlias<"mov${s}${p} $Rd, $imm",
(MVNi rGPR:$Rd, so_imm_not:$imm, pred:$p, cc_out:$s)>; (MVNi rGPR:$Rd, so_imm_not:$imm, pred:$p, cc_out:$s)>;
// Likewise, "add Rd, so_imm_neg" -> sub
def : ARMInstAlias<"add${s}${p} $Rd, $Rn, $imm",
(SUBri GPR:$Rd, GPR:$Rn, so_imm_neg:$imm, pred:$p, cc_out:$s)>;
def : ARMInstAlias<"add${s}${p} $Rd, $imm",
(SUBri GPR:$Rd, GPR:$Rd, so_imm_neg:$imm, pred:$p, cc_out:$s)>;
// The shifter forms of the MOV instruction are aliased to the ASR, LSL, // The shifter forms of the MOV instruction are aliased to the ASR, LSL,
// LSR, ROR, and RRX instructions. // LSR, ROR, and RRX instructions.

View File

@ -80,18 +80,19 @@ def t2_so_imm : Operand<i32>, ImmLeaf<i32, [{
// only used on aliases (Pat<> and InstAlias<>). The actual encoding // only used on aliases (Pat<> and InstAlias<>). The actual encoding
// is handled by the destination instructions, which use t2_so_imm. // is handled by the destination instructions, which use t2_so_imm.
def t2_so_imm_not_asmoperand : AsmOperandClass { let Name = "T2SOImmNot"; } def t2_so_imm_not_asmoperand : AsmOperandClass { let Name = "T2SOImmNot"; }
def t2_so_imm_not : Operand<i32>, def t2_so_imm_not : Operand<i32>, PatLeaf<(imm), [{
PatLeaf<(imm), [{
return ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())) != -1; return ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())) != -1;
}], t2_so_imm_not_XFORM> { }], t2_so_imm_not_XFORM> {
let ParserMatchClass = t2_so_imm_not_asmoperand; let ParserMatchClass = t2_so_imm_not_asmoperand;
} }
// t2_so_imm_neg - Match an immediate that is a negation of a t2_so_imm. // t2_so_imm_neg - Match an immediate that is a negation of a t2_so_imm.
def t2_so_imm_neg : Operand<i32>, def t2_so_imm_neg_asmoperand : AsmOperandClass { let Name = "T2SOImmNeg"; }
PatLeaf<(imm), [{ def t2_so_imm_neg : Operand<i32>, PatLeaf<(imm), [{
return ARM_AM::getT2SOImmVal(-((uint32_t)N->getZExtValue())) != -1; return ARM_AM::getT2SOImmVal(-((uint32_t)N->getZExtValue())) != -1;
}], t2_so_imm_neg_XFORM>; }], t2_so_imm_neg_XFORM> {
let ParserMatchClass = t2_so_imm_neg_asmoperand;
}
/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095]. /// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
def imm0_4095 : Operand<i32>, def imm0_4095 : Operand<i32>,
@ -4096,6 +4097,13 @@ def : t2InstAlias<"sxth${p} $Rd, $Rm$rot",
// for isel. // for isel.
def : t2InstAlias<"mov${p} $Rd, $imm", def : t2InstAlias<"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, zero_reg)>;
// Likewise, "add Rd, so_imm_neg" -> sub
def : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm",
(t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm,
pred:$p, cc_out:$s)>;
def : t2InstAlias<"add${s}${p} $Rd, $imm",
(t2SUBri GPRnopc:$Rd, GPRnopc:$Rd, t2_so_imm_neg:$imm,
pred:$p, cc_out:$s)>;
// Wide 'mul' encoding can be specified with only two operands. // Wide 'mul' encoding can be specified with only two operands.

View File

@ -749,6 +749,14 @@ public:
int64_t Value = CE->getValue(); int64_t Value = CE->getValue();
return ARM_AM::getSOImmVal(~Value) != -1; return ARM_AM::getSOImmVal(~Value) != -1;
} }
bool isARMSOImmNeg() const {
if (Kind != k_Immediate)
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
return ARM_AM::getSOImmVal(-Value) != -1;
}
bool isT2SOImm() const { bool isT2SOImm() const {
if (Kind != k_Immediate) if (Kind != k_Immediate)
return false; return false;
@ -765,6 +773,14 @@ public:
int64_t Value = CE->getValue(); int64_t Value = CE->getValue();
return ARM_AM::getT2SOImmVal(~Value) != -1; return ARM_AM::getT2SOImmVal(~Value) != -1;
} }
bool isT2SOImmNeg() const {
if (Kind != k_Immediate)
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
return ARM_AM::getT2SOImmVal(-Value) != -1;
}
bool isSetEndImm() const { bool isSetEndImm() const {
if (Kind != k_Immediate) if (Kind != k_Immediate)
return false; return false;
@ -1321,6 +1337,14 @@ public:
Inst.addOperand(MCOperand::CreateImm(~CE->getValue())); Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
} }
void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The operand is actually a t2_so_imm, but we have its
// negation in the assembly source, so twiddle it here.
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
}
void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const { void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!"); assert(N == 1 && "Invalid number of operands!");
// The operand is actually a so_imm, but we have its bitwise // The operand is actually a so_imm, but we have its bitwise
@ -1329,6 +1353,14 @@ public:
Inst.addOperand(MCOperand::CreateImm(~CE->getValue())); Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
} }
void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The operand is actually a so_imm, but we have its
// negation in the assembly source, so twiddle it here.
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
}
void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const { void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!"); assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt()))); Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));

View File

@ -173,6 +173,9 @@ Lforward:
add r6, r7, ror r9 add r6, r7, ror r9
add r4, r5, rrx add r4, r5, rrx
add r0, #-4
add r4, r5, #-21
@ CHECK: add r4, r5, #61440 @ encoding: [0x0f,0x4a,0x85,0xe2] @ CHECK: add r4, r5, #61440 @ encoding: [0x0f,0x4a,0x85,0xe2]
@ CHECK: add r4, r5, r6 @ encoding: [0x06,0x40,0x85,0xe0] @ CHECK: add r4, r5, r6 @ encoding: [0x06,0x40,0x85,0xe0]
@ CHECK: add r4, r5, r6, lsl #5 @ encoding: [0x86,0x42,0x85,0xe0] @ CHECK: add r4, r5, r6, lsl #5 @ encoding: [0x86,0x42,0x85,0xe0]
@ -187,7 +190,6 @@ Lforward:
@ CHECK: add r6, r7, r8, ror r9 @ encoding: [0x78,0x69,0x87,0xe0] @ CHECK: add r6, r7, r8, ror r9 @ encoding: [0x78,0x69,0x87,0xe0]
@ CHECK: add r4, r5, r6, rrx @ encoding: [0x66,0x40,0x85,0xe0] @ CHECK: add r4, r5, r6, rrx @ encoding: [0x66,0x40,0x85,0xe0]
@ CHECK: add r5, r5, #61440 @ encoding: [0x0f,0x5a,0x85,0xe2] @ CHECK: add r5, r5, #61440 @ encoding: [0x0f,0x5a,0x85,0xe2]
@ CHECK: add r4, r4, r5 @ encoding: [0x05,0x40,0x84,0xe0] @ CHECK: add r4, r4, r5 @ encoding: [0x05,0x40,0x84,0xe0]
@ CHECK: add r4, r4, r5, lsl #5 @ encoding: [0x85,0x42,0x84,0xe0] @ CHECK: add r4, r4, r5, lsl #5 @ encoding: [0x85,0x42,0x84,0xe0]
@ -201,6 +203,9 @@ Lforward:
@ CHECK: add r6, r6, r7, ror r9 @ encoding: [0x77,0x69,0x86,0xe0] @ CHECK: add r6, r6, r7, ror r9 @ encoding: [0x77,0x69,0x86,0xe0]
@ CHECK: add r4, r4, r5, rrx @ encoding: [0x65,0x40,0x84,0xe0] @ CHECK: add r4, r4, r5, rrx @ encoding: [0x65,0x40,0x84,0xe0]
@ CHECK: sub r0, r0, #4 @ encoding: [0x04,0x00,0x40,0xe2]
@ CHECK: sub r4, r5, #21 @ encoding: [0x15,0x40,0x45,0xe2]
@------------------------------------------------------------------------------ @------------------------------------------------------------------------------
@ AND @ AND