[llvm] [DAGCombiner] Inverse transform `(select c, (and X, 1), 0)` -> `(and (zext c), X)` (PR #66793)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 21 06:51:28 PDT 2023
https://github.com/goldsteinn updated https://github.com/llvm/llvm-project/pull/66793
>From a39f0e6164af8ae795693e114a65af256a5fa252 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Tue, 19 Sep 2023 12:07:10 -0500
Subject: [PATCH 1/2] [X86][AArch64][RISCV] Add tests for combining `(select c,
(and X, 1), 0)` -> `(and (zext c), X)`; NFC
---
.../CodeGen/AArch64/select-to-and-zext.ll | 91 +++++++++
llvm/test/CodeGen/RISCV/select-to-and-zext.ll | 152 ++++++++++++++
llvm/test/CodeGen/X86/select-to-and-zext.ll | 189 ++++++++++++++++++
3 files changed, 432 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/select-to-and-zext.ll
create mode 100644 llvm/test/CodeGen/RISCV/select-to-and-zext.ll
create mode 100644 llvm/test/CodeGen/X86/select-to-and-zext.ll
diff --git a/llvm/test/CodeGen/AArch64/select-to-and-zext.ll b/llvm/test/CodeGen/AArch64/select-to-and-zext.ll
new file mode 100644
index 000000000000000..9773108e596705d
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/select-to-and-zext.ll
@@ -0,0 +1,91 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=aarch64-none-elf -verify-machineinstrs %s -o - | FileCheck %s
+
+define i32 @from_cmpeq(i32 %xx, i32 %y) {
+; CHECK-LABEL: from_cmpeq:
+; CHECK: // %bb.0:
+; CHECK-NEXT: and w8, w1, #0x1
+; CHECK-NEXT: cmp w0, #9
+; CHECK-NEXT: csel w0, w8, wzr, eq
+; CHECK-NEXT: ret
+ %x = icmp eq i32 %xx, 9
+ %masked = and i32 %y, 1
+
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_cmpeq_fail_bad_andmask(i32 %xx, i32 %y) {
+; CHECK-LABEL: from_cmpeq_fail_bad_andmask:
+; CHECK: // %bb.0:
+; CHECK-NEXT: and w8, w1, #0x3
+; CHECK-NEXT: cmp w0, #9
+; CHECK-NEXT: csel w0, w8, wzr, eq
+; CHECK-NEXT: ret
+ %x = icmp eq i32 %xx, 9
+ %masked = and i32 %y, 3
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_i1(i1 %x, i32 %y) {
+; CHECK-LABEL: from_i1:
+; CHECK: // %bb.0:
+; CHECK-NEXT: and w8, w1, #0x1
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csel w0, w8, wzr, ne
+; CHECK-NEXT: ret
+ %masked = and i32 %y, 1
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_trunc_i8(i8 %xx, i32 %y) {
+; CHECK-LABEL: from_trunc_i8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: and w8, w1, #0x1
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csel w0, w8, wzr, ne
+; CHECK-NEXT: ret
+ %masked = and i32 %y, 1
+ %x = trunc i8 %xx to i1
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_trunc_i64(i64 %xx, i32 %y) {
+; CHECK-LABEL: from_trunc_i64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: and w8, w1, #0x1
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csel w0, w8, wzr, ne
+; CHECK-NEXT: ret
+ %masked = and i32 %y, 1
+ %x = trunc i64 %xx to i1
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_i1_fail_bad_select0(i1 %x, i32 %y) {
+; CHECK-LABEL: from_i1_fail_bad_select0:
+; CHECK: // %bb.0:
+; CHECK-NEXT: and w8, w1, #0x1
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csinc w0, w8, wzr, ne
+; CHECK-NEXT: ret
+ %masked = and i32 %y, 1
+ %r = select i1 %x, i32 %masked, i32 1
+ ret i32 %r
+}
+
+define i32 @from_i1_fail_bad_select1(i1 %x, i32 %y) {
+; CHECK-LABEL: from_i1_fail_bad_select1:
+; CHECK: // %bb.0:
+; CHECK-NEXT: and w8, w1, #0x1
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csel w0, wzr, w8, ne
+; CHECK-NEXT: ret
+ %masked = and i32 %y, 1
+ %r = select i1 %x, i32 0, i32 %masked
+ ret i32 %r
+}
diff --git a/llvm/test/CodeGen/RISCV/select-to-and-zext.ll b/llvm/test/CodeGen/RISCV/select-to-and-zext.ll
new file mode 100644
index 000000000000000..949247f8ef2df56
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/select-to-and-zext.ll
@@ -0,0 +1,152 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN: | FileCheck %s -check-prefix=RV32I
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
+; RUN: | FileCheck %s -check-prefix=RV64I
+
+
+define i32 @from_cmpeq(i32 %xx, i32 %y) {
+; RV32I-LABEL: from_cmpeq:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, -9
+; RV32I-NEXT: seqz a0, a0
+; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: from_cmpeq:
+; RV64I: # %bb.0:
+; RV64I-NEXT: sext.w a0, a0
+; RV64I-NEXT: addi a0, a0, -9
+; RV64I-NEXT: seqz a0, a0
+; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: ret
+ %x = icmp eq i32 %xx, 9
+ %masked = and i32 %y, 1
+
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_cmpeq_fail_bad_andmask(i32 %xx, i32 %y) {
+; RV32I-LABEL: from_cmpeq_fail_bad_andmask:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, -9
+; RV32I-NEXT: snez a0, a0
+; RV32I-NEXT: addi a0, a0, -1
+; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: andi a0, a0, 3
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: from_cmpeq_fail_bad_andmask:
+; RV64I: # %bb.0:
+; RV64I-NEXT: sext.w a0, a0
+; RV64I-NEXT: addi a0, a0, -9
+; RV64I-NEXT: snez a0, a0
+; RV64I-NEXT: addiw a0, a0, -1
+; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: andi a0, a0, 3
+; RV64I-NEXT: ret
+ %x = icmp eq i32 %xx, 9
+ %masked = and i32 %y, 3
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_i1(i1 %x, i32 %y) {
+; RV32I-LABEL: from_i1:
+; RV32I: # %bb.0:
+; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: andi a0, a0, 1
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: from_i1:
+; RV64I: # %bb.0:
+; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: andi a0, a0, 1
+; RV64I-NEXT: ret
+ %masked = and i32 %y, 1
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_trunc_i8(i8 %xx, i32 %y) {
+; RV32I-LABEL: from_trunc_i8:
+; RV32I: # %bb.0:
+; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: andi a0, a0, 1
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: from_trunc_i8:
+; RV64I: # %bb.0:
+; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: andi a0, a0, 1
+; RV64I-NEXT: ret
+ %masked = and i32 %y, 1
+ %x = trunc i8 %xx to i1
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_trunc_i64(i64 %xx, i32 %y) {
+; RV32I-LABEL: from_trunc_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: and a0, a2, a0
+; RV32I-NEXT: andi a0, a0, 1
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: from_trunc_i64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: andi a0, a0, 1
+; RV64I-NEXT: ret
+ %masked = and i32 %y, 1
+ %x = trunc i64 %xx to i1
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_i1_fail_bad_select0(i1 %x, i32 %y) {
+; RV32I-LABEL: from_i1_fail_bad_select0:
+; RV32I: # %bb.0:
+; RV32I-NEXT: andi a0, a0, 1
+; RV32I-NEXT: bnez a0, .LBB5_2
+; RV32I-NEXT: # %bb.1:
+; RV32I-NEXT: li a0, 1
+; RV32I-NEXT: ret
+; RV32I-NEXT: .LBB5_2:
+; RV32I-NEXT: andi a0, a1, 1
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: from_i1_fail_bad_select0:
+; RV64I: # %bb.0:
+; RV64I-NEXT: andi a0, a0, 1
+; RV64I-NEXT: bnez a0, .LBB5_2
+; RV64I-NEXT: # %bb.1:
+; RV64I-NEXT: li a0, 1
+; RV64I-NEXT: ret
+; RV64I-NEXT: .LBB5_2:
+; RV64I-NEXT: andi a0, a1, 1
+; RV64I-NEXT: ret
+ %masked = and i32 %y, 1
+ %r = select i1 %x, i32 %masked, i32 1
+ ret i32 %r
+}
+
+define i32 @from_i1_fail_bad_select1(i1 %x, i32 %y) {
+; RV32I-LABEL: from_i1_fail_bad_select1:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, -1
+; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: andi a0, a0, 1
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: from_i1_fail_bad_select1:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addiw a0, a0, -1
+; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: andi a0, a0, 1
+; RV64I-NEXT: ret
+ %masked = and i32 %y, 1
+ %r = select i1 %x, i32 0, i32 %masked
+ ret i32 %r
+}
diff --git a/llvm/test/CodeGen/X86/select-to-and-zext.ll b/llvm/test/CodeGen/X86/select-to-and-zext.ll
new file mode 100644
index 000000000000000..ec1ac398d564173
--- /dev/null
+++ b/llvm/test/CodeGen/X86/select-to-and-zext.ll
@@ -0,0 +1,189 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-pc-linux-gnu | FileCheck %s --check-prefix=X86
+; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu | FileCheck %s --check-prefix=X64
+
+define i32 @from_cmpeq(i32 %xx, i32 %y) {
+; X86-LABEL: from_cmpeq:
+; X86: # %bb.0:
+; X86-NEXT: cmpl $9, {{[0-9]+}}(%esp) # encoding: [0x83,0x7c,0x24,0x04,0x09]
+; X86-NEXT: je .LBB0_1 # encoding: [0x74,A]
+; X86-NEXT: # fixup A - offset: 1, value: .LBB0_1-1, kind: FK_PCRel_1
+; X86-NEXT: # %bb.2:
+; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: .LBB0_1:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
+; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
+; X86-NEXT: retl # encoding: [0xc3]
+;
+; X64-LABEL: from_cmpeq:
+; X64: # %bb.0:
+; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
+; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X64-NEXT: cmpl $9, %edi # encoding: [0x83,0xff,0x09]
+; X64-NEXT: cmovel %esi, %eax # encoding: [0x0f,0x44,0xc6]
+; X64-NEXT: retq # encoding: [0xc3]
+ %x = icmp eq i32 %xx, 9
+ %masked = and i32 %y, 1
+
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_cmpeq_fail_bad_andmask(i32 %xx, i32 %y) {
+; X86-LABEL: from_cmpeq_fail_bad_andmask:
+; X86: # %bb.0:
+; X86-NEXT: cmpl $9, {{[0-9]+}}(%esp) # encoding: [0x83,0x7c,0x24,0x04,0x09]
+; X86-NEXT: je .LBB1_1 # encoding: [0x74,A]
+; X86-NEXT: # fixup A - offset: 1, value: .LBB1_1-1, kind: FK_PCRel_1
+; X86-NEXT: # %bb.2:
+; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: .LBB1_1:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
+; X86-NEXT: andl $3, %eax # encoding: [0x83,0xe0,0x03]
+; X86-NEXT: retl # encoding: [0xc3]
+;
+; X64-LABEL: from_cmpeq_fail_bad_andmask:
+; X64: # %bb.0:
+; X64-NEXT: andl $3, %esi # encoding: [0x83,0xe6,0x03]
+; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X64-NEXT: cmpl $9, %edi # encoding: [0x83,0xff,0x09]
+; X64-NEXT: cmovel %esi, %eax # encoding: [0x0f,0x44,0xc6]
+; X64-NEXT: retq # encoding: [0xc3]
+ %x = icmp eq i32 %xx, 9
+ %masked = and i32 %y, 3
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_i1(i1 %x, i32 %y) {
+; X86-LABEL: from_i1:
+; X86: # %bb.0:
+; X86-NEXT: testb $1, {{[0-9]+}}(%esp) # encoding: [0xf6,0x44,0x24,0x04,0x01]
+; X86-NEXT: jne .LBB2_1 # encoding: [0x75,A]
+; X86-NEXT: # fixup A - offset: 1, value: .LBB2_1-1, kind: FK_PCRel_1
+; X86-NEXT: # %bb.2:
+; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: .LBB2_1:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
+; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
+; X86-NEXT: retl # encoding: [0xc3]
+;
+; X64-LABEL: from_i1:
+; X64: # %bb.0:
+; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
+; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X64-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01]
+; X64-NEXT: cmovnel %esi, %eax # encoding: [0x0f,0x45,0xc6]
+; X64-NEXT: retq # encoding: [0xc3]
+ %masked = and i32 %y, 1
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_trunc_i8(i8 %xx, i32 %y) {
+; X86-LABEL: from_trunc_i8:
+; X86: # %bb.0:
+; X86-NEXT: testb $1, {{[0-9]+}}(%esp) # encoding: [0xf6,0x44,0x24,0x04,0x01]
+; X86-NEXT: jne .LBB3_1 # encoding: [0x75,A]
+; X86-NEXT: # fixup A - offset: 1, value: .LBB3_1-1, kind: FK_PCRel_1
+; X86-NEXT: # %bb.2:
+; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: .LBB3_1:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
+; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
+; X86-NEXT: retl # encoding: [0xc3]
+;
+; X64-LABEL: from_trunc_i8:
+; X64: # %bb.0:
+; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
+; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X64-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01]
+; X64-NEXT: cmovnel %esi, %eax # encoding: [0x0f,0x45,0xc6]
+; X64-NEXT: retq # encoding: [0xc3]
+ %masked = and i32 %y, 1
+ %x = trunc i8 %xx to i1
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_trunc_i64(i64 %xx, i32 %y) {
+; X86-LABEL: from_trunc_i64:
+; X86: # %bb.0:
+; X86-NEXT: testb $1, {{[0-9]+}}(%esp) # encoding: [0xf6,0x44,0x24,0x04,0x01]
+; X86-NEXT: jne .LBB4_1 # encoding: [0x75,A]
+; X86-NEXT: # fixup A - offset: 1, value: .LBB4_1-1, kind: FK_PCRel_1
+; X86-NEXT: # %bb.2:
+; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: .LBB4_1:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x0c]
+; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
+; X86-NEXT: retl # encoding: [0xc3]
+;
+; X64-LABEL: from_trunc_i64:
+; X64: # %bb.0:
+; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
+; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X64-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01]
+; X64-NEXT: cmovnel %esi, %eax # encoding: [0x0f,0x45,0xc6]
+; X64-NEXT: retq # encoding: [0xc3]
+ %masked = and i32 %y, 1
+ %x = trunc i64 %xx to i1
+ %r = select i1 %x, i32 %masked, i32 0
+ ret i32 %r
+}
+
+define i32 @from_i1_fail_bad_select0(i1 %x, i32 %y) {
+; X86-LABEL: from_i1_fail_bad_select0:
+; X86: # %bb.0:
+; X86-NEXT: testb $1, {{[0-9]+}}(%esp) # encoding: [0xf6,0x44,0x24,0x04,0x01]
+; X86-NEXT: jne .LBB5_1 # encoding: [0x75,A]
+; X86-NEXT: # fixup A - offset: 1, value: .LBB5_1-1, kind: FK_PCRel_1
+; X86-NEXT: # %bb.2:
+; X86-NEXT: movl $1, %eax # encoding: [0xb8,0x01,0x00,0x00,0x00]
+; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: .LBB5_1:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
+; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
+; X86-NEXT: retl # encoding: [0xc3]
+;
+; X64-LABEL: from_i1_fail_bad_select0:
+; X64: # %bb.0:
+; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
+; X64-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01]
+; X64-NEXT: movl $1, %eax # encoding: [0xb8,0x01,0x00,0x00,0x00]
+; X64-NEXT: cmovnel %esi, %eax # encoding: [0x0f,0x45,0xc6]
+; X64-NEXT: retq # encoding: [0xc3]
+ %masked = and i32 %y, 1
+ %r = select i1 %x, i32 %masked, i32 1
+ ret i32 %r
+}
+
+define i32 @from_i1_fail_bad_select1(i1 %x, i32 %y) {
+; X86-LABEL: from_i1_fail_bad_select1:
+; X86: # %bb.0:
+; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X86-NEXT: testb $1, {{[0-9]+}}(%esp) # encoding: [0xf6,0x44,0x24,0x04,0x01]
+; X86-NEXT: jne .LBB6_2 # encoding: [0x75,A]
+; X86-NEXT: # fixup A - offset: 1, value: .LBB6_2-1, kind: FK_PCRel_1
+; X86-NEXT: # %bb.1:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
+; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
+; X86-NEXT: .LBB6_2:
+; X86-NEXT: retl # encoding: [0xc3]
+;
+; X64-LABEL: from_i1_fail_bad_select1:
+; X64: # %bb.0:
+; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
+; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; X64-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01]
+; X64-NEXT: cmovel %esi, %eax # encoding: [0x0f,0x44,0xc6]
+; X64-NEXT: retq # encoding: [0xc3]
+ %masked = and i32 %y, 1
+ %r = select i1 %x, i32 0, i32 %masked
+ ret i32 %r
+}
>From b1ee87607f5314ac83cc9f83f916a03e66943a2c Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Tue, 19 Sep 2023 12:02:53 -0500
Subject: [PATCH 2/2] [DAGCombiner] Combine `(select c, (and X, 1), 0)` ->
`(and (zext c), X)`
The middle end canonicalizes:
`(and (zext c), X)`
-> `(select c, (and X, 1), 0)`
But the `and` + `zext` form gets better codegen.
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 32 +++
.../CodeGen/AArch64/select-to-and-zext.ll | 15 +-
llvm/test/CodeGen/RISCV/select-to-and-zext.ll | 16 +-
llvm/test/CodeGen/SystemZ/pr60413.ll | 194 +++++++++---------
llvm/test/CodeGen/X86/select-to-and-zext.ll | 168 +++++++--------
5 files changed, 211 insertions(+), 214 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 693523e737acf66..ef069b801c2e74a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6299,6 +6299,35 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
return SDValue();
}
+// Combine `(select c, (X & 1), 0)` -> `(and (zext c), X)`.
+// We canonicalize to the `select` form in the middle end, but the `and` form
+// gets better codegen and all tested targets (arm, x86, riscv)
+static SDValue combineSelectAsExtAnd(SDValue Cond, SDValue T, SDValue F,
+ const SDLoc &DL, SelectionDAG &DAG) {
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ if (!isNullConstant(F))
+ return SDValue();
+
+ EVT CondVT = Cond.getValueType();
+ ISD::NodeType BoolExtOpc =
+ TLI.getExtendForContent(TLI.getBooleanContents(CondVT));
+ if (BoolExtOpc != ISD::ZERO_EXTEND)
+ return SDValue();
+
+ if (T.getOpcode() != ISD::AND)
+ return SDValue();
+
+ if (!isOneConstant(T.getOperand(1)))
+ return SDValue();
+
+ EVT OpVT = T.getValueType();
+
+ SDValue CondMask =
+ OpVT == CondVT ? Cond : DAG.getBoolExtOrTrunc(Cond, DL, OpVT, CondVT);
+ return DAG.getNode(ISD::AND, DL, OpVT, CondMask, T.getOperand(0));
+}
+
+
/// This contains all DAGCombine rules which reduce two values combined by
/// an And operation to a single value. This makes them reusable in the context
/// of visitSELECT(). Rules involving constants are not included as
@@ -11609,6 +11638,9 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) {
if (SDValue BinOp = foldSelectOfBinops(N))
return BinOp;
+ if (SDValue R = combineSelectAsExtAnd(N0, N1, N2, DL, DAG))
+ return R;
+
return SDValue();
}
diff --git a/llvm/test/CodeGen/AArch64/select-to-and-zext.ll b/llvm/test/CodeGen/AArch64/select-to-and-zext.ll
index 9773108e596705d..42a7c2114ed27ee 100644
--- a/llvm/test/CodeGen/AArch64/select-to-and-zext.ll
+++ b/llvm/test/CodeGen/AArch64/select-to-and-zext.ll
@@ -31,9 +31,8 @@ define i32 @from_cmpeq_fail_bad_andmask(i32 %xx, i32 %y) {
define i32 @from_i1(i1 %x, i32 %y) {
; CHECK-LABEL: from_i1:
; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w1, #0x1
-; CHECK-NEXT: tst w0, #0x1
-; CHECK-NEXT: csel w0, w8, wzr, ne
+; CHECK-NEXT: and w8, w0, w1
+; CHECK-NEXT: and w0, w8, #0x1
; CHECK-NEXT: ret
%masked = and i32 %y, 1
%r = select i1 %x, i32 %masked, i32 0
@@ -43,9 +42,8 @@ define i32 @from_i1(i1 %x, i32 %y) {
define i32 @from_trunc_i8(i8 %xx, i32 %y) {
; CHECK-LABEL: from_trunc_i8:
; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w1, #0x1
-; CHECK-NEXT: tst w0, #0x1
-; CHECK-NEXT: csel w0, w8, wzr, ne
+; CHECK-NEXT: and w8, w0, w1
+; CHECK-NEXT: and w0, w8, #0x1
; CHECK-NEXT: ret
%masked = and i32 %y, 1
%x = trunc i8 %xx to i1
@@ -56,9 +54,8 @@ define i32 @from_trunc_i8(i8 %xx, i32 %y) {
define i32 @from_trunc_i64(i64 %xx, i32 %y) {
; CHECK-LABEL: from_trunc_i64:
; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w1, #0x1
-; CHECK-NEXT: tst w0, #0x1
-; CHECK-NEXT: csel w0, w8, wzr, ne
+; CHECK-NEXT: and w8, w0, w1
+; CHECK-NEXT: and w0, w8, #0x1
; CHECK-NEXT: ret
%masked = and i32 %y, 1
%x = trunc i64 %xx to i1
diff --git a/llvm/test/CodeGen/RISCV/select-to-and-zext.ll b/llvm/test/CodeGen/RISCV/select-to-and-zext.ll
index 949247f8ef2df56..eacc26c18415da6 100644
--- a/llvm/test/CodeGen/RISCV/select-to-and-zext.ll
+++ b/llvm/test/CodeGen/RISCV/select-to-and-zext.ll
@@ -10,7 +10,7 @@ define i32 @from_cmpeq(i32 %xx, i32 %y) {
; RV32I: # %bb.0:
; RV32I-NEXT: addi a0, a0, -9
; RV32I-NEXT: seqz a0, a0
-; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: ret
;
; RV64I-LABEL: from_cmpeq:
@@ -18,7 +18,7 @@ define i32 @from_cmpeq(i32 %xx, i32 %y) {
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: addi a0, a0, -9
; RV64I-NEXT: seqz a0, a0
-; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: ret
%x = icmp eq i32 %xx, 9
%masked = and i32 %y, 1
@@ -55,13 +55,13 @@ define i32 @from_cmpeq_fail_bad_andmask(i32 %xx, i32 %y) {
define i32 @from_i1(i1 %x, i32 %y) {
; RV32I-LABEL: from_i1:
; RV32I: # %bb.0:
-; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: andi a0, a0, 1
; RV32I-NEXT: ret
;
; RV64I-LABEL: from_i1:
; RV64I: # %bb.0:
-; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: andi a0, a0, 1
; RV64I-NEXT: ret
%masked = and i32 %y, 1
@@ -72,13 +72,13 @@ define i32 @from_i1(i1 %x, i32 %y) {
define i32 @from_trunc_i8(i8 %xx, i32 %y) {
; RV32I-LABEL: from_trunc_i8:
; RV32I: # %bb.0:
-; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: andi a0, a0, 1
; RV32I-NEXT: ret
;
; RV64I-LABEL: from_trunc_i8:
; RV64I: # %bb.0:
-; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: andi a0, a0, 1
; RV64I-NEXT: ret
%masked = and i32 %y, 1
@@ -90,13 +90,13 @@ define i32 @from_trunc_i8(i8 %xx, i32 %y) {
define i32 @from_trunc_i64(i64 %xx, i32 %y) {
; RV32I-LABEL: from_trunc_i64:
; RV32I: # %bb.0:
-; RV32I-NEXT: and a0, a2, a0
+; RV32I-NEXT: and a0, a0, a2
; RV32I-NEXT: andi a0, a0, 1
; RV32I-NEXT: ret
;
; RV64I-LABEL: from_trunc_i64:
; RV64I: # %bb.0:
-; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: andi a0, a0, 1
; RV64I-NEXT: ret
%masked = and i32 %y, 1
diff --git a/llvm/test/CodeGen/SystemZ/pr60413.ll b/llvm/test/CodeGen/SystemZ/pr60413.ll
index 532dbde89c826c6..5a629567d070694 100644
--- a/llvm/test/CodeGen/SystemZ/pr60413.ll
+++ b/llvm/test/CodeGen/SystemZ/pr60413.ll
@@ -13,21 +13,29 @@ declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #0
define dso_local void @m() local_unnamed_addr #1 {
; CHECK-LABEL: m:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: stmg %r13, %r15, 104(%r15)
+; CHECK-NEXT: stmg %r12, %r15, 96(%r15)
; CHECK-NEXT: aghi %r15, -168
-; CHECK-NEXT: llhrl %r1, f+4
-; CHECK-NEXT: sll %r1, 8
-; CHECK-NEXT: larl %r2, f
-; CHECK-NEXT: ic %r1, 6(%r2)
-; CHECK-NEXT: lr %r0, %r1
-; CHECK-NEXT: nilh %r0, 255
-; CHECK-NEXT: vlvgp %v1, %r1, %r0
-; CHECK-NEXT: vlvgf %v1, %r1, 0
-; CHECK-NEXT: vlvgf %v1, %r1, 2
-; CHECK-NEXT: vlvgp %v0, %r0, %r1
+; CHECK-NEXT: llhrl %r2, f+4
+; CHECK-NEXT: sll %r2, 8
+; CHECK-NEXT: larl %r1, f
+; CHECK-NEXT: ic %r2, 6(%r1)
+; CHECK-NEXT: larl %r1, e
+; CHECK-NEXT: lb %r0, 3(%r1)
+; CHECK-NEXT: clfi %r2, 128
+; CHECK-NEXT: ipm %r1
+; CHECK-NEXT: risbg %r1, %r1, 63, 191, 36
+; CHECK-NEXT: vlvgp %v1, %r2, %r0
+; CHECK-NEXT: vlvgf %v1, %r2, 0
+; CHECK-NEXT: vlvgf %v1, %r2, 2
+; CHECK-NEXT: vlvgp %v0, %r0, %r2
+; CHECK-NEXT: vlvgp %v2, %r2, %r2
+; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d
+; CHECK-NEXT: nilh %r2, 255
+; CHECK-NEXT: chi %r2, 128
+; CHECK-NEXT: ipm %r2
+; CHECK-NEXT: risbg %r2, %r2, 63, 191, 36
; CHECK-NEXT: vlvgf %v0, %r0, 0
; CHECK-NEXT: vlvgf %v0, %r0, 2
-; CHECK-NEXT: vlvgp %v2, %r1, %r1
; CHECK-NEXT: vrepf %v2, %v2, 1
; CHECK-NEXT: vgbm %v3, 30583
; CHECK-NEXT: vn %v0, %v0, %v3
@@ -35,96 +43,84 @@ define dso_local void @m() local_unnamed_addr #1 {
; CHECK-NEXT: vn %v2, %v2, %v3
; CHECK-NEXT: vrepif %v3, 127
; CHECK-NEXT: vchlf %v1, %v1, %v3
-; CHECK-NEXT: vlgvf %r13, %v1, 0
+; CHECK-NEXT: vlgvf %r12, %v1, 0
; CHECK-NEXT: vchlf %v2, %v2, %v3
-; CHECK-NEXT: vlgvf %r3, %v2, 1
-; CHECK-NEXT: nilf %r3, 1
-; CHECK-NEXT: vlgvf %r4, %v2, 0
-; CHECK-NEXT: risbg %r2, %r4, 48, 176, 15
-; CHECK-NEXT: rosbg %r2, %r3, 32, 49, 14
-; CHECK-NEXT: vlgvf %r5, %v2, 2
-; CHECK-NEXT: nilf %r5, 1
-; CHECK-NEXT: rosbg %r2, %r5, 32, 50, 13
-; CHECK-NEXT: vlgvf %r14, %v2, 3
+; CHECK-NEXT: vlgvf %r4, %v2, 1
+; CHECK-NEXT: nilf %r4, 1
+; CHECK-NEXT: vlgvf %r5, %v2, 0
+; CHECK-NEXT: risbg %r3, %r5, 48, 176, 15
+; CHECK-NEXT: rosbg %r3, %r4, 32, 49, 14
+; CHECK-NEXT: vlgvf %r14, %v2, 2
; CHECK-NEXT: nilf %r14, 1
-; CHECK-NEXT: rosbg %r2, %r14, 32, 51, 12
-; CHECK-NEXT: rosbg %r2, %r13, 52, 52, 11
-; CHECK-NEXT: vlgvf %r13, %v1, 1
-; CHECK-NEXT: rosbg %r2, %r13, 53, 53, 10
-; CHECK-NEXT: vlgvf %r13, %v1, 2
-; CHECK-NEXT: rosbg %r2, %r13, 54, 54, 9
-; CHECK-NEXT: vlgvf %r13, %v1, 3
-; CHECK-NEXT: rosbg %r2, %r13, 55, 55, 8
+; CHECK-NEXT: rosbg %r3, %r14, 32, 50, 13
+; CHECK-NEXT: vlgvf %r13, %v2, 3
+; CHECK-NEXT: nilf %r13, 1
+; CHECK-NEXT: rosbg %r3, %r13, 32, 51, 12
+; CHECK-NEXT: rosbg %r3, %r12, 52, 52, 11
+; CHECK-NEXT: vlgvf %r12, %v1, 1
+; CHECK-NEXT: rosbg %r3, %r12, 53, 53, 10
+; CHECK-NEXT: vlgvf %r12, %v1, 2
+; CHECK-NEXT: rosbg %r3, %r12, 54, 54, 9
+; CHECK-NEXT: vlgvf %r12, %v1, 3
+; CHECK-NEXT: rosbg %r3, %r12, 55, 55, 8
; CHECK-NEXT: vchlf %v0, %v0, %v3
-; CHECK-NEXT: vlgvf %r13, %v0, 0
-; CHECK-NEXT: rosbg %r2, %r13, 56, 56, 7
-; CHECK-NEXT: vlgvf %r13, %v0, 1
-; CHECK-NEXT: rosbg %r2, %r13, 57, 57, 6
-; CHECK-NEXT: vlgvf %r13, %v0, 2
-; CHECK-NEXT: rosbg %r2, %r13, 58, 58, 5
-; CHECK-NEXT: vlgvf %r13, %v0, 3
-; CHECK-NEXT: rosbg %r2, %r13, 59, 59, 4
-; CHECK-NEXT: nilf %r4, 1
-; CHECK-NEXT: rosbg %r2, %r4, 32, 60, 3
-; CHECK-NEXT: rosbg %r2, %r3, 32, 61, 2
-; CHECK-NEXT: rosbg %r2, %r5, 32, 62, 1
-; CHECK-NEXT: or %r2, %r14
-; CHECK-NEXT: vlgvb %r4, %v0, 1
-; CHECK-NEXT: vlgvb %r3, %v0, 0
-; CHECK-NEXT: risbg %r3, %r3, 48, 176, 15
-; CHECK-NEXT: rosbg %r3, %r4, 49, 49, 14
-; CHECK-NEXT: vlgvb %r4, %v0, 2
-; CHECK-NEXT: rosbg %r3, %r4, 50, 50, 13
-; CHECK-NEXT: vlgvb %r4, %v0, 3
-; CHECK-NEXT: rosbg %r3, %r4, 51, 51, 12
-; CHECK-NEXT: vlgvb %r4, %v0, 4
-; CHECK-NEXT: rosbg %r3, %r4, 52, 52, 11
-; CHECK-NEXT: vlgvb %r4, %v0, 5
-; CHECK-NEXT: rosbg %r3, %r4, 53, 53, 10
-; CHECK-NEXT: vlgvb %r4, %v0, 6
-; CHECK-NEXT: rosbg %r3, %r4, 54, 54, 9
-; CHECK-NEXT: vlgvb %r4, %v0, 7
-; CHECK-NEXT: rosbg %r3, %r4, 55, 55, 8
-; CHECK-NEXT: vlgvb %r4, %v0, 8
-; CHECK-NEXT: rosbg %r3, %r4, 56, 56, 7
-; CHECK-NEXT: vlgvb %r4, %v0, 9
-; CHECK-NEXT: rosbg %r3, %r4, 57, 57, 6
-; CHECK-NEXT: vlgvb %r4, %v0, 10
-; CHECK-NEXT: rosbg %r3, %r4, 58, 58, 5
-; CHECK-NEXT: vlgvb %r4, %v0, 11
-; CHECK-NEXT: rosbg %r3, %r4, 59, 59, 4
-; CHECK-NEXT: vlgvb %r4, %v0, 12
-; CHECK-NEXT: rosbg %r3, %r4, 60, 60, 3
-; CHECK-NEXT: vlgvb %r4, %v0, 13
-; CHECK-NEXT: rosbg %r3, %r4, 61, 61, 2
-; CHECK-NEXT: vlgvb %r4, %v0, 14
-; CHECK-NEXT: rosbg %r3, %r4, 62, 62, 1
-; CHECK-NEXT: vlgvb %r4, %v0, 15
-; CHECK-NEXT: rosbg %r3, %r4, 63, 63, 0
-; CHECK-NEXT: xilf %r3, 4294967295
-; CHECK-NEXT: clijhe %r1, 128, .LBB0_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: larl %r1, e
-; CHECK-NEXT: llc %r1, 3(%r1)
-; CHECK-NEXT: nilf %r1, 1
-; CHECK-NEXT: j .LBB0_3
-; CHECK-NEXT: .LBB0_2: # %entry
-; CHECK-NEXT: lhi %r1, 0
-; CHECK-NEXT: .LBB0_3: # %entry
-; CHECK-NEXT: or %r2, %r3
-; CHECK-NEXT: chi %r0, 128
-; CHECK-NEXT: jl .LBB0_5
-; CHECK-NEXT: # %bb.4: # %entry
-; CHECK-NEXT: lhi %r1, 0
-; CHECK-NEXT: .LBB0_5: # %entry
-; CHECK-NEXT: tmll %r2, 65535
-; CHECK-NEXT: je .LBB0_7
-; CHECK-NEXT: # %bb.6: # %entry
-; CHECK-NEXT: lhi %r1, 0
-; CHECK-NEXT: .LBB0_7: # %entry
-; CHECK-NEXT: larl %r2, g
-; CHECK-NEXT: stc %r1, 0(%r2)
-; CHECK-NEXT: lmg %r13, %r15, 272(%r15)
+; CHECK-NEXT: vlgvf %r12, %v0, 0
+; CHECK-NEXT: rosbg %r3, %r12, 56, 56, 7
+; CHECK-NEXT: vlgvf %r12, %v0, 1
+; CHECK-NEXT: rosbg %r3, %r12, 57, 57, 6
+; CHECK-NEXT: vlgvf %r12, %v0, 2
+; CHECK-NEXT: rosbg %r3, %r12, 58, 58, 5
+; CHECK-NEXT: vlgvf %r12, %v0, 3
+; CHECK-NEXT: rosbg %r3, %r12, 59, 59, 4
+; CHECK-NEXT: nilf %r5, 1
+; CHECK-NEXT: rosbg %r3, %r5, 32, 60, 3
+; CHECK-NEXT: rosbg %r3, %r4, 32, 61, 2
+; CHECK-NEXT: rosbg %r3, %r14, 32, 62, 1
+; CHECK-NEXT: or %r3, %r13
+; CHECK-NEXT: vlgvb %r5, %v0, 1
+; CHECK-NEXT: vlgvb %r4, %v0, 0
+; CHECK-NEXT: risbg %r4, %r4, 48, 176, 15
+; CHECK-NEXT: rosbg %r4, %r5, 49, 49, 14
+; CHECK-NEXT: vlgvb %r5, %v0, 2
+; CHECK-NEXT: rosbg %r4, %r5, 50, 50, 13
+; CHECK-NEXT: vlgvb %r5, %v0, 3
+; CHECK-NEXT: rosbg %r4, %r5, 51, 51, 12
+; CHECK-NEXT: vlgvb %r5, %v0, 4
+; CHECK-NEXT: rosbg %r4, %r5, 52, 52, 11
+; CHECK-NEXT: vlgvb %r5, %v0, 5
+; CHECK-NEXT: rosbg %r4, %r5, 53, 53, 10
+; CHECK-NEXT: vlgvb %r5, %v0, 6
+; CHECK-NEXT: rosbg %r4, %r5, 54, 54, 9
+; CHECK-NEXT: vlgvb %r5, %v0, 7
+; CHECK-NEXT: rosbg %r4, %r5, 55, 55, 8
+; CHECK-NEXT: vlgvb %r5, %v0, 8
+; CHECK-NEXT: rosbg %r4, %r5, 56, 56, 7
+; CHECK-NEXT: vlgvb %r5, %v0, 9
+; CHECK-NEXT: rosbg %r4, %r5, 57, 57, 6
+; CHECK-NEXT: vlgvb %r5, %v0, 10
+; CHECK-NEXT: rosbg %r4, %r5, 58, 58, 5
+; CHECK-NEXT: vlgvb %r5, %v0, 11
+; CHECK-NEXT: rosbg %r4, %r5, 59, 59, 4
+; CHECK-NEXT: vlgvb %r5, %v0, 12
+; CHECK-NEXT: rosbg %r4, %r5, 60, 60, 3
+; CHECK-NEXT: vlgvb %r5, %v0, 13
+; CHECK-NEXT: rosbg %r4, %r5, 61, 61, 2
+; CHECK-NEXT: vlgvb %r5, %v0, 14
+; CHECK-NEXT: rosbg %r4, %r5, 62, 62, 1
+; CHECK-NEXT: vlgvb %r5, %v0, 15
+; CHECK-NEXT: rosbg %r4, %r5, 63, 63, 0
+; CHECK-NEXT: xilf %r4, 4294967295
+; CHECK-NEXT: or %r4, %r3
+; CHECK-NEXT: tmll %r4, 65535
+; CHECK-NEXT: ipm %r3
+; CHECK-NEXT: afi %r3, -268435456
+; CHECK-NEXT: srl %r3, 31
+; CHECK-NEXT: nr %r2, %r1
+; CHECK-NEXT: nr %r2, %r3
+; CHECK-NEXT: nr %r2, %r0
+; CHECK-NEXT: larl %r1, g
+; CHECK-NEXT: stc %r2, 0(%r1)
+; CHECK-NEXT: lmg %r12, %r15, 264(%r15)
; CHECK-NEXT: br %r14
entry:
%n = alloca i32, align 4
diff --git a/llvm/test/CodeGen/X86/select-to-and-zext.ll b/llvm/test/CodeGen/X86/select-to-and-zext.ll
index ec1ac398d564173..7dadbd76a5bb17c 100644
--- a/llvm/test/CodeGen/X86/select-to-and-zext.ll
+++ b/llvm/test/CodeGen/X86/select-to-and-zext.ll
@@ -5,24 +5,19 @@
define i32 @from_cmpeq(i32 %xx, i32 %y) {
; X86-LABEL: from_cmpeq:
; X86: # %bb.0:
-; X86-NEXT: cmpl $9, {{[0-9]+}}(%esp) # encoding: [0x83,0x7c,0x24,0x04,0x09]
-; X86-NEXT: je .LBB0_1 # encoding: [0x74,A]
-; X86-NEXT: # fixup A - offset: 1, value: .LBB0_1-1, kind: FK_PCRel_1
-; X86-NEXT: # %bb.2:
-; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X86-NEXT: retl # encoding: [0xc3]
-; X86-NEXT: .LBB0_1:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
-; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
-; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: xorl %eax, %eax
+; X86-NEXT: cmpl $9, {{[0-9]+}}(%esp)
+; X86-NEXT: sete %al
+; X86-NEXT: andl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: retl
;
; X64-LABEL: from_cmpeq:
; X64: # %bb.0:
-; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
-; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X64-NEXT: cmpl $9, %edi # encoding: [0x83,0xff,0x09]
-; X64-NEXT: cmovel %esi, %eax # encoding: [0x0f,0x44,0xc6]
-; X64-NEXT: retq # encoding: [0xc3]
+; X64-NEXT: xorl %eax, %eax
+; X64-NEXT: cmpl $9, %edi
+; X64-NEXT: sete %al
+; X64-NEXT: andl %esi, %eax
+; X64-NEXT: retq
%x = icmp eq i32 %xx, 9
%masked = and i32 %y, 1
@@ -33,24 +28,23 @@ define i32 @from_cmpeq(i32 %xx, i32 %y) {
define i32 @from_cmpeq_fail_bad_andmask(i32 %xx, i32 %y) {
; X86-LABEL: from_cmpeq_fail_bad_andmask:
; X86: # %bb.0:
-; X86-NEXT: cmpl $9, {{[0-9]+}}(%esp) # encoding: [0x83,0x7c,0x24,0x04,0x09]
-; X86-NEXT: je .LBB1_1 # encoding: [0x74,A]
-; X86-NEXT: # fixup A - offset: 1, value: .LBB1_1-1, kind: FK_PCRel_1
+; X86-NEXT: cmpl $9, {{[0-9]+}}(%esp)
+; X86-NEXT: je .LBB1_1
; X86-NEXT: # %bb.2:
-; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: xorl %eax, %eax
+; X86-NEXT: retl
; X86-NEXT: .LBB1_1:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
-; X86-NEXT: andl $3, %eax # encoding: [0x83,0xe0,0x03]
-; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: andl $3, %eax
+; X86-NEXT: retl
;
; X64-LABEL: from_cmpeq_fail_bad_andmask:
; X64: # %bb.0:
-; X64-NEXT: andl $3, %esi # encoding: [0x83,0xe6,0x03]
-; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X64-NEXT: cmpl $9, %edi # encoding: [0x83,0xff,0x09]
-; X64-NEXT: cmovel %esi, %eax # encoding: [0x0f,0x44,0xc6]
-; X64-NEXT: retq # encoding: [0xc3]
+; X64-NEXT: andl $3, %esi
+; X64-NEXT: xorl %eax, %eax
+; X64-NEXT: cmpl $9, %edi
+; X64-NEXT: cmovel %esi, %eax
+; X64-NEXT: retq
%x = icmp eq i32 %xx, 9
%masked = and i32 %y, 3
%r = select i1 %x, i32 %masked, i32 0
@@ -60,24 +54,17 @@ define i32 @from_cmpeq_fail_bad_andmask(i32 %xx, i32 %y) {
define i32 @from_i1(i1 %x, i32 %y) {
; X86-LABEL: from_i1:
; X86: # %bb.0:
-; X86-NEXT: testb $1, {{[0-9]+}}(%esp) # encoding: [0xf6,0x44,0x24,0x04,0x01]
-; X86-NEXT: jne .LBB2_1 # encoding: [0x75,A]
-; X86-NEXT: # fixup A - offset: 1, value: .LBB2_1-1, kind: FK_PCRel_1
-; X86-NEXT: # %bb.2:
-; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X86-NEXT: retl # encoding: [0xc3]
-; X86-NEXT: .LBB2_1:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
-; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
-; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: andl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: andl $1, %eax
+; X86-NEXT: retl
;
; X64-LABEL: from_i1:
; X64: # %bb.0:
-; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
-; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X64-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01]
-; X64-NEXT: cmovnel %esi, %eax # encoding: [0x0f,0x45,0xc6]
-; X64-NEXT: retq # encoding: [0xc3]
+; X64-NEXT: movl %edi, %eax
+; X64-NEXT: andl %esi, %eax
+; X64-NEXT: andl $1, %eax
+; X64-NEXT: retq
%masked = and i32 %y, 1
%r = select i1 %x, i32 %masked, i32 0
ret i32 %r
@@ -86,24 +73,17 @@ define i32 @from_i1(i1 %x, i32 %y) {
define i32 @from_trunc_i8(i8 %xx, i32 %y) {
; X86-LABEL: from_trunc_i8:
; X86: # %bb.0:
-; X86-NEXT: testb $1, {{[0-9]+}}(%esp) # encoding: [0xf6,0x44,0x24,0x04,0x01]
-; X86-NEXT: jne .LBB3_1 # encoding: [0x75,A]
-; X86-NEXT: # fixup A - offset: 1, value: .LBB3_1-1, kind: FK_PCRel_1
-; X86-NEXT: # %bb.2:
-; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X86-NEXT: retl # encoding: [0xc3]
-; X86-NEXT: .LBB3_1:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
-; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
-; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: andl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: andl $1, %eax
+; X86-NEXT: retl
;
; X64-LABEL: from_trunc_i8:
; X64: # %bb.0:
-; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
-; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X64-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01]
-; X64-NEXT: cmovnel %esi, %eax # encoding: [0x0f,0x45,0xc6]
-; X64-NEXT: retq # encoding: [0xc3]
+; X64-NEXT: movl %edi, %eax
+; X64-NEXT: andl %esi, %eax
+; X64-NEXT: andl $1, %eax
+; X64-NEXT: retq
%masked = and i32 %y, 1
%x = trunc i8 %xx to i1
%r = select i1 %x, i32 %masked, i32 0
@@ -113,24 +93,18 @@ define i32 @from_trunc_i8(i8 %xx, i32 %y) {
define i32 @from_trunc_i64(i64 %xx, i32 %y) {
; X86-LABEL: from_trunc_i64:
; X86: # %bb.0:
-; X86-NEXT: testb $1, {{[0-9]+}}(%esp) # encoding: [0xf6,0x44,0x24,0x04,0x01]
-; X86-NEXT: jne .LBB4_1 # encoding: [0x75,A]
-; X86-NEXT: # fixup A - offset: 1, value: .LBB4_1-1, kind: FK_PCRel_1
-; X86-NEXT: # %bb.2:
-; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X86-NEXT: retl # encoding: [0xc3]
-; X86-NEXT: .LBB4_1:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x0c]
-; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
-; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: andl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: andl $1, %eax
+; X86-NEXT: retl
;
; X64-LABEL: from_trunc_i64:
; X64: # %bb.0:
-; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
-; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X64-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01]
-; X64-NEXT: cmovnel %esi, %eax # encoding: [0x0f,0x45,0xc6]
-; X64-NEXT: retq # encoding: [0xc3]
+; X64-NEXT: movq %rdi, %rax
+; X64-NEXT: andl %esi, %eax
+; X64-NEXT: andl $1, %eax
+; X64-NEXT: # kill: def $eax killed $eax killed $rax
+; X64-NEXT: retq
%masked = and i32 %y, 1
%x = trunc i64 %xx to i1
%r = select i1 %x, i32 %masked, i32 0
@@ -140,24 +114,23 @@ define i32 @from_trunc_i64(i64 %xx, i32 %y) {
define i32 @from_i1_fail_bad_select0(i1 %x, i32 %y) {
; X86-LABEL: from_i1_fail_bad_select0:
; X86: # %bb.0:
-; X86-NEXT: testb $1, {{[0-9]+}}(%esp) # encoding: [0xf6,0x44,0x24,0x04,0x01]
-; X86-NEXT: jne .LBB5_1 # encoding: [0x75,A]
-; X86-NEXT: # fixup A - offset: 1, value: .LBB5_1-1, kind: FK_PCRel_1
+; X86-NEXT: testb $1, {{[0-9]+}}(%esp)
+; X86-NEXT: jne .LBB5_1
; X86-NEXT: # %bb.2:
-; X86-NEXT: movl $1, %eax # encoding: [0xb8,0x01,0x00,0x00,0x00]
-; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: movl $1, %eax
+; X86-NEXT: retl
; X86-NEXT: .LBB5_1:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
-; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
-; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: andl $1, %eax
+; X86-NEXT: retl
;
; X64-LABEL: from_i1_fail_bad_select0:
; X64: # %bb.0:
-; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
-; X64-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01]
-; X64-NEXT: movl $1, %eax # encoding: [0xb8,0x01,0x00,0x00,0x00]
-; X64-NEXT: cmovnel %esi, %eax # encoding: [0x0f,0x45,0xc6]
-; X64-NEXT: retq # encoding: [0xc3]
+; X64-NEXT: andl $1, %esi
+; X64-NEXT: testb $1, %dil
+; X64-NEXT: movl $1, %eax
+; X64-NEXT: cmovnel %esi, %eax
+; X64-NEXT: retq
%masked = and i32 %y, 1
%r = select i1 %x, i32 %masked, i32 1
ret i32 %r
@@ -166,23 +139,22 @@ define i32 @from_i1_fail_bad_select0(i1 %x, i32 %y) {
define i32 @from_i1_fail_bad_select1(i1 %x, i32 %y) {
; X86-LABEL: from_i1_fail_bad_select1:
; X86: # %bb.0:
-; X86-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X86-NEXT: testb $1, {{[0-9]+}}(%esp) # encoding: [0xf6,0x44,0x24,0x04,0x01]
-; X86-NEXT: jne .LBB6_2 # encoding: [0x75,A]
-; X86-NEXT: # fixup A - offset: 1, value: .LBB6_2-1, kind: FK_PCRel_1
+; X86-NEXT: xorl %eax, %eax
+; X86-NEXT: testb $1, {{[0-9]+}}(%esp)
+; X86-NEXT: jne .LBB6_2
; X86-NEXT: # %bb.1:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08]
-; X86-NEXT: andl $1, %eax # encoding: [0x83,0xe0,0x01]
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: andl $1, %eax
; X86-NEXT: .LBB6_2:
-; X86-NEXT: retl # encoding: [0xc3]
+; X86-NEXT: retl
;
; X64-LABEL: from_i1_fail_bad_select1:
; X64: # %bb.0:
-; X64-NEXT: andl $1, %esi # encoding: [0x83,0xe6,0x01]
-; X64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
-; X64-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01]
-; X64-NEXT: cmovel %esi, %eax # encoding: [0x0f,0x44,0xc6]
-; X64-NEXT: retq # encoding: [0xc3]
+; X64-NEXT: andl $1, %esi
+; X64-NEXT: xorl %eax, %eax
+; X64-NEXT: testb $1, %dil
+; X64-NEXT: cmovel %esi, %eax
+; X64-NEXT: retq
%masked = and i32 %y, 1
%r = select i1 %x, i32 0, i32 %masked
ret i32 %r
More information about the llvm-commits
mailing list