if (VT.isVector()) {
SDValue FoldedVOp = SimplifyVBinOp(N);
if (FoldedVOp.getNode()) return FoldedVOp;
+
+ BuildVectorSDNode *N1CV = dyn_cast<BuildVectorSDNode>(N1);
+ // If setcc produces all-one true value then:
+ // (shl (and (setcc) N01CV) N1CV) -> (and (setcc) N01CV<<N1CV)
+ if (N1CV && N1CV->isConstant() &&
+ TLI.getBooleanContents(true) ==
+ TargetLowering::ZeroOrNegativeOneBooleanContent &&
+ N0.getOpcode() == ISD::AND) {
+ SDValue N00 = N0->getOperand(0);
+ SDValue N01 = N0->getOperand(1);
+ BuildVectorSDNode *N01CV = dyn_cast<BuildVectorSDNode>(N01);
+
+ if (N01CV && N01CV->isConstant() && N00.getOpcode() == ISD::SETCC) {
+ SDValue C = DAG.FoldConstantArithmetic(ISD::SHL, VT, N01CV, N1CV);
+ if (C.getNode())
+ return DAG.getNode(ISD::AND, SDLoc(N), VT, N00, C);
+ }
+ }
}
// fold (shl c1, c2) -> c1<<c2
--- /dev/null
+; RUN: llc < %s -o - -mcpu=generic -march=x86-64 -mattr=+sse2 | FileCheck %s
+; RUN: llc < %s -o - -mcpu=generic -march=x86-64 -mattr=+avx | FileCheck %s
+
+define <8 x i16> @foo(<8 x i16> %a, <8 x i16> %b) {
+; CHECK: .short 32
+; CHECK-NEXT: .short 32
+; CHECK-NEXT: .short 32
+; CHECK-NEXT: .short 32
+; CHECK-NEXT: .short 32
+; CHECK-NEXT: .short 32
+; CHECK-NEXT: .short 32
+; CHECK-NEXT: .short 32
+; CHECK-LABEL: foo
+; CHECK-NOT: psll
+entry:
+ %icmp = icmp eq <8 x i16> %a, %b
+ %zext = zext <8 x i1> %icmp to <8 x i16>
+ %shl = shl nuw nsw <8 x i16> %zext, <i16 5, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5>
+ ret <8 x i16> %shl
+}
+
+; Don't fail with an assert due to an undef in the buildvector
+define <8 x i16> @bar(<8 x i16> %a, <8 x i16> %b) {
+; CHECK-LABEL: bar
+entry:
+ %icmp = icmp eq <8 x i16> %a, %b
+ %zext = zext <8 x i1> %icmp to <8 x i16>
+ %shl = shl nuw nsw <8 x i16> %zext, <i16 5, i16 undef, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5>
+ ret <8 x i16> %shl
+}