Skip to content

Commit

Permalink
ARMAsmParser: clean up of isImmediate functions
Browse files Browse the repository at this point in the history
- we are now using immediate AsmOperands so that the range check functions are
  tablegen'ed.
- Big bonus is that error messages become much more accurate, i.e. instead of a
  useless "invalid operand" error message it will not say that the immediate
  operand must in range [x,y], which is why regression tests needed updating.

More tablegen operand descriptions could probably benefit from using
immediateAsmOperand, but this is a first good step to get rid of most of the
nearly identical range check functions. I will address the remaining immediate
operands in next clean ups.

Differential Revision: https://reviews.llvm.org/D31333

llvm-svn: 299358
  • Loading branch information
Sjoerd Meijer committed Apr 3, 2017
1 parent 0b8949e commit 1179470
Show file tree
Hide file tree
Showing 14 changed files with 193 additions and 282 deletions.
12 changes: 6 additions & 6 deletions llvm/lib/Target/ARM/ARMInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def s_cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 CPSR))> {

// ARM special operands for disassembly only.
//
def SetEndAsmOperand : ImmAsmOperand {
def SetEndAsmOperand : ImmAsmOperand<0,1> {
let Name = "SetEndImm";
let ParserMethod = "parseSetEndImm";
}
Expand Down Expand Up @@ -221,25 +221,25 @@ def banked_reg : Operand<i32> {
// 16 imm6<5:4> = '01', 16 - <imm> is encoded in imm6<3:0>
// 32 imm6<5> = '1', 32 - <imm> is encoded in imm6<4:0>
// 64 64 - <imm> is encoded in imm6<5:0>
def shr_imm8_asm_operand : ImmAsmOperand { let Name = "ShrImm8"; }
def shr_imm8_asm_operand : ImmAsmOperand<1,8> { let Name = "ShrImm8"; }
def shr_imm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 8; }]> {
let EncoderMethod = "getShiftRight8Imm";
let DecoderMethod = "DecodeShiftRight8Imm";
let ParserMatchClass = shr_imm8_asm_operand;
}
def shr_imm16_asm_operand : ImmAsmOperand { let Name = "ShrImm16"; }
def shr_imm16_asm_operand : ImmAsmOperand<1,16> { let Name = "ShrImm16"; }
def shr_imm16 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 16; }]> {
let EncoderMethod = "getShiftRight16Imm";
let DecoderMethod = "DecodeShiftRight16Imm";
let ParserMatchClass = shr_imm16_asm_operand;
}
def shr_imm32_asm_operand : ImmAsmOperand { let Name = "ShrImm32"; }
def shr_imm32_asm_operand : ImmAsmOperand<1,32> { let Name = "ShrImm32"; }
def shr_imm32 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 32; }]> {
let EncoderMethod = "getShiftRight32Imm";
let DecoderMethod = "DecodeShiftRight32Imm";
let ParserMatchClass = shr_imm32_asm_operand;
}
def shr_imm64_asm_operand : ImmAsmOperand { let Name = "ShrImm64"; }
def shr_imm64_asm_operand : ImmAsmOperand<1,64> { let Name = "ShrImm64"; }
def shr_imm64 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 64; }]> {
let EncoderMethod = "getShiftRight64Imm";
let DecoderMethod = "DecodeShiftRight64Imm";
Expand Down Expand Up @@ -957,7 +957,7 @@ class ADivA1I<bits<3> opcod, dag oops, dag iops,
}

// PKH instructions
def PKHLSLAsmOperand : ImmAsmOperand {
def PKHLSLAsmOperand : ImmAsmOperand<0,31> {
let Name = "PKHLSLImm";
let ParserMethod = "parsePKHLSLImm";
}
Expand Down
73 changes: 49 additions & 24 deletions llvm/lib/Target/ARM/ARMInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,16 @@ def fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fsub node:$lhs, node:$rhs),[{
//

// Immediate operands with a shared generic asm render method.
class ImmAsmOperand : AsmOperandClass { let RenderMethod = "addImmOperands"; }
class ImmAsmOperand<int Low, int High> : AsmOperandClass {
let RenderMethod = "addImmOperands";
let PredicateMethod = "isImmediate<" # Low # "," # High # ">";
let DiagnosticType = "ImmRange" # Low # "_" # High;
}

class ImmAsmOperandMinusOne<int Low, int High> : AsmOperandClass {
let PredicateMethod = "isImmediate<" # Low # "," # High # ">";
let DiagnosticType = "ImmRange" # Low # "_" # High;
}

// Operands that are part of a memory addressing mode.
class MemOperand : Operand<i32> { let OperandType = "OPERAND_MEMORY"; }
Expand Down Expand Up @@ -663,61 +672,71 @@ def arm_i32imm : PatLeaf<(imm), [{
}]>;

/// imm0_1 predicate - Immediate in the range [0,1].
def Imm0_1AsmOperand: ImmAsmOperand { let Name = "Imm0_1"; }
def Imm0_1AsmOperand: ImmAsmOperand<0,1> { let Name = "Imm0_1"; }
def imm0_1 : Operand<i32> { let ParserMatchClass = Imm0_1AsmOperand; }

/// imm0_3 predicate - Immediate in the range [0,3].
def Imm0_3AsmOperand: ImmAsmOperand { let Name = "Imm0_3"; }
def Imm0_3AsmOperand: ImmAsmOperand<0,3> { let Name = "Imm0_3"; }
def imm0_3 : Operand<i32> { let ParserMatchClass = Imm0_3AsmOperand; }

/// imm0_7 predicate - Immediate in the range [0,7].
def Imm0_7AsmOperand: ImmAsmOperand { let Name = "Imm0_7"; }
def Imm0_7AsmOperand: ImmAsmOperand<0,7> {
let Name = "Imm0_7";
}
def imm0_7 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 8;
}]> {
let ParserMatchClass = Imm0_7AsmOperand;
}

/// imm8_255 predicate - Immediate in the range [8,255].
def Imm8_255AsmOperand: ImmAsmOperand<8,255> { let Name = "Imm8_255"; }
def imm8_255 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 8 && Imm < 256;
}]> {
let ParserMatchClass = Imm8_255AsmOperand;
}

/// imm8 predicate - Immediate is exactly 8.
def Imm8AsmOperand: ImmAsmOperand { let Name = "Imm8"; }
def Imm8AsmOperand: ImmAsmOperand<8,8> { let Name = "Imm8"; }
def imm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm == 8; }]> {
let ParserMatchClass = Imm8AsmOperand;
}

/// imm16 predicate - Immediate is exactly 16.
def Imm16AsmOperand: ImmAsmOperand { let Name = "Imm16"; }
def Imm16AsmOperand: ImmAsmOperand<16,16> { let Name = "Imm16"; }
def imm16 : Operand<i32>, ImmLeaf<i32, [{ return Imm == 16; }]> {
let ParserMatchClass = Imm16AsmOperand;
}

/// imm32 predicate - Immediate is exactly 32.
def Imm32AsmOperand: ImmAsmOperand { let Name = "Imm32"; }
def Imm32AsmOperand: ImmAsmOperand<32,32> { let Name = "Imm32"; }
def imm32 : Operand<i32>, ImmLeaf<i32, [{ return Imm == 32; }]> {
let ParserMatchClass = Imm32AsmOperand;
}

def imm8_or_16 : ImmLeaf<i32, [{ return Imm == 8 || Imm == 16;}]>;

/// imm1_7 predicate - Immediate in the range [1,7].
def Imm1_7AsmOperand: ImmAsmOperand { let Name = "Imm1_7"; }
def Imm1_7AsmOperand: ImmAsmOperand<1,7> { let Name = "Imm1_7"; }
def imm1_7 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm < 8; }]> {
let ParserMatchClass = Imm1_7AsmOperand;
}

/// imm1_15 predicate - Immediate in the range [1,15].
def Imm1_15AsmOperand: ImmAsmOperand { let Name = "Imm1_15"; }
def Imm1_15AsmOperand: ImmAsmOperand<1,15> { let Name = "Imm1_15"; }
def imm1_15 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm < 16; }]> {
let ParserMatchClass = Imm1_15AsmOperand;
}

/// imm1_31 predicate - Immediate in the range [1,31].
def Imm1_31AsmOperand: ImmAsmOperand { let Name = "Imm1_31"; }
def Imm1_31AsmOperand: ImmAsmOperand<1,31> { let Name = "Imm1_31"; }
def imm1_31 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm < 32; }]> {
let ParserMatchClass = Imm1_31AsmOperand;
}

/// imm0_15 predicate - Immediate in the range [0,15].
def Imm0_15AsmOperand: ImmAsmOperand {
def Imm0_15AsmOperand: ImmAsmOperand<0,15> {
let Name = "Imm0_15";
let DiagnosticType = "ImmRange0_15";
}
Expand All @@ -728,31 +747,31 @@ def imm0_15 : Operand<i32>, ImmLeaf<i32, [{
}

/// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31].
def Imm0_31AsmOperand: ImmAsmOperand { let Name = "Imm0_31"; }
def Imm0_31AsmOperand: ImmAsmOperand<0,31> { let Name = "Imm0_31"; }
def imm0_31 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 32;
}]> {
let ParserMatchClass = Imm0_31AsmOperand;
}

/// imm0_32 predicate - True if the 32-bit immediate is in the range [0,32].
def Imm0_32AsmOperand: ImmAsmOperand { let Name = "Imm0_32"; }
def Imm0_32AsmOperand: ImmAsmOperand<0,32> { let Name = "Imm0_32"; }
def imm0_32 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 32;
return Imm >= 0 && Imm < 33;
}]> {
let ParserMatchClass = Imm0_32AsmOperand;
}

/// imm0_63 predicate - True if the 32-bit immediate is in the range [0,63].
def Imm0_63AsmOperand: ImmAsmOperand { let Name = "Imm0_63"; }
def Imm0_63AsmOperand: ImmAsmOperand<0,63> { let Name = "Imm0_63"; }
def imm0_63 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 64;
}]> {
let ParserMatchClass = Imm0_63AsmOperand;
}

/// imm0_239 predicate - Immediate in the range [0,239].
def Imm0_239AsmOperand : ImmAsmOperand {
def Imm0_239AsmOperand : ImmAsmOperand<0,239> {
let Name = "Imm0_239";
let DiagnosticType = "ImmRange0_239";
}
Expand All @@ -761,13 +780,13 @@ def imm0_239 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 240; }]> {
}

/// imm0_255 predicate - Immediate in the range [0,255].
def Imm0_255AsmOperand : ImmAsmOperand { let Name = "Imm0_255"; }
def Imm0_255AsmOperand : ImmAsmOperand<0,255> { let Name = "Imm0_255"; }
def imm0_255 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> {
let ParserMatchClass = Imm0_255AsmOperand;
}

/// imm0_65535 - An immediate is in the range [0.65535].
def Imm0_65535AsmOperand: ImmAsmOperand { let Name = "Imm0_65535"; }
/// imm0_65535 - An immediate is in the range [0,65535].
def Imm0_65535AsmOperand: ImmAsmOperand<0,65535> { let Name = "Imm0_65535"; }
def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 65536;
}]> {
Expand All @@ -785,19 +804,23 @@ def imm0_65535_neg : Operand<i32>, ImmLeaf<i32, [{
// FIXME: This really needs a Thumb version separate from the ARM version.
// While the range is the same, and can thus use the same match class,
// the encoding is different so it should have a different encoder method.
def Imm0_65535ExprAsmOperand: ImmAsmOperand { let Name = "Imm0_65535Expr"; }
def Imm0_65535ExprAsmOperand: AsmOperandClass {
let Name = "Imm0_65535Expr";
let RenderMethod = "addImmOperands";
}

def imm0_65535_expr : Operand<i32> {
let EncoderMethod = "getHiLo16ImmOpValue";
let ParserMatchClass = Imm0_65535ExprAsmOperand;
}

def Imm256_65535ExprAsmOperand: ImmAsmOperand { let Name = "Imm256_65535Expr"; }
def Imm256_65535ExprAsmOperand: ImmAsmOperand<256,65535> { let Name = "Imm256_65535Expr"; }
def imm256_65535_expr : Operand<i32> {
let ParserMatchClass = Imm256_65535ExprAsmOperand;
}

/// imm24b - True if the 32-bit immediate is encodable in 24 bits.
def Imm24bitAsmOperand: ImmAsmOperand { let Name = "Imm24bit"; }
def Imm24bitAsmOperand: ImmAsmOperand<0,0xffffff> { let Name = "Imm24bit"; }
def imm24b : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm <= 0xffffff;
}]> {
Expand Down Expand Up @@ -826,7 +849,9 @@ def imm1_32_XFORM: SDNodeXForm<imm, [{
return CurDAG->getTargetConstant((int)N->getZExtValue() - 1, SDLoc(N),
MVT::i32);
}]>;
def Imm1_32AsmOperand: AsmOperandClass { let Name = "Imm1_32"; }
def Imm1_32AsmOperand: ImmAsmOperandMinusOne<1,32> {
let Name = "Imm1_32";
}
def imm1_32 : Operand<i32>, PatLeaf<(imm), [{
uint64_t Imm = N->getZExtValue();
return Imm > 0 && Imm <= 32;
Expand All @@ -840,7 +865,7 @@ def imm1_16_XFORM: SDNodeXForm<imm, [{
return CurDAG->getTargetConstant((int)N->getZExtValue() - 1, SDLoc(N),
MVT::i32);
}]>;
def Imm1_16AsmOperand: AsmOperandClass { let Name = "Imm1_16"; }
def Imm1_16AsmOperand: ImmAsmOperandMinusOne<1,16> { let Name = "Imm1_16"; }
def imm1_16 : Operand<i32>, PatLeaf<(imm), [{ return Imm > 0 && Imm <= 16; }],
imm1_16_XFORM> {
let PrintMethod = "printImmPlusOneOperand";
Expand Down
5 changes: 1 addition & 4 deletions llvm/lib/Target/ARM/ARMInstrThumb.td
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def imm_sr_XFORM: SDNodeXForm<imm, [{
unsigned Imm = N->getZExtValue();
return CurDAG->getTargetConstant((Imm == 32 ? 0 : Imm), SDLoc(N), MVT::i32);
}]>;
def ThumbSRImmAsmOperand: AsmOperandClass { let Name = "ImmThumbSR"; }
def ThumbSRImmAsmOperand: ImmAsmOperand<1,32> { let Name = "ImmThumbSR"; }
def imm_sr : Operand<i32>, PatLeaf<(imm), [{
uint64_t Imm = N->getZExtValue();
return Imm > 0 && Imm <= 32;
Expand Down Expand Up @@ -53,9 +53,6 @@ def imm0_255_comp : PatLeaf<(i32 imm), [{
return ~((uint32_t)N->getZExtValue()) < 256;
}]>;

def imm8_255 : ImmLeaf<i32, [{
return Imm >= 8 && Imm < 256;
}]>;
def imm8_255_neg : PatLeaf<(i32 imm), [{
unsigned Val = -N->getZExtValue();
return Val >= 8 && Val < 256;
Expand Down
10 changes: 7 additions & 3 deletions llvm/lib/Target/ARM/ARMInstrThumb2.td
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ def t2_so_imm_notSext16_XFORM : SDNodeXForm<imm, [{
// t2_so_imm - Match a 32-bit immediate operand, which is an
// 8-bit immediate rotated by an arbitrary number of bits, or an 8-bit
// immediate splatted into multiple bytes of the word.
def t2_so_imm_asmoperand : ImmAsmOperand { let Name = "T2SOImm"; }
def t2_so_imm_asmoperand : AsmOperandClass {
let Name = "T2SOImm";
let RenderMethod = "addImmOperands";

}
def t2_so_imm : Operand<i32>, ImmLeaf<i32, [{
return ARM_AM::getT2SOImmVal(Imm) != -1;
}]> {
Expand Down Expand Up @@ -116,8 +120,8 @@ def t2_so_imm_neg : Operand<i32>, ImmLeaf<i32, [{
let ParserMatchClass = t2_so_imm_neg_asmoperand;
}

/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
def imm0_4095_asmoperand: ImmAsmOperand { let Name = "Imm0_4095"; }
/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0,4095].
def imm0_4095_asmoperand: ImmAsmOperand<0,4095> { let Name = "Imm0_4095"; }
def imm0_4095 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 4096;
}]> {
Expand Down
Loading

0 comments on commit 1179470

Please sign in to comment.