[llvm] [InstCombine] Fix miscompilation caused by #90436 (PR #91133)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sun May 5 21:57:08 PDT 2024


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/91133

>From 71c2249f077036c3f04424e715910b7d35031d33 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 6 May 2024 00:22:21 +0800
Subject: [PATCH 1/3] [InstCombine] Add pre-commit tests for PR91127. NFC.

---
 llvm/test/Transforms/InstCombine/pr91127.ll | 82 +++++++++++++++++++++
 1 file changed, 82 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/pr91127.ll

diff --git a/llvm/test/Transforms/InstCombine/pr91127.ll b/llvm/test/Transforms/InstCombine/pr91127.ll
new file mode 100644
index 00000000000000..3582841c0de79d
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/pr91127.ll
@@ -0,0 +1,82 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+define i1 @test_eq1(i32 %x, i16 %y) {
+; CHECK-LABEL: define i1 @test_eq1(
+; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y]] to i32
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[TMP1]], [[X]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nsw i32 %x to i8
+  %conv2 = trunc nsw i16 %y to i8
+  %cond = icmp eq i8 %conv1, %conv2
+  ret i1 %cond
+}
+
+; FIXME: It is weird that we generate truncs for test_eq2, but not for test_eq1.
+
+define i1 @test_eq2(i32 %x, i16 %y) {
+; CHECK-LABEL: define i1 @test_eq2(
+; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[X]] to i16
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i16 [[TMP1]], [[Y]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nsw i32 %x to i8
+  %conv2 = trunc nsw i16 %y to i8
+  %cond = icmp eq i8 %conv2, %conv1
+  ret i1 %cond
+}
+
+define i1 @test_ult(i32 %x, i16 %y) {
+; CHECK-LABEL: define i1 @test_ult(
+; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y]] to i32
+; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i32 [[TMP1]], [[X]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nsw i32 %x to i8
+  %conv2 = trunc nsw i16 %y to i8
+  %cond = icmp ult i8 %conv1, %conv2
+  ret i1 %cond
+}
+
+define i1 @test_slt(i32 %x, i16 %y) {
+; CHECK-LABEL: define i1 @test_slt(
+; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y]] to i32
+; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[TMP1]], [[X]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nsw i32 %x to i8
+  %conv2 = trunc nsw i16 %y to i8
+  %cond = icmp slt i8 %conv1, %conv2
+  ret i1 %cond
+}
+
+define i1 @test_ult_nuw(i32 %x, i16 %y) {
+; CHECK-LABEL: define i1 @test_ult_nuw(
+; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y]] to i32
+; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i32 [[TMP1]], [[X]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nuw nsw i32 %x to i8
+  %conv2 = trunc nuw nsw i16 %y to i8
+  %cond = icmp ult i8 %conv1, %conv2
+  ret i1 %cond
+}
+
+define i1 @test_slt_nuw(i32 %x, i16 %y) {
+; CHECK-LABEL: define i1 @test_slt_nuw(
+; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y]] to i32
+; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[TMP1]], [[X]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nuw nsw i32 %x to i8
+  %conv2 = trunc nuw nsw i16 %y to i8
+  %cond = icmp slt i8 %conv1, %conv2
+  ret i1 %cond
+}

>From 3465baef1793fa11c51ad5f8ba95724c4063221c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 6 May 2024 00:23:44 +0800
Subject: [PATCH 2/3] [InstCombine] Fix miscompilation caused by PR90436

---
 llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 1 +
 llvm/test/Transforms/InstCombine/pr91127.ll             | 6 +++---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index c60a290ce72e06..7092fb5e509bb1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1510,6 +1510,7 @@ InstCombinerImpl::foldICmpTruncWithTruncOrExt(ICmpInst &Cmp,
       std::swap(X, Y);
       Pred = Cmp.getSwappedPredicate(Pred);
     }
+    YIsSExt = !(NoWrapFlags & TruncInst::NoUnsignedWrap);
   }
   // Try to match icmp (trunc nuw X), (zext Y)
   else if (!Cmp.isSigned() &&
diff --git a/llvm/test/Transforms/InstCombine/pr91127.ll b/llvm/test/Transforms/InstCombine/pr91127.ll
index 3582841c0de79d..43d431486d2d1b 100644
--- a/llvm/test/Transforms/InstCombine/pr91127.ll
+++ b/llvm/test/Transforms/InstCombine/pr91127.ll
@@ -4,7 +4,7 @@
 define i1 @test_eq1(i32 %x, i16 %y) {
 ; CHECK-LABEL: define i1 @test_eq1(
 ; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[Y]] to i32
 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[TMP1]], [[X]]
 ; CHECK-NEXT:    ret i1 [[COND]]
 ;
@@ -32,7 +32,7 @@ define i1 @test_eq2(i32 %x, i16 %y) {
 define i1 @test_ult(i32 %x, i16 %y) {
 ; CHECK-LABEL: define i1 @test_ult(
 ; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[Y]] to i32
 ; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i32 [[TMP1]], [[X]]
 ; CHECK-NEXT:    ret i1 [[COND]]
 ;
@@ -45,7 +45,7 @@ define i1 @test_ult(i32 %x, i16 %y) {
 define i1 @test_slt(i32 %x, i16 %y) {
 ; CHECK-LABEL: define i1 @test_slt(
 ; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[Y]] to i32
 ; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[TMP1]], [[X]]
 ; CHECK-NEXT:    ret i1 [[COND]]
 ;

>From 19f8cb22e824e97a36c1a2c7072eeca92f76686b Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 6 May 2024 12:56:32 +0800
Subject: [PATCH 3/3] [InstCombine] Address review comments. NFC.

---
 .../InstCombine/icmp-of-trunc-ext.ll          | 74 +++++++++++++++++
 llvm/test/Transforms/InstCombine/pr91127.ll   | 82 -------------------
 2 files changed, 74 insertions(+), 82 deletions(-)
 delete mode 100644 llvm/test/Transforms/InstCombine/pr91127.ll

diff --git a/llvm/test/Transforms/InstCombine/icmp-of-trunc-ext.ll b/llvm/test/Transforms/InstCombine/icmp-of-trunc-ext.ll
index 0a8bf013dc55d2..a1757fbb84b231 100644
--- a/llvm/test/Transforms/InstCombine/icmp-of-trunc-ext.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-of-trunc-ext.ll
@@ -568,3 +568,77 @@ define i1 @trunc_equality_both_sext(i32 %x, i8 %y) {
   %c = icmp ne i16 %xt, %ye
   ret i1 %c
 }
+
+define i1 @test_eq1(i32 %x, i16 %y) {
+; CHECK-LABEL: @test_eq1(
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nsw i32 %x to i8
+  %conv2 = trunc nsw i16 %y to i8
+  %cond = icmp eq i8 %conv1, %conv2
+  ret i1 %cond
+}
+
+; FIXME: It is weird that we generate truncs for test_eq2, but not for test_eq1.
+
+define i1 @test_eq2(i32 %x, i16 %y) {
+; CHECK-LABEL: @test_eq2(
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i16 [[TMP1]], [[Y:%.*]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nsw i32 %x to i8
+  %conv2 = trunc nsw i16 %y to i8
+  %cond = icmp eq i8 %conv2, %conv1
+  ret i1 %cond
+}
+
+define i1 @test_ult(i32 %x, i16 %y) {
+; CHECK-LABEL: @test_ult(
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i32 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nsw i32 %x to i8
+  %conv2 = trunc nsw i16 %y to i8
+  %cond = icmp ult i8 %conv1, %conv2
+  ret i1 %cond
+}
+
+define i1 @test_slt(i32 %x, i16 %y) {
+; CHECK-LABEL: @test_slt(
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nsw i32 %x to i8
+  %conv2 = trunc nsw i16 %y to i8
+  %cond = icmp slt i8 %conv1, %conv2
+  ret i1 %cond
+}
+
+define i1 @test_ult_nuw(i32 %x, i16 %y) {
+; CHECK-LABEL: @test_ult_nuw(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i32 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nuw nsw i32 %x to i8
+  %conv2 = trunc nuw nsw i16 %y to i8
+  %cond = icmp ult i8 %conv1, %conv2
+  ret i1 %cond
+}
+
+define i1 @test_slt_nuw(i32 %x, i16 %y) {
+; CHECK-LABEL: @test_slt_nuw(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv1 = trunc nuw nsw i32 %x to i8
+  %conv2 = trunc nuw nsw i16 %y to i8
+  %cond = icmp slt i8 %conv1, %conv2
+  ret i1 %cond
+}
diff --git a/llvm/test/Transforms/InstCombine/pr91127.ll b/llvm/test/Transforms/InstCombine/pr91127.ll
deleted file mode 100644
index 43d431486d2d1b..00000000000000
--- a/llvm/test/Transforms/InstCombine/pr91127.ll
+++ /dev/null
@@ -1,82 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
-; RUN: opt -S -passes=instcombine < %s | FileCheck %s
-
-define i1 @test_eq1(i32 %x, i16 %y) {
-; CHECK-LABEL: define i1 @test_eq1(
-; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[Y]] to i32
-; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[TMP1]], [[X]]
-; CHECK-NEXT:    ret i1 [[COND]]
-;
-  %conv1 = trunc nsw i32 %x to i8
-  %conv2 = trunc nsw i16 %y to i8
-  %cond = icmp eq i8 %conv1, %conv2
-  ret i1 %cond
-}
-
-; FIXME: It is weird that we generate truncs for test_eq2, but not for test_eq1.
-
-define i1 @test_eq2(i32 %x, i16 %y) {
-; CHECK-LABEL: define i1 @test_eq2(
-; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[X]] to i16
-; CHECK-NEXT:    [[COND:%.*]] = icmp eq i16 [[TMP1]], [[Y]]
-; CHECK-NEXT:    ret i1 [[COND]]
-;
-  %conv1 = trunc nsw i32 %x to i8
-  %conv2 = trunc nsw i16 %y to i8
-  %cond = icmp eq i8 %conv2, %conv1
-  ret i1 %cond
-}
-
-define i1 @test_ult(i32 %x, i16 %y) {
-; CHECK-LABEL: define i1 @test_ult(
-; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[Y]] to i32
-; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i32 [[TMP1]], [[X]]
-; CHECK-NEXT:    ret i1 [[COND]]
-;
-  %conv1 = trunc nsw i32 %x to i8
-  %conv2 = trunc nsw i16 %y to i8
-  %cond = icmp ult i8 %conv1, %conv2
-  ret i1 %cond
-}
-
-define i1 @test_slt(i32 %x, i16 %y) {
-; CHECK-LABEL: define i1 @test_slt(
-; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[Y]] to i32
-; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[TMP1]], [[X]]
-; CHECK-NEXT:    ret i1 [[COND]]
-;
-  %conv1 = trunc nsw i32 %x to i8
-  %conv2 = trunc nsw i16 %y to i8
-  %cond = icmp slt i8 %conv1, %conv2
-  ret i1 %cond
-}
-
-define i1 @test_ult_nuw(i32 %x, i16 %y) {
-; CHECK-LABEL: define i1 @test_ult_nuw(
-; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y]] to i32
-; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i32 [[TMP1]], [[X]]
-; CHECK-NEXT:    ret i1 [[COND]]
-;
-  %conv1 = trunc nuw nsw i32 %x to i8
-  %conv2 = trunc nuw nsw i16 %y to i8
-  %cond = icmp ult i8 %conv1, %conv2
-  ret i1 %cond
-}
-
-define i1 @test_slt_nuw(i32 %x, i16 %y) {
-; CHECK-LABEL: define i1 @test_slt_nuw(
-; CHECK-SAME: i32 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[Y]] to i32
-; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[TMP1]], [[X]]
-; CHECK-NEXT:    ret i1 [[COND]]
-;
-  %conv1 = trunc nuw nsw i32 %x to i8
-  %conv2 = trunc nuw nsw i16 %y to i8
-  %cond = icmp slt i8 %conv1, %conv2
-  ret i1 %cond
-}



More information about the llvm-commits mailing list