[AArch64][GlobalISel] Select TBZ for icmp sge x, 0.
authorAmara Emerson <amara@apple.com>
Sat, 12 Nov 2022 03:54:39 +0000 (19:54 -0800)
committerAmara Emerson <amara@apple.com>
Sat, 12 Nov 2022 04:15:46 +0000 (20:15 -0800)
This results in some nice size improvements on -Os CTMark:
Program                                       size.__text
                                              sdag           gisel           diff
consumer-typeset/consumer-typeset             414124.00      414052.00      -0.0%
tramp3d-v4/tramp3d-v4                         356840.00      356732.00      -0.0%
lencod/lencod                                 427560.00      427396.00      -0.0%
7zip/7zip-benchmark                           568400.00      568172.00      -0.0%
Bullet/bullet                                 455660.00      455428.00      -0.1%
mafft/pairlocalalign                          248236.00      248040.00      -0.1%
sqlite3/sqlite3                               284404.00      284176.00      -0.1%
ClamAV/clamscan                               381052.00      380604.00      -0.1%
SPASS/SPASS                                   411932.00      411296.00      -0.2%
kimwitu++/kc                                  439696.00      438992.00      -0.2%
                           Geomean difference                               -0.1%

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
llvm/test/CodeGen/AArch64/GlobalISel/select-tbnz-from-cmp.mir [new file with mode: 0644]
llvm/test/CodeGen/AArch64/GlobalISel/tbnz-slt.mir [deleted file]

index bc9277f861be67261f65b79f465a1a774b27db99..f14f7c4bb45db97fb0e253aff33ee2f6ca8e48dd 100644 (file)
@@ -1682,6 +1682,15 @@ bool AArch64InstructionSelector::tryOptCompareBranchFedByICmp(
       I.eraseFromParent();
       return true;
     }
+
+    // Inversely, if we have a signed greater-than-or-equal comparison to zero,
+    // we can test if the msb is zero.
+    if (C == 0 && Pred == CmpInst::ICMP_SGE) {
+      uint64_t Bit = MRI.getType(LHS).getSizeInBits() - 1;
+      emitTestBit(LHS, Bit, /*IsNegative = */ false, DestMBB, MIB);
+      I.eraseFromParent();
+      return true;
+    }
   }
 
   // Attempt to handle commutative condition codes. Right now, that's only
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-tbnz-from-cmp.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-tbnz-from-cmp.mir
new file mode 100644 (file)
index 0000000..30db00a
--- /dev/null
@@ -0,0 +1,217 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple aarch64-unknown-unknown -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+#
+# Test that we can produce a TBNZ when we have a slt compare against 0.
+#
+# The bit tested should be the size of the test register minus 1.
+#
+
+...
+---
+name:            tbnzx_slt
+alignment:       4
+legalized:       true
+regBankSelected: true
+body:             |
+  ; CHECK-LABEL: name: tbnzx_slt
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   %copy:gpr64 = COPY $x0
+  ; CHECK-NEXT:   TBNZX %copy, 63, %bb.1
+  ; CHECK-NEXT:   B %bb.0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   RET_ReallyLR
+  bb.0:
+    successors: %bb.0, %bb.1
+    liveins: $x0
+    %copy:gpr(s64) = COPY $x0
+    %zero:gpr(s64) = G_CONSTANT i64 0
+    %cmp:gpr(s32) = G_ICMP intpred(slt), %copy(s64), %zero
+    G_BRCOND %cmp, %bb.1
+    G_BR %bb.0
+  bb.1:
+    RET_ReallyLR
+
+...
+---
+name:            tbnzw_slt
+alignment:       4
+legalized:       true
+regBankSelected: true
+body:             |
+  ; CHECK-LABEL: name: tbnzw_slt
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   %copy:gpr32 = COPY $w0
+  ; CHECK-NEXT:   TBNZW %copy, 31, %bb.1
+  ; CHECK-NEXT:   B %bb.0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   RET_ReallyLR
+  bb.0:
+    successors: %bb.0, %bb.1
+    liveins: $x0
+    %copy:gpr(s32) = COPY $w0
+    %zero:gpr(s32) = G_CONSTANT i32 0
+    %cmp:gpr(s32) = G_ICMP intpred(slt), %copy(s32), %zero
+    G_BRCOND %cmp, %bb.1
+    G_BR %bb.0
+  bb.1:
+    RET_ReallyLR
+
+...
+---
+name:            tbnzx_sge
+alignment:       4
+legalized:       true
+regBankSelected: true
+body:             |
+  ; CHECK-LABEL: name: tbnzx_sge
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   %copy:gpr64 = COPY $x0
+  ; CHECK-NEXT:   TBZX %copy, 63, %bb.1
+  ; CHECK-NEXT:   B %bb.0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   RET_ReallyLR
+  bb.0:
+    successors: %bb.0, %bb.1
+    liveins: $x0
+    %copy:gpr(s64) = COPY $x0
+    %zero:gpr(s64) = G_CONSTANT i64 0
+    %cmp:gpr(s32) = G_ICMP intpred(sge), %copy(s64), %zero
+    G_BRCOND %cmp, %bb.1
+    G_BR %bb.0
+  bb.1:
+    RET_ReallyLR
+
+...
+---
+name:            tbnzw_sge
+alignment:       4
+legalized:       true
+regBankSelected: true
+body:             |
+  ; CHECK-LABEL: name: tbnzw_sge
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   %copy:gpr32 = COPY $w0
+  ; CHECK-NEXT:   TBZW %copy, 31, %bb.1
+  ; CHECK-NEXT:   B %bb.0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   RET_ReallyLR
+  bb.0:
+    successors: %bb.0, %bb.1
+    liveins: $x0
+    %copy:gpr(s32) = COPY $w0
+    %zero:gpr(s32) = G_CONSTANT i32 0
+    %cmp:gpr(s32) = G_ICMP intpred(sge), %copy(s32), %zero
+    G_BRCOND %cmp, %bb.1
+    G_BR %bb.0
+  bb.1:
+    RET_ReallyLR
+
+...
+---
+name:            no_tbnz_not_zero
+alignment:       4
+legalized:       true
+regBankSelected: true
+body:             |
+  ; CHECK-LABEL: name: no_tbnz_not_zero
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   %copy:gpr32sp = COPY $w0
+  ; CHECK-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri %copy, 1, 0, implicit-def $nzcv
+  ; CHECK-NEXT:   Bcc 11, %bb.1, implicit $nzcv
+  ; CHECK-NEXT:   B %bb.0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   RET_ReallyLR
+  bb.0:
+    successors: %bb.0, %bb.1
+    liveins: $x0
+    %copy:gpr(s32) = COPY $w0
+    %one:gpr(s32) = G_CONSTANT i32 1
+    %cmp:gpr(s32) = G_ICMP intpred(slt), %copy(s32), %one
+    G_BRCOND %cmp, %bb.1
+    G_BR %bb.0
+  bb.1:
+    RET_ReallyLR
+
+...
+---
+name:            dont_fold_and
+alignment:       4
+legalized:       true
+regBankSelected: true
+body:             |
+  ; CHECK-LABEL: name: dont_fold_and
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   %copy:gpr64 = COPY $x0
+  ; CHECK-NEXT:   [[ANDSXri:%[0-9]+]]:gpr64 = ANDSXri %copy, 8000, implicit-def $nzcv
+  ; CHECK-NEXT:   Bcc 11, %bb.1, implicit $nzcv
+  ; CHECK-NEXT:   B %bb.0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   RET_ReallyLR
+  bb.0:
+    successors: %bb.0, %bb.1
+    liveins: $x0
+    %copy:gpr(s64) = COPY $x0
+    %bit:gpr(s64) = G_CONSTANT i64 8
+    %zero:gpr(s64) = G_CONSTANT i64 0
+    %c:gpr(s64) = G_CONSTANT i64 8
+    %and:gpr(s64) = G_AND %copy, %bit
+    %cmp:gpr(s32) = G_ICMP intpred(slt), %and(s64), %zero
+    G_BRCOND %cmp, %bb.1
+    G_BR %bb.0
+  bb.1:
+    RET_ReallyLR
+
+...
+---
+name:            dont_commute
+alignment:       4
+legalized:       true
+regBankSelected: true
+body:             |
+  ; CHECK-LABEL: name: dont_commute
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   %copy:gpr64 = COPY $x0
+  ; CHECK-NEXT:   %zero:gpr64 = COPY $xzr
+  ; CHECK-NEXT:   [[SUBSXrr:%[0-9]+]]:gpr64 = SUBSXrr %zero, %copy, implicit-def $nzcv
+  ; CHECK-NEXT:   Bcc 11, %bb.1, implicit $nzcv
+  ; CHECK-NEXT:   B %bb.0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   RET_ReallyLR
+  bb.0:
+    successors: %bb.0, %bb.1
+    liveins: $x0
+    %copy:gpr(s64) = COPY $x0
+    %zero:gpr(s64) = G_CONSTANT i64 0
+    %cmp:gpr(s32) = G_ICMP intpred(slt), %zero, %copy(s64)
+    G_BRCOND %cmp, %bb.1
+    G_BR %bb.0
+  bb.1:
+    RET_ReallyLR
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/tbnz-slt.mir b/llvm/test/CodeGen/AArch64/GlobalISel/tbnz-slt.mir
deleted file mode 100644 (file)
index ce87e73..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple aarch64-unknown-unknown -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
-#
-# Test that we can produce a TBNZ when we have a slt compare against 0.
-#
-# The bit tested should be the size of the test register minus 1.
-#
-
-...
----
-name:            tbnzx_slt
-alignment:       4
-legalized:       true
-regBankSelected: true
-body:             |
-  ; CHECK-LABEL: name: tbnzx_slt
-  ; CHECK: bb.0:
-  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
-  ; CHECK-NEXT:   liveins: $x0
-  ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %copy:gpr64 = COPY $x0
-  ; CHECK-NEXT:   TBNZX %copy, 63, %bb.1
-  ; CHECK-NEXT:   B %bb.0
-  ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT: bb.1:
-  ; CHECK-NEXT:   RET_ReallyLR
-  bb.0:
-    successors: %bb.0, %bb.1
-    liveins: $x0
-    %copy:gpr(s64) = COPY $x0
-    %zero:gpr(s64) = G_CONSTANT i64 0
-    %cmp:gpr(s32) = G_ICMP intpred(slt), %copy(s64), %zero
-    G_BRCOND %cmp, %bb.1
-    G_BR %bb.0
-  bb.1:
-    RET_ReallyLR
-
-...
----
-name:            tbnzw_slt
-alignment:       4
-legalized:       true
-regBankSelected: true
-body:             |
-  ; CHECK-LABEL: name: tbnzw_slt
-  ; CHECK: bb.0:
-  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
-  ; CHECK-NEXT:   liveins: $x0
-  ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %copy:gpr32 = COPY $w0
-  ; CHECK-NEXT:   TBNZW %copy, 31, %bb.1
-  ; CHECK-NEXT:   B %bb.0
-  ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT: bb.1:
-  ; CHECK-NEXT:   RET_ReallyLR
-  bb.0:
-    successors: %bb.0, %bb.1
-    liveins: $x0
-    %copy:gpr(s32) = COPY $w0
-    %zero:gpr(s32) = G_CONSTANT i32 0
-    %cmp:gpr(s32) = G_ICMP intpred(slt), %copy(s32), %zero
-    G_BRCOND %cmp, %bb.1
-    G_BR %bb.0
-  bb.1:
-    RET_ReallyLR
-
-...
----
-name:            no_tbnz_not_zero
-alignment:       4
-legalized:       true
-regBankSelected: true
-body:             |
-  ; CHECK-LABEL: name: no_tbnz_not_zero
-  ; CHECK: bb.0:
-  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
-  ; CHECK-NEXT:   liveins: $x0
-  ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %copy:gpr32sp = COPY $w0
-  ; CHECK-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri %copy, 1, 0, implicit-def $nzcv
-  ; CHECK-NEXT:   Bcc 11, %bb.1, implicit $nzcv
-  ; CHECK-NEXT:   B %bb.0
-  ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT: bb.1:
-  ; CHECK-NEXT:   RET_ReallyLR
-  bb.0:
-    successors: %bb.0, %bb.1
-    liveins: $x0
-    %copy:gpr(s32) = COPY $w0
-    %one:gpr(s32) = G_CONSTANT i32 1
-    %cmp:gpr(s32) = G_ICMP intpred(slt), %copy(s32), %one
-    G_BRCOND %cmp, %bb.1
-    G_BR %bb.0
-  bb.1:
-    RET_ReallyLR
-
-...
----
-name:            dont_fold_and
-alignment:       4
-legalized:       true
-regBankSelected: true
-body:             |
-  ; CHECK-LABEL: name: dont_fold_and
-  ; CHECK: bb.0:
-  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
-  ; CHECK-NEXT:   liveins: $x0
-  ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %copy:gpr64 = COPY $x0
-  ; CHECK-NEXT:   [[ANDSXri:%[0-9]+]]:gpr64 = ANDSXri %copy, 8000, implicit-def $nzcv
-  ; CHECK-NEXT:   Bcc 11, %bb.1, implicit $nzcv
-  ; CHECK-NEXT:   B %bb.0
-  ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT: bb.1:
-  ; CHECK-NEXT:   RET_ReallyLR
-  bb.0:
-    successors: %bb.0, %bb.1
-    liveins: $x0
-    %copy:gpr(s64) = COPY $x0
-    %bit:gpr(s64) = G_CONSTANT i64 8
-    %zero:gpr(s64) = G_CONSTANT i64 0
-    %c:gpr(s64) = G_CONSTANT i64 8
-    %and:gpr(s64) = G_AND %copy, %bit
-    %cmp:gpr(s32) = G_ICMP intpred(slt), %and(s64), %zero
-    G_BRCOND %cmp, %bb.1
-    G_BR %bb.0
-  bb.1:
-    RET_ReallyLR
-
-...
----
-name:            dont_commute
-alignment:       4
-legalized:       true
-regBankSelected: true
-body:             |
-  ; CHECK-LABEL: name: dont_commute
-  ; CHECK: bb.0:
-  ; CHECK-NEXT:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
-  ; CHECK-NEXT:   liveins: $x0
-  ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %copy:gpr64 = COPY $x0
-  ; CHECK-NEXT:   %zero:gpr64 = COPY $xzr
-  ; CHECK-NEXT:   [[SUBSXrr:%[0-9]+]]:gpr64 = SUBSXrr %zero, %copy, implicit-def $nzcv
-  ; CHECK-NEXT:   Bcc 11, %bb.1, implicit $nzcv
-  ; CHECK-NEXT:   B %bb.0
-  ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT: bb.1:
-  ; CHECK-NEXT:   RET_ReallyLR
-  bb.0:
-    successors: %bb.0, %bb.1
-    liveins: $x0
-    %copy:gpr(s64) = COPY $x0
-    %zero:gpr(s64) = G_CONSTANT i64 0
-    %cmp:gpr(s32) = G_ICMP intpred(slt), %zero, %copy(s64)
-    G_BRCOND %cmp, %bb.1
-    G_BR %bb.0
-  bb.1:
-    RET_ReallyLR