185 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; If we zero-extend some value, and then immediately left-shift-out all the new5; sign bits, and apply a mask to keep only the sign bit (which is the original6; sign bit from before zero-extension), we might as well just sign-extend7; and apply the same signmask.8 9declare void @use32(i32)10 11; Basic pattern12 13define i32 @t0(i16 %x) {14; CHECK-LABEL: @t0(15; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext i16 [[X:%.*]] to i3216; CHECK-NEXT: [[R:%.*]] = and i32 [[X_SIGNEXT]], -214748364817; CHECK-NEXT: ret i32 [[R]]18;19 %i0 = zext i16 %x to i3220 %i1 = shl i32 %i0, 1621 %r = and i32 %i1, -214748364822 ret i32 %r23}24define i32 @t1(i8 %x) {25; CHECK-LABEL: @t1(26; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext i8 [[X:%.*]] to i3227; CHECK-NEXT: [[R:%.*]] = and i32 [[X_SIGNEXT]], -214748364828; CHECK-NEXT: ret i32 [[R]]29;30 %i0 = zext i8 %x to i3231 %i1 = shl i32 %i0, 2432 %r = and i32 %i1, -214748364833 ret i32 %r34}35 36; Some negative tests37 38define i32 @n2(i16 %x) {39; CHECK-LABEL: @n2(40; CHECK-NEXT: ret i32 041;42 %i0 = zext i16 %x to i3243 %i1 = shl i32 %i0, 15 ; undershifting44 %r = and i32 %i1, -214748364845 ret i32 %r46}47define i32 @n3(i16 %x) {48; CHECK-LABEL: @n3(49; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i3250; CHECK-NEXT: [[I1:%.*]] = shl i32 [[I0]], 1751; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -214748364852; CHECK-NEXT: ret i32 [[R]]53;54 %i0 = zext i16 %x to i3255 %i1 = shl i32 %i0, 17 ; overshifting56 %r = and i32 %i1, -214748364857 ret i32 %r58}59define i32 @n4(i16 %x) {60; CHECK-LABEL: @n4(61; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i3262; CHECK-NEXT: [[I1:%.*]] = shl nuw i32 [[I0]], 1663; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -107374182464; CHECK-NEXT: ret i32 [[R]]65;66 %i0 = zext i16 %x to i3267 %i1 = shl i32 %i0, 1668 %r = and i32 %i1, 3221225472 ; not a sign bit69 ret i32 %r70}71 72; Extra-use tests73 74define i32 @t5(i16 %x) {75; CHECK-LABEL: @t5(76; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i3277; CHECK-NEXT: call void @use32(i32 [[I0]])78; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext i16 [[X]] to i3279; CHECK-NEXT: [[R:%.*]] = and i32 [[X_SIGNEXT]], -214748364880; CHECK-NEXT: ret i32 [[R]]81;82 %i0 = zext i16 %x to i3283 call void @use32(i32 %i0)84 %i1 = shl i32 %i0, 1685 %r = and i32 %i1, -214748364886 ret i32 %r87}88define i32 @n6(i16 %x) {89; CHECK-LABEL: @n6(90; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i3291; CHECK-NEXT: [[I1:%.*]] = shl nuw i32 [[I0]], 1692; CHECK-NEXT: call void @use32(i32 [[I1]])93; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -214748364894; CHECK-NEXT: ret i32 [[R]]95;96 %i0 = zext i16 %x to i3297 %i1 = shl i32 %i0, 16 ; not one-use98 call void @use32(i32 %i1)99 %r = and i32 %i1, -2147483648100 ret i32 %r101}102define i32 @n7(i16 %x) {103; CHECK-LABEL: @n7(104; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i32105; CHECK-NEXT: call void @use32(i32 [[I0]])106; CHECK-NEXT: [[I1:%.*]] = shl nuw i32 [[I0]], 16107; CHECK-NEXT: call void @use32(i32 [[I1]])108; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -2147483648109; CHECK-NEXT: ret i32 [[R]]110;111 %i0 = zext i16 %x to i32 ; not one-use112 call void @use32(i32 %i0)113 %i1 = shl i32 %i0, 16 ; not one-use114 call void @use32(i32 %i1)115 %r = and i32 %i1, -2147483648116 ret i32 %r117}118 119; Some vector tests120 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> %r131}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> %r143}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> %r157}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> %r171}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> %r184}185