309 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4define i1 @ceil_shift4(i32 %arg0) {5; CHECK-LABEL: define i1 @ceil_shift4(6; CHECK-SAME: i32 [[ARG0:%.*]]) {7; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 08; CHECK-NEXT: ret i1 [[TMP1]]9;10 %quot = lshr i32 %arg0, 411 %rem = and i32 %arg0, 1512 %has_rem = icmp ne i32 %rem, 013 %zext_has_rem = zext i1 %has_rem to i3214 %quot_or_rem = or i32 %quot, %zext_has_rem15 %is_zero = icmp eq i32 %quot_or_rem, 016 ret i1 %is_zero17}18 19define i1 @ceil_shift4_add(i32 %arg0) {20; CHECK-LABEL: define i1 @ceil_shift4_add(21; CHECK-SAME: i32 [[ARG0:%.*]]) {22; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 023; CHECK-NEXT: ret i1 [[TMP6]]24;25 %quot = lshr i32 %arg0, 426 %rem = and i32 %arg0, 1527 %has_rem = icmp ne i32 %rem, 028 %zext_has_rem = zext i1 %has_rem to i3229 %ceil = add i32 %quot, %zext_has_rem30 %res = icmp eq i32 %ceil, 031 ret i1 %res32}33 34define i1 @ceil_shift6(i32 %arg0) {35; CHECK-LABEL: define i1 @ceil_shift6(36; CHECK-SAME: i32 [[ARG0:%.*]]) {37; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 038; CHECK-NEXT: ret i1 [[TMP1]]39;40 %quot = lshr i32 %arg0, 641 %rem = and i32 %arg0, 6342 %has_rem = icmp ne i32 %rem, 043 %zext_has_rem = zext i1 %has_rem to i3244 %quot_or_rem = or i32 %quot, %zext_has_rem45 %res = icmp eq i32 %quot_or_rem, 046 ret i1 %res47}48 49define i1 @ceil_shift6_ne(i32 %arg0) {50; CHECK-LABEL: define i1 @ceil_shift6_ne(51; CHECK-SAME: i32 [[ARG0:%.*]]) {52; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[ARG0]], 053; CHECK-NEXT: ret i1 [[RES]]54;55 %quot = lshr i32 %arg0, 656 %rem = and i32 %arg0, 6357 %has_rem = icmp ne i32 %rem, 058 %zext_has_rem = zext i1 %has_rem to i3259 %quot_or_rem = or i32 %quot, %zext_has_rem60 %res = icmp ne i32 %quot_or_rem, 061 ret i1 %res62}63 64define i1 @ceil_shift11(i32 %arg0) {65; CHECK-LABEL: define i1 @ceil_shift11(66; CHECK-SAME: i32 [[ARG0:%.*]]) {67; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 068; CHECK-NEXT: ret i1 [[TMP1]]69;70 %quot = lshr i32 %arg0, 1171 %rem = and i32 %arg0, 204772 %has_rem = icmp ne i32 %rem, 073 %zext_has_rem = zext i1 %has_rem to i3274 %quot_or_rem = or i32 %quot, %zext_has_rem75 %res = icmp eq i32 %quot_or_rem, 076 ret i1 %res77}78 79define i1 @ceil_shift11_ne(i32 %arg0) {80; CHECK-LABEL: define i1 @ceil_shift11_ne(81; CHECK-SAME: i32 [[ARG0:%.*]]) {82; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[ARG0]], 083; CHECK-NEXT: ret i1 [[RES]]84;85 %quot = lshr i32 %arg0, 686 %rem = and i32 %arg0, 6387 %has_rem = icmp ne i32 %rem, 088 %zext_has_rem = zext i1 %has_rem to i3289 %quot_or_rem = or i32 %quot, %zext_has_rem90 %res = icmp ne i32 %quot_or_rem, 091 ret i1 %res92}93 94define i1 @ceil_shift0(i32 %arg0) {95; CHECK-LABEL: define i1 @ceil_shift0(96; CHECK-SAME: i32 [[ARG0:%.*]]) {97; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 098; CHECK-NEXT: ret i1 [[TMP1]]99;100 %quot = lshr i32 %arg0, 0101 %rem = and i32 %arg0, 0102 %has_rem = icmp ne i32 %rem, 0103 %zext_has_rem = zext i1 %has_rem to i32104 %quot_or_rem = or i32 %quot, %zext_has_rem105 %res = icmp eq i32 %quot_or_rem, 0106 ret i1 %res107}108 109define i1 @ceil_shift4_comm(i32 %arg0) {110; CHECK-LABEL: define i1 @ceil_shift4_comm(111; CHECK-SAME: i32 [[ARG0:%.*]]) {112; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0113; CHECK-NEXT: ret i1 [[TMP6]]114;115 %quot = lshr i32 %arg0, 4116 %rem = and i32 %arg0, 15117 %has_rem = icmp ne i32 %rem, 0118 %zext_has_rem = zext i1 %has_rem to i32119 %quot_or_rem = or i32 %zext_has_rem, %quot120 %res = icmp eq i32 %quot_or_rem, 0121 ret i1 %res122}123 124declare void @use(i32)125 126define i1 @ceil_shift4_used_1(i32 %arg0) {127; CHECK-LABEL: define i1 @ceil_shift4_used_1(128; CHECK-SAME: i32 [[ARG0:%.*]]) {129; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG0]], 4130; CHECK-NEXT: call void @use(i32 [[TMP1]])131; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0132; CHECK-NEXT: ret i1 [[TMP6]]133;134 %quot = lshr i32 %arg0, 4135 call void @use(i32 %quot)136 %rem = and i32 %arg0, 15137 %has_rem = icmp ne i32 %rem, 0138 %zext_has_rem = zext i1 %has_rem to i32139 %quot_or_rem = or i32 %quot, %zext_has_rem140 %res = icmp eq i32 %quot_or_rem, 0141 ret i1 %res142}143 144define i1 @ceil_shift4_used_5(i32 %arg0) {145; CHECK-LABEL: define i1 @ceil_shift4_used_5(146; CHECK-SAME: i32 [[ARG0:%.*]]) {147; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG0]], 4148; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[ARG0]], 15149; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0150; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32151; CHECK-NEXT: [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]152; CHECK-NEXT: call void @use(i32 [[TMP5]])153; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0154; CHECK-NEXT: ret i1 [[TMP6]]155;156 %quot = lshr i32 %arg0, 4157 %rem = and i32 %arg0, 15158 %has_rem = icmp ne i32 %rem, 0159 %zext_has_rem = zext i1 %has_rem to i32160 %quot_or_rem = or i32 %quot, %zext_has_rem161 call void @use(i32 %quot_or_rem)162 %res = icmp eq i32 %quot_or_rem, 0163 ret i1 %res164}165 166define i1 @ceil_shift4_used_add_nuw_nsw(i32 %arg0) {167; CHECK-LABEL: define i1 @ceil_shift4_used_add_nuw_nsw(168; CHECK-SAME: i32 [[ARG0:%.*]]) {169; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 4170; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 15171; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0172; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32173; CHECK-NEXT: [[CEIL:%.*]] = add nuw nsw i32 [[QUOT]], [[ZEXT_HAS_REM]]174; CHECK-NEXT: call void @use(i32 [[CEIL]])175; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[ARG0]], 0176; CHECK-NEXT: ret i1 [[RES]]177;178 %quot = lshr i32 %arg0, 4179 %rem = and i32 %arg0, 15180 %has_rem = icmp ne i32 %rem, 0181 %zext_has_rem = zext i1 %has_rem to i32182 %ceil = add nuw nsw i32 %quot, %zext_has_rem183 call void @use(i32 %ceil)184 %res = icmp eq i32 %ceil, 0185 ret i1 %res186}187 188define <4 x i1> @ceil_shift4_v4i32(<4 x i32> %arg0) {189; CHECK-LABEL: define <4 x i1> @ceil_shift4_v4i32(190; CHECK-SAME: <4 x i32> [[ARG0:%.*]]) {191; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[ARG0]], zeroinitializer192; CHECK-NEXT: ret <4 x i1> [[TMP1]]193;194 %quot = lshr <4 x i32> %arg0, splat (i32 16)195 %rem = and <4 x i32> %arg0, splat (i32 65535)196 %has_rem = icmp ne <4 x i32> %rem, zeroinitializer197 %zext_has_rem = zext <4 x i1> %has_rem to <4 x i32>198 %quot_or_rem = or <4 x i32> %quot, %zext_has_rem199 %res = icmp eq <4 x i32> %quot_or_rem, zeroinitializer200 ret <4 x i1> %res201}202 203define <8 x i1> @ceil_shift4_v8i16(<8 x i16> %arg0) {204; CHECK-LABEL: define <8 x i1> @ceil_shift4_v8i16(205; CHECK-SAME: <8 x i16> [[ARG0:%.*]]) {206; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <8 x i16> [[ARG0]], zeroinitializer207; CHECK-NEXT: ret <8 x i1> [[TMP1]]208;209 %quot = lshr <8 x i16> %arg0, splat (i16 4)210 %rem = and <8 x i16> %arg0, splat (i16 15)211 %has_rem = icmp ne <8 x i16> %rem, zeroinitializer212 %zext_has_rem = zext <8 x i1> %has_rem to <8 x i16>213 %quot_or_rem = or <8 x i16> %quot, %zext_has_rem214 %res = icmp eq <8 x i16> %quot_or_rem, zeroinitializer215 ret <8 x i1> %res216}217 218; negative tests219 220define i1 @ceil_shift_not_mask_1(i32 %arg0) {221; CHECK-LABEL: define i1 @ceil_shift_not_mask_1(222; CHECK-SAME: i32 [[ARG0:%.*]]) {223; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG0]], 4224; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[ARG0]], 31225; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0226; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32227; CHECK-NEXT: [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]228; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0229; CHECK-NEXT: ret i1 [[TMP6]]230;231 %quot = lshr i32 %arg0, 4232 %rem = and i32 %arg0, 31233 %has_rem = icmp ne i32 %rem, 0234 %zext_has_rem = zext i1 %has_rem to i32235 %quot_or_rem = or i32 %quot, %zext_has_rem236 %res = icmp eq i32 %quot_or_rem, 0237 ret i1 %res238}239 240define i1 @ceil_shift_not_mask_2(i32 %arg0) {241; CHECK-LABEL: define i1 @ceil_shift_not_mask_2(242; CHECK-SAME: i32 [[ARG0:%.*]]) {243; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG0]], 5244; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[ARG0]], 15245; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0246; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32247; CHECK-NEXT: [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]248; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0249; CHECK-NEXT: ret i1 [[TMP6]]250;251 %quot = lshr i32 %arg0, 5252 %rem = and i32 %arg0, 15253 %has_rem = icmp ne i32 %rem, 0254 %zext_has_rem = zext i1 %has_rem to i32255 %quot_or_rem = or i32 %quot, %zext_has_rem256 %res = icmp eq i32 %quot_or_rem, 0257 ret i1 %res258}259 260define i1 @ceil_shift_not_add_or(i32 %arg0) {261; CHECK-LABEL: define i1 @ceil_shift_not_add_or(262; CHECK-SAME: i32 [[ARG0:%.*]]) {263; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 15264; CHECK-NEXT: [[HAS_REM_NOT:%.*]] = icmp eq i32 [[REM]], 0265; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ARG0]], 32266; CHECK-NEXT: [[RES1:%.*]] = icmp eq i32 [[TMP1]], 0267; CHECK-NEXT: [[RES:%.*]] = or i1 [[HAS_REM_NOT]], [[RES1]]268; CHECK-NEXT: ret i1 [[RES]]269;270 %quot = lshr i32 %arg0, 5271 %rem = and i32 %arg0, 15272 %has_rem = icmp ne i32 %rem, 0273 %zext_has_rem = zext i1 %has_rem to i32274 %quot_and_rem = and i32 %quot, %zext_has_rem275 %res = icmp eq i32 %quot_and_rem, 0276 ret i1 %res277}278 279define i32 @ceil_shift_should_infer_ge_zero(i32 %x) {280; CHECK-LABEL: define i32 @ceil_shift_should_infer_ge_zero(281; CHECK-SAME: i32 [[X:%.*]]) {282; CHECK-NEXT: [[COND_NOT:%.*]] = icmp eq i32 [[X]], 0283; CHECK-NEXT: br i1 [[COND_NOT]], label %[[IF_ELSE:.*]], label %[[IF_THEN:.*]]284; CHECK: [[IF_THEN]]:285; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 20286; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[X]], 1048575287; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0288; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32289; CHECK-NEXT: [[TMP5:%.*]] = add nuw nsw i32 [[TMP1]], [[TMP4]]290; CHECK-NEXT: ret i32 [[TMP5]]291; CHECK: [[IF_ELSE]]:292; CHECK-NEXT: ret i32 0293;294 %cond = icmp ne i32 %x, 0295 br i1 %cond, label %if.then, label %if.else296 297if.then:298 %quot = lshr i32 %x, 20299 %rem = and i32 %x, 1048575300 %has_rem = icmp ne i32 %rem, 0301 %zext_has_rem = zext i1 %has_rem to i32302 %ceil = add nuw nsw i32 %quot, %zext_has_rem303 %max = call i32 @llvm.umax.i32(i32 %ceil, i32 1)304 ret i32 %max305 306if.else:307 ret i32 0308}309