diff --git a/llvm/test/Transforms/InstCombine/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll --- a/llvm/test/Transforms/InstCombine/mul.ll +++ b/llvm/test/Transforms/InstCombine/mul.ll @@ -607,3 +607,236 @@ %mul = mul i32 %sel, %y ret i32 %mul } + + +; TODO. 'select + mul' -> 'select + shl' for power of twos + +define i32 @shift_if_power2(i32 %x, i1 %cond) { +; CHECK-LABEL: @shift_if_power2( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 16, i32 4 +; CHECK-NEXT: [[R:%.*]] = mul i32 [[SEL]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %sel = select i1 %cond, i32 16, i32 4 + %r = mul i32 %sel, %x + ret i32 %r +} + +define i32 @shift_if_power2_nuw(i32 %x, i1 %cond) { +; CHECK-LABEL: @shift_if_power2_nuw( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 16, i32 4 +; CHECK-NEXT: [[R:%.*]] = mul nuw i32 [[SEL]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %sel = select i1 %cond, i32 16, i32 4 + %r = mul nuw i32 %sel, %x + ret i32 %r +} + +define i32 @shift_if_power2_nsw(i32 %x, i1 %cond) { +; CHECK-LABEL: @shift_if_power2_nsw( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 16, i32 4 +; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[SEL]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %sel = select i1 %cond, i32 16, i32 4 + %r = mul nsw i32 %sel, %x + ret i32 %r +} + +define i32 @shift_if_power2_nuw_nsw(i32 %x, i1 %cond) { +; CHECK-LABEL: @shift_if_power2_nuw_nsw( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 16, i32 4 +; CHECK-NEXT: [[R:%.*]] = mul nuw nsw i32 [[SEL]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %sel = select i1 %cond, i32 16, i32 4 + %r = mul nuw nsw i32 %sel, %x + ret i32 %r +} + +define i32 @shift_if_power2_nuw_nsw_min(i32 %x, i1 %cond) { +; CHECK-LABEL: @shift_if_power2_nuw_nsw_min( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 -2, i32 -2147483648 +; CHECK-NEXT: [[R:%.*]] = mul nuw nsw i32 [[SEL]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %sel = select i1 %cond, i32 -2, i32 -2147483648 + %r = mul nuw nsw i32 %sel, %x + ret i32 %r +} + +define i32 @shift_if_power2_double_select(i32 %x, i32 %y, i1 %cond1, i1 %cond2) { +; CHECK-LABEL: @shift_if_power2_double_select( +; CHECK-NEXT: [[SHL_RES:%.*]] = shl i32 8, [[Y:%.*]] +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND1:%.*]], i32 [[SHL_RES]], i32 1024 +; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 16, i32 [[SEL1]] +; CHECK-NEXT: [[R:%.*]] = mul nuw i32 [[SEL2]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %shl.res = shl i32 8, %y + %sel1 = select i1 %cond1, i32 %shl.res, i32 1024 + %sel2 = select i1 %cond2, i32 16, i32 %sel1 + %r = mul nuw i32 %x, %sel2 + ret i32 %r +} + +define i32 @shift_if_power2_double_select_zext(i32 %x, i16 %y, i1 %cond1, i1 %cond2) { +; CHECK-LABEL: @shift_if_power2_double_select_zext( +; CHECK-NEXT: [[SHL_RES:%.*]] = shl nsw i16 8, [[Y:%.*]] +; CHECK-NEXT: [[SHL:%.*]] = zext i16 [[SHL_RES]] to i32 +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND1:%.*]], i32 [[SHL]], i32 1024 +; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 16, i32 [[SEL1]] +; CHECK-NEXT: [[R:%.*]] = mul nuw i32 [[SEL2]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %shl.res = shl nsw i16 8, %y + %shl = zext i16 %shl.res to i32 + %sel1 = select i1 %cond1, i32 %shl, i32 1024 + %sel2 = select i1 %cond2, i32 16, i32 %sel1 + %r = mul nuw i32 %x, %sel2 + ret i32 %r +} + +define i32 @shift_if_power2_double_select_zext_mul_nsw(i32 %x, i16 %y, i1 %cond1, i1 %cond2) { +; CHECK-LABEL: @shift_if_power2_double_select_zext_mul_nsw( +; CHECK-NEXT: [[SHL_RES:%.*]] = shl i16 8, [[Y:%.*]] +; CHECK-NEXT: [[SHL:%.*]] = zext i16 [[SHL_RES]] to i32 +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND1:%.*]], i32 [[SHL]], i32 1024 +; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 16, i32 [[SEL1]] +; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[SEL2]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %shl.res = shl i16 8, %y + %shl = zext i16 %shl.res to i32 + %sel1 = select i1 %cond1, i32 %shl, i32 1024 + %sel2 = select i1 %cond2, i32 16, i32 %sel1 + %r = mul nsw i32 %x, %sel2 + ret i32 %r +} + +define i32 @shift_if_power2_double_select_zext_shift_nsw(i32 %x, i16 %y, i1 %cond1, i1 %cond2) { +; CHECK-LABEL: @shift_if_power2_double_select_zext_shift_nsw( +; CHECK-NEXT: [[SHL_RES:%.*]] = shl nsw i16 8, [[Y:%.*]] +; CHECK-NEXT: [[SHL:%.*]] = zext i16 [[SHL_RES]] to i32 +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND1:%.*]], i32 [[SHL]], i32 1024 +; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 16, i32 [[SEL1]] +; CHECK-NEXT: [[R:%.*]] = mul nuw nsw i32 [[SEL2]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %shl.res = shl nsw i16 8, %y + %shl = zext i16 %shl.res to i32 + %sel1 = select i1 %cond1, i32 %shl, i32 1024 + %sel2 = select i1 %cond2, i32 16, i32 %sel1 + %r = mul nuw nsw i32 %x, %sel2 + ret i32 %r +} + +define i32 @shift_if_power2_zero(i32 %x, i1 %cond) { +; CHECK-LABEL: @shift_if_power2_zero( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 1, i32 4 +; CHECK-NEXT: [[R:%.*]] = mul i32 [[SEL]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %sel = select i1 %cond, i32 1, i32 4 + %r = mul i32 %sel, %x + ret i32 %r +} + +define <2 x i8> @shift_if_power2_vector(<2 x i8> %px, i1 %cond) { +; CHECK-LABEL: @shift_if_power2_vector( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> , <2 x i8> +; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[SEL]], [[PX:%.*]] +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %sel = select i1 %cond, <2 x i8> , <2 x i8> + %r = mul <2 x i8> %px, %sel + ret <2 x i8> %r +} + +define i32 @shift_if_extra_use(i32 %x, i1 %cond) { +; CHECK-LABEL: @shift_if_extra_use( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 4, i32 128 +; CHECK-NEXT: call void @use32(i32 [[SEL]]) +; CHECK-NEXT: [[R:%.*]] = mul i32 [[SEL]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %sel = select i1 %cond, i32 4, i32 128 + call void @use32(i32 %sel) + %r = mul i32 %sel, %x + ret i32 %r +} + +; Negative tests for power2 + +define i32 @shift_if_one_not_power2(i32 %x, i1 %cond) { +; CHECK-LABEL: @shift_if_one_not_power2( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 5, i32 4 +; CHECK-NEXT: [[R:%.*]] = mul i32 [[SEL]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %sel = select i1 %cond, i32 5, i32 4 + %r = mul i32 %sel, %x + ret i32 %r +} + +define i32 @shift_if_not_power2_double_select(i32 %x, i32 %y, i1 %cond1, i1 %cond2) { +; CHECK-LABEL: @shift_if_not_power2_double_select( +; CHECK-NEXT: [[SHL_RES:%.*]] = shl i32 7, [[Y:%.*]] +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND1:%.*]], i32 [[SHL_RES]], i32 1024 +; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 16, i32 [[SEL1]] +; CHECK-NEXT: [[R:%.*]] = mul nuw i32 [[SEL2]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %shl.res = shl i32 7, %y + %sel1 = select i1 %cond1, i32 %shl.res, i32 1024 + %sel2 = select i1 %cond2, i32 16, i32 %sel1 + %r = mul nuw i32 %x, %sel2 + ret i32 %r +} + +define <2 x i8> @shift_if_one_not_power2_vector(<2 x i8> %px, i1 %cond) { +; CHECK-LABEL: @shift_if_one_not_power2_vector( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> , <2 x i8> +; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[SEL]], [[PX:%.*]] +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %sel = select i1 %cond, <2 x i8> , <2 x i8> + %r = mul <2 x i8> %px, %sel + ret <2 x i8> %r +} + +; Undef select + mul tests + +define <2 x i8> @shift_if_undef_vector(<2 x i8> %px, i1 %cond) { +; CHECK-LABEL: @shift_if_undef_vector( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> , <2 x i8> +; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[SEL]], [[PX:%.*]] +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %sel = select i1 %cond, <2 x i8> , <2 x i8> + %r = mul <2 x i8> %px, %sel + ret <2 x i8> %r +} + +define <2 x i8> @shift_if_different_lanes_undef_vector(<2 x i8> %px, i1 %cond) { +; CHECK-LABEL: @shift_if_different_lanes_undef_vector( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> , <2 x i8> +; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[SEL]], [[PX:%.*]] +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %sel = select i1 %cond, <2 x i8> , <2 x i8> + %r = mul <2 x i8> %px, %sel + ret <2 x i8> %r +} + +define <2 x i8> @shift_if_same_lane_undef_vector(<2 x i8> %px, i1 %cond) { +; CHECK-LABEL: @shift_if_same_lane_undef_vector( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> , <2 x i8> +; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[SEL]], [[PX:%.*]] +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %sel = select i1 %cond, <2 x i8> , <2 x i8> + %r = mul <2 x i8> %px, %sel + ret <2 x i8> %r +}