aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/X86/X86InstrTBM.td
blob: ed514038a12e4911a3242d9e78aa5a028541e4df (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//====-- X86InstrTBM.td - TBM X86 Instruction Definition -*- tablegen -*-=====//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defining the TBM X86 instructions.
// 
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// TBM Instructions
//
let Predicates = [HasTBM], Defs = [EFLAGS] in {

multiclass tbm_bextri<bits<8> opc, RegisterClass RC, string OpcodeStr,
                      X86MemOperand x86memop, PatFrag ld_frag,
                      SDNode OpNode, Operand immtype,
                      SDPatternOperator immoperator,
                      X86FoldableSchedWrite Sched> {
  def ri : Ii32<opc,  MRMSrcReg, (outs RC:$dst), (ins RC:$src1, immtype:$cntl),
                !strconcat(OpcodeStr,
                           "\t{$cntl, $src1, $dst|$dst, $src1, $cntl}"),
                [(set RC:$dst, (OpNode RC:$src1, immoperator:$cntl))]>,
                XOP, XOPA, Sched<[Sched]>;
  def mi : Ii32<opc,  MRMSrcMem, (outs RC:$dst),
                (ins x86memop:$src1, immtype:$cntl),
                !strconcat(OpcodeStr,
                           "\t{$cntl, $src1, $dst|$dst, $src1, $cntl}"),
                [(set RC:$dst, (OpNode (ld_frag addr:$src1), immoperator:$cntl))]>,
                XOP, XOPA, Sched<[Sched.Folded]>;
}

defm BEXTRI32 : tbm_bextri<0x10, GR32, "bextr{l}", i32mem, loadi32,
                           X86bextri, i32imm, timm, WriteBEXTR>;
let ImmT = Imm32S in
defm BEXTRI64 : tbm_bextri<0x10, GR64, "bextr{q}", i64mem, loadi64,
                           X86bextri, i64i32imm,
                           i64timmSExt32, WriteBEXTR>, REX_W;

multiclass tbm_binary_rm<bits<8> opc, Format FormReg, Format FormMem,
                         RegisterClass RC, string OpcodeStr,
                         X86MemOperand x86memop, X86FoldableSchedWrite Sched> {
let hasSideEffects = 0 in {
  def rr : I<opc,  FormReg, (outs RC:$dst), (ins RC:$src),
             !strconcat(OpcodeStr,"\t{$src, $dst|$dst, $src}"), []>,
             XOP_4V, XOP9, Sched<[Sched]>;
  let mayLoad = 1 in
  def rm : I<opc,  FormMem, (outs RC:$dst), (ins x86memop:$src),
             !strconcat(OpcodeStr,"\t{$src, $dst|$dst, $src}"), []>,
             XOP_4V, XOP9, Sched<[Sched.Folded]>;
}
}

multiclass tbm_binary_intr<bits<8> opc, string OpcodeStr,
                           X86FoldableSchedWrite Sched,
                           Format FormReg, Format FormMem> {
  defm NAME#32 : tbm_binary_rm<opc, FormReg, FormMem, GR32, OpcodeStr#"{l}",
                               i32mem, Sched>;
  defm NAME#64 : tbm_binary_rm<opc, FormReg, FormMem, GR64, OpcodeStr#"{q}",
                               i64mem, Sched>, REX_W;
}

defm BLCFILL : tbm_binary_intr<0x01, "blcfill", WriteALU, MRM1r, MRM1m>;
defm BLCI    : tbm_binary_intr<0x02, "blci", WriteALU, MRM6r, MRM6m>;
defm BLCIC   : tbm_binary_intr<0x01, "blcic", WriteALU, MRM5r, MRM5m>;
defm BLCMSK  : tbm_binary_intr<0x02, "blcmsk", WriteALU, MRM1r, MRM1m>;
defm BLCS    : tbm_binary_intr<0x01, "blcs", WriteALU, MRM3r, MRM3m>;
defm BLSFILL : tbm_binary_intr<0x01, "blsfill", WriteALU, MRM2r, MRM2m>;
defm BLSIC   : tbm_binary_intr<0x01, "blsic", WriteALU, MRM6r, MRM6m>;
defm T1MSKC  : tbm_binary_intr<0x01, "t1mskc", WriteALU, MRM7r, MRM7m>;
defm TZMSK   : tbm_binary_intr<0x01, "tzmsk", WriteALU, MRM4r, MRM4m>;
} // HasTBM, EFLAGS

// Use BEXTRI for 64-bit 'and' with large immediate 'mask'.
let Predicates = [HasTBM] in {
  def : Pat<(and GR64:$src, AndMask64:$mask),
            (BEXTRI64ri GR64:$src, (BEXTRMaskXForm imm:$mask))>;

  def : Pat<(and (loadi64 addr:$src), AndMask64:$mask),
            (BEXTRI64mi addr:$src, (BEXTRMaskXForm imm:$mask))>;
}

//===----------------------------------------------------------------------===//
// Pattern fragments to auto generate TBM instructions.
//===----------------------------------------------------------------------===//

let Predicates = [HasTBM] in {
  // FIXME: patterns for the load versions are not implemented
  def : Pat<(and GR32:$src, (add GR32:$src, 1)),
            (BLCFILL32rr GR32:$src)>;
  def : Pat<(and GR64:$src, (add GR64:$src, 1)),
            (BLCFILL64rr GR64:$src)>;

  def : Pat<(or GR32:$src, (not (add GR32:$src, 1))),
            (BLCI32rr GR32:$src)>;
  def : Pat<(or GR64:$src, (not (add GR64:$src, 1))),
            (BLCI64rr GR64:$src)>;

  // Extra patterns because opt can optimize the above patterns to this.
  def : Pat<(or GR32:$src, (sub -2, GR32:$src)),
            (BLCI32rr GR32:$src)>;
  def : Pat<(or GR64:$src, (sub -2, GR64:$src)),
            (BLCI64rr GR64:$src)>;

  def : Pat<(and (not GR32:$src), (add GR32:$src, 1)),
            (BLCIC32rr GR32:$src)>;
  def : Pat<(and (not GR64:$src), (add GR64:$src, 1)),
            (BLCIC64rr GR64:$src)>;

  def : Pat<(xor GR32:$src, (add GR32:$src, 1)),
            (BLCMSK32rr GR32:$src)>;
  def : Pat<(xor GR64:$src, (add GR64:$src, 1)),
            (BLCMSK64rr GR64:$src)>;

  def : Pat<(or GR32:$src, (add GR32:$src, 1)),
            (BLCS32rr GR32:$src)>;
  def : Pat<(or GR64:$src, (add GR64:$src, 1)),
            (BLCS64rr GR64:$src)>;

  def : Pat<(or GR32:$src, (add GR32:$src, -1)),
            (BLSFILL32rr GR32:$src)>;
  def : Pat<(or GR64:$src, (add GR64:$src, -1)),
            (BLSFILL64rr GR64:$src)>;

  def : Pat<(or (not GR32:$src), (add GR32:$src, -1)),
            (BLSIC32rr GR32:$src)>;
  def : Pat<(or (not GR64:$src), (add GR64:$src, -1)),
            (BLSIC64rr GR64:$src)>;

  def : Pat<(or (not GR32:$src), (add GR32:$src, 1)),
            (T1MSKC32rr GR32:$src)>;
  def : Pat<(or (not GR64:$src), (add GR64:$src, 1)),
            (T1MSKC64rr GR64:$src)>;

  def : Pat<(and (not GR32:$src), (add GR32:$src, -1)),
            (TZMSK32rr GR32:$src)>;
  def : Pat<(and (not GR64:$src), (add GR64:$src, -1)),
            (TZMSK64rr GR64:$src)>;

  // Patterns to match flag producing ops.
  def : Pat<(and_flag_nocf GR32:$src, (add GR32:$src, 1)),
            (BLCFILL32rr GR32:$src)>;
  def : Pat<(and_flag_nocf GR64:$src, (add GR64:$src, 1)),
            (BLCFILL64rr GR64:$src)>;

  def : Pat<(or_flag_nocf GR32:$src, (not (add GR32:$src, 1))),
            (BLCI32rr GR32:$src)>;
  def : Pat<(or_flag_nocf GR64:$src, (not (add GR64:$src, 1))),
            (BLCI64rr GR64:$src)>;

  // Extra patterns because opt can optimize the above patterns to this.
  def : Pat<(or_flag_nocf GR32:$src, (sub -2, GR32:$src)),
            (BLCI32rr GR32:$src)>;
  def : Pat<(or_flag_nocf GR64:$src, (sub -2, GR64:$src)),
            (BLCI64rr GR64:$src)>;

  def : Pat<(and_flag_nocf (not GR32:$src), (add GR32:$src, 1)),
            (BLCIC32rr GR32:$src)>;
  def : Pat<(and_flag_nocf (not GR64:$src), (add GR64:$src, 1)),
            (BLCIC64rr GR64:$src)>;

  def : Pat<(xor_flag_nocf GR32:$src, (add GR32:$src, 1)),
            (BLCMSK32rr GR32:$src)>;
  def : Pat<(xor_flag_nocf GR64:$src, (add GR64:$src, 1)),
            (BLCMSK64rr GR64:$src)>;

  def : Pat<(or_flag_nocf GR32:$src, (add GR32:$src, 1)),
            (BLCS32rr GR32:$src)>;
  def : Pat<(or_flag_nocf GR64:$src, (add GR64:$src, 1)),
            (BLCS64rr GR64:$src)>;

  def : Pat<(or_flag_nocf GR32:$src, (add GR32:$src, -1)),
            (BLSFILL32rr GR32:$src)>;
  def : Pat<(or_flag_nocf GR64:$src, (add GR64:$src, -1)),
            (BLSFILL64rr GR64:$src)>;

  def : Pat<(or_flag_nocf (not GR32:$src), (add GR32:$src, -1)),
            (BLSIC32rr GR32:$src)>;
  def : Pat<(or_flag_nocf (not GR64:$src), (add GR64:$src, -1)),
            (BLSIC64rr GR64:$src)>;

  def : Pat<(or_flag_nocf (not GR32:$src), (add GR32:$src, 1)),
            (T1MSKC32rr GR32:$src)>;
  def : Pat<(or_flag_nocf (not GR64:$src), (add GR64:$src, 1)),
            (T1MSKC64rr GR64:$src)>;

  def : Pat<(and_flag_nocf (not GR32:$src), (add GR32:$src, -1)),
            (TZMSK32rr GR32:$src)>;
  def : Pat<(and_flag_nocf (not GR64:$src), (add GR64:$src, -1)),
            (TZMSK64rr GR64:$src)>;
} // HasTBM