[llvm] r324903 - [AArch64] Refactor identification of SIMD immediates
Evandro Menezes via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 12 08:41:41 PST 2018
Author: evandro
Date: Mon Feb 12 08:41:41 2018
New Revision: 324903
URL: http://llvm.org/viewvc/llvm-project?rev=324903&view=rev
Log:
[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
Modified:
llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp?rev=324903&r1=324902&r2=324903&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp Mon Feb 12 08:41:41 2018
@@ -6234,96 +6234,235 @@ static bool resolveBuildVector(BuildVect
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)) {
- // We only have BIC vector immediate instruction, which is and-not.
- CnstBits = ~CnstBits;
+ if (resolveBuildVector(BVN, DefBits, UndefBits)) {
+ SDValue NewOp;
- // 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);
- }
- }
-
- if (SecondTry)
- goto FailedModImm;
- SecondTry = true;
- CnstBits = ~UndefBits;
- goto AttemptModImm;
+ // We only have BIC vector immediate instruction, which is and-not.
+ 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;
+ }
}
-// 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::LowerVect
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 (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 (SecondTry)
- goto FailedModImm;
- SecondTry = true;
- CnstBits = UndefBits;
- goto AttemptModImm;
+ if (resolveBuildVector(BVN, DefBits, UndefBits)) {
+ SDValue NewOp;
+
+ 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;
+ }
}
-// 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::LowerBUIL
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 (CnstBits.getHiBits(64) == CnstBits.getLoBits(64)) {
- CnstBits = CnstBits.zextOrTrunc(64);
- uint64_t CnstVal = CnstBits.getZExtValue();
-
- // 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;
-
- // 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);
- }
-
- // 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;
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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:
More information about the llvm-commits
mailing list