1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 4 5; Perform the shift first and merge the truncs as long as all zero/sign 6; bits created by the shift are removed by the trunc. 7 8declare void @use(i32) 9 10define i8 @trunc_lshr_trunc(i64 %a) { 11; CHECK-LABEL: @trunc_lshr_trunc( 12; CHECK-NEXT: [[C1:%.*]] = lshr i64 [[A:%.*]], 8 13; CHECK-NEXT: [[D:%.*]] = trunc i64 [[C1]] to i8 14; CHECK-NEXT: ret i8 [[D]] 15; 16 %b = trunc i64 %a to i32 17 %c = lshr i32 %b, 8 18 %d = trunc i32 %c to i8 19 ret i8 %d 20} 21 22define <2 x i8> @trunc_lshr_trunc_uniform(<2 x i64> %a) { 23; CHECK-LABEL: @trunc_lshr_trunc_uniform( 24; CHECK-NEXT: [[C1:%.*]] = lshr <2 x i64> [[A:%.*]], <i64 8, i64 8> 25; CHECK-NEXT: [[D:%.*]] = trunc <2 x i64> [[C1]] to <2 x i8> 26; CHECK-NEXT: ret <2 x i8> [[D]] 27; 28 %b = trunc <2 x i64> %a to <2 x i32> 29 %c = lshr <2 x i32> %b, <i32 8, i32 8> 30 %d = trunc <2 x i32> %c to <2 x i8> 31 ret <2 x i8> %d 32} 33 34define <2 x i8> @trunc_lshr_trunc_nonuniform(<2 x i64> %a) { 35; CHECK-LABEL: @trunc_lshr_trunc_nonuniform( 36; CHECK-NEXT: [[C1:%.*]] = lshr <2 x i64> [[A:%.*]], <i64 8, i64 2> 37; CHECK-NEXT: [[D:%.*]] = trunc <2 x i64> [[C1]] to <2 x i8> 38; CHECK-NEXT: ret <2 x i8> [[D]] 39; 40 %b = trunc <2 x i64> %a to <2 x i32> 41 %c = lshr <2 x i32> %b, <i32 8, i32 2> 42 %d = trunc <2 x i32> %c to <2 x i8> 43 ret <2 x i8> %d 44} 45 46define <2 x i8> @trunc_lshr_trunc_uniform_undef(<2 x i64> %a) { 47; CHECK-LABEL: @trunc_lshr_trunc_uniform_undef( 48; CHECK-NEXT: [[C1:%.*]] = lshr <2 x i64> [[A:%.*]], <i64 24, i64 undef> 49; CHECK-NEXT: [[D:%.*]] = trunc <2 x i64> [[C1]] to <2 x i8> 50; CHECK-NEXT: ret <2 x i8> [[D]] 51; 52 %b = trunc <2 x i64> %a to <2 x i32> 53 %c = lshr <2 x i32> %b, <i32 24, i32 undef> 54 %d = trunc <2 x i32> %c to <2 x i8> 55 ret <2 x i8> %d 56} 57 58define i8 @trunc_lshr_trunc_outofrange(i64 %a) { 59; CHECK-LABEL: @trunc_lshr_trunc_outofrange( 60; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i32 61; CHECK-NEXT: [[C:%.*]] = lshr i32 [[B]], 25 62; CHECK-NEXT: [[D:%.*]] = trunc i32 [[C]] to i8 63; CHECK-NEXT: ret i8 [[D]] 64; 65 %b = trunc i64 %a to i32 66 %c = lshr i32 %b, 25 67 %d = trunc i32 %c to i8 68 ret i8 %d 69} 70 71define <2 x i8> @trunc_lshr_trunc_nonuniform_outofrange(<2 x i64> %a) { 72; CHECK-LABEL: @trunc_lshr_trunc_nonuniform_outofrange( 73; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> 74; CHECK-NEXT: [[C:%.*]] = lshr <2 x i32> [[B]], <i32 8, i32 25> 75; CHECK-NEXT: [[D:%.*]] = trunc <2 x i32> [[C]] to <2 x i8> 76; CHECK-NEXT: ret <2 x i8> [[D]] 77; 78 %b = trunc <2 x i64> %a to <2 x i32> 79 %c = lshr <2 x i32> %b, <i32 8, i32 25> 80 %d = trunc <2 x i32> %c to <2 x i8> 81 ret <2 x i8> %d 82} 83 84define i8 @trunc_ashr_trunc(i64 %a) { 85; CHECK-LABEL: @trunc_ashr_trunc( 86; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[A:%.*]], 8 87; CHECK-NEXT: [[D:%.*]] = trunc i64 [[TMP1]] to i8 88; CHECK-NEXT: ret i8 [[D]] 89; 90 %b = trunc i64 %a to i32 91 %c = ashr i32 %b, 8 92 %d = trunc i32 %c to i8 93 ret i8 %d 94} 95 96define i8 @trunc_ashr_trunc_exact(i64 %a) { 97; CHECK-LABEL: @trunc_ashr_trunc_exact( 98; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i64 [[A:%.*]], 8 99; CHECK-NEXT: [[D:%.*]] = trunc i64 [[TMP1]] to i8 100; CHECK-NEXT: ret i8 [[D]] 101; 102 %b = trunc i64 %a to i32 103 %c = ashr exact i32 %b, 8 104 %d = trunc i32 %c to i8 105 ret i8 %d 106} 107 108define <2 x i8> @trunc_ashr_trunc_uniform(<2 x i64> %a) { 109; CHECK-LABEL: @trunc_ashr_trunc_uniform( 110; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i64> [[A:%.*]], <i64 8, i64 8> 111; CHECK-NEXT: [[D:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i8> 112; CHECK-NEXT: ret <2 x i8> [[D]] 113; 114 %b = trunc <2 x i64> %a to <2 x i32> 115 %c = ashr <2 x i32> %b, <i32 8, i32 8> 116 %d = trunc <2 x i32> %c to <2 x i8> 117 ret <2 x i8> %d 118} 119 120define <2 x i8> @trunc_ashr_trunc_nonuniform(<2 x i64> %a) { 121; CHECK-LABEL: @trunc_ashr_trunc_nonuniform( 122; CHECK-NEXT: [[C1:%.*]] = ashr <2 x i64> [[A:%.*]], <i64 0, i64 23> 123; CHECK-NEXT: [[D:%.*]] = trunc <2 x i64> [[C1]] to <2 x i8> 124; CHECK-NEXT: ret <2 x i8> [[D]] 125; 126 %b = trunc <2 x i64> %a to <2 x i32> 127 %c = ashr <2 x i32> %b, <i32 0, i32 23> 128 %d = trunc <2 x i32> %c to <2 x i8> 129 ret <2 x i8> %d 130} 131 132define <2 x i8> @trunc_ashr_trunc_uniform_undef(<2 x i64> %a) { 133; CHECK-LABEL: @trunc_ashr_trunc_uniform_undef( 134; CHECK-NEXT: [[C1:%.*]] = ashr <2 x i64> [[A:%.*]], <i64 8, i64 undef> 135; CHECK-NEXT: [[D:%.*]] = trunc <2 x i64> [[C1]] to <2 x i8> 136; CHECK-NEXT: ret <2 x i8> [[D]] 137; 138 %b = trunc <2 x i64> %a to <2 x i32> 139 %c = ashr <2 x i32> %b, <i32 8, i32 undef> 140 %d = trunc <2 x i32> %c to <2 x i8> 141 ret <2 x i8> %d 142} 143 144define i8 @trunc_ashr_trunc_outofrange(i64 %a) { 145; CHECK-LABEL: @trunc_ashr_trunc_outofrange( 146; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i32 147; CHECK-NEXT: [[C:%.*]] = ashr i32 [[B]], 25 148; CHECK-NEXT: [[D:%.*]] = trunc i32 [[C]] to i8 149; CHECK-NEXT: ret i8 [[D]] 150; 151 %b = trunc i64 %a to i32 152 %c = ashr i32 %b, 25 153 %d = trunc i32 %c to i8 154 ret i8 %d 155} 156 157define <2 x i8> @trunc_ashr_trunc_nonuniform_outofrange(<2 x i64> %a) { 158; CHECK-LABEL: @trunc_ashr_trunc_nonuniform_outofrange( 159; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> 160; CHECK-NEXT: [[C:%.*]] = ashr <2 x i32> [[B]], <i32 8, i32 25> 161; CHECK-NEXT: [[D:%.*]] = trunc <2 x i32> [[C]] to <2 x i8> 162; CHECK-NEXT: ret <2 x i8> [[D]] 163; 164 %b = trunc <2 x i64> %a to <2 x i32> 165 %c = ashr <2 x i32> %b, <i32 8, i32 25> 166 %d = trunc <2 x i32> %c to <2 x i8> 167 ret <2 x i8> %d 168} 169 170define i8 @trunc_ashr_trunc_multiuse(i64 %a) { 171; CHECK-LABEL: @trunc_ashr_trunc_multiuse( 172; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i32 173; CHECK-NEXT: [[C:%.*]] = ashr i32 [[B]], 9 174; CHECK-NEXT: [[D:%.*]] = trunc i32 [[C]] to i8 175; CHECK-NEXT: call void @use(i32 [[C]]) 176; CHECK-NEXT: ret i8 [[D]] 177; 178 %b = trunc i64 %a to i32 179 %c = ashr i32 %b, 9 180 %d = trunc i32 %c to i8 181 call void @use(i32 %c) 182 ret i8 %d 183} 184