Skip to content

Commit 9262e37

Browse files
authored
[InstCombine] Fold shuffled intrinsic operands with constant operands (#141300)
We currently pull shuffles through binops and intrinsics, which is an important canonical form for VectorCombine to be able to scalarize vector sequences. But while binops can be folded with a constant operand, intrinsics currently require all operands to be shufflevectors. This extends intrinsic folding to be in line with regular binops by reusing the constant "unshuffling" logic. As far as I can tell the list of currently folded intrinsics don't require any special UB handling. This change in combination with #138095 and #137823 fixes the following C: ```c void max(int *x, int *y, int n) { for (int i = 0; i < n; i++) x[i] += *y > 42 ? *y : 42; } ``` Not using the splatted vector form on RISC-V with `-O3 -march=rva23u64`: ```asm vmv.s.x v8, a4 li a4, 42 vmax.vx v10, v8, a4 vrgather.vi v8, v10, 0 .LBB0_9: # %vector.body # =>This Inner Loop Header: Depth=1 vl2re32.v v10, (a5) vadd.vv v10, v10, v8 vs2r.v v10, (a5) ``` i.e., it now generates ```asm li a6, 42 max a6, a4, a6 .LBB0_9: # %vector.body # =>This Inner Loop Header: Depth=1 vl2re32.v v8, (a5) vadd.vx v8, v8, a6 vs2r.v v8, (a5) ```
1 parent 2e7489c commit 9262e37

File tree

6 files changed

+180
-15
lines changed

6 files changed

+180
-15
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,9 +1399,8 @@ static Instruction *factorizeMinMaxTree(IntrinsicInst *II) {
13991399

14001400
/// If all arguments of the intrinsic are unary shuffles with the same mask,
14011401
/// try to shuffle after the intrinsic.
1402-
static Instruction *
1403-
foldShuffledIntrinsicOperands(IntrinsicInst *II,
1404-
InstCombiner::BuilderTy &Builder) {
1402+
Instruction *
1403+
InstCombinerImpl::foldShuffledIntrinsicOperands(IntrinsicInst *II) {
14051404
// TODO: This should be extended to handle other intrinsics like fshl, ctpop,
14061405
// etc. Use llvm::isTriviallyVectorizable() and related to determine
14071406
// which intrinsics are safe to shuffle?
@@ -1419,25 +1418,33 @@ foldShuffledIntrinsicOperands(IntrinsicInst *II,
14191418
}
14201419

14211420
Value *X;
1421+
Constant *C;
14221422
ArrayRef<int> Mask;
1423-
if (!match(II->getArgOperand(0),
1424-
m_Shuffle(m_Value(X), m_Undef(), m_Mask(Mask))))
1423+
auto *NonConstArg = find_if_not(II->args(), IsaPred<Constant>);
1424+
if (!NonConstArg ||
1425+
!match(NonConstArg, m_Shuffle(m_Value(X), m_Undef(), m_Mask(Mask))))
14251426
return nullptr;
14261427

14271428
// At least 1 operand must have 1 use because we are creating 2 instructions.
14281429
if (none_of(II->args(), [](Value *V) { return V->hasOneUse(); }))
14291430
return nullptr;
14301431

14311432
// See if all arguments are shuffled with the same mask.
1432-
SmallVector<Value *, 4> NewArgs(II->arg_size());
1433-
NewArgs[0] = X;
1433+
SmallVector<Value *, 4> NewArgs;
14341434
Type *SrcTy = X->getType();
1435-
for (unsigned i = 1, e = II->arg_size(); i != e; ++i) {
1436-
if (!match(II->getArgOperand(i),
1437-
m_Shuffle(m_Value(X), m_Undef(), m_SpecificMask(Mask))) ||
1438-
X->getType() != SrcTy)
1435+
for (Value *Arg : II->args()) {
1436+
if (match(Arg, m_Shuffle(m_Value(X), m_Undef(), m_SpecificMask(Mask))) &&
1437+
X->getType() == SrcTy)
1438+
NewArgs.push_back(X);
1439+
else if (match(Arg, m_ImmConstant(C))) {
1440+
// If it's a constant, try find the constant that would be shuffled to C.
1441+
if (Constant *ShuffledC =
1442+
unshuffleConstant(Mask, C, cast<VectorType>(SrcTy)))
1443+
NewArgs.push_back(ShuffledC);
1444+
else
1445+
return nullptr;
1446+
} else
14391447
return nullptr;
1440-
NewArgs[i] = X;
14411448
}
14421449

14431450
// intrinsic (shuf X, M), (shuf Y, M), ... --> shuf (intrinsic X, Y, ...), M
@@ -3849,7 +3856,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
38493856
if (Instruction *R = FoldOpIntoSelect(*II, Sel))
38503857
return R;
38513858

3852-
if (Instruction *Shuf = foldShuffledIntrinsicOperands(II, Builder))
3859+
if (Instruction *Shuf = foldShuffledIntrinsicOperands(II))
38533860
return Shuf;
38543861

38553862
// Some intrinsics (like experimental_gc_statepoint) can be used in invoke

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
147147
Instruction *visitAddrSpaceCast(AddrSpaceCastInst &CI);
148148
Instruction *foldItoFPtoI(CastInst &FI);
149149
Instruction *visitSelectInst(SelectInst &SI);
150+
Instruction *foldShuffledIntrinsicOperands(IntrinsicInst *II);
150151
Instruction *visitCallInst(CallInst &CI);
151152
Instruction *visitInvokeInst(InvokeInst &II);
152153
Instruction *visitCallBrInst(CallBrInst &CBI);
@@ -604,6 +605,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
604605
Instruction *foldVectorBinop(BinaryOperator &Inst);
605606
Instruction *foldVectorSelect(SelectInst &Sel);
606607
Instruction *foldSelectShuffle(ShuffleVectorInst &Shuf);
608+
Constant *unshuffleConstant(ArrayRef<int> ShMask, Constant *C,
609+
VectorType *NewCTy);
607610

608611
/// Given a binary operator, cast instruction, or select which has a PHI node
609612
/// as operand #0, see if we can fold the instruction into the PHI (which is

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,8 +2100,8 @@ static bool shouldMergeGEPs(GEPOperator &GEP, GEPOperator &Src) {
21002100
///
21012101
/// A 1-to-1 mapping is not required. Example:
21022102
/// ShMask = <1,1,2,2> and C = <5,5,6,6> --> NewC = <poison,5,6,poison>
2103-
static Constant *unshuffleConstant(ArrayRef<int> ShMask, Constant *C,
2104-
VectorType *NewCTy) {
2103+
Constant *InstCombinerImpl::unshuffleConstant(ArrayRef<int> ShMask, Constant *C,
2104+
VectorType *NewCTy) {
21052105
if (isa<ScalableVectorType>(NewCTy)) {
21062106
Constant *Splat = C->getSplatValue();
21072107
if (!Splat)

llvm/test/Transforms/InstCombine/fma.ll

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,67 @@ define <2 x float> @fma_unary_shuffle_ops_narrowing(<3 x float> %x, <3 x float>
802802
ret <2 x float> %r
803803
}
804804

805+
define <2 x float> @fma_unary_shuffle_ops_1_const(<2 x float> %x, <2 x float> %y) {
806+
; CHECK-LABEL: @fma_unary_shuffle_ops_1_const(
807+
; CHECK-NEXT: [[Y:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> <float 2.000000e+00, float 1.000000e+00>, <2 x float> [[Y1:%.*]])
808+
; CHECK-NEXT: [[B:%.*]] = shufflevector <2 x float> [[Y]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
809+
; CHECK-NEXT: ret <2 x float> [[B]]
810+
;
811+
%a = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 0>
812+
%b = shufflevector <2 x float> %y, <2 x float> poison, <2 x i32> <i32 1, i32 0>
813+
%r = call <2 x float> @llvm.fma(<2 x float> %a, <2 x float> <float 1.0, float 2.0>, <2 x float> %b)
814+
ret <2 x float> %r
815+
}
816+
817+
define <2 x float> @fma_unary_shuffle_ops_2_const(<2 x float> %x) {
818+
; CHECK-LABEL: @fma_unary_shuffle_ops_2_const(
819+
; CHECK-NEXT: [[X:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> <float 2.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 1.000000e+00>, <2 x float> [[X1:%.*]])
820+
; CHECK-NEXT: [[A:%.*]] = shufflevector <2 x float> [[X]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
821+
; CHECK-NEXT: ret <2 x float> [[A]]
822+
;
823+
%a = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 0>
824+
%r = call <2 x float> @llvm.fma(<2 x float> <float 1.0, float 2.0>, <2 x float> <float 1.0, float 2.0>, <2 x float> %a)
825+
ret <2 x float> %r
826+
}
827+
828+
define <vscale x 2 x float> @fma_unary_shuffle_ops_1_const_scalable(<vscale x 2 x float> %x, <vscale x 2 x float> %y) {
829+
; CHECK-LABEL: @fma_unary_shuffle_ops_1_const_scalable(
830+
; CHECK-NEXT: [[R:%.*]] = call <vscale x 2 x float> @llvm.fma.nxv2f32(<vscale x 2 x float> [[A:%.*]], <vscale x 2 x float> splat (float 4.200000e+01), <vscale x 2 x float> [[B:%.*]])
831+
; CHECK-NEXT: [[R1:%.*]] = shufflevector <vscale x 2 x float> [[R]], <vscale x 2 x float> poison, <vscale x 2 x i32> zeroinitializer
832+
; CHECK-NEXT: ret <vscale x 2 x float> [[R1]]
833+
;
834+
%a = shufflevector <vscale x 2 x float> %x, <vscale x 2 x float> poison, <vscale x 2 x i32> zeroinitializer
835+
%b = shufflevector <vscale x 2 x float> %y, <vscale x 2 x float> poison, <vscale x 2 x i32> zeroinitializer
836+
%r = call <vscale x 2 x float> @llvm.fma(<vscale x 2 x float> %a, <vscale x 2 x float> splat (float 42.0), <vscale x 2 x float> %b)
837+
ret <vscale x 2 x float> %r
838+
}
839+
840+
define <vscale x 2 x float> @fma_unary_shuffle_ops_2_const_scalable(<vscale x 2 x float> %x) {
841+
; CHECK-LABEL: @fma_unary_shuffle_ops_2_const_scalable(
842+
; CHECK-NEXT: [[X:%.*]] = call <vscale x 2 x float> @llvm.fma.nxv2f32(<vscale x 2 x float> splat (float 4.200000e+01), <vscale x 2 x float> splat (float 4.200000e+01), <vscale x 2 x float> [[X1:%.*]])
843+
; CHECK-NEXT: [[A:%.*]] = shufflevector <vscale x 2 x float> [[X]], <vscale x 2 x float> poison, <vscale x 2 x i32> zeroinitializer
844+
; CHECK-NEXT: ret <vscale x 2 x float> [[A]]
845+
;
846+
%a = shufflevector <vscale x 2 x float> %x, <vscale x 2 x float> poison, <vscale x 2 x i32> zeroinitializer
847+
%r = call <vscale x 2 x float> @llvm.fma(<vscale x 2 x float> splat (float 42.0), <vscale x 2 x float> splat (float 42.0), <vscale x 2 x float> %a)
848+
ret <vscale x 2 x float> %r
849+
}
850+
851+
define <3 x float> @fma_unary_shuffle_ops_widening_1_const(<2 x float> %x, <2 x float> %y) {
852+
; CHECK-LABEL: @fma_unary_shuffle_ops_widening_1_const(
853+
; CHECK-NEXT: [[A:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 poison>
854+
; CHECK-NEXT: call void @use_vec3(<3 x float> [[A]])
855+
; CHECK-NEXT: [[Y:%.*]] = call fast <2 x float> @llvm.fma.v2f32(<2 x float> [[X]], <2 x float> splat (float 4.200000e+01), <2 x float> [[Y1:%.*]])
856+
; CHECK-NEXT: [[B:%.*]] = shufflevector <2 x float> [[Y]], <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 poison>
857+
; CHECK-NEXT: ret <3 x float> [[B]]
858+
;
859+
%a = shufflevector <2 x float> %x, <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 poison>
860+
call void @use_vec3(<3 x float> %a)
861+
%b = shufflevector <2 x float> %y, <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 poison>
862+
%r = call fast <3 x float> @llvm.fma(<3 x float> %a, <3 x float> splat (float 42.0), <3 x float> %b)
863+
ret <3 x float> %r
864+
}
865+
805866
; negative test - must have 3 shuffles
806867

807868
define <2 x float> @fma_unary_shuffle_ops_unshuffled(<2 x float> %x, <2 x float> %y, <2 x float> %z) {

llvm/test/Transforms/InstCombine/fsh.ll

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,67 @@ define <2 x i31> @fsh_unary_shuffle_ops_narrowing(<3 x i31> %x, <3 x i31> %y, <3
930930
ret <2 x i31> %r
931931
}
932932

933+
define <2 x i32> @fsh_unary_shuffle_ops_1_const(<2 x i32> %x, <2 x i32> %y) {
934+
; CHECK-LABEL: @fsh_unary_shuffle_ops_1_const(
935+
; CHECK-NEXT: [[Y:%.*]] = call <2 x i32> @llvm.fshr.v2i32(<2 x i32> <i32 2, i32 1>, <2 x i32> [[X:%.*]], <2 x i32> [[Y1:%.*]])
936+
; CHECK-NEXT: [[B:%.*]] = shufflevector <2 x i32> [[Y]], <2 x i32> poison, <2 x i32> <i32 1, i32 0>
937+
; CHECK-NEXT: ret <2 x i32> [[B]]
938+
;
939+
%a = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> <i32 1, i32 0>
940+
%b = shufflevector <2 x i32> %y, <2 x i32> poison, <2 x i32> <i32 1, i32 0>
941+
%r = call <2 x i32> @llvm.fshr(<2 x i32> <i32 1, i32 2>, <2 x i32> %a, <2 x i32> %b)
942+
ret <2 x i32> %r
943+
}
944+
945+
define <2 x i32> @fsh_unary_shuffle_ops_2_const(<2 x i32> %x) {
946+
; CHECK-LABEL: @fsh_unary_shuffle_ops_2_const(
947+
; CHECK-NEXT: [[X:%.*]] = call <2 x i32> @llvm.fshr.v2i32(<2 x i32> <i32 2, i32 1>, <2 x i32> <i32 2, i32 1>, <2 x i32> [[X1:%.*]])
948+
; CHECK-NEXT: [[A:%.*]] = shufflevector <2 x i32> [[X]], <2 x i32> poison, <2 x i32> <i32 1, i32 0>
949+
; CHECK-NEXT: ret <2 x i32> [[A]]
950+
;
951+
%a = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> <i32 1, i32 0>
952+
%r = call <2 x i32> @llvm.fshr(<2 x i32> <i32 1, i32 2>, <2 x i32> <i32 1, i32 2>, <2 x i32> %a)
953+
ret <2 x i32> %r
954+
}
955+
956+
define <vscale x 2 x i32> @fsh_unary_shuffle_ops_1_const_scalable(<vscale x 2 x i32> %x, <vscale x 2 x i32> %y) {
957+
; CHECK-LABEL: @fsh_unary_shuffle_ops_1_const_scalable(
958+
; CHECK-NEXT: [[Y:%.*]] = call <vscale x 2 x i32> @llvm.fshr.nxv2i32(<vscale x 2 x i32> splat (i32 42), <vscale x 2 x i32> [[X:%.*]], <vscale x 2 x i32> [[Y1:%.*]])
959+
; CHECK-NEXT: [[B:%.*]] = shufflevector <vscale x 2 x i32> [[Y]], <vscale x 2 x i32> poison, <vscale x 2 x i32> zeroinitializer
960+
; CHECK-NEXT: ret <vscale x 2 x i32> [[B]]
961+
;
962+
%a = shufflevector <vscale x 2 x i32> %x, <vscale x 2 x i32> poison, <vscale x 2 x i32> zeroinitializer
963+
%b = shufflevector <vscale x 2 x i32> %y, <vscale x 2 x i32> poison, <vscale x 2 x i32> zeroinitializer
964+
%r = call <vscale x 2 x i32> @llvm.fshr(<vscale x 2 x i32> splat (i32 42), <vscale x 2 x i32> %a, <vscale x 2 x i32> %b)
965+
ret <vscale x 2 x i32> %r
966+
}
967+
968+
define <vscale x 2 x i32> @fsh_unary_shuffle_ops_2_const_scalable(<vscale x 2 x i32> %x) {
969+
; CHECK-LABEL: @fsh_unary_shuffle_ops_2_const_scalable(
970+
; CHECK-NEXT: [[X:%.*]] = call <vscale x 2 x i32> @llvm.fshr.nxv2i32(<vscale x 2 x i32> splat (i32 42), <vscale x 2 x i32> splat (i32 42), <vscale x 2 x i32> [[X1:%.*]])
971+
; CHECK-NEXT: [[A:%.*]] = shufflevector <vscale x 2 x i32> [[X]], <vscale x 2 x i32> poison, <vscale x 2 x i32> zeroinitializer
972+
; CHECK-NEXT: ret <vscale x 2 x i32> [[A]]
973+
;
974+
%a = shufflevector <vscale x 2 x i32> %x, <vscale x 2 x i32> poison, <vscale x 2 x i32> zeroinitializer
975+
%r = call <vscale x 2 x i32> @llvm.fshr(<vscale x 2 x i32> splat (i32 42), <vscale x 2 x i32> splat (i32 42), <vscale x 2 x i32> %a)
976+
ret <vscale x 2 x i32> %r
977+
}
978+
979+
define <3 x i32> @fsh_unary_shuffle_ops_widening_1_const(<2 x i32> %x, <2 x i32> %y) {
980+
; CHECK-LABEL: @fsh_unary_shuffle_ops_widening_1_const(
981+
; CHECK-NEXT: [[A:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <3 x i32> <i32 1, i32 0, i32 poison>
982+
; CHECK-NEXT: call void @use_v3(<3 x i32> [[A]])
983+
; CHECK-NEXT: [[Y:%.*]] = call <2 x i32> @llvm.fshr.v2i32(<2 x i32> splat (i32 42), <2 x i32> [[X]], <2 x i32> [[Y1:%.*]])
984+
; CHECK-NEXT: [[B:%.*]] = shufflevector <2 x i32> [[Y]], <2 x i32> poison, <3 x i32> <i32 1, i32 0, i32 poison>
985+
; CHECK-NEXT: ret <3 x i32> [[B]]
986+
;
987+
%a = shufflevector <2 x i32> %x, <2 x i32> poison, <3 x i32> <i32 1, i32 0, i32 poison>
988+
call void @use_v3(<3 x i32> %a)
989+
%b = shufflevector <2 x i32> %y, <2 x i32> poison, <3 x i32> <i32 1, i32 0, i32 poison>
990+
%r = call <3 x i32> @llvm.fshr(<3 x i32> splat (i32 42), <3 x i32> %a, <3 x i32> %b)
991+
ret <3 x i32> %r
992+
}
993+
933994
; negative test - must have 3 shuffles
934995

935996
define <2 x i32> @fsh_unary_shuffle_ops_unshuffled(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z) {

llvm/test/Transforms/InstCombine/minmax-intrinsics.ll

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2416,6 +2416,39 @@ define <3 x i8> @umin_unary_shuffle_ops_narrowing(<4 x i8> %x, <4 x i8> %y) {
24162416
ret <3 x i8> %r
24172417
}
24182418

2419+
define <3 x i8> @smax_unary_shuffle_ops_lhs_const(<3 x i8> %x) {
2420+
; CHECK-LABEL: @smax_unary_shuffle_ops_lhs_const(
2421+
; CHECK-NEXT: [[X:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X1:%.*]], <3 x i8> <i8 1, i8 0, i8 2>)
2422+
; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2423+
; CHECK-NEXT: ret <3 x i8> [[SX]]
2424+
;
2425+
%sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2426+
%r = call <3 x i8> @llvm.smax(<3 x i8> %sx, <3 x i8> <i8 0, i8 1, i8 2>)
2427+
ret <3 x i8> %r
2428+
}
2429+
2430+
define <vscale x 3 x i8> @smax_unary_shuffle_ops_lhs_const_scalable(<vscale x 3 x i8> %x) {
2431+
; CHECK-LABEL: @smax_unary_shuffle_ops_lhs_const_scalable(
2432+
; CHECK-NEXT: [[R:%.*]] = call <vscale x 3 x i8> @llvm.smax.nxv3i8(<vscale x 3 x i8> [[SX:%.*]], <vscale x 3 x i8> splat (i8 42))
2433+
; CHECK-NEXT: [[R1:%.*]] = shufflevector <vscale x 3 x i8> [[R]], <vscale x 3 x i8> poison, <vscale x 3 x i32> zeroinitializer
2434+
; CHECK-NEXT: ret <vscale x 3 x i8> [[R1]]
2435+
;
2436+
%sx = shufflevector <vscale x 3 x i8> %x, <vscale x 3 x i8> poison, <vscale x 3 x i32> zeroinitializer
2437+
%r = call <vscale x 3 x i8> @llvm.smax(<vscale x 3 x i8> %sx, <vscale x 3 x i8> splat (i8 42))
2438+
ret <vscale x 3 x i8> %r
2439+
}
2440+
2441+
define <3 x i8> @smax_unary_shuffle_ops_lhs_const_widening(<2 x i8> %x) {
2442+
; CHECK-LABEL: @smax_unary_shuffle_ops_lhs_const_widening(
2443+
; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[X1:%.*]], <2 x i8> <i8 1, i8 0>)
2444+
; CHECK-NEXT: [[SX:%.*]] = shufflevector <2 x i8> [[X]], <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 poison>
2445+
; CHECK-NEXT: ret <3 x i8> [[SX]]
2446+
;
2447+
%sx = shufflevector <2 x i8> %x, <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 poison>
2448+
%r = call <3 x i8> @llvm.smax(<3 x i8> %sx, <3 x i8> <i8 0, i8 1, i8 2>)
2449+
ret <3 x i8> %r
2450+
}
2451+
24192452
; negative test - must have 2 shuffles
24202453

24212454
define <3 x i8> @smax_unary_shuffle_ops_unshuffled_op(<3 x i8> %x, <3 x i8> %y) {

0 commit comments

Comments
 (0)