[llvm] [InstCombine] Missed optimization: Fold (sext(a) & sext(c1)) == c2 to (a & c1) == c2 (PR #112646)
Lee Wei via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 16 18:56:16 PDT 2024
https://github.com/leewei05 created https://github.com/llvm/llvm-project/pull/112646
Alive2: https://alive2.llvm.org/ce/z/eHAC-5
Fixes the first code pattern from https://github.com/llvm/llvm-project/issues/85830
The original Alive2 proof from the issue has three code patterns and the second pattern is already being optimized by LLVM.
https://alive2.llvm.org/ce/z/44YNAL
Since this is my first PR to LLVM, I was thinking that I can add a follow-up PR for the third pattern after merging this one. Please let me know where I can improve, thanks!
>From b5893dcb0c38f7f6072b3baecd30e8d667a1c808 Mon Sep 17 00:00:00 2001
From: Lee <lee10202013 at gmail.com>
Date: Sat, 12 Oct 2024 15:13:47 -0600
Subject: [PATCH 1/2] Add pre-commit tests
---
llvm/test/Transforms/InstCombine/sext-and.ll | 50 ++++++++++++++++++++
1 file changed, 50 insertions(+)
create mode 100644 llvm/test/Transforms/InstCombine/sext-and.ll
diff --git a/llvm/test/Transforms/InstCombine/sext-and.ll b/llvm/test/Transforms/InstCombine/sext-and.ll
new file mode 100644
index 00000000000000..0062fffc3be120
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/sext-and.ll
@@ -0,0 +1,50 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+declare void @use(i8)
+
+define i1 @fold_sext_to_and(i8 %x) {
+; CHECK-LABEL: define i1 @fold_sext_to_and(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32
+; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], -2147483647
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: ret i1 [[TMP3]]
+;
+ %1 = sext i8 %x to i32
+ %2 = and i32 %1, -2147483647
+ %3 = icmp eq i32 %2, 1
+ ret i1 %3
+}
+
+define i1 @fold_sext_to_and_multi_use(i8 %x) {
+; CHECK-LABEL: define i1 @fold_sext_to_and_multi_use(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32
+; CHECK-NEXT: call void @use(i32 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], -2147483647
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: ret i1 [[TMP3]]
+;
+ %1 = sext i8 %x to i32
+ call void @use(i32 %1)
+ %2 = and i32 %1, -2147483647
+ %3 = icmp eq i32 %2, 1
+ ret i1 %3
+}
+
+; Negative tests
+
+define i1 @fold_sext_to_and_wrong(i2 %x) {
+; CHECK-LABEL: define i1 @fold_sext_to_and_wrong(
+; CHECK-SAME: i2 [[X:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = sext i2 [[X]] to i32
+; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], -2147483647
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: ret i1 [[TMP3]]
+;
+ %1 = sext i2 %x to i32
+ %2 = and i32 %1, -2147483647
+ %3 = icmp eq i32 %2, 1
+ ret i1 %3
+}
>From 7b7d698e92aeb54fedf8d21c2d130195814dc74b Mon Sep 17 00:00:00 2001
From: Lee <lee10202013 at gmail.com>
Date: Wed, 16 Oct 2024 19:45:18 -0600
Subject: [PATCH 2/2] Apply transformations
---
.../InstCombine/InstCombineCompares.cpp | 24 +++++++++++++++++++
llvm/test/Transforms/InstCombine/sext-and.ll | 9 ++++---
2 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 18a6fdcec1728e..8a79c44777c1a4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -24,6 +24,7 @@
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/KnownBits.h"
@@ -7687,6 +7688,29 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
if (Instruction *Res = foldReductionIdiom(I, Builder, DL))
return Res;
+ {
+ Value *A, *B;
+ const APInt *C;
+ ICmpInst::Predicate PredEq = ICmpInst::ICMP_EQ;
+ if (I.getPredicate() == PredEq) {
+ if (match(Op0, m_And(m_Value(A), m_APInt(C))) && match(Op1, m_One())) {
+ if (*C == APInt::getSignedMinValue(C->getBitWidth()) + 1) {
+ if (match(A, m_SExt(m_Value(B))) &&
+ B->getType()->getIntegerBitWidth() > 2) {
+ auto *InputTy = B->getType();
+ Value *AndInst = Builder.CreateAnd(
+ B,
+ ConstantInt::get(InputTy, APInt::getSignedMinValue(
+ InputTy->getIntegerBitWidth()) +
+ 1));
+ return CmpInst::Create(Instruction::ICmp, PredEq, AndInst,
+ ConstantInt::get(InputTy, 1));
+ }
+ }
+ }
+ }
+ }
+
return Changed ? &I : nullptr;
}
diff --git a/llvm/test/Transforms/InstCombine/sext-and.ll b/llvm/test/Transforms/InstCombine/sext-and.ll
index 0062fffc3be120..a4ce0f41a5afb8 100644
--- a/llvm/test/Transforms/InstCombine/sext-and.ll
+++ b/llvm/test/Transforms/InstCombine/sext-and.ll
@@ -6,9 +6,8 @@ declare void @use(i8)
define i1 @fold_sext_to_and(i8 %x) {
; CHECK-LABEL: define i1 @fold_sext_to_and(
; CHECK-SAME: i8 [[X:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32
-; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], -2147483647
-; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], -127
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: ret i1 [[TMP3]]
;
%1 = sext i8 %x to i32
@@ -22,8 +21,8 @@ define i1 @fold_sext_to_and_multi_use(i8 %x) {
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32
; CHECK-NEXT: call void @use(i32 [[TMP1]])
-; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], -2147483647
-; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[X]], -127
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP2]], 1
; CHECK-NEXT: ret i1 [[TMP3]]
;
%1 = sext i8 %x to i32
More information about the llvm-commits
mailing list