1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=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]], splat (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} 132 133define <2 x i32> @t9(<2 x i16> %x) { 134; CHECK-LABEL: @t9( 135; CHECK-NEXT: [[I1:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32> 136; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[I1]], splat (i32 -2147483648) 137; CHECK-NEXT: ret <2 x i32> [[R]] 138; 139 %i0 = zext <2 x i16> %x to <2 x i32> 140 %i1 = shl <2 x i32> %i0, <i32 16, i32 poison> 141 %r = and <2 x i32> %i1, <i32 -2147483648, i32 -2147483648> 142 ret <2 x i32> %r 143} 144 145; If we folded this, we wouldn't be able to keep the undef mask. 146define <2 x i32> @t10_undef(<2 x i16> %x) { 147; CHECK-LABEL: @t10_undef( 148; CHECK-NEXT: [[I0:%.*]] = zext <2 x i16> [[X:%.*]] to <2 x i32> 149; CHECK-NEXT: [[I1:%.*]] = shl nuw <2 x i32> [[I0]], splat (i32 16) 150; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[I1]], <i32 -2147483648, i32 undef> 151; CHECK-NEXT: ret <2 x i32> [[R]] 152; 153 %i0 = zext <2 x i16> %x to <2 x i32> 154 %i1 = shl <2 x i32> %i0, <i32 16, i32 16> 155 %r = and <2 x i32> %i1, <i32 -2147483648, i32 undef> 156 ret <2 x i32> %r 157} 158 159define <2 x i32> @t10_poison(<2 x i16> %x) { 160; CHECK-LABEL: @t10_poison( 161; CHECK-NEXT: [[I1:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32> 162; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[I1]], <i32 -2147483648, i32 poison> 163; CHECK-NEXT: ret <2 x i32> [[R]] 164; 165 %i0 = zext <2 x i16> %x to <2 x i32> 166 %i1 = shl <2 x i32> %i0, <i32 16, i32 16> 167 %r = and <2 x i32> %i1, <i32 -2147483648, i32 poison> 168 ; CAREFUL! We can't keep poison mask here, since high bits are no longer zero, 169 ; we must sanitize it to 0. 170 ret <2 x i32> %r 171} 172 173define <2 x i32> @t11(<2 x i16> %x) { 174; CHECK-LABEL: @t11( 175; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32> 176; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 poison> 177; CHECK-NEXT: ret <2 x i32> [[R]] 178; 179 %i0 = zext <2 x i16> %x to <2 x i32> 180 %i1 = shl <2 x i32> %i0, <i32 16, i32 poison> 181 %r = and <2 x i32> %i1, <i32 -2147483648, i32 poison> 182 ; Here poison mask is fine. 183 ret <2 x i32> %r 184} 185