Index: llvm/docs/TableGen/ProgRef.rst =================================================================== --- llvm/docs/TableGen/ProgRef.rst +++ llvm/docs/TableGen/ProgRef.rst @@ -211,8 +211,8 @@ : !getdagop !gt !head !if !isa : !le !listconcat !listsplat !lt !mul : !ne !not !or !setdagop !shl - : !size !sra !srl !strconcat !subst - : !tail !xor + : !size !sra !srl !strconcat !sub + : !subst !tail !xor The ``!cond`` operator has a slightly different syntax compared to other bang operators, so it is defined separately: @@ -1660,6 +1660,9 @@ are not strings, in which case an implicit ``!cast`` is done on those operands. +``!sub(``\ *a*\ ``,`` *b*\ ``, ...)`` + This operator subtracts *a*, *b*, etc., and produces the difference. + ``!subst(``\ *target*\ ``,`` *repl*\ ``,`` *value*\ ``)`` This operator replaces all occurrences of the *target* in the *value* with the *repl* and produces the resulting value. For strings, this is straightforward. Index: llvm/include/llvm/TableGen/Record.h =================================================================== --- llvm/include/llvm/TableGen/Record.h +++ llvm/include/llvm/TableGen/Record.h @@ -808,7 +808,7 @@ /// !op (X, Y) - Combine two inits. class BinOpInit : public OpInit, public FoldingSetNode { public: - enum BinaryOp : uint8_t { ADD, MUL, AND, OR, XOR, SHL, SRA, SRL, LISTCONCAT, + enum BinaryOp : uint8_t { ADD, SUB, MUL, AND, OR, XOR, SHL, SRA, SRL, LISTCONCAT, LISTSPLAT, STRCONCAT, CONCAT, EQ, NE, LE, LT, GE, GT, SETDAGOP }; Index: llvm/lib/TableGen/Record.cpp =================================================================== --- llvm/lib/TableGen/Record.cpp +++ llvm/lib/TableGen/Record.cpp @@ -1024,6 +1024,7 @@ break; } case ADD: + case SUB: case MUL: case AND: case OR: @@ -1040,9 +1041,10 @@ int64_t Result; switch (getOpcode()) { default: llvm_unreachable("Bad opcode!"); - case ADD: Result = LHSv + RHSv; break; - case MUL: Result = LHSv * RHSv; break; - case AND: Result = LHSv & RHSv; break; + case ADD: Result = LHSv + RHSv; break; + case SUB: Result = LHSv - RHSv; break; + case MUL: Result = LHSv * RHSv; break; + case AND: Result = LHSv & RHSv; break; case OR: Result = LHSv | RHSv; break; case XOR: Result = LHSv ^ RHSv; break; case SHL: Result = (uint64_t)LHSv << (uint64_t)RHSv; break; @@ -1072,6 +1074,7 @@ switch (getOpcode()) { case CONCAT: Result = "!con"; break; case ADD: Result = "!add"; break; + case SUB: Result = "!sub"; break; case MUL: Result = "!mul"; break; case AND: Result = "!and"; break; case OR: Result = "!or"; break; Index: llvm/lib/TableGen/TGLexer.h =================================================================== --- llvm/lib/TableGen/TGLexer.h +++ llvm/lib/TableGen/TGLexer.h @@ -51,7 +51,7 @@ MultiClass, String, Defset, Defvar, If, Then, ElseKW, // !keywords. - XConcat, XADD, XMUL, XNOT, XAND, XOR, XXOR, XSRA, XSRL, XSHL, + XConcat, XADD, XSUB, XMUL, XNOT, XAND, XOR, XXOR, XSRA, XSRL, XSHL, XListConcat, XListSplat, XStrConcat, XCast, XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond, XEq, XIsA, XDag, XNe, XLe, XLt, XGe, XGt, XSetDagOp, XGetDagOp, Index: llvm/lib/TableGen/TGLexer.cpp =================================================================== --- llvm/lib/TableGen/TGLexer.cpp +++ llvm/lib/TableGen/TGLexer.cpp @@ -562,6 +562,7 @@ .Case("con", tgtok::XConcat) .Case("dag", tgtok::XDag) .Case("add", tgtok::XADD) + .Case("sub", tgtok::XSUB) .Case("mul", tgtok::XMUL) .Case("not", tgtok::XNOT) .Case("and", tgtok::XAND) Index: llvm/lib/TableGen/TGParser.cpp =================================================================== --- llvm/lib/TableGen/TGParser.cpp +++ llvm/lib/TableGen/TGParser.cpp @@ -1075,6 +1075,7 @@ case tgtok::XConcat: case tgtok::XADD: + case tgtok::XSUB: case tgtok::XMUL: case tgtok::XAND: case tgtok::XOR: @@ -1101,6 +1102,7 @@ default: llvm_unreachable("Unhandled code!"); case tgtok::XConcat: Code = BinOpInit::CONCAT; break; case tgtok::XADD: Code = BinOpInit::ADD; break; + case tgtok::XSUB: Code = BinOpInit::SUB; break; case tgtok::XMUL: Code = BinOpInit::MUL; break; case tgtok::XAND: Code = BinOpInit::AND; break; case tgtok::XOR: Code = BinOpInit::OR; break; @@ -1137,6 +1139,7 @@ case tgtok::XSRL: case tgtok::XSHL: case tgtok::XADD: + case tgtok::XSUB: case tgtok::XMUL: Type = IntRecTy::get(); ArgType = IntRecTy::get(); @@ -1249,10 +1252,11 @@ ListType->getAsString() + "'"); return nullptr; } - if (Code != BinOpInit::ADD && Code != BinOpInit::AND && - Code != BinOpInit::OR && Code != BinOpInit::XOR && - Code != BinOpInit::SRA && Code != BinOpInit::SRL && - Code != BinOpInit::SHL && Code != BinOpInit::MUL) + if (Code != BinOpInit::ADD && Code != BinOpInit::SUB && + Code != BinOpInit::AND && Code != BinOpInit::OR && + Code != BinOpInit::XOR && Code != BinOpInit::SRA && + Code != BinOpInit::SRL && Code != BinOpInit::SHL && + Code != BinOpInit::MUL) ArgType = Resolved; } @@ -1288,8 +1292,9 @@ // shorthand for nesting them. if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT || Code == BinOpInit::CONCAT || Code == BinOpInit::ADD || - Code == BinOpInit::AND || Code == BinOpInit::OR || - Code == BinOpInit::XOR || Code == BinOpInit::MUL) { + Code == BinOpInit::SUB || Code == BinOpInit::AND || + Code == BinOpInit::OR || Code == BinOpInit::XOR || + Code == BinOpInit::MUL) { while (InitList.size() > 2) { Init *RHS = InitList.pop_back_val(); RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))->Fold(CurRec); @@ -1799,6 +1804,7 @@ /// SimpleValue ::= '(' IDValue DagArgList ')' /// SimpleValue ::= CONCATTOK '(' Value ',' Value ')' /// SimpleValue ::= ADDTOK '(' Value ',' Value ')' +/// SimpleValue ::= SUBTOK '(' Value ',' Value ')' /// SimpleValue ::= SHLTOK '(' Value ',' Value ')' /// SimpleValue ::= SRATOK '(' Value ',' Value ')' /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' @@ -2094,6 +2100,7 @@ case tgtok::XConcat: case tgtok::XDag: case tgtok::XADD: + case tgtok::XSUB: case tgtok::XMUL: case tgtok::XNOT: case tgtok::XAND: Index: llvm/lib/Target/AMDGPU/SIRegisterInfo.td =================================================================== --- llvm/lib/Target/AMDGPU/SIRegisterInfo.td +++ llvm/lib/Target/AMDGPU/SIRegisterInfo.td @@ -27,17 +27,17 @@ def lo16 : SubRegIndex<16, 0>; def hi16 : SubRegIndex<16, 16>; -foreach Index = 0-31 in { +foreach Index = 0...31 in { def sub#Index : SubRegIndex<32, !shl(Index, 5)>; } -foreach Index = 1-31 in { +foreach Index = 1...31 in { def sub#Index#_lo16 : ComposedSubRegIndex(sub#Index), lo16>; def sub#Index#_hi16 : ComposedSubRegIndex(sub#Index), hi16>; } -foreach Size = {2-6,8,16} in { - foreach Index = Indexes.slice in { +foreach Size = {2...6,8,16} in { + foreach Index = Indexes.slice in { def !foldl("", Indexes.slice, acc, cur, !strconcat(acc#!if(!eq(acc,""),"","_"), "sub"#!add(cur, Index))) : SubRegIndex { @@ -89,7 +89,7 @@ class RegSeqNames { int next = !add(start, stride); - int end_reg = !add(!add(start, size), -1); + int end_reg = !add(start, size, -1); list ret = !if(!le(end_reg, last_reg), !listconcat([prefix # "[" # start # ":" # end_reg # "]"], @@ -102,7 +102,7 @@ int start = 0> { dag trunc_rc = (trunc RC, !if(!and(!eq(stride, 1), !eq(start, 0)), - !add(!add(last_reg, 2), !mul(size, -1)), + !sub(!add(last_reg, 2), size), !add(last_reg, 1))); list ret = !if(!lt(start, size), @@ -247,7 +247,7 @@ let HWEncoding = 110; } -foreach Index = 0-15 in { +foreach Index = 0...15 in { defm TTMP#Index#_vi : SIRegLoHi16<"ttmp"#Index, !add(112, Index)>; defm TTMP#Index#_gfx9_gfx10 : SIRegLoHi16<"ttmp"#Index, !add(108, Index)>; defm TTMP#Index : SIRegLoHi16<"ttmp"#Index, 0>; @@ -274,7 +274,7 @@ def FLAT_SCR : FlatReg; // SGPR registers -foreach Index = 0-105 in { +foreach Index = 0...105 in { defm SGPR#Index : SIRegLoHi16 <"s"#Index, Index>, DwarfRegNum<[!if(!le(Index, 63), !add(Index, 32), !add(Index, 1024)), @@ -282,14 +282,14 @@ } // VGPR registers -foreach Index = 0-255 in { +foreach Index = 0...255 in { defm VGPR#Index : SIRegLoHi16 <"v"#Index, Index, 0, 1>, DwarfRegNum<[!add(Index, 2560), !add(Index, 1536)]>; } // AccVGPR registers -foreach Index = 0-255 in { +foreach Index = 0...255 in { defm AGPR#Index : SIRegLoHi16 <"a"#Index, Index, 1, 1>, DwarfRegNum<[!add(Index, 3072), !add(Index, 2048)]>; @@ -389,7 +389,7 @@ class TmpRegTuplesBase subRegs, list indices = getSubRegs.ret, - int index1 = !add(index, !add(size, -1)), + int index1 = !add(index, size, -1), string name = "ttmp["#index#":"#index1#"]"> : RegisterWithSubRegs { let HWEncoding = subRegs[0].HWEncoding; Index: llvm/test/TableGen/arithmetic.td =================================================================== --- llvm/test/TableGen/arithmetic.td +++ llvm/test/TableGen/arithmetic.td @@ -5,6 +5,7 @@ // CHECK: def A0 { // CHECK: bits<8> add = { 0, 1, 0, 0, 0, 0, 0, 0 }; +// CHECK: bits<8> sub = { 0, 0, 1, 1, 1, 1, 1, 0 }; // CHECK: bits<8> and = { 0, 0, 0, 0, 0, 0, 0, 1 }; // CHECK: bits<8> or = { 0, 0, 1, 1, 1, 1, 1, 1 }; // CHECK: bits<8> xor = { 0, 0, 1, 1, 1, 1, 1, 0 }; @@ -16,8 +17,9 @@ class A a, bits<2> b> { // Operands of different bits types are allowed. bits<8> add = !add(a, b); + bits<8> sub = !sub(a, b); bits<8> and = !and(a, b); - bits<8> or = !or(a, b); + bits<8> or = !or(a, b); bits<8> xor = !xor(a, b); bits<8> srl = !srl(a, b); bits<8> sra = !sra(a, b); @@ -25,3 +27,4 @@ } def A0 : A<63, 1>; + Index: llvm/test/TableGen/math.td =================================================================== --- llvm/test/TableGen/math.td +++ llvm/test/TableGen/math.td @@ -1,37 +1,45 @@ // RUN: llvm-tblgen %s | FileCheck %s // XFAIL: vg_leak +// CHECK: def shifts +// CHECK: shifted_b = 8 +// CHECK: shifted_i = 8 def shifts { bits<2> b = 0b10; int i = 2; int shifted_b = !shl(b, 2); int shifted_i = !shl(i, 2); } -// CHECK: def shifts -// CHECK: shifted_b = 8 -// CHECK: shifted_i = 8 class Int { int Value = value; } -def v1022 : Int<1022>; +def int2 : Int<2>; +def int1022 : Int<1022>; +def int1024 : Int<1024>; -// CHECK: def v0 +// CHECK: def v0a // CHECK: Value = 0 +def v0a : Int; + +// CHECK: def v0b +// CHECK: Value = 0 +def v0b : Int; // CHECK: def v1 // CHECK: Value = 1 +def v1 : Int; + +// CHECK: def v1021 +// CHECK: Value = 1021 +def v1021 : Int; // CHECK: def v1023 // CHECK: Value = 1023 -def v1023 : Int; +def v1023 : Int; -def v1024 : Int<1024>; -// CHECK: def v1024 -// CHECK: Value = 1024 - -def v1025 : Int; +def v1025 : Int; // CHECK: def v1025 // CHECK: Value = 1025 @@ -42,20 +50,13 @@ // CHECK: def v1a // CHECK: Value = 1 -// CHECK: def v2 -// CHECK: Value = 2 -def v2 : Int<2>; - -def v2048 : Int; // CHECK: def v2048 // CHECK: Value = 2048 - -def v0 : Int; -def v1 : Int; +def v2048 : Int; // CHECK: def v3072 // CHECK: Value = 3072 -def v3072 : Int; +def v3072 : Int; // CHECK: def v4 // CHECK: Value = 4 @@ -63,8 +64,8 @@ // CHECK: def v7 // CHECK: Value = 7 -def v4 : Int; -def v7 : Int; +def v4 : Int; +def v7 : Int; def v1a : Int; // CHECK: def v84 @@ -79,4 +80,10 @@ // CHECK: Value = 924 def v924 : Int; +// CHECK: def v925 +// CHECK: Value = 925 +def v925 : Int; +// CHECK: def vneg +// CHECK: Value = -2 +def vneg : Int; \ No newline at end of file