; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -mtriple=x86_64-- -expand-ir-insts -expand-div-rem-bits 0 < %s | FileCheck %s ; RUN: opt -S -mtriple=x86_64-- -passes='require,expand-ir-insts' -expand-div-rem-bits 0 < %s | FileCheck %s ; Test power-of-2 division/remainder expansion. ;--- udiv --- define i32 @udiv_by_8(i32 %x) { ; CHECK-LABEL: @udiv_by_8( ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[X:%.*]], 3 ; CHECK-NEXT: ret i32 [[R]] ; %r = udiv i32 %x, 8 ret i32 %r } define i32 @udiv_by_1(i32 %x) { ; CHECK-LABEL: @udiv_by_1( ; CHECK-NEXT: ret i32 [[X:%.*]] ; %r = udiv i32 %x, 1 ret i32 %r } define i32 @udiv_exact_by_8(i32 %x) { ; CHECK-LABEL: @udiv_exact_by_8( ; CHECK-NEXT: [[R:%.*]] = lshr exact i32 [[X:%.*]], 3 ; CHECK-NEXT: ret i32 [[R]] ; %r = udiv exact i32 %x, 8 ret i32 %r } ;--- sdiv --- define i32 @sdiv_by_8(i32 %x) { ; CHECK-LABEL: @sdiv_by_8( ; CHECK-NEXT: [[X:%.*]] = freeze i32 [[X1:%.*]] ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X]], 31 ; CHECK-NEXT: [[BIAS:%.*]] = lshr i32 [[SIGN]], 29 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i32 [[X]], [[BIAS]] ; CHECK-NEXT: [[R:%.*]] = ashr i32 [[ADJUSTED]], 3 ; CHECK-NEXT: ret i32 [[R]] ; %r = sdiv i32 %x, 8 ret i32 %r } define i32 @sdiv_by_neg8(i32 %x) { ; CHECK-LABEL: @sdiv_by_neg8( ; CHECK-NEXT: [[X:%.*]] = freeze i32 [[X1:%.*]] ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X]], 31 ; CHECK-NEXT: [[BIAS:%.*]] = lshr i32 [[SIGN]], 29 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i32 [[X]], [[BIAS]] ; CHECK-NEXT: [[PRE_NEG:%.*]] = ashr i32 [[ADJUSTED]], 3 ; CHECK-NEXT: [[R:%.*]] = sub i32 0, [[PRE_NEG]] ; CHECK-NEXT: ret i32 [[R]] ; %r = sdiv i32 %x, -8 ret i32 %r } define i32 @sdiv_by_2(i32 %x) { ; CHECK-LABEL: @sdiv_by_2( ; CHECK-NEXT: [[X:%.*]] = freeze i32 [[X1:%.*]] ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X]], 31 ; CHECK-NEXT: [[BIAS:%.*]] = lshr i32 [[SIGN]], 31 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i32 [[X]], [[BIAS]] ; CHECK-NEXT: [[R:%.*]] = ashr i32 [[ADJUSTED]], 1 ; CHECK-NEXT: ret i32 [[R]] ; %r = sdiv i32 %x, 2 ret i32 %r } define i32 @sdiv_by_1(i32 %x) { ; CHECK-LABEL: @sdiv_by_1( ; CHECK-NEXT: ret i32 [[X:%.*]] ; %r = sdiv i32 %x, 1 ret i32 %r } define i32 @sdiv_by_neg1(i32 %x) { ; CHECK-LABEL: @sdiv_by_neg1( ; CHECK-NEXT: [[R:%.*]] = sub i32 0, [[X:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %r = sdiv i32 %x, -1 ret i32 %r } define i32 @sdiv_exact_by_8(i32 %x) { ; CHECK-LABEL: @sdiv_exact_by_8( ; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[X:%.*]], 3 ; CHECK-NEXT: ret i32 [[R]] ; %r = sdiv exact i32 %x, 8 ret i32 %r } define i32 @sdiv_exact_by_neg8(i32 %x) { ; CHECK-LABEL: @sdiv_exact_by_neg8( ; CHECK-NEXT: [[PRE_NEG:%.*]] = ashr exact i32 [[X:%.*]], 3 ; CHECK-NEXT: [[R:%.*]] = sub i32 0, [[PRE_NEG]] ; CHECK-NEXT: ret i32 [[R]] ; %r = sdiv exact i32 %x, -8 ret i32 %r } define i32 @sdiv_exact_by_2(i32 %x) { ; CHECK-LABEL: @sdiv_exact_by_2( ; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[X:%.*]], 1 ; CHECK-NEXT: ret i32 [[R]] ; %r = sdiv exact i32 %x, 2 ret i32 %r } define i32 @sdiv_by_intmin(i32 %x) { ; CHECK-LABEL: @sdiv_by_intmin( ; CHECK-NEXT: [[X:%.*]] = freeze i32 [[X1:%.*]] ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X]], 31 ; CHECK-NEXT: [[BIAS:%.*]] = lshr i32 [[SIGN]], 1 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i32 [[X]], [[BIAS]] ; CHECK-NEXT: [[PRE_NEG:%.*]] = ashr i32 [[ADJUSTED]], 31 ; CHECK-NEXT: [[R:%.*]] = sub i32 0, [[PRE_NEG]] ; CHECK-NEXT: ret i32 [[R]] ; %r = sdiv i32 %x, -2147483648 ret i32 %r } define i32 @sdiv_large_pow2(i32 %x) { ; CHECK-LABEL: @sdiv_large_pow2( ; CHECK-NEXT: [[X:%.*]] = freeze i32 [[X1:%.*]] ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X]], 31 ; CHECK-NEXT: [[BIAS:%.*]] = lshr i32 [[SIGN]], 16 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i32 [[X]], [[BIAS]] ; CHECK-NEXT: [[R:%.*]] = ashr i32 [[ADJUSTED]], 16 ; CHECK-NEXT: ret i32 [[R]] ; %r = sdiv i32 %x, 65536 ret i32 %r } ;--- urem --- define i32 @urem_by_8(i32 %x) { ; CHECK-LABEL: @urem_by_8( ; CHECK-NEXT: [[R:%.*]] = and i32 [[X:%.*]], 7 ; CHECK-NEXT: ret i32 [[R]] ; %r = urem i32 %x, 8 ret i32 %r } define i32 @urem_by_1(i32 %x) { ; CHECK-LABEL: @urem_by_1( ; CHECK-NEXT: ret i32 0 ; %r = urem i32 %x, 1 ret i32 %r } ;--- srem --- define i32 @srem_by_8(i32 %x) { ; CHECK-LABEL: @srem_by_8( ; CHECK-NEXT: [[X:%.*]] = freeze i32 [[X1:%.*]] ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X]], 31 ; CHECK-NEXT: [[BIAS:%.*]] = lshr i32 [[SIGN]], 29 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i32 [[X]], [[BIAS]] ; CHECK-NEXT: [[SHIFTED:%.*]] = ashr i32 [[ADJUSTED]], 3 ; CHECK-NEXT: [[TRUNCATED:%.*]] = shl i32 [[SHIFTED]], 3 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[X]], [[TRUNCATED]] ; CHECK-NEXT: ret i32 [[R]] ; %r = srem i32 %x, 8 ret i32 %r } define i32 @srem_by_neg8(i32 %x) { ; CHECK-LABEL: @srem_by_neg8( ; CHECK-NEXT: [[X:%.*]] = freeze i32 [[X1:%.*]] ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X]], 31 ; CHECK-NEXT: [[BIAS:%.*]] = lshr i32 [[SIGN]], 29 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i32 [[X]], [[BIAS]] ; CHECK-NEXT: [[SHIFTED:%.*]] = ashr i32 [[ADJUSTED]], 3 ; CHECK-NEXT: [[TRUNCATED:%.*]] = shl i32 [[SHIFTED]], 3 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[X]], [[TRUNCATED]] ; CHECK-NEXT: ret i32 [[R]] ; %r = srem i32 %x, -8 ret i32 %r } define i32 @srem_by_2(i32 %x) { ; CHECK-LABEL: @srem_by_2( ; CHECK-NEXT: [[X:%.*]] = freeze i32 [[X1:%.*]] ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X]], 31 ; CHECK-NEXT: [[BIAS:%.*]] = lshr i32 [[SIGN]], 31 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i32 [[X]], [[BIAS]] ; CHECK-NEXT: [[SHIFTED:%.*]] = ashr i32 [[ADJUSTED]], 1 ; CHECK-NEXT: [[TRUNCATED:%.*]] = shl i32 [[SHIFTED]], 1 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[X]], [[TRUNCATED]] ; CHECK-NEXT: ret i32 [[R]] ; %r = srem i32 %x, 2 ret i32 %r } define i32 @srem_by_1(i32 %x) { ; CHECK-LABEL: @srem_by_1( ; CHECK-NEXT: ret i32 0 ; %r = srem i32 %x, 1 ret i32 %r } define i32 @srem_by_neg1(i32 %x) { ; CHECK-LABEL: @srem_by_neg1( ; CHECK-NEXT: ret i32 0 ; %r = srem i32 %x, -1 ret i32 %r } define i32 @srem_by_intmin(i32 %x) { ; CHECK-LABEL: @srem_by_intmin( ; CHECK-NEXT: [[X:%.*]] = freeze i32 [[X1:%.*]] ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X]], 31 ; CHECK-NEXT: [[BIAS:%.*]] = lshr i32 [[SIGN]], 1 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i32 [[X]], [[BIAS]] ; CHECK-NEXT: [[SHIFTED:%.*]] = ashr i32 [[ADJUSTED]], 31 ; CHECK-NEXT: [[TRUNCATED:%.*]] = shl i32 [[SHIFTED]], 31 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[X]], [[TRUNCATED]] ; CHECK-NEXT: ret i32 [[R]] ; %r = srem i32 %x, -2147483648 ret i32 %r } define i32 @srem_large_pow2(i32 %x) { ; CHECK-LABEL: @srem_large_pow2( ; CHECK-NEXT: [[X:%.*]] = freeze i32 [[X1:%.*]] ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X]], 31 ; CHECK-NEXT: [[BIAS:%.*]] = lshr i32 [[SIGN]], 16 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i32 [[X]], [[BIAS]] ; CHECK-NEXT: [[SHIFTED:%.*]] = ashr i32 [[ADJUSTED]], 16 ; CHECK-NEXT: [[TRUNCATED:%.*]] = shl i32 [[SHIFTED]], 16 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[X]], [[TRUNCATED]] ; CHECK-NEXT: ret i32 [[R]] ; %r = srem i32 %x, 65536 ret i32 %r }