[llvm] r335017 - [X86] Add a new VEX_WPrefix encoding to tag EVEX instruction that have VEX.W==1, but can be converted to their VEX equivalent that uses VEX.W==0.
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 18 21:24:42 PDT 2018
Author: ctopper
Date: Mon Jun 18 21:24:42 2018
New Revision: 335017
URL: http://llvm.org/viewvc/llvm-project?rev=335017&view=rev
Log:
[X86] Add a new VEX_WPrefix encoding to tag EVEX instruction that have VEX.W==1, but can be converted to their VEX equivalent that uses VEX.W==0.
EVEX makes heavy use of the VEX.W bit to indicate 64-bit element vs 32-bit elements. Many of the VEX instructions were split into 2 versions with different masking granularity.
The EVEX->VEX table generate can collapse the two versions if the VEX version uses is tagged as VEX_WIG. But if the VEX version is instead marked VEX.W==0 we can't combine them because we don't know if there is also a VEX version with VEX.W==1.
This patch adds a new VEX_W1X tag that indicates the EVEX instruction encodes with VEX.W==1, but is safe to convert to a VEX instruction with VEX.W==0.
This allows us to remove a bunch of manual EVEX->VEX table entries. We may want to look into splitting up the VEX_WPrefix field which would simplify the disassembler.
Modified:
llvm/trunk/lib/Target/X86/X86InstrAVX512.td
llvm/trunk/lib/Target/X86/X86InstrFormats.td
llvm/trunk/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp
llvm/trunk/utils/TableGen/X86RecognizableInstr.cpp
llvm/trunk/utils/TableGen/X86RecognizableInstr.h
Modified: llvm/trunk/lib/Target/X86/X86InstrAVX512.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrAVX512.td?rev=335017&r1=335016&r2=335017&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrAVX512.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrAVX512.td Mon Jun 18 21:24:42 2018
@@ -593,7 +593,7 @@ multiclass vinsert_for_type<ValueType El
X86VectorVTInfo< 2, EltVT64, VR128X>,
X86VectorVTInfo< 4, EltVT64, VR256X>,
null_frag, vinsert128_insert, sched>,
- VEX_W, EVEX_V256;
+ VEX_W1X, EVEX_V256;
// Even with DQI we'd like to only use these instructions for masking.
let Predicates = [HasDQI] in {
@@ -890,7 +890,7 @@ multiclass vextract_for_type<ValueType E
X86VectorVTInfo< 4, EltVT64, VR256X>,
X86VectorVTInfo< 2, EltVT64, VR128X>,
null_frag, vextract128_extract, SchedRR, SchedMR>,
- VEX_W, EVEX_V256, EVEX_CD8<64, CD8VT2>;
+ VEX_W1X, EVEX_V256, EVEX_CD8<64, CD8VT2>;
// Even with DQI we'd like to only use these instructions for masking.
let Predicates = [HasDQI] in {
@@ -1265,7 +1265,7 @@ multiclass avx512_fp_broadcast_ss<bits<8
defm VBROADCASTSS : avx512_fp_broadcast_ss<0x18, "vbroadcastss",
avx512vl_f32_info>;
defm VBROADCASTSD : avx512_fp_broadcast_sd<0x19, "vbroadcastsd",
- avx512vl_f64_info>, VEX_W;
+ avx512vl_f64_info>, VEX_W1X;
multiclass avx512_int_broadcast_reg<bits<8> opc, SchedWrite SchedRR,
X86VectorVTInfo _, SDPatternOperator OpNode,
@@ -1378,7 +1378,7 @@ defm VPBROADCASTW : avx512_int_broadcas
defm VPBROADCASTD : avx512_int_broadcast_rm_vl<0x58, "vpbroadcastd",
avx512vl_i32_info, HasAVX512>;
defm VPBROADCASTQ : avx512_int_broadcast_rm_vl<0x59, "vpbroadcastq",
- avx512vl_i64_info, HasAVX512>, VEX_W;
+ avx512vl_i64_info, HasAVX512>, VEX_W1X;
multiclass avx512_subvec_broadcast_rm<bits<8> opc, string OpcodeStr,
X86VectorVTInfo _Dst, X86VectorVTInfo _Src> {
@@ -1586,10 +1586,10 @@ def : Pat<(v32i8 (X86SubVBroadcast (v16i
let Predicates = [HasVLX, HasDQI] in {
defm VBROADCASTI64X2Z128 : avx512_subvec_broadcast_rm_dq<0x5a, "vbroadcasti64x2",
- v4i64x_info, v2i64x_info>, VEX_W,
+ v4i64x_info, v2i64x_info>, VEX_W1X,
EVEX_V256, EVEX_CD8<64, CD8VT2>;
defm VBROADCASTF64X2Z128 : avx512_subvec_broadcast_rm_dq<0x1a, "vbroadcastf64x2",
- v4f64x_info, v2f64x_info>, VEX_W,
+ v4f64x_info, v2f64x_info>, VEX_W1X,
EVEX_V256, EVEX_CD8<64, CD8VT2>;
// Patterns for selects of bitcasted operations.
@@ -6293,7 +6293,7 @@ defm VPERMILPS : avx512_permil<"vpermilp
avx512vl_i32_info>;
let ExeDomain = SSEPackedDouble in
defm VPERMILPD : avx512_permil<"vpermilpd", 0x05, 0x0D, avx512vl_f64_info,
- avx512vl_i64_info>, VEX_W;
+ avx512vl_i64_info>, VEX_W1X;
//===----------------------------------------------------------------------===//
// AVX-512 - VPSHUFD, VPSHUFLW, VPSHUFHW
Modified: llvm/trunk/lib/Target/X86/X86InstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrFormats.td?rev=335017&r1=335016&r2=335017&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrFormats.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrFormats.td Mon Jun 18 21:24:42 2018
@@ -208,6 +208,11 @@ class TAXD : TA { Prefix OpPrefix = XD;
class VEX { Encoding OpEnc = EncVEX; }
class VEX_W { bits<2> VEX_WPrefix = 1; }
class VEX_WIG { bits<2> VEX_WPrefix = 2; }
+// Special version of VEX_W that can be changed to VEX.W==0 for EVEX2VEX.
+// FIXME: We should consider adding separate bits for VEX_WIG and the extra
+// part of W1X. This would probably simplify the tablegen emitters and
+// the TSFlags creation below.
+class VEX_W1X { bits<2> VEX_WPrefix = 3; }
class VEX_4V : VEX { bit hasVEX_4V = 1; }
class VEX_L { bit hasVEX_L = 1; }
class VEX_LIG { bit ignoresVEX_L = 1; }
Modified: llvm/trunk/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp?rev=335017&r1=335016&r2=335017&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp Mon Jun 18 21:24:42 2018
@@ -94,36 +94,6 @@ void X86EVEX2VEXTablesEmitter::printTabl
{"VMOVDQU16Z256rr", "VMOVDQUYrr", false},
{"VMOVDQU16Z256rr_REV", "VMOVDQUYrr_REV", false},
- {"VPERMILPDZ128mi", "VPERMILPDmi", true},
- {"VPERMILPDZ128ri", "VPERMILPDri", true},
- {"VPERMILPDZ128rm", "VPERMILPDrm", true},
- {"VPERMILPDZ128rr", "VPERMILPDrr", true},
- {"VPERMILPDZ256mi", "VPERMILPDYmi", false},
- {"VPERMILPDZ256ri", "VPERMILPDYri", false},
- {"VPERMILPDZ256rm", "VPERMILPDYrm", false},
- {"VPERMILPDZ256rr", "VPERMILPDYrr", false},
-
- {"VPBROADCASTQZ128m", "VPBROADCASTQrm", true},
- {"VPBROADCASTQZ128r", "VPBROADCASTQrr", true},
- {"VPBROADCASTQZ256m", "VPBROADCASTQYrm", false},
- {"VPBROADCASTQZ256r", "VPBROADCASTQYrr", false},
-
- {"VBROADCASTSDZ256m", "VBROADCASTSDYrm", false},
- {"VBROADCASTSDZ256r", "VBROADCASTSDYrr", false},
-
- {"VBROADCASTF64X2Z128rm", "VBROADCASTF128", false},
- {"VBROADCASTI64X2Z128rm", "VBROADCASTI128", false},
-
- {"VEXTRACTF64x2Z256mr", "VEXTRACTF128mr", false},
- {"VEXTRACTF64x2Z256rr", "VEXTRACTF128rr", false},
- {"VEXTRACTI64x2Z256mr", "VEXTRACTI128mr", false},
- {"VEXTRACTI64x2Z256rr", "VEXTRACTI128rr", false},
-
- {"VINSERTF64x2Z256rm", "VINSERTF128rm", false},
- {"VINSERTF64x2Z256rr", "VINSERTF128rr", false},
- {"VINSERTI64x2Z256rm", "VINSERTI128rm", false},
- {"VINSERTI64x2Z256rr", "VINSERTI128rr", false},
-
// These will require some custom adjustment in the conversion pass.
{"VALIGNDZ128rri", "VPALIGNRrri", true},
{"VALIGNQZ128rri", "VPALIGNRrri", true},
@@ -137,25 +107,6 @@ void X86EVEX2VEXTablesEmitter::printTabl
{"VSHUFI32X4Z256rri", "VPERM2I128rr", false},
{"VSHUFI64X2Z256rmi", "VPERM2I128rm", false},
{"VSHUFI64X2Z256rri", "VPERM2I128rr", false},
-
- // These can be replaced if we verify the scale part of the immediate is
- // zero.
- {"VRNDSCALEPDZ128rri", "VROUNDPDr", true},
- {"VRNDSCALEPDZ128rmi", "VROUNDPDm", true},
- {"VRNDSCALEPSZ128rri", "VROUNDPSr", true},
- {"VRNDSCALEPSZ128rmi", "VROUNDPSm", true},
- {"VRNDSCALEPDZ256rri", "VROUNDPDYr", false},
- {"VRNDSCALEPDZ256rmi", "VROUNDPDYm", false},
- {"VRNDSCALEPSZ256rri", "VROUNDPSYr", false},
- {"VRNDSCALEPSZ256rmi", "VROUNDPSYm", false},
- {"VRNDSCALESDZr", "VROUNDSDr", true},
- {"VRNDSCALESDZm", "VROUNDSDm", true},
- {"VRNDSCALESSZr", "VROUNDSSr", true},
- {"VRNDSCALESSZm", "VROUNDSSm", true},
- {"VRNDSCALESDZr_Int", "VROUNDSDr_Int", true},
- {"VRNDSCALESDZm_Int", "VROUNDSDm_Int", true},
- {"VRNDSCALESSZr_Int", "VROUNDSSr_Int", true},
- {"VRNDSCALESSZm_Int", "VROUNDSSm_Int", true},
};
// Print the manually added entries
@@ -203,31 +154,34 @@ static inline uint64_t getValueFromBitsI
// Function object - Operator() returns true if the given VEX instruction
// matches the EVEX instruction of this object.
class IsMatch {
- const CodeGenInstruction *Inst;
+ const CodeGenInstruction *EVEXInst;
public:
- IsMatch(const CodeGenInstruction *Inst) : Inst(Inst) {}
+ IsMatch(const CodeGenInstruction *EVEXInst) : EVEXInst(EVEXInst) {}
- bool operator()(const CodeGenInstruction *Inst2) {
- Record *Rec1 = Inst->TheDef;
- Record *Rec2 = Inst2->TheDef;
- uint64_t Rec1WVEX =
- getValueFromBitsInit(Rec1->getValueAsBitsInit("VEX_WPrefix"));
- uint64_t Rec2WVEX =
- getValueFromBitsInit(Rec2->getValueAsBitsInit("VEX_WPrefix"));
+ bool operator()(const CodeGenInstruction *VEXInst) {
+ Record *RecE = EVEXInst->TheDef;
+ Record *RecV = VEXInst->TheDef;
+ uint64_t EVEX_W =
+ getValueFromBitsInit(RecE->getValueAsBitsInit("VEX_WPrefix"));
+ uint64_t VEX_W =
+ getValueFromBitsInit(RecV->getValueAsBitsInit("VEX_WPrefix"));
- if (Rec2->getValueAsDef("OpEnc")->getName().str() != "EncVEX" ||
+ if (RecV->getValueAsDef("OpEnc")->getName().str() != "EncVEX" ||
// VEX/EVEX fields
- Rec2->getValueAsDef("OpPrefix") != Rec1->getValueAsDef("OpPrefix") ||
- Rec2->getValueAsDef("OpMap") != Rec1->getValueAsDef("OpMap") ||
- Rec2->getValueAsBit("hasVEX_4V") != Rec1->getValueAsBit("hasVEX_4V") ||
- !equalBitsInits(Rec2->getValueAsBitsInit("EVEX_LL"),
- Rec1->getValueAsBitsInit("EVEX_LL")) ||
- (Rec1WVEX != 2 && Rec2WVEX != 2 && Rec1WVEX != Rec2WVEX) ||
+ RecV->getValueAsDef("OpPrefix") != RecE->getValueAsDef("OpPrefix") ||
+ RecV->getValueAsDef("OpMap") != RecE->getValueAsDef("OpMap") ||
+ RecV->getValueAsBit("hasVEX_4V") != RecE->getValueAsBit("hasVEX_4V") ||
+ !equalBitsInits(RecV->getValueAsBitsInit("EVEX_LL"),
+ RecE->getValueAsBitsInit("EVEX_LL")) ||
+ // Match is allowed if either is VEX_WIG, or they match, or EVEX
+ // is VEX_W1X and VEX is VEX_W0.
+ (!(EVEX_W == 2 || VEX_W == 2 || EVEX_W == VEX_W ||
+ (EVEX_W == 3 && VEX_W == 0))) ||
// Instruction's format
- Rec2->getValueAsDef("Form") != Rec1->getValueAsDef("Form") ||
- Rec2->getValueAsBit("isAsmParserOnly") !=
- Rec1->getValueAsBit("isAsmParserOnly"))
+ RecV->getValueAsDef("Form") != RecE->getValueAsDef("Form") ||
+ RecV->getValueAsBit("isAsmParserOnly") !=
+ RecE->getValueAsBit("isAsmParserOnly"))
return false;
// This is needed for instructions with intrinsic version (_Int).
@@ -236,9 +190,9 @@ public:
// Also for instructions that their EVEX version was upgraded to work with
// k-registers. For example VPCMPEQBrm (xmm output register) and
// VPCMPEQBZ128rm (k register output register).
- for (unsigned i = 0, e = Inst->Operands.size(); i < e; i++) {
- Record *OpRec1 = Inst->Operands[i].Rec;
- Record *OpRec2 = Inst2->Operands[i].Rec;
+ for (unsigned i = 0, e = EVEXInst->Operands.size(); i < e; i++) {
+ Record *OpRec1 = EVEXInst->Operands[i].Rec;
+ Record *OpRec2 = VEXInst->Operands[i].Rec;
if (OpRec1 == OpRec2)
continue;
Modified: llvm/trunk/utils/TableGen/X86RecognizableInstr.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/X86RecognizableInstr.cpp?rev=335017&r1=335016&r2=335017&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/X86RecognizableInstr.cpp (original)
+++ llvm/trunk/utils/TableGen/X86RecognizableInstr.cpp Mon Jun 18 21:24:42 2018
@@ -164,7 +164,8 @@ InstructionContext RecognizableInstr::in
llvm_unreachable("Don't support VEX.L if EVEX_L2 is enabled");
}
// VEX_L & VEX_W
- if (!EncodeRC && HasVEX_LPrefix && VEX_WPrefix == X86Local::VEX_W1) {
+ if (!EncodeRC && HasVEX_LPrefix && (VEX_WPrefix == X86Local::VEX_W1 ||
+ VEX_WPrefix == X86Local::VEX_W1X)) {
if (OpPrefix == X86Local::PD)
insnContext = EVEX_KB(IC_EVEX_L_W_OPSIZE);
else if (OpPrefix == X86Local::XS)
@@ -192,7 +193,8 @@ InstructionContext RecognizableInstr::in
llvm_unreachable("Invalid prefix");
}
} else if (!EncodeRC && HasEVEX_L2Prefix &&
- VEX_WPrefix == X86Local::VEX_W1) {
+ (VEX_WPrefix == X86Local::VEX_W1 ||
+ VEX_WPrefix == X86Local::VEX_W1X)) {
// EVEX_L2 & VEX_W
if (OpPrefix == X86Local::PD)
insnContext = EVEX_KB(IC_EVEX_L2_W_OPSIZE);
@@ -221,7 +223,8 @@ InstructionContext RecognizableInstr::in
llvm_unreachable("Invalid prefix");
}
}
- else if (VEX_WPrefix == X86Local::VEX_W1) {
+ else if (VEX_WPrefix == X86Local::VEX_W1 ||
+ VEX_WPrefix == X86Local::VEX_W1X) {
// VEX_W
if (OpPrefix == X86Local::PD)
insnContext = EVEX_KB(IC_EVEX_W_OPSIZE);
@@ -251,7 +254,8 @@ InstructionContext RecognizableInstr::in
}
/// eof EVEX
} else if (Encoding == X86Local::VEX || Encoding == X86Local::XOP) {
- if (HasVEX_LPrefix && VEX_WPrefix == X86Local::VEX_W1) {
+ if (HasVEX_LPrefix && (VEX_WPrefix == X86Local::VEX_W1 ||
+ VEX_WPrefix == X86Local::VEX_W1X)) {
if (OpPrefix == X86Local::PD)
insnContext = IC_VEX_L_W_OPSIZE;
else if (OpPrefix == X86Local::XS)
@@ -266,7 +270,8 @@ InstructionContext RecognizableInstr::in
}
} else if (OpPrefix == X86Local::PD && HasVEX_LPrefix)
insnContext = IC_VEX_L_OPSIZE;
- else if (OpPrefix == X86Local::PD && VEX_WPrefix == X86Local::VEX_W1)
+ else if (OpPrefix == X86Local::PD && (VEX_WPrefix == X86Local::VEX_W1 ||
+ VEX_WPrefix == X86Local::VEX_W1X))
insnContext = IC_VEX_W_OPSIZE;
else if (OpPrefix == X86Local::PD)
insnContext = IC_VEX_OPSIZE;
@@ -274,11 +279,14 @@ InstructionContext RecognizableInstr::in
insnContext = IC_VEX_L_XS;
else if (HasVEX_LPrefix && OpPrefix == X86Local::XD)
insnContext = IC_VEX_L_XD;
- else if (VEX_WPrefix == X86Local::VEX_W1 && OpPrefix == X86Local::XS)
+ else if ((VEX_WPrefix == X86Local::VEX_W1 ||
+ VEX_WPrefix == X86Local::VEX_W1X) && OpPrefix == X86Local::XS)
insnContext = IC_VEX_W_XS;
- else if (VEX_WPrefix == X86Local::VEX_W1 && OpPrefix == X86Local::XD)
+ else if ((VEX_WPrefix == X86Local::VEX_W1 ||
+ VEX_WPrefix == X86Local::VEX_W1X) && OpPrefix == X86Local::XD)
insnContext = IC_VEX_W_XD;
- else if (VEX_WPrefix == X86Local::VEX_W1 && OpPrefix == X86Local::PS)
+ else if ((VEX_WPrefix == X86Local::VEX_W1 ||
+ VEX_WPrefix == X86Local::VEX_W1X) && OpPrefix == X86Local::PS)
insnContext = IC_VEX_W;
else if (HasVEX_LPrefix && OpPrefix == X86Local::PS)
insnContext = IC_VEX_L;
Modified: llvm/trunk/utils/TableGen/X86RecognizableInstr.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/X86RecognizableInstr.h?rev=335017&r1=335016&r2=335017&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/X86RecognizableInstr.h (original)
+++ llvm/trunk/utils/TableGen/X86RecognizableInstr.h Mon Jun 18 21:24:42 2018
@@ -142,7 +142,7 @@ namespace X86Local {
};
enum {
- VEX_W0 = 0, VEX_W1 = 1, VEX_WIG = 2
+ VEX_W0 = 0, VEX_W1 = 1, VEX_WIG = 2, VEX_W1X = 3
};
}
More information about the llvm-commits
mailing list