summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/AArch64/AArch64ISelLowering.cpp')
-rw-r--r--llvm/lib/Target/AArch64/AArch64ISelLowering.cpp64
1 files changed, 44 insertions, 20 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 857d97166c5..407c81d14a2 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -6339,8 +6339,8 @@ static SDValue tryAdvSIMDModImm16(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
if (LHS)
Mov = DAG.getNode(NewOp, dl, MovTy, *LHS,
- DAG.getConstant(Value, dl, MVT::i32),
- DAG.getConstant(Shift, dl, MVT::i32));
+ 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),
@@ -6583,9 +6583,9 @@ SDValue AArch64TargetLowering::LowerVectorOR(SDValue Op,
return Res;
}
- SDValue LHS = Op.getOperand(0);
EVT VT = Op.getValueType();
+ SDValue LHS = Op.getOperand(0);
BuildVectorSDNode *BVN =
dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode());
if (!BVN) {
@@ -6642,25 +6642,13 @@ static SDValue NormalizeBuildVector(SDValue Op,
return DAG.getBuildVector(VT, dl, Ops);
}
-SDValue AArch64TargetLowering::LowerBUILD_VECTOR(SDValue Op,
- SelectionDAG &DAG) const {
- SDLoc dl(Op);
+static SDValue ConstantBuildVector(SDValue Op, SelectionDAG &DAG) {
EVT VT = Op.getValueType();
- Op = NormalizeBuildVector(Op, DAG);
- BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Op.getNode());
APInt DefBits(VT.getSizeInBits(), 0);
APInt UndefBits(VT.getSizeInBits(), 0);
+ BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Op.getNode());
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)) ||
@@ -6692,6 +6680,34 @@ SDValue AArch64TargetLowering::LowerBUILD_VECTOR(SDValue Op,
return NewOp;
}
+ return SDValue();
+}
+
+SDValue AArch64TargetLowering::LowerBUILD_VECTOR(SDValue Op,
+ SelectionDAG &DAG) const {
+ EVT VT = Op.getValueType();
+
+ // Try to build a simple constant vector.
+ Op = NormalizeBuildVector(Op, DAG);
+ if (VT.isInteger()) {
+ // Certain vector constants, used to express things like logical NOT and
+ // arithmetic NEG, are passed through unmodified. This allows special
+ // patterns for these operations to match, which will lower these constants
+ // to whatever is proven necessary.
+ BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Op.getNode());
+ if (BVN->isConstant())
+ if (ConstantSDNode *Const = BVN->getConstantSplatNode()) {
+ unsigned BitSize = VT.getVectorElementType().getSizeInBits();
+ APInt Val(BitSize,
+ Const->getAPIntValue().zextOrTrunc(BitSize).getZExtValue());
+ if (Val.isNullValue() || Val.isAllOnesValue())
+ return Op;
+ }
+ }
+
+ if (SDValue V = ConstantBuildVector(Op, DAG))
+ return V;
+
// Scan through the operands to find some interesting properties we can
// exploit:
// 1) If only one value is used, we can use a DUP, or
@@ -6704,6 +6720,7 @@ SDValue AArch64TargetLowering::LowerBUILD_VECTOR(SDValue Op,
// lanes such that we can directly materialize the vector
// some other way (MOVI, e.g.), we can be sneaky.
// 5) if all operands are EXTRACT_VECTOR_ELT, check for VUZP.
+ SDLoc dl(Op);
unsigned NumElts = VT.getVectorNumElements();
bool isOnlyLowElement = true;
bool usesOnlyOneValue = true;
@@ -6855,16 +6872,23 @@ SDValue AArch64TargetLowering::LowerBUILD_VECTOR(SDValue Op,
// is better than the default, which will perform a separate initialization
// for each lane.
if (NumConstantLanes > 0 && usesOnlyOneConstantValue) {
- SDValue Val = DAG.getNode(AArch64ISD::DUP, dl, VT, ConstantValue);
+ // Firstly, try to materialize the splat constant.
+ SDValue Vec = DAG.getSplatBuildVector(VT, dl, ConstantValue),
+ Val = ConstantBuildVector(Vec, DAG);
+ if (!Val) {
+ // Otherwise, materialize the constant and splat it.
+ Val = DAG.getNode(AArch64ISD::DUP, dl, VT, ConstantValue);
+ DAG.ReplaceAllUsesWith(Vec.getNode(), &Val);
+ }
+
// Now insert the non-constant lanes.
for (unsigned i = 0; i < NumElts; ++i) {
SDValue V = Op.getOperand(i);
SDValue LaneIdx = DAG.getConstant(i, dl, MVT::i64);
- if (!isa<ConstantSDNode>(V) && !isa<ConstantFPSDNode>(V)) {
+ if (!isa<ConstantSDNode>(V) && !isa<ConstantFPSDNode>(V))
// Note that type legalization likely mucked about with the VT of the
// source operand, so we may have to convert it here before inserting.
Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, VT, Val, V, LaneIdx);
- }
}
return Val;
}
OpenPOWER on IntegriCloud