diff --git a/llvm/test/Transforms/InstCombine/bit_ceil.ll b/llvm/test/Transforms/InstCombine/bit_ceil.ll index 440ab3d697e59d..aa98896aac5493 100644 --- a/llvm/test/Transforms/InstCombine/bit_ceil.ll +++ b/llvm/test/Transforms/InstCombine/bit_ceil.ll @@ -1,6 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s +; std::bit_ceil(x) define i32 @bit_ceil_32(i32 %x) { ; CHECK-LABEL: @bit_ceil_32( ; CHECK-NEXT: [[DEC:%.*]] = add i32 [[X:%.*]], -1 @@ -20,6 +21,7 @@ define i32 @bit_ceil_32(i32 %x) { ret i32 %sel } +; std::bit_ceil(x) define i64 @bit_ceil_64(i64 %x) { ; CHECK-LABEL: @bit_ceil_64( ; CHECK-NEXT: [[DEC:%.*]] = add i64 [[X:%.*]], -1 @@ -39,5 +41,116 @@ define i64 @bit_ceil_64(i64 %x) { ret i64 %sel } +; std::bit_ceil(x - 1) +define i32 @bit_ceil_32_minus_1(i32 %x) { +; CHECK-LABEL: @bit_ceil_32_minus_1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X:%.*]], -2 +; CHECK-NEXT: [[CTLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[SUB]], i1 false), !range [[RNG0]] +; CHECK-NEXT: [[SUB2:%.*]] = sub nuw nsw i32 32, [[CTLZ]] +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[SUB2]] +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], -3 +; CHECK-NEXT: [[ULT:%.*]] = icmp ult i32 [[ADD]], -2 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ULT]], i32 [[SHL]], i32 1 +; CHECK-NEXT: ret i32 [[SEL]] +; +entry: + %sub = add i32 %x, -2 + %ctlz = tail call i32 @llvm.ctlz.i32(i32 %sub, i1 false) + %sub2 = sub nuw nsw i32 32, %ctlz + %shl = shl nuw i32 1, %sub2 + %add = add i32 %x, -3 + %ult = icmp ult i32 %add, -2 + %sel = select i1 %ult, i32 %shl, i32 1 + ret i32 %sel +} + +; std::bit_ceil(x + 1) +define i32 @bit_ceil_32_plus_1(i32 %x) { +; CHECK-LABEL: @bit_ceil_32_plus_1( +; CHECK-NEXT: [[CTLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false), !range [[RNG0]] +; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 32, [[CTLZ]] +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[SUB]] +; CHECK-NEXT: [[DEC:%.*]] = add i32 [[X]], -1 +; CHECK-NEXT: [[ULT:%.*]] = icmp ult i32 [[DEC]], -2 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ULT]], i32 [[SHL]], i32 1 +; CHECK-NEXT: ret i32 [[SEL]] +; + %ctlz = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false) + %sub = sub i32 32, %ctlz + %shl = shl i32 1, %sub + %dec = add i32 %x, -1 + %ult = icmp ult i32 %dec, -2 + %sel = select i1 %ult, i32 %shl, i32 1 + ret i32 %sel +} + +define i32 @bit_ceil_plus_2(i32 %x) { +; CHECK-LABEL: @bit_ceil_plus_2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X:%.*]], 1 +; CHECK-NEXT: [[CTLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[SUB]], i1 false), !range [[RNG0]] +; CHECK-NEXT: [[SUB2:%.*]] = sub nuw nsw i32 32, [[CTLZ]] +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[SUB2]] +; CHECK-NEXT: [[ULT:%.*]] = icmp ult i32 [[X]], -2 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ULT]], i32 [[SHL]], i32 1 +; CHECK-NEXT: ret i32 [[SEL]] +; +entry: + %sub = add i32 %x, 1 + %ctlz = tail call i32 @llvm.ctlz.i32(i32 %sub, i1 false) + %sub2 = sub nuw nsw i32 32, %ctlz + %shl = shl nuw i32 1, %sub2 + %ult = icmp ult i32 %x, -2 + %sel = select i1 %ult, i32 %shl, i32 1 + ret i32 %sel +} + +; std::bit_ceil(-x) +define i32 @bit_ceil_32_neg(i32 %x) { +; CHECK-LABEL: @bit_ceil_32_neg( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB:%.*]] = xor i32 [[X:%.*]], -1 +; CHECK-NEXT: [[CTLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[SUB]], i1 false), !range [[RNG0]] +; CHECK-NEXT: [[SUB2:%.*]] = sub nuw nsw i32 32, [[CTLZ]] +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[SUB2]] +; CHECK-NEXT: [[NOTSUB:%.*]] = add i32 [[X]], -1 +; CHECK-NEXT: [[ULT:%.*]] = icmp ult i32 [[NOTSUB]], -2 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ULT]], i32 [[SHL]], i32 1 +; CHECK-NEXT: ret i32 [[SEL]] +; +entry: + %sub = xor i32 %x, -1 + %ctlz = tail call i32 @llvm.ctlz.i32(i32 %sub, i1 false) + %sub2 = sub nuw nsw i32 32, %ctlz + %shl = shl nuw i32 1, %sub2 + %notsub = add i32 %x, -1 + %ult = icmp ult i32 %notsub, -2 + %sel = select i1 %ult, i32 %shl, i32 1 + ret i32 %sel +} + +; std::bit_ceil(~x) +define i32 @bit_ceil_not(i32 %x) { +; CHECK-LABEL: @bit_ceil_not( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB:%.*]] = sub i32 -2, [[X:%.*]] +; CHECK-NEXT: [[CTLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[SUB]], i1 false), !range [[RNG0]] +; CHECK-NEXT: [[SUB2:%.*]] = sub nuw nsw i32 32, [[CTLZ]] +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[SUB2]] +; CHECK-NEXT: [[ULT:%.*]] = icmp ult i32 [[X]], -2 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ULT]], i32 [[SHL]], i32 1 +; CHECK-NEXT: ret i32 [[SEL]] +; +entry: + %sub = sub i32 -2, %x + %ctlz = tail call i32 @llvm.ctlz.i32(i32 %sub, i1 false) + %sub2 = sub nuw nsw i32 32, %ctlz + %shl = shl nuw i32 1, %sub2 + %ult = icmp ult i32 %x, -2 + %sel = select i1 %ult, i32 %shl, i32 1 + ret i32 %sel +} + declare i32 @llvm.ctlz.i32(i32, i1 immarg) declare i64 @llvm.ctlz.i64(i64, i1 immarg)