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
|
//===-- X86InstrCMovSetCC.td - Conditional Move and SetCC --*- 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 describes the X86 conditional move and set on condition
// instructions.
//
//===----------------------------------------------------------------------===//
// CMOV instructions.
multiclass Cmov<X86TypeInfo t, string args, bit ndd = 0, string suffix = ""> {
let isCommutable = 1, SchedRW = [WriteCMOV] in
def rr#suffix : ITy<0x40, MRMSrcRegCC, t, (outs t.RegClass:$dst),
(ins t.RegClass:$src1, t.RegClass:$src2, ccode:$cond),
"cmov${cond}", args,
[(set t.RegClass:$dst, (X86cmov t.RegClass:$src1,
t.RegClass:$src2, timm:$cond, EFLAGS))]>, UseEFLAGS, NDD<ndd>;
let SchedRW = [WriteCMOV.Folded, WriteCMOV.ReadAfterFold] in
def rm#suffix : ITy<0x40, MRMSrcMemCC, t, (outs t.RegClass:$dst),
(ins t.RegClass:$src1, t.MemOperand:$src2, ccode:$cond),
"cmov${cond}", args,
[(set t.RegClass:$dst, (X86cmov t.RegClass:$src1,
(t.LoadNode addr:$src2), timm:$cond, EFLAGS))]>, UseEFLAGS, NDD<ndd>;
}
multiclass Cfcmov<X86TypeInfo t> {
let isCommutable = 1, SchedRW = [WriteCMOV] in {
let Predicates = [HasCMOV, HasCF, In64BitMode] in {
def rr : ITy<0x40, MRMDestRegCC, t, (outs t.RegClass:$dst),
(ins t.RegClass:$src1, ccode:$cond),
"cfcmov${cond}", unaryop_ndd_args,
[(set t.RegClass:$dst,
(X86cmov 0, t.RegClass:$src1, timm:$cond, EFLAGS))]>, UseEFLAGS, NF;
def rr_REV : ITy<0x40, MRMSrcRegCC, t, (outs t.RegClass:$dst),
(ins t.RegClass:$src1, ccode:$cond),
"cfcmov${cond}", unaryop_ndd_args,
[]>, UseEFLAGS, EVEX, T_MAP4;
}
let Predicates = [HasCMOV, HasCF, HasNDD, In64BitMode] in
def rr_ND : ITy<0x40, MRMSrcRegCC, t, (outs t.RegClass:$dst),
(ins t.RegClass:$src1, t.RegClass:$src2, ccode:$cond),
"cfcmov${cond}", binop_ndd_args, []>, UseEFLAGS, NDD<1>, NF;
}
let SchedRW = [WriteCMOV.Folded, WriteCMOV.ReadAfterFold] in {
let Predicates = [HasCMOV, HasCF, In64BitMode], mayLoad = 1 in
def rm : ITy<0x40, MRMSrcMemCC, t, (outs t.RegClass:$dst),
(ins t.MemOperand:$src1, ccode:$cond),
"cfcmov${cond}", unaryop_ndd_args, []>, UseEFLAGS, EVEX, T_MAP4;
let Predicates = [HasCMOV, HasCF, HasNDD, In64BitMode], mayLoad = 1 in
def rm_ND : ITy<0x40, MRMSrcMemCC, t, (outs t.RegClass:$dst),
(ins t.RegClass:$src1, t.MemOperand:$src2, ccode:$cond),
"cfcmov${cond}", binop_ndd_args, []>, UseEFLAGS, NDD<1>, NF;
}
let SchedRW = [WriteCMOV, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault],
Predicates = [HasCMOV, HasCF, In64BitMode], mayStore = 1 in
def mr : ITy<0x40, MRMDestMemCC, t, (outs),
(ins t.MemOperand:$dst, t.RegClass:$src1, ccode:$cond),
"cfcmov${cond}", unaryop_ndd_args, []>, UseEFLAGS, NF;
}
let isCodeGenOnly = 1, ForceDisassemble = 1 in {
let Predicates = [HasCMOV, NoNDD], Constraints = "$dst = $src1" in {
defm CMOV16 : Cmov<Xi16, binop_args>, OpSize16, TB;
defm CMOV32 : Cmov<Xi32, binop_args>, OpSize32, TB;
defm CMOV64 : Cmov<Xi64, binop_args>, TB;
}
let Predicates = [HasCMOV, HasNDD, In64BitMode] in {
defm CMOV16 : Cmov<Xi16, binop_ndd_args, 1, "_ND">, PD;
defm CMOV32 : Cmov<Xi32, binop_ndd_args, 1, "_ND">;
defm CMOV64 : Cmov<Xi64, binop_ndd_args, 1, "_ND">;
}
defm CFCMOV16 : Cfcmov<Xi16>, PD;
defm CFCMOV32 : Cfcmov<Xi32>;
defm CFCMOV64 : Cfcmov<Xi64>;
} // isCodeGenOnly = 1, ForceDisassemble = 1
def inv_cond_XFORM : SDNodeXForm<imm, [{
X86::CondCode CC = static_cast<X86::CondCode>(N->getZExtValue());
return CurDAG->getTargetConstant(X86::GetOppositeBranchCondition(CC),
SDLoc(N), MVT::i8);
}]>;
// Conditional moves with folded loads with operands swapped and conditions
// inverted.
let Predicates = [HasCMOV, NoNDD] in {
def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, timm:$cond, EFLAGS),
(CMOV16rm GR16:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>;
def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, timm:$cond, EFLAGS),
(CMOV32rm GR32:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>;
def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, timm:$cond, EFLAGS),
(CMOV64rm GR64:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>;
}
let Predicates = [HasCMOV, HasNDD] in {
def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, timm:$cond, EFLAGS),
(CMOV16rm_ND GR16:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>;
def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, timm:$cond, EFLAGS),
(CMOV32rm_ND GR32:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>;
def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, timm:$cond, EFLAGS),
(CMOV64rm_ND GR64:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>;
}
let Predicates = [HasCMOV, HasCF] in {
def : Pat<(X86cmov GR16:$src1, 0, timm:$cond, EFLAGS),
(CFCMOV16rr GR16:$src1, (inv_cond_XFORM timm:$cond))>;
def : Pat<(X86cmov GR32:$src1, 0, timm:$cond, EFLAGS),
(CFCMOV32rr GR32:$src1, (inv_cond_XFORM timm:$cond))>;
def : Pat<(X86cmov GR64:$src1, 0, timm:$cond, EFLAGS),
(CFCMOV64rr GR64:$src1, (inv_cond_XFORM timm:$cond))>;
def : Pat<(X86cload addr:$src1, 0, timm:$cond, EFLAGS),
(CFCMOV16rm addr:$src1, timm:$cond)>;
def : Pat<(X86cload addr:$src1, 0, timm:$cond, EFLAGS),
(CFCMOV32rm addr:$src1, timm:$cond)>;
def : Pat<(X86cload addr:$src1, 0, timm:$cond, EFLAGS),
(CFCMOV64rm addr:$src1, timm:$cond)>;
def : Pat<(X86cload addr:$src2, GR16:$src1, timm:$cond, EFLAGS),
(CFCMOV16rm_ND GR16:$src1, addr:$src2, timm:$cond)>;
def : Pat<(X86cload addr:$src2, GR32:$src1, timm:$cond, EFLAGS),
(CFCMOV32rm_ND GR32:$src1, addr:$src2, timm:$cond)>;
def : Pat<(X86cload addr:$src2, GR64:$src1, timm:$cond, EFLAGS),
(CFCMOV64rm_ND GR64:$src1, addr:$src2, timm:$cond)>;
def : Pat<(X86cstore GR16:$src2, addr:$src1, timm:$cond, EFLAGS),
(CFCMOV16mr addr:$src1, GR16:$src2, timm:$cond)>;
def : Pat<(X86cstore GR32:$src2, addr:$src1, timm:$cond, EFLAGS),
(CFCMOV32mr addr:$src1, GR32:$src2, timm:$cond)>;
def : Pat<(X86cstore GR64:$src2, addr:$src1, timm:$cond, EFLAGS),
(CFCMOV64mr addr:$src1, GR64:$src2, timm:$cond)>;
}
// SetCC instructions.
let Uses = [EFLAGS], isCodeGenOnly = 1, ForceDisassemble = 1 in {
def SETCCr : I<0x90, MRMXrCC, (outs GR8:$dst), (ins ccode:$cond),
"set${cond}\t$dst",
[(set GR8:$dst, (X86setcc timm:$cond, EFLAGS))]>,
TB, Sched<[WriteSETCC]>;
def SETCCm : I<0x90, MRMXmCC, (outs), (ins i8mem:$dst, ccode:$cond),
"set${cond}\t$dst",
[(store (X86setcc timm:$cond, EFLAGS), addr:$dst)]>,
TB, Sched<[WriteSETCCStore]>;
} // Uses = [EFLAGS]
// SetZUCC and promoted SetCC instructions.
let Uses = [EFLAGS], isCodeGenOnly = 1, ForceDisassemble = 1,
hasSideEffects = 0, Predicates = [In64BitMode], Predicates = [HasNDD] in {
def SETZUCCr : I<0x40, MRMXrCC, (outs GR8:$dst), (ins ccode:$cond),
"setzu${cond}\t$dst", []>,
XD, ZU, NoCD8, Sched<[WriteSETCC]>;
def SETCCr_EVEX : I<0x40, MRMXrCC, (outs GR8:$dst), (ins ccode:$cond),
"set${cond}\t$dst", []>,
XD, PL, Sched<[WriteSETCC]>;
let mayStore = 1 in {
def SETZUCCm : I<0x40, MRMXmCC, (outs), (ins i8mem:$dst, ccode:$cond),
"setzu${cond}\t$dst", []>,
XD, ZU, NoCD8, Sched<[WriteSETCCStore]>;
def SETCCm_EVEX : I<0x40, MRMXmCC, (outs), (ins i8mem:$dst, ccode:$cond),
"set${cond}\t$dst", []>,
XD, PL, Sched<[WriteSETCCStore]>;
}
}
// SALC is an undocumented instruction. Information for this instruction can be found
// here http://www.rcollins.org/secrets/opcodes/SALC.html
// Set AL if carry.
let Uses = [EFLAGS], Defs = [AL], SchedRW = [WriteALU] in {
def SALC : I<0xD6, RawFrm, (outs), (ins), "salc", []>, Requires<[Not64BitMode]>;
}
|