1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare void @use(<4 x i16>) 5 6define void @test(<16 x i8> %w, ptr %o1, ptr %o2) { 7; CHECK-LABEL: @test( 8; CHECK-NEXT: [[V_BC:%.*]] = bitcast <16 x i8> [[W:%.*]] to <4 x i32> 9; CHECK-NEXT: [[V_EXTRACT:%.*]] = extractelement <4 x i32> [[V_BC]], i64 3 10; CHECK-NEXT: [[V_BC1:%.*]] = bitcast <16 x i8> [[W]] to <4 x float> 11; CHECK-NEXT: [[V_EXTRACT2:%.*]] = extractelement <4 x float> [[V_BC1]], i64 3 12; CHECK-NEXT: store i32 [[V_EXTRACT]], ptr [[O1:%.*]], align 4 13; CHECK-NEXT: store float [[V_EXTRACT2]], ptr [[O2:%.*]], align 4 14; CHECK-NEXT: ret void 15; 16 %v = shufflevector <16 x i8> %w, <16 x i8> poison, <4 x i32> <i32 12, i32 13, i32 14, i32 15> 17 %f = bitcast <4 x i8> %v to float 18 %i = bitcast <4 x i8> %v to i32 19 store i32 %i, ptr %o1, align 4 20 store float %f, ptr %o2, align 4 21 ret void 22} 23 24; Shuffle-of-bitcast-splat --> splat-bitcast 25 26define <4 x i16> @splat_bitcast_operand(<8 x i8> %x) { 27; CHECK-LABEL: @splat_bitcast_operand( 28; CHECK-NEXT: [[S1:%.*]] = shufflevector <8 x i8> [[X:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> 29; CHECK-NEXT: [[S2:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16> 30; CHECK-NEXT: ret <4 x i16> [[S2]] 31; 32 %s1 = shufflevector <8 x i8> %x, <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> 33 %bc = bitcast <8 x i8> %s1 to <4 x i16> 34 %s2 = shufflevector <4 x i16> %bc, <4 x i16> poison, <4 x i32> <i32 0, i32 2, i32 1, i32 0> 35 ret <4 x i16> %s2 36} 37 38; Shuffle-of-bitcast-splat --> splat-bitcast 39 40define <4 x i16> @splat_bitcast_operand_uses(<8 x i8> %x) { 41; CHECK-LABEL: @splat_bitcast_operand_uses( 42; CHECK-NEXT: [[S1:%.*]] = shufflevector <8 x i8> [[X:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> 43; CHECK-NEXT: [[BC:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16> 44; CHECK-NEXT: call void @use(<4 x i16> [[BC]]) 45; CHECK-NEXT: [[S2:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16> 46; CHECK-NEXT: ret <4 x i16> [[S2]] 47; 48 %s1 = shufflevector <8 x i8> %x, <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> 49 %bc = bitcast <8 x i8> %s1 to <4 x i16> 50 call void @use(<4 x i16> %bc) 51 %s2 = shufflevector <4 x i16> %bc, <4 x i16> poison, <4 x i32> <i32 0, i32 2, i32 1, i32 0> 52 ret <4 x i16> %s2 53} 54 55; Shuffle-of-bitcast-splat --> splat-bitcast 56 57define <4 x i32> @splat_bitcast_operand_same_size_src_elt(<4 x float> %x) { 58; CHECK-LABEL: @splat_bitcast_operand_same_size_src_elt( 59; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x float> [[X:%.*]] to <4 x i32> 60; CHECK-NEXT: [[BC:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2> 61; CHECK-NEXT: ret <4 x i32> [[BC]] 62; 63 %s1 = shufflevector <4 x float> %x, <4 x float> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2> 64 %bc = bitcast <4 x float> %s1 to <4 x i32> 65 %s2 = shufflevector <4 x i32> %bc, <4 x i32> poison, <4 x i32> <i32 0, i32 2, i32 1, i32 0> 66 ret <4 x i32> %s2 67} 68 69; Scaled mask is inverse of first mask. 70 71define <4 x i32> @shuf_bitcast_operand(<16 x i8> %x) { 72; CHECK-LABEL: @shuf_bitcast_operand( 73; CHECK-NEXT: [[S2:%.*]] = bitcast <16 x i8> [[X:%.*]] to <4 x i32> 74; CHECK-NEXT: ret <4 x i32> [[S2]] 75; 76 %s1 = shufflevector <16 x i8> %x, <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> 77 %bc = bitcast <16 x i8> %s1 to <4 x i32> 78 %s2 = shufflevector <4 x i32> %bc, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 79 ret <4 x i32> %s2 80} 81 82; TODO: Could allow fold for length-changing shuffles. 83 84define <5 x i16> @splat_bitcast_operand_change_type(<8 x i8> %x) { 85; CHECK-LABEL: @splat_bitcast_operand_change_type( 86; CHECK-NEXT: [[S1:%.*]] = shufflevector <8 x i8> [[X:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> 87; CHECK-NEXT: [[BC:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16> 88; CHECK-NEXT: [[S2:%.*]] = shufflevector <4 x i16> [[BC]], <4 x i16> poison, <5 x i32> <i32 0, i32 2, i32 1, i32 0, i32 3> 89; CHECK-NEXT: ret <5 x i16> [[S2]] 90; 91 %s1 = shufflevector <8 x i8> %x, <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> 92 %bc = bitcast <8 x i8> %s1 to <4 x i16> 93 %s2 = shufflevector <4 x i16> %bc, <4 x i16> poison, <5 x i32> <i32 0, i32 2, i32 1, i32 0, i32 3> 94 ret <5 x i16> %s2 95} 96 97; Shuffle-of-bitcast-splat --> splat-bitcast 98 99define <4 x i16> @splat_bitcast_operand_wider_src_elt(<2 x i32> %x) { 100; CHECK-LABEL: @splat_bitcast_operand_wider_src_elt( 101; CHECK-NEXT: [[S1:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> <i32 1, i32 1> 102; CHECK-NEXT: [[S2:%.*]] = bitcast <2 x i32> [[S1]] to <4 x i16> 103; CHECK-NEXT: ret <4 x i16> [[S2]] 104; 105 %s1 = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> <i32 1, i32 1> 106 %bc = bitcast <2 x i32> %s1 to <4 x i16> 107 %s2 = shufflevector <4 x i16> %bc, <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1> 108 ret <4 x i16> %s2 109} 110 111; Shuffle-of-bitcast-splat --> splat-bitcast 112 113define <4 x i16> @splat_bitcast_operand_wider_src_elt_uses(<2 x i32> %x) { 114; CHECK-LABEL: @splat_bitcast_operand_wider_src_elt_uses( 115; CHECK-NEXT: [[S1:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> <i32 1, i32 1> 116; CHECK-NEXT: [[BC:%.*]] = bitcast <2 x i32> [[S1]] to <4 x i16> 117; CHECK-NEXT: call void @use(<4 x i16> [[BC]]) 118; CHECK-NEXT: [[S2:%.*]] = bitcast <2 x i32> [[S1]] to <4 x i16> 119; CHECK-NEXT: ret <4 x i16> [[S2]] 120; 121 %s1 = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> <i32 1, i32 1> 122 %bc = bitcast <2 x i32> %s1 to <4 x i16> 123 call void @use(<4 x i16> %bc) 124 %s2 = shufflevector <4 x i16> %bc, <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1> 125 ret <4 x i16> %s2 126} 127 128; Scaled mask is inverse of first mask. 129 130define <16 x i8> @shuf_bitcast_operand_wider_src(<4 x i32> %x) { 131; CHECK-LABEL: @shuf_bitcast_operand_wider_src( 132; CHECK-NEXT: [[S2:%.*]] = bitcast <4 x i32> [[X:%.*]] to <16 x i8> 133; CHECK-NEXT: ret <16 x i8> [[S2]] 134; 135 %s1 = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 136 %bc = bitcast <4 x i32> %s1 to <16 x i8> 137 %s2 = shufflevector <16 x i8> %bc, <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> 138 ret <16 x i8> %s2 139} 140 141; Negative test - the 2nd mask can't be widened 142 143define <16 x i8> @shuf_bitcast_operand_cannot_widen(<4 x i32> %x) { 144; CHECK-LABEL: @shuf_bitcast_operand_cannot_widen( 145; CHECK-NEXT: [[S1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 146; CHECK-NEXT: [[BC:%.*]] = bitcast <4 x i32> [[S1]] to <16 x i8> 147; CHECK-NEXT: [[S2:%.*]] = shufflevector <16 x i8> [[BC]], <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 12, i32 13, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> 148; CHECK-NEXT: ret <16 x i8> [[S2]] 149; 150 %s1 = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 151 %bc = bitcast <4 x i32> %s1 to <16 x i8> 152 %s2 = shufflevector <16 x i8> %bc, <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 12, i32 13, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> 153 ret <16 x i8> %s2 154} 155 156; Negative test - the 2nd mask can't be widened 157 158define <16 x i8> @shuf_bitcast_operand_cannot_widen_undef(<4 x i32> %x) { 159; CHECK-LABEL: @shuf_bitcast_operand_cannot_widen_undef( 160; CHECK-NEXT: [[S1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 161; CHECK-NEXT: [[BC:%.*]] = bitcast <4 x i32> [[S1]] to <16 x i8> 162; CHECK-NEXT: [[S2:%.*]] = shufflevector <16 x i8> [[BC]], <16 x i8> poison, <16 x i32> <i32 12, i32 poison, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> 163; CHECK-NEXT: ret <16 x i8> [[S2]] 164; 165 %s1 = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 166 %bc = bitcast <4 x i32> %s1 to <16 x i8> 167 %s2 = shufflevector <16 x i8> %bc, <16 x i8> poison, <16 x i32> <i32 12, i32 undef, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> 168 ret <16 x i8> %s2 169} 170