1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; If we zero-extend some value, and then immediately left-shift-out all the new 5; sign bits, and apply a mask to keep only the sign bit (which is the original 6; sign bit from before zero-extension), we might as well just sign-extend 7; and apply the same signmask. 8 9declare void @use32(i32) 10 11; Basic pattern 12 13define i32 @t0(i16 %x) { 14; CHECK-LABEL: @t0( 15; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext i16 [[X:%.*]] to i32 16; CHECK-NEXT: [[R:%.*]] = and i32 [[X_SIGNEXT]], -2147483648 17; CHECK-NEXT: ret i32 [[R]] 18; 19 %i0 = zext i16 %x to i32 20 %i1 = shl i32 %i0, 16 21 %r = and i32 %i1, -2147483648 22 ret i32 %r 23} 24define i32 @t1(i8 %x) { 25; CHECK-LABEL: @t1( 26; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext i8 [[X:%.*]] to i32 27; CHECK-NEXT: [[R:%.*]] = and i32 [[X_SIGNEXT]], -2147483648 28; CHECK-NEXT: ret i32 [[R]] 29; 30 %i0 = zext i8 %x to i32 31 %i1 = shl i32 %i0, 24 32 %r = and i32 %i1, -2147483648 33 ret i32 %r 34} 35 36; Some negative tests 37 38define i32 @n2(i16 %x) { 39; CHECK-LABEL: @n2( 40; CHECK-NEXT: ret i32 0 41; 42 %i0 = zext i16 %x to i32 43 %i1 = shl i32 %i0, 15 ; undershifting 44 %r = and i32 %i1, -2147483648 45 ret i32 %r 46} 47define i32 @n3(i16 %x) { 48; CHECK-LABEL: @n3( 49; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i32 50; CHECK-NEXT: [[I1:%.*]] = shl i32 [[I0]], 17 51; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -2147483648 52; CHECK-NEXT: ret i32 [[R]] 53; 54 %i0 = zext i16 %x to i32 55 %i1 = shl i32 %i0, 17 ; overshifting 56 %r = and i32 %i1, -2147483648 57 ret i32 %r 58} 59define i32 @n4(i16 %x) { 60; CHECK-LABEL: @n4( 61; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i32 62; CHECK-NEXT: [[I1:%.*]] = shl nuw i32 [[I0]], 16 63; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -1073741824 64; CHECK-NEXT: ret i32 [[R]] 65; 66 %i0 = zext i16 %x to i32 67 %i1 = shl i32 %i0, 16 68 %r = and i32 %i1, 3221225472 ; not a sign bit 69 ret i32 %r 70} 71 72; Extra-use tests 73 74define i32 @t5(i16 %x) { 75; CHECK-LABEL: @t5( 76; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i32 77; CHECK-NEXT: call void @use32(i32 [[I0]]) 78; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext i16 [[X]] to i32 79; CHECK-NEXT: [[R:%.*]] = and i32 [[X_SIGNEXT]], -2147483648 80; CHECK-NEXT: ret i32 [[R]] 81; 82 %i0 = zext i16 %x to i32 83 call void @use32(i32 %i0) 84 %i1 = shl i32 %i0, 16 85 %r = and i32 %i1, -2147483648 86 ret i32 %r 87} 88define i32 @n6(i16 %x) { 89; CHECK-LABEL: @n6( 90; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i32 91; CHECK-NEXT: [[I1:%.*]] = shl nuw i32 [[I0]], 16 92; CHECK-NEXT: call void @use32(i32 [[I1]]) 93; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -2147483648 94; CHECK-NEXT: ret i32 [[R]] 95; 96 %i0 = zext i16 %x to i32 97 %i1 = shl i32 %i0, 16 ; not one-use 98 call void @use32(i32 %i1) 99 %r = and i32 %i1, -2147483648 100 ret i32 %r 101} 102define i32 @n7(i16 %x) { 103; CHECK-LABEL: @n7( 104; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i32 105; CHECK-NEXT: call void @use32(i32 [[I0]]) 106; CHECK-NEXT: [[I1:%.*]] = shl nuw i32 [[I0]], 16 107; CHECK-NEXT: call void @use32(i32 [[I1]]) 108; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -2147483648 109; CHECK-NEXT: ret i32 [[R]] 110; 111 %i0 = zext i16 %x to i32 ; not one-use 112 call void @use32(i32 %i0) 113 %i1 = shl i32 %i0, 16 ; not one-use 114 call void @use32(i32 %i1) 115 %r = and i32 %i1, -2147483648 116 ret i32 %r 117} 118 119; Some vector tests 120 121define <2 x i32> @t8(<2 x i16> %x) { 122; CHECK-LABEL: @t8( 123; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32> 124; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 -2147483648> 125; CHECK-NEXT: ret <2 x i32> [[R]] 126; 127 %i0 = zext <2 x i16> %x to <2 x i32> 128 %i1 = shl <2 x i32> %i0, <i32 16, i32 16> 129 %r = and <2 x i32> %i1, <i32 -2147483648, i32 -2147483648> 130 ret <2 x i32> %r 131} 132define <2 x i32> @t9(<2 x i16> %x) { 133; CHECK-LABEL: @t9( 134; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32> 135; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 undef> 136; CHECK-NEXT: ret <2 x i32> [[R]] 137; 138 %i0 = zext <2 x i16> %x to <2 x i32> 139 %i1 = shl <2 x i32> %i0, <i32 16, i32 undef> 140 %r = and <2 x i32> %i1, <i32 -2147483648, i32 -2147483648> 141 ; Here undef can be propagated into the mask. 142 ret <2 x i32> %r 143} 144define <2 x i32> @t10(<2 x i16> %x) { 145; CHECK-LABEL: @t10( 146; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32> 147; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 0> 148; CHECK-NEXT: ret <2 x i32> [[R]] 149; 150 %i0 = zext <2 x i16> %x to <2 x i32> 151 %i1 = shl <2 x i32> %i0, <i32 16, i32 16> 152 %r = and <2 x i32> %i1, <i32 -2147483648, i32 undef> 153 ; CAREFUL! We can't keep undef mask here, since high bits are no longer zero, 154 ; we must sanitize it to 0. 155 ret <2 x i32> %r 156} 157define <2 x i32> @t11(<2 x i16> %x) { 158; CHECK-LABEL: @t11( 159; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32> 160; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 undef> 161; CHECK-NEXT: ret <2 x i32> [[R]] 162; 163 %i0 = zext <2 x i16> %x to <2 x i32> 164 %i1 = shl <2 x i32> %i0, <i32 16, i32 undef> 165 %r = and <2 x i32> %i1, <i32 -2147483648, i32 undef> 166 ; Here undef mask is fine. 167 ret <2 x i32> %r 168} 169