1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -instcombine -S < %s | FileCheck %s 3 4define float @foo1(float %a) { 5; CHECK-LABEL: @foo1( 6; CHECK-NEXT: [[B:%.*]] = fcmp ogt float [[A:%.*]], 0.000000e+00 7; CHECK-NEXT: [[C:%.*]] = select i1 [[B]], float [[A]], float 0.000000e+00 8; CHECK-NEXT: [[D:%.*]] = fcmp olt float [[C]], 1.000000e+00 9; CHECK-NEXT: [[F:%.*]] = select i1 [[D]], float [[C]], float 1.000000e+00 10; CHECK-NEXT: ret float [[F]] 11; 12 %b = fcmp ogt float %a, 0.0 13 %c = select i1 %b, float %a, float 0.0 14 %d = fcmp olt float %c, 1.0 15 %f = select i1 %d, float %c, float 1.0 16 ret float %f 17} 18 19define float @foo2(float %a) { 20; CHECK-LABEL: @foo2( 21; CHECK-NEXT: [[B:%.*]] = fcmp ogt float [[A:%.*]], 0.000000e+00 22; CHECK-NEXT: [[C:%.*]] = select i1 [[B]], float [[A]], float 0.000000e+00 23; CHECK-NEXT: [[D:%.*]] = fcmp olt float [[C]], 1.000000e+00 24; CHECK-NEXT: [[E:%.*]] = select i1 [[B]], float [[A]], float 0.000000e+00 25; CHECK-NEXT: [[F:%.*]] = select i1 [[D]], float [[E]], float 1.000000e+00 26; CHECK-NEXT: ret float [[F]] 27; 28 %b = fcmp ogt float %a, 0.0 29 %c = select i1 %b, float %a, float 0.0 30 %d = fcmp olt float %c, 1.0 31 %e = select i1 %b, float %a, float 0.0 32 %f = select i1 %d, float %e, float 1.0 33 ret float %f 34} 35 36define <2 x i32> @foo3(<2 x i1> %vec_bool, i1 %bool, <2 x i32> %V) { 37; CHECK-LABEL: @foo3( 38; CHECK-NEXT: [[SEL0:%.*]] = select <2 x i1> [[VEC_BOOL:%.*]], <2 x i32> zeroinitializer, <2 x i32> [[V:%.*]] 39; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[BOOL:%.*]], <2 x i32> [[SEL0]], <2 x i32> [[V]] 40; CHECK-NEXT: ret <2 x i32> [[SEL1]] 41; 42 %sel0 = select <2 x i1> %vec_bool, <2 x i32> zeroinitializer, <2 x i32> %V 43 %sel1 = select i1 %bool, <2 x i32> %sel0, <2 x i32> %V 44 ret <2 x i32> %sel1 45} 46 47; Four variations of (select (select-shuffle)) with a common operand. 48 49define <4 x i8> @sel_shuf_commute0(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) { 50; CHECK-LABEL: @sel_shuf_commute0( 51; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[Y:%.*]], <4 x i8> [[X:%.*]] 52; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[X]], <4 x i8> [[SEL]], <4 x i32> <i32 0, i32 5, i32 2, i32 7> 53; CHECK-NEXT: ret <4 x i8> [[R]] 54; 55 %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 7> 56 %r = select <4 x i1> %cmp, <4 x i8> %blend, <4 x i8> %x 57 ret <4 x i8> %r 58} 59 60; Weird types are ok. 61 62define <5 x i9> @sel_shuf_commute1(<5 x i9> %x, <5 x i9> %y, <5 x i1> %cmp) { 63; CHECK-LABEL: @sel_shuf_commute1( 64; CHECK-NEXT: [[SEL:%.*]] = select <5 x i1> [[CMP:%.*]], <5 x i9> [[X:%.*]], <5 x i9> [[Y:%.*]] 65; CHECK-NEXT: [[R:%.*]] = shufflevector <5 x i9> [[SEL]], <5 x i9> [[Y]], <5 x i32> <i32 0, i32 6, i32 2, i32 8, i32 9> 66; CHECK-NEXT: ret <5 x i9> [[R]] 67; 68 %blend = shufflevector <5 x i9> %x, <5 x i9> %y, <5 x i32> <i32 0, i32 6, i32 2, i32 8, i32 9> 69 %r = select <5 x i1> %cmp, <5 x i9> %blend, <5 x i9> %y 70 ret <5 x i9> %r 71} 72 73define <4 x float> @sel_shuf_commute2(<4 x float> %x, <4 x float> %y, <4 x i1> %cmp) { 74; CHECK-LABEL: @sel_shuf_commute2( 75; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]] 76; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[X]], <4 x float> [[SEL]], <4 x i32> <i32 0, i32 1, i32 2, i32 7> 77; CHECK-NEXT: ret <4 x float> [[R]] 78; 79 %blend = shufflevector <4 x float> %x, <4 x float> %y, <4 x i32> <i32 0, i32 1, i32 2, i32 7> 80 %r = select <4 x i1> %cmp, <4 x float> %x, <4 x float> %blend 81 ret <4 x float> %r 82} 83 84; Scalar condition is ok. 85 86define <4 x i8> @sel_shuf_commute3(<4 x i8> %x, <4 x i8> %y, i1 %cmp) { 87; CHECK-LABEL: @sel_shuf_commute3( 88; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP:%.*]], <4 x i8> [[Y:%.*]], <4 x i8> [[X:%.*]] 89; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[SEL]], <4 x i8> [[Y]], <4 x i32> <i32 0, i32 5, i32 2, i32 3> 90; CHECK-NEXT: ret <4 x i8> [[R]] 91; 92 %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 3> 93 %r = select i1 %cmp, <4 x i8> %y, <4 x i8> %blend 94 ret <4 x i8> %r 95} 96 97declare void @use(<4 x i8>) 98 99; Negative test - extra use would require another instruction. 100 101define <4 x i8> @sel_shuf_use(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) { 102; CHECK-LABEL: @sel_shuf_use( 103; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7> 104; CHECK-NEXT: call void @use(<4 x i8> [[BLEND]]) 105; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[BLEND]], <4 x i8> [[X]] 106; CHECK-NEXT: ret <4 x i8> [[R]] 107; 108 %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 7> 109 call void @use(<4 x i8> %blend) 110 %r = select <4 x i1> %cmp, <4 x i8> %blend, <4 x i8> %x 111 ret <4 x i8> %r 112} 113 114; Negative test - undef in shuffle mask prevents transform. 115 116define <4 x i8> @sel_shuf_undef(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) { 117; CHECK-LABEL: @sel_shuf_undef( 118; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 undef> 119; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[BLEND]], <4 x i8> [[Y]] 120; CHECK-NEXT: ret <4 x i8> [[R]] 121; 122 %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 undef> 123 %r = select <4 x i1> %cmp, <4 x i8> %blend, <4 x i8> %y 124 ret <4 x i8> %r 125} 126 127; Negative test - not a "select shuffle" 128 129define <4 x i8> @sel_shuf_not(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) { 130; CHECK-LABEL: @sel_shuf_not( 131; CHECK-NEXT: [[NOTBLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 6> 132; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[NOTBLEND]], <4 x i8> [[Y]] 133; CHECK-NEXT: ret <4 x i8> [[R]] 134; 135 %notblend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 6> 136 %r = select <4 x i1> %cmp, <4 x i8> %notblend, <4 x i8> %y 137 ret <4 x i8> %r 138} 139 140; Negative test - must shuffle one of the select operands 141 142define <4 x i8> @sel_shuf_no_common_operand(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp, <4 x i8> %z) { 143; CHECK-LABEL: @sel_shuf_no_common_operand( 144; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 3> 145; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[Z:%.*]], <4 x i8> [[BLEND]] 146; CHECK-NEXT: ret <4 x i8> [[R]] 147; 148 %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 3> 149 %r = select <4 x i1> %cmp, <4 x i8> %z, <4 x i8> %blend 150 ret <4 x i8> %r 151} 152 153; Negative test - don't crash (this is not a select shuffle because it changes vector length) 154 155define <2 x i8> @sel_shuf_narrowing_commute1(<4 x i8> %x, <4 x i8> %y, <2 x i8> %x2, <2 x i1> %cmp) { 156; CHECK-LABEL: @sel_shuf_narrowing_commute1( 157; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 5> 158; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[CMP:%.*]], <2 x i8> [[BLEND]], <2 x i8> [[X2:%.*]] 159; CHECK-NEXT: ret <2 x i8> [[R]] 160; 161 %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <2 x i32> <i32 0, i32 5> 162 %r = select <2 x i1> %cmp, <2 x i8> %blend, <2 x i8> %x2 163 ret <2 x i8> %r 164} 165 166; Negative test - don't crash (this is not a select shuffle because it changes vector length) 167 168define <2 x i8> @sel_shuf_narrowing_commute2(<4 x i8> %x, <4 x i8> %y, <2 x i8> %x2, <2 x i1> %cmp) { 169; CHECK-LABEL: @sel_shuf_narrowing_commute2( 170; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 5> 171; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[CMP:%.*]], <2 x i8> [[X2:%.*]], <2 x i8> [[BLEND]] 172; CHECK-NEXT: ret <2 x i8> [[R]] 173; 174 %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <2 x i32> <i32 0, i32 5> 175 %r = select <2 x i1> %cmp, <2 x i8> %x2, <2 x i8> %blend 176 ret <2 x i8> %r 177} 178