forked from OSchip/llvm-project
[AArch64] Refactor identification of SIMD immediates
Get rid of icky goto loops and make the code easier to maintain (NFC). Differential revision: https://reviews.llvm.org/D42723 llvm-svn: 324903
This commit is contained in:
parent
cfd451b746
commit
7dc0f1ec45
|
@ -6234,96 +6234,235 @@ static bool resolveBuildVector(BuildVectorSDNode *BVN, APInt &CnstBits,
|
|||
return false;
|
||||
}
|
||||
|
||||
// Try 64-bit splatted SIMD immediate.
|
||||
static SDValue tryAdvSIMDModImm64(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
|
||||
const APInt &Bits) {
|
||||
if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
|
||||
uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
|
||||
EVT VT = Op.getValueType();
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v2i64 : MVT::f64;
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType10(Value)) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType10(Value);
|
||||
|
||||
SDLoc dl(Op);
|
||||
SDValue Mov = DAG.getNode(NewOp, dl, MovTy,
|
||||
DAG.getConstant(Value, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
// Try 32-bit splatted SIMD immediate.
|
||||
static SDValue tryAdvSIMDModImm32(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
|
||||
const APInt &Bits,
|
||||
const SDValue *LHS = nullptr) {
|
||||
if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
|
||||
uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
|
||||
EVT VT = Op.getValueType();
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
bool isAdvSIMDModImm = false;
|
||||
uint64_t Shift;
|
||||
|
||||
if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType1(Value))) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType1(Value);
|
||||
Shift = 0;
|
||||
}
|
||||
else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType2(Value))) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType2(Value);
|
||||
Shift = 8;
|
||||
}
|
||||
else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType3(Value))) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType3(Value);
|
||||
Shift = 16;
|
||||
}
|
||||
else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType4(Value))) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType4(Value);
|
||||
Shift = 24;
|
||||
}
|
||||
|
||||
if (isAdvSIMDModImm) {
|
||||
SDLoc dl(Op);
|
||||
SDValue Mov;
|
||||
|
||||
if (LHS)
|
||||
Mov = DAG.getNode(NewOp, dl, MovTy, *LHS,
|
||||
DAG.getConstant(Value, dl, MVT::i32),
|
||||
DAG.getConstant(Shift, dl, MVT::i32));
|
||||
else
|
||||
Mov = DAG.getNode(NewOp, dl, MovTy,
|
||||
DAG.getConstant(Value, dl, MVT::i32),
|
||||
DAG.getConstant(Shift, dl, MVT::i32));
|
||||
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
// Try 16-bit splatted SIMD immediate.
|
||||
static SDValue tryAdvSIMDModImm16(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
|
||||
const APInt &Bits,
|
||||
const SDValue *LHS = nullptr) {
|
||||
if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
|
||||
uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
|
||||
EVT VT = Op.getValueType();
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v8i16 : MVT::v4i16;
|
||||
bool isAdvSIMDModImm = false;
|
||||
uint64_t Shift;
|
||||
|
||||
if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType5(Value))) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType5(Value);
|
||||
Shift = 0;
|
||||
}
|
||||
else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType6(Value))) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType6(Value);
|
||||
Shift = 8;
|
||||
}
|
||||
|
||||
if (isAdvSIMDModImm) {
|
||||
SDLoc dl(Op);
|
||||
SDValue Mov;
|
||||
|
||||
if (LHS)
|
||||
Mov = DAG.getNode(NewOp, dl, MovTy, *LHS,
|
||||
DAG.getConstant(Value, dl, MVT::i32),
|
||||
DAG.getConstant(Shift, dl, MVT::i32));
|
||||
else
|
||||
Mov = DAG.getNode(NewOp, dl, MovTy,
|
||||
DAG.getConstant(Value, dl, MVT::i32),
|
||||
DAG.getConstant(Shift, dl, MVT::i32));
|
||||
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
// Try 32-bit splatted SIMD immediate with shifted ones.
|
||||
static SDValue tryAdvSIMDModImm321s(unsigned NewOp, SDValue Op,
|
||||
SelectionDAG &DAG, const APInt &Bits) {
|
||||
if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
|
||||
uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
|
||||
EVT VT = Op.getValueType();
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
bool isAdvSIMDModImm = false;
|
||||
uint64_t Shift;
|
||||
|
||||
if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType7(Value))) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType7(Value);
|
||||
Shift = 264;
|
||||
}
|
||||
else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType8(Value))) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType8(Value);
|
||||
Shift = 272;
|
||||
}
|
||||
|
||||
if (isAdvSIMDModImm) {
|
||||
SDLoc dl(Op);
|
||||
SDValue Mov = DAG.getNode(NewOp, dl, MovTy,
|
||||
DAG.getConstant(Value, dl, MVT::i32),
|
||||
DAG.getConstant(Shift, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
// Try 8-bit splatted SIMD immediate.
|
||||
static SDValue tryAdvSIMDModImm8(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
|
||||
const APInt &Bits) {
|
||||
if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
|
||||
uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
|
||||
EVT VT = Op.getValueType();
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v16i8 : MVT::v8i8;
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType9(Value)) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType9(Value);
|
||||
|
||||
SDLoc dl(Op);
|
||||
SDValue Mov = DAG.getNode(NewOp, dl, MovTy,
|
||||
DAG.getConstant(Value, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
// Try FP splatted SIMD immediate.
|
||||
static SDValue tryAdvSIMDModImmFP(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
|
||||
const APInt &Bits) {
|
||||
if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
|
||||
uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
|
||||
EVT VT = Op.getValueType();
|
||||
bool isWide = (VT.getSizeInBits() == 128);
|
||||
MVT MovTy;
|
||||
bool isAdvSIMDModImm = false;
|
||||
|
||||
if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType11(Value))) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType11(Value);
|
||||
MovTy = isWide ? MVT::v4f32 : MVT::v2f32;
|
||||
}
|
||||
else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType12(Value))) {
|
||||
Value = AArch64_AM::encodeAdvSIMDModImmType12(Value);
|
||||
MovTy = isWide ? MVT::v2f64 : MVT::f64;
|
||||
}
|
||||
|
||||
if (isAdvSIMDModImm) {
|
||||
SDLoc dl(Op);
|
||||
SDValue Mov = DAG.getNode(NewOp, dl, MovTy,
|
||||
DAG.getConstant(Value, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
SDValue AArch64TargetLowering::LowerVectorAND(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
BuildVectorSDNode *BVN =
|
||||
dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode());
|
||||
SDValue LHS = Op.getOperand(0);
|
||||
SDLoc dl(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
|
||||
BuildVectorSDNode *BVN =
|
||||
dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode());
|
||||
if (!BVN) {
|
||||
// AND commutes, so try swapping the operands.
|
||||
LHS = Op.getOperand(1);
|
||||
BVN = dyn_cast<BuildVectorSDNode>(Op.getOperand(0).getNode());
|
||||
}
|
||||
if (!BVN)
|
||||
return Op;
|
||||
|
||||
APInt CnstBits(VT.getSizeInBits(), 0);
|
||||
APInt DefBits(VT.getSizeInBits(), 0);
|
||||
APInt UndefBits(VT.getSizeInBits(), 0);
|
||||
if (resolveBuildVector(BVN, CnstBits, UndefBits)) {
|
||||
if (resolveBuildVector(BVN, DefBits, UndefBits)) {
|
||||
SDValue NewOp;
|
||||
|
||||
// We only have BIC vector immediate instruction, which is and-not.
|
||||
CnstBits = ~CnstBits;
|
||||
|
||||
// We make use of a little bit of goto ickiness in order to avoid having to
|
||||
// duplicate the immediate matching logic for the undef toggled case.
|
||||
bool SecondTry = false;
|
||||
AttemptModImm:
|
||||
|
||||
if (CnstBits.getHiBits(64) == CnstBits.getLoBits(64)) {
|
||||
CnstBits = CnstBits.zextOrTrunc(64);
|
||||
uint64_t CnstVal = CnstBits.getZExtValue();
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType1(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType1(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::BICi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(0, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType2(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType2(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::BICi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(8, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType3(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType3(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::BICi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(16, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType4(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType4(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::BICi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(24, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType5(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType5(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v8i16 : MVT::v4i16;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::BICi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(0, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType6(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType6(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v8i16 : MVT::v4i16;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::BICi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(8, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
DefBits = ~DefBits;
|
||||
if ((NewOp = tryAdvSIMDModImm32(AArch64ISD::BICi, Op, DAG,
|
||||
DefBits, &LHS)) ||
|
||||
(NewOp = tryAdvSIMDModImm16(AArch64ISD::BICi, Op, DAG,
|
||||
DefBits, &LHS)))
|
||||
return NewOp;
|
||||
else {
|
||||
DefBits = ~UndefBits;
|
||||
if ((NewOp = tryAdvSIMDModImm32(AArch64ISD::BICi, Op, DAG,
|
||||
DefBits, &LHS)) ||
|
||||
(NewOp = tryAdvSIMDModImm16(AArch64ISD::BICi, Op, DAG,
|
||||
DefBits, &LHS)))
|
||||
return NewOp;
|
||||
}
|
||||
|
||||
if (SecondTry)
|
||||
goto FailedModImm;
|
||||
SecondTry = true;
|
||||
CnstBits = ~UndefBits;
|
||||
goto AttemptModImm;
|
||||
}
|
||||
|
||||
// We can always fall back to a non-immediate AND.
|
||||
FailedModImm:
|
||||
// We can always fall back to a non-immediate AND.
|
||||
return Op;
|
||||
}
|
||||
|
||||
|
@ -6434,96 +6573,40 @@ SDValue AArch64TargetLowering::LowerVectorOR(SDValue Op,
|
|||
return Res;
|
||||
}
|
||||
|
||||
BuildVectorSDNode *BVN =
|
||||
dyn_cast<BuildVectorSDNode>(Op.getOperand(0).getNode());
|
||||
SDValue LHS = Op.getOperand(1);
|
||||
SDLoc dl(Op);
|
||||
SDValue LHS = Op.getOperand(0);
|
||||
EVT VT = Op.getValueType();
|
||||
|
||||
// OR commutes, so try swapping the operands.
|
||||
BuildVectorSDNode *BVN =
|
||||
dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode());
|
||||
if (!BVN) {
|
||||
LHS = Op.getOperand(0);
|
||||
BVN = dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode());
|
||||
// OR commutes, so try swapping the operands.
|
||||
LHS = Op.getOperand(1);
|
||||
BVN = dyn_cast<BuildVectorSDNode>(Op.getOperand(0).getNode());
|
||||
}
|
||||
if (!BVN)
|
||||
return Op;
|
||||
|
||||
APInt CnstBits(VT.getSizeInBits(), 0);
|
||||
APInt DefBits(VT.getSizeInBits(), 0);
|
||||
APInt UndefBits(VT.getSizeInBits(), 0);
|
||||
if (resolveBuildVector(BVN, CnstBits, UndefBits)) {
|
||||
// We make use of a little bit of goto ickiness in order to avoid having to
|
||||
// duplicate the immediate matching logic for the undef toggled case.
|
||||
bool SecondTry = false;
|
||||
AttemptModImm:
|
||||
if (resolveBuildVector(BVN, DefBits, UndefBits)) {
|
||||
SDValue NewOp;
|
||||
|
||||
if (CnstBits.getHiBits(64) == CnstBits.getLoBits(64)) {
|
||||
CnstBits = CnstBits.zextOrTrunc(64);
|
||||
uint64_t CnstVal = CnstBits.getZExtValue();
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType1(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType1(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::ORRi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(0, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType2(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType2(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::ORRi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(8, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType3(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType3(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::ORRi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(16, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType4(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType4(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::ORRi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(24, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType5(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType5(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v8i16 : MVT::v4i16;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::ORRi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(0, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType6(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType6(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v8i16 : MVT::v4i16;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::ORRi, dl, MovTy, LHS,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(8, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
if ((NewOp = tryAdvSIMDModImm32(AArch64ISD::ORRi, Op, DAG,
|
||||
DefBits, &LHS)) ||
|
||||
(NewOp = tryAdvSIMDModImm16(AArch64ISD::ORRi, Op, DAG,
|
||||
DefBits, &LHS)))
|
||||
return NewOp;
|
||||
else {
|
||||
DefBits = UndefBits;
|
||||
if ((NewOp = tryAdvSIMDModImm32(AArch64ISD::ORRi, Op, DAG,
|
||||
DefBits, &LHS)) ||
|
||||
(NewOp = tryAdvSIMDModImm16(AArch64ISD::ORRi, Op, DAG,
|
||||
DefBits, &LHS)))
|
||||
return NewOp;
|
||||
}
|
||||
|
||||
if (SecondTry)
|
||||
goto FailedModImm;
|
||||
SecondTry = true;
|
||||
CnstBits = UndefBits;
|
||||
goto AttemptModImm;
|
||||
}
|
||||
|
||||
// We can always fall back to a non-immediate OR.
|
||||
FailedModImm:
|
||||
// We can always fall back to a non-immediate OR.
|
||||
return Op;
|
||||
}
|
||||
|
||||
|
@ -6555,222 +6638,51 @@ SDValue AArch64TargetLowering::LowerBUILD_VECTOR(SDValue Op,
|
|||
SelectionDAG &DAG) const {
|
||||
SDLoc dl(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
|
||||
Op = NormalizeBuildVector(Op, DAG);
|
||||
BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Op.getNode());
|
||||
|
||||
APInt CnstBits(VT.getSizeInBits(), 0);
|
||||
APInt DefBits(VT.getSizeInBits(), 0);
|
||||
APInt UndefBits(VT.getSizeInBits(), 0);
|
||||
if (resolveBuildVector(BVN, CnstBits, UndefBits)) {
|
||||
// We make use of a little bit of goto ickiness in order to avoid having to
|
||||
// duplicate the immediate matching logic for the undef toggled case.
|
||||
bool SecondTry = false;
|
||||
AttemptModImm:
|
||||
if (resolveBuildVector(BVN, DefBits, UndefBits)) {
|
||||
// Certain magic vector constants (used to express things like NOT
|
||||
// and NEG) are passed through unmodified. This allows codegen patterns
|
||||
// for these operations to match. Special-purpose patterns will lower
|
||||
// these immediates to MOVI if it proves necessary.
|
||||
uint64_t DefVal = DefBits.zextOrTrunc(64).getZExtValue();
|
||||
if (DefBits.getHiBits(64) == DefBits.getLoBits(64) &&
|
||||
VT.isInteger() && (DefVal == 0 || DefVal == UINT64_MAX))
|
||||
return Op;
|
||||
|
||||
if (CnstBits.getHiBits(64) == CnstBits.getLoBits(64)) {
|
||||
CnstBits = CnstBits.zextOrTrunc(64);
|
||||
uint64_t CnstVal = CnstBits.getZExtValue();
|
||||
SDValue NewOp;
|
||||
if ((NewOp = tryAdvSIMDModImm64(AArch64ISD::MOVIedit, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm32(AArch64ISD::MOVIshift, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm321s(AArch64ISD::MOVImsl, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm16(AArch64ISD::MOVIshift, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm8(AArch64ISD::MOVI, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImmFP(AArch64ISD::FMOV, Op, DAG, DefBits)))
|
||||
return NewOp;
|
||||
|
||||
// Certain magic vector constants (used to express things like NOT
|
||||
// and NEG) are passed through unmodified. This allows codegen patterns
|
||||
// for these operations to match. Special-purpose patterns will lower
|
||||
// these immediates to MOVIs if it proves necessary.
|
||||
if (VT.isInteger() && (CnstVal == 0 || CnstVal == ~0ULL))
|
||||
return Op;
|
||||
DefBits = ~DefBits;
|
||||
if ((NewOp = tryAdvSIMDModImm32(AArch64ISD::MVNIshift, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm321s(AArch64ISD::MVNImsl, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm16(AArch64ISD::MVNIshift, Op, DAG, DefBits)))
|
||||
return NewOp;
|
||||
|
||||
// The many faces of MOVI...
|
||||
if (AArch64_AM::isAdvSIMDModImmType10(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType10(CnstVal);
|
||||
if (VT.getSizeInBits() == 128) {
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVIedit, dl, MVT::v2i64,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
DefBits = UndefBits;
|
||||
if ((NewOp = tryAdvSIMDModImm64(AArch64ISD::MOVIedit, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm32(AArch64ISD::MOVIshift, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm321s(AArch64ISD::MOVImsl, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm16(AArch64ISD::MOVIshift, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm8(AArch64ISD::MOVI, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImmFP(AArch64ISD::FMOV, Op, DAG, DefBits)))
|
||||
return NewOp;
|
||||
|
||||
// Support the V64 version via subregister insertion.
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVIedit, dl, MVT::f64,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType1(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType1(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(0, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType2(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType2(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(8, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType3(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType3(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(16, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType4(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType4(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(24, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType5(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType5(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v8i16 : MVT::v4i16;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(0, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType6(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType6(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v8i16 : MVT::v4i16;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(8, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType7(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType7(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVImsl, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(264, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType8(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType8(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVImsl, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(272, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType9(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType9(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v16i8 : MVT::v8i8;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MOVI, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
// The few faces of FMOV...
|
||||
if (AArch64_AM::isAdvSIMDModImmType11(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType11(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4f32 : MVT::v2f32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::FMOV, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType12(CnstVal) &&
|
||||
VT.getSizeInBits() == 128) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType12(CnstVal);
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::FMOV, dl, MVT::v2f64,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
// The many faces of MVNI...
|
||||
CnstVal = ~CnstVal;
|
||||
if (AArch64_AM::isAdvSIMDModImmType1(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType1(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MVNIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(0, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType2(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType2(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MVNIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(8, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType3(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType3(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MVNIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(16, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType4(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType4(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MVNIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(24, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType5(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType5(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v8i16 : MVT::v4i16;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MVNIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(0, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType6(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType6(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v8i16 : MVT::v4i16;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MVNIshift, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(8, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType7(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType7(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MVNImsl, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(264, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
|
||||
if (AArch64_AM::isAdvSIMDModImmType8(CnstVal)) {
|
||||
CnstVal = AArch64_AM::encodeAdvSIMDModImmType8(CnstVal);
|
||||
MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Mov = DAG.getNode(AArch64ISD::MVNImsl, dl, MovTy,
|
||||
DAG.getConstant(CnstVal, dl, MVT::i32),
|
||||
DAG.getConstant(272, dl, MVT::i32));
|
||||
return DAG.getNode(AArch64ISD::NVCAST, dl, VT, Mov);
|
||||
}
|
||||
}
|
||||
|
||||
if (SecondTry)
|
||||
goto FailedModImm;
|
||||
SecondTry = true;
|
||||
CnstBits = UndefBits;
|
||||
goto AttemptModImm;
|
||||
DefBits = ~UndefBits;
|
||||
if ((NewOp = tryAdvSIMDModImm32(AArch64ISD::MVNIshift, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm321s(AArch64ISD::MVNImsl, Op, DAG, DefBits)) ||
|
||||
(NewOp = tryAdvSIMDModImm16(AArch64ISD::MVNIshift, Op, DAG, DefBits)))
|
||||
return NewOp;
|
||||
}
|
||||
FailedModImm:
|
||||
|
||||
// Scan through the operands to find some interesting properties we can
|
||||
// exploit:
|
||||
|
|
Loading…
Reference in New Issue