@@ -4430,4 +4430,88 @@ define i32 @ceil_div_wrong_cmp(i32 range(i32 0, 100) %x) {
44304430 %r = add i32 %shr , %ext
44314431 ret i32 %r
44324432}
4433+
4434+ ; Multi-use test: all intermediate values have uses
4435+ define i32 @ceil_div_multi_use (i32 range(i32 0 , 100 ) %x ) {
4436+ ; CHECK-LABEL: @ceil_div_multi_use(
4437+ ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 3
4438+ ; CHECK-NEXT: call void @use_i32(i32 [[SHR]])
4439+ ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 7
4440+ ; CHECK-NEXT: call void @use_i32(i32 [[AND]])
4441+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
4442+ ; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[CMP]] to i32
4443+ ; CHECK-NEXT: call void @use_i32(i32 [[EXT]])
4444+ ; CHECK-NEXT: [[R:%.*]] = add nuw nsw i32 [[SHR]], [[EXT]]
4445+ ; CHECK-NEXT: ret i32 [[R]]
4446+ ;
4447+ %shr = lshr i32 %x , 3
4448+ call void @use_i32 (i32 %shr )
4449+ %and = and i32 %x , 7
4450+ call void @use_i32 (i32 %and )
4451+ %cmp = icmp ne i32 %and , 0
4452+ %ext = zext i1 %cmp to i32
4453+ call void @use_i32 (i32 %ext )
4454+ %r = add i32 %shr , %ext
4455+ ret i32 %r
4456+ }
4457+
4458+ ; Commuted test: add operands are swapped
4459+ define i32 @ceil_div_commuted (i32 range(i32 0 , 100 ) %x ) {
4460+ ; CHECK-LABEL: @ceil_div_commuted(
4461+ ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[X:%.*]], 7
4462+ ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[TMP1]], 3
4463+ ; CHECK-NEXT: ret i32 [[R]]
4464+ ;
4465+ %shr = lshr i32 %x , 3
4466+ %and = and i32 %x , 7
4467+ %cmp = icmp ne i32 %and , 0
4468+ %ext = zext i1 %cmp to i32
4469+ %r = add i32 %ext , %shr ; Operands swapped
4470+ ret i32 %r
4471+ }
4472+
4473+ ; Commuted with multi-use
4474+ define i32 @ceil_div_commuted_multi_use (i32 range(i32 0 , 100 ) %x ) {
4475+ ; CHECK-LABEL: @ceil_div_commuted_multi_use(
4476+ ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 3
4477+ ; CHECK-NEXT: call void @use_i32(i32 [[SHR]])
4478+ ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 7
4479+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
4480+ ; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[CMP]] to i32
4481+ ; CHECK-NEXT: call void @use_i32(i32 [[EXT]])
4482+ ; CHECK-NEXT: [[R:%.*]] = add nuw nsw i32 [[SHR]], [[EXT]]
4483+ ; CHECK-NEXT: ret i32 [[R]]
4484+ ;
4485+ %shr = lshr i32 %x , 3
4486+ call void @use_i32 (i32 %shr )
4487+ %and = and i32 %x , 7
4488+ %cmp = icmp ne i32 %and , 0
4489+ %ext = zext i1 %cmp to i32
4490+ call void @use_i32 (i32 %ext )
4491+ %r = add i32 %ext , %shr ; Operands swapped
4492+ ret i32 %r
4493+ }
4494+
4495+ ; Multi-use with vector type
4496+ define <2 x i32 > @ceil_div_vec_multi_use (<2 x i32 > range(i32 0 , 1000 ) %x ) {
4497+ ; CHECK-LABEL: @ceil_div_vec_multi_use(
4498+ ; CHECK-NEXT: [[SHR:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 3)
4499+ ; CHECK-NEXT: call void @use_vec(<2 x i32> [[SHR]])
4500+ ; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X]], splat (i32 7)
4501+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[AND]], zeroinitializer
4502+ ; CHECK-NEXT: [[EXT:%.*]] = zext <2 x i1> [[CMP]] to <2 x i32>
4503+ ; CHECK-NEXT: [[R:%.*]] = add nuw nsw <2 x i32> [[SHR]], [[EXT]]
4504+ ; CHECK-NEXT: ret <2 x i32> [[R]]
4505+ ;
4506+ %shr = lshr <2 x i32 > %x , <i32 3 , i32 3 >
4507+ call void @use_vec (<2 x i32 > %shr )
4508+ %and = and <2 x i32 > %x , <i32 7 , i32 7 >
4509+ %cmp = icmp ne <2 x i32 > %and , <i32 0 , i32 0 >
4510+ %ext = zext <2 x i1 > %cmp to <2 x i32 >
4511+ %r = add <2 x i32 > %shr , %ext
4512+ ret <2 x i32 > %r
4513+ }
4514+
4515+ declare void @use_i32 (i32 )
4516+ declare void @use_vec (<2 x i32 >)
44334517declare void @fake_func (i32 )
0 commit comments