ARM assembly aliases for add negative immediates using sub.

'add r2, #-1024' should just use 'sub r2, #1024' rather than erroring out.
Thumb1 aliases for adding a negative immediate to the stack pointer,
also.

rdar://11192734

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154123 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2012-04-05 20:57:13 +00:00
parent ba9536a3c6
commit 4e53fe8dc6
4 changed files with 76 additions and 5 deletions

View File

@ -91,6 +91,12 @@ def t_imm0_508s4 : Operand<i32> {
let ParserMatchClass = t_imm0_508s4_asmoperand;
let OperandType = "OPERAND_IMMEDIATE";
}
// Alias use only, so no printer is necessary.
def t_imm0_508s4_neg_asmoperand: AsmOperandClass { let Name = "Imm0_508s4Neg"; }
def t_imm0_508s4_neg : Operand<i32> {
let ParserMatchClass = t_imm0_508s4_neg_asmoperand;
let OperandType = "OPERAND_IMMEDIATE";
}
// Define Thumb specific addressing modes.
@ -345,6 +351,11 @@ def tSUBspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm),
let DecoderMethod = "DecodeThumbAddSPImm";
}
def : tInstAlias<"add${p} sp, $imm",
(tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>;
def : tInstAlias<"add${p} sp, sp, $imm",
(tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>;
// Can optionally specify SP as a three operand instruction.
def : tInstAlias<"add${p} sp, sp, $imm",
(tADDspi SP, t_imm0_508s4:$imm, pred:$p)>;

View File

@ -96,14 +96,19 @@ def t2_so_imm_neg : Operand<i32>, PatLeaf<(imm), [{
}
/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
def imm0_4095 : Operand<i32>,
ImmLeaf<i32, [{
def imm0_4095_asmoperand: ImmAsmOperand { let Name = "Imm0_4095"; }
def imm0_4095 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 4096;
}]>;
}]> {
let ParserMatchClass = imm0_4095_asmoperand;
}
def imm0_4095_neg : PatLeaf<(i32 imm), [{
def imm0_4095_neg_asmoperand: AsmOperandClass { let Name = "Imm0_4095Neg"; }
def imm0_4095_neg : Operand<i32>, PatLeaf<(i32 imm), [{
return (uint32_t)(-N->getZExtValue()) < 4096;
}], imm_neg_XFORM>;
}], imm_neg_XFORM> {
let ParserMatchClass = imm0_4095_neg_asmoperand;
}
def imm0_255_neg : PatLeaf<(i32 imm), [{
return (uint32_t)(-N->getZExtValue()) < 255;
@ -3969,6 +3974,19 @@ def : t2InstAlias<"add${s}${p} $Rdn, $ShiftedRm",
(t2ADDrs GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_reg:$ShiftedRm,
pred:$p, cc_out:$s)>;
// add w/ negative immediates is just a 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${p} $Rd, $Rn, $imm",
(t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>;
def : t2InstAlias<"add${s}${p} $Rdn, $imm",
(t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p,
cc_out:$s)>;
def : t2InstAlias<"add${p} $Rdn, $imm",
(t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>;
// Aliases for SUB without the ".w" optional width specifier.
def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $imm",
(t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;

View File

@ -579,6 +579,14 @@ public:
int64_t Value = CE->getValue();
return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
}
bool isImm0_508s4Neg() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = -CE->getValue();
// explicitly exclude zero. we want that to use the normal 0_508 version.
return ((Value & 3) == 0) && Value > 0 && Value <= 508;
}
bool isImm0_255() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
@ -586,6 +594,20 @@ public:
int64_t Value = CE->getValue();
return Value >= 0 && Value < 256;
}
bool isImm0_4095() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
return Value >= 0 && Value < 4096;
}
bool isImm0_4095Neg() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = -CE->getValue();
return Value > 0 && Value < 4096;
}
bool isImm0_1() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
@ -1499,6 +1521,14 @@ public:
Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
}
void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The immediate is scaled by four in the encoding and is stored
// in the MCInst as such. Lop off the low two bits here.
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4)));
}
void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The immediate is scaled by four in the encoding and is stored
@ -1557,6 +1587,14 @@ public:
Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
}
void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The operand is actually an imm0_4095, 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 {
assert(N == 1 && "Invalid number of operands!");
// The operand is actually a so_imm, but we have its bitwise

View File

@ -59,12 +59,16 @@ _func:
add sp, sp, #4
add r2, sp, #8
add r2, sp, #1020
add sp, sp, #-8
add sp, #-8
@ CHECK: add sp, #4 @ encoding: [0x01,0xb0]
@ CHECK: add sp, #508 @ encoding: [0x7f,0xb0]
@ CHECK: add sp, #4 @ encoding: [0x01,0xb0]
@ CHECK: add r2, sp, #8 @ encoding: [0x02,0xaa]
@ CHECK: add r2, sp, #1020 @ encoding: [0xff,0xaa]
@ CHECK: sub sp, #8 @ encoding: [0x82,0xb0]
@ CHECK: sub sp, #8 @ encoding: [0x82,0xb0]
@------------------------------------------------------------------------------