[llvm] [CodeGenPrepare] Unfold slow ctpop when used in power-of-two test (PR #102731)

Sergei Barannikov via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 19 22:25:48 PDT 2025


================
@@ -0,0 +1,99 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -p 'require<profile-summary>,function(codegenprepare)' -S %s \
+; RUN:   | FileCheck %s --check-prefix=SLOW
+; RUN: opt -p 'require<profile-summary>,function(codegenprepare)' -S --mattr=+zbb %s \
+; RUN:   | FileCheck %s --check-prefix=FAST
+; REQUIRES: riscv64-registered-target
+
+target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
+target triple = "riscv64"
+
+define i64 @test_ult_2(i64 %x, i64 %y, i64 %a, i64 %b) {
+; SLOW-LABEL: define i64 @test_ult_2(
+; SLOW-SAME: i64 [[X:%.*]], i64 [[Y:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
+; SLOW-NEXT:  [[ENTRY:.*]]:
+; SLOW-NEXT:    [[TMP0:%.*]] = add i64 [[X]], -1
+; SLOW-NEXT:    [[TMP1:%.*]] = and i64 [[X]], [[TMP0]]
+; SLOW-NEXT:    [[CMP1:%.*]] = icmp ne i64 [[TMP1]], 0
+; SLOW-NEXT:    [[CMP2:%.*]] = icmp sgt i64 [[Y]], 0
+; SLOW-NEXT:    [[CMP:%.*]] = or i1 [[CMP2]], [[CMP1]]
+; SLOW-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+; SLOW:       [[IF_THEN]]:
+; SLOW-NEXT:    br label %[[IF_END]]
+; SLOW:       [[IF_END]]:
+; SLOW-NEXT:    [[RES:%.*]] = phi i64 [ [[A]], %[[IF_THEN]] ], [ [[B]], %[[ENTRY]] ]
+; SLOW-NEXT:    ret i64 [[RES]]
+;
+; FAST-LABEL: define i64 @test_ult_2(
+; FAST-SAME: i64 [[X:%.*]], i64 [[Y:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0:[0-9]+]] {
+; FAST-NEXT:  [[ENTRY:.*]]:
+; FAST-NEXT:    [[CTPOP:%.*]] = call i64 @llvm.ctpop.i64(i64 [[X]])
+; FAST-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[CTPOP]], 1
+; FAST-NEXT:    [[CMP2:%.*]] = icmp sgt i64 [[Y]], 0
+; FAST-NEXT:    [[CMP:%.*]] = or i1 [[CMP2]], [[CMP1]]
+; FAST-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+; FAST:       [[IF_THEN]]:
+; FAST-NEXT:    br label %[[IF_END]]
+; FAST:       [[IF_END]]:
+; FAST-NEXT:    [[RES:%.*]] = phi i64 [ [[A]], %[[IF_THEN]] ], [ [[B]], %[[ENTRY]] ]
+; FAST-NEXT:    ret i64 [[RES]]
+;
+entry:
+  %ctpop = call i64 @llvm.ctpop.i64(i64 %x)
+  %cmp1 = icmp ugt i64 %ctpop, 1
+  %cmp2 = icmp sgt i64 %y, 0
+  %cmp = or i1 %cmp2, %cmp1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  br label %if.end
+
+if.end:
+  %res = phi i64 [ %a, %if.then ], [ %b, %entry ]
+  ret i64 %res
+}
+
+define i64 @test_ugt_1(i64 %x, i64 %y, i64 %a, i64 %b) {
+; SLOW-LABEL: define i64 @test_ugt_1(
+; SLOW-SAME: i64 [[X:%.*]], i64 [[Y:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
+; SLOW-NEXT:  [[ENTRY:.*]]:
+; SLOW-NEXT:    [[TMP0:%.*]] = add i64 [[X]], -1
+; SLOW-NEXT:    [[TMP1:%.*]] = and i64 [[X]], [[TMP0]]
+; SLOW-NEXT:    [[CMP1:%.*]] = icmp ne i64 [[TMP1]], 0
+; SLOW-NEXT:    [[CMP2:%.*]] = icmp sgt i64 [[Y]], 0
+; SLOW-NEXT:    [[CMP:%.*]] = or i1 [[CMP2]], [[CMP1]]
+; SLOW-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+; SLOW:       [[IF_THEN]]:
+; SLOW-NEXT:    br label %[[IF_END]]
+; SLOW:       [[IF_END]]:
+; SLOW-NEXT:    [[RES:%.*]] = phi i64 [ [[A]], %[[IF_THEN]] ], [ [[B]], %[[ENTRY]] ]
+; SLOW-NEXT:    ret i64 [[RES]]
+;
+; FAST-LABEL: define i64 @test_ugt_1(
+; FAST-SAME: i64 [[X:%.*]], i64 [[Y:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] {
+; FAST-NEXT:  [[ENTRY:.*]]:
+; FAST-NEXT:    [[CTPOP:%.*]] = call i64 @llvm.ctpop.i64(i64 [[X]])
+; FAST-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[CTPOP]], 1
+; FAST-NEXT:    [[CMP2:%.*]] = icmp sgt i64 [[Y]], 0
+; FAST-NEXT:    [[CMP:%.*]] = or i1 [[CMP2]], [[CMP1]]
+; FAST-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+; FAST:       [[IF_THEN]]:
+; FAST-NEXT:    br label %[[IF_END]]
+; FAST:       [[IF_END]]:
+; FAST-NEXT:    [[RES:%.*]] = phi i64 [ [[A]], %[[IF_THEN]] ], [ [[B]], %[[ENTRY]] ]
+; FAST-NEXT:    ret i64 [[RES]]
+;
+entry:
+  %ctpop = call i64 @llvm.ctpop.i64(i64 %x)
+  %cmp1 = icmp ugt i64 %ctpop, 1
+  %cmp2 = icmp sgt i64 %y, 0
+  %cmp = or i1 %cmp2, %cmp1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  br label %if.end
+
+if.end:
+  %res = phi i64 [ %a, %if.then ], [ %b, %entry ]
+  ret i64 %res
+}
----------------
s-barannikov wrote:

Forgot to add `==1` / `!= 1` tests, will do.


https://github.com/llvm/llvm-project/pull/102731


More information about the llvm-commits mailing list