Skip to content

Commit e31f28d

Browse files
committed
[InstCombine] Fold (ct{t,l}z Pow2) -> Log2(Pow2)
Do so we can find `Log2(Pow2)` for "free" with `takeLog2`
1 parent b00d3bf commit e31f28d

File tree

2 files changed

+22
-10
lines changed

2 files changed

+22
-10
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,22 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
588588
}
589589
}
590590

591+
// cttz(Pow2) -> Log2(Pow2)
592+
// ctlz(Pow2) -> BitWidth - 1 - Log2(Pow2)
593+
if (IsTZ || II.hasOneUse()) {
594+
if (auto *R = IC.tryGetLog2(Op0, match(Op1, m_One()))) {
595+
if (IsTZ)
596+
return IC.replaceInstUsesWith(II, R);
597+
BinaryOperator *BO = BinaryOperator::CreateSub(
598+
ConstantInt::get(R->getType(),
599+
R->getType()->getScalarSizeInBits() - 1),
600+
R);
601+
BO->setHasNoSignedWrap();
602+
BO->setHasNoUnsignedWrap();
603+
return BO;
604+
}
605+
}
606+
591607
KnownBits Known = IC.computeKnownBits(Op0, 0, &II);
592608

593609
// Create a mask for bits above (ctlz) or below (cttz) the first known one.

llvm/test/Transforms/InstCombine/cttz.ll

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,7 @@ define i16 @cttz_assume(i16 %x) {
302302
declare void @use.i8(i8)
303303
define i8 @fold_ctz_log2(i8 %x) {
304304
; CHECK-LABEL: @fold_ctz_log2(
305-
; CHECK-NEXT: [[P2:%.*]] = shl nuw i8 1, [[X:%.*]]
306-
; CHECK-NEXT: [[V:%.*]] = call i8 @llvm.umin.i8(i8 [[P2]], i8 32)
307-
; CHECK-NEXT: [[R:%.*]] = call range(i8 0, 9) i8 @llvm.cttz.i8(i8 [[V]], i1 true)
305+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 5)
308306
; CHECK-NEXT: ret i8 [[R]]
309307
;
310308
%p2 = shl i8 1, %x
@@ -343,11 +341,10 @@ define i8 @fold_ctz_log2_maybe_z(i8 %x, i8 %y, i1 %c) {
343341

344342
define i8 @fold_ctz_log2_maybe_z_okay(i8 %x, i8 %y, i1 %c) {
345343
; CHECK-LABEL: @fold_ctz_log2_maybe_z_okay(
346-
; CHECK-NEXT: [[X:%.*]] = shl i8 2, [[X1:%.*]]
347-
; CHECK-NEXT: [[Y:%.*]] = shl i8 4, [[Y1:%.*]]
344+
; CHECK-NEXT: [[X:%.*]] = add i8 [[X1:%.*]], 1
345+
; CHECK-NEXT: [[Y:%.*]] = add i8 [[Y1:%.*]], 2
348346
; CHECK-NEXT: [[V_V:%.*]] = select i1 [[C:%.*]], i8 [[X]], i8 [[Y]]
349-
; CHECK-NEXT: [[R:%.*]] = call range(i8 1, 9) i8 @llvm.cttz.i8(i8 [[V_V]], i1 true)
350-
; CHECK-NEXT: ret i8 [[R]]
347+
; CHECK-NEXT: ret i8 [[V_V]]
351348
;
352349
%p2 = shl i8 2, %x
353350
%p2_2 = shl i8 4, %y
@@ -358,9 +355,8 @@ define i8 @fold_ctz_log2_maybe_z_okay(i8 %x, i8 %y, i1 %c) {
358355

359356
define i8 @fold_clz_log2(i8 %x) {
360357
; CHECK-LABEL: @fold_clz_log2(
361-
; CHECK-NEXT: [[P2:%.*]] = shl nuw i8 1, [[X:%.*]]
362-
; CHECK-NEXT: [[V:%.*]] = call i8 @llvm.umin.i8(i8 [[P2]], i8 32)
363-
; CHECK-NEXT: [[R:%.*]] = call range(i8 2, 9) i8 @llvm.ctlz.i8(i8 [[V]], i1 true)
358+
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 5)
359+
; CHECK-NEXT: [[R:%.*]] = xor i8 [[TMP1]], 7
364360
; CHECK-NEXT: ret i8 [[R]]
365361
;
366362
%p2 = shl i8 1, %x

0 commit comments

Comments
 (0)