[llvm] goldsteinn/pr71330 (PR #71489)

via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 6 21:45:38 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: None (goldsteinn)

<details>
<summary>Changes</summary>

- [InstCombine] Add reduced test for PR 71330; NFC
- [InstCombine] Fix buggy transform in `foldNestedSelects`; PR 71330


---
Full diff: https://github.com/llvm/llvm-project/pull/71489.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (+9-2) 
- (added) llvm/test/Transforms/InstCombine/pr71330.ll (+229) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 9bd49f76d4bd5b7..71c2d68881441ac 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2891,8 +2891,15 @@ static Instruction *foldNestedSelects(SelectInst &OuterSelVal,
     std::swap(InnerSel.TrueVal, InnerSel.FalseVal);
 
   Value *AltCond = nullptr;
-  auto matchOuterCond = [OuterSel, &AltCond](auto m_InnerCond) {
-    return match(OuterSel.Cond, m_c_LogicalOp(m_InnerCond, m_Value(AltCond)));
+  auto matchOuterCond = [OuterSel, IsAndVariant, &AltCond](auto m_InnerCond) {
+    // An unsimplified select condition can match both LogicalAnd and LogicalOr
+    // (select true, true, false). Since below we assume that LogicalAnd implies
+    // InnerSel match the FVal and vice versa for LogicalOr, we can't match the
+    // alternative pattern here.
+    return IsAndVariant ? match(OuterSel.Cond,
+                                m_c_LogicalAnd(m_InnerCond, m_Value(AltCond)))
+                        : match(OuterSel.Cond,
+                                m_c_LogicalOr(m_InnerCond, m_Value(AltCond)));
   };
 
   // Finally, match the condition that was driving the outermost `select`,
diff --git a/llvm/test/Transforms/InstCombine/pr71330.ll b/llvm/test/Transforms/InstCombine/pr71330.ll
new file mode 100644
index 000000000000000..635eb42182ec642
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/pr71330.ll
@@ -0,0 +1,229 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -O3 -S < %s | FileCheck %s
+
+ at e = global i8 5
+ at c = global i64 0
+ at k = global i8 0
+ at n = global i16 0
+ at o = global i32 0
+
+define void @pr71330(ptr %s, i32 %.pre, i8 %0) {
+; CHECK-LABEL: define void @pr71330(
+; CHECK-SAME: ptr nocapture writeonly [[S:%.*]], i32 [[DOTPRE:%.*]], i8 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i32 [[DOTPRE]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label [[FOR_COND5_PREHEADER:%.*]], label [[COMMON_RET:%.*]]
+; CHECK:       for.cond5.preheader:
+; CHECK-NEXT:    [[TOBOOL28_NOT:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr @e, align 1
+; CHECK-NEXT:    [[DOTFR:%.*]] = freeze i8 [[TMP1]]
+; CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[DOTFR]] to i32
+; CHECK-NEXT:    [[C_PROMOTED:%.*]] = load i64, ptr @c, align 8
+; CHECK-NEXT:    [[K_PROMOTED:%.*]] = load i8, ptr @k, align 1
+; CHECK-NEXT:    [[TOBOOL19_NOT1:%.*]] = icmp eq i8 [[DOTFR]], 0
+; CHECK-NEXT:    [[ADD9_US:%.*]] = add nsw i32 [[CONV]], 9
+; CHECK-NEXT:    br i1 [[TOBOOL19_NOT1]], label [[FOR_COND7_PREHEADER_SPLIT_US_SPLIT:%.*]], label [[FOR_COND7_PREHEADER10:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       for.cond7.preheader10:
+; CHECK-NEXT:    [[CONV10:%.*]] = sext i32 [[ADD9_US]] to i64
+; CHECK-NEXT:    [[INC:%.*]] = or i8 [[K_PROMOTED]], 1
+; CHECK-NEXT:    [[INC24:%.*]] = or i64 [[C_PROMOTED]], 1
+; CHECK-NEXT:    [[ADD1112:%.*]] = or i64 [[C_PROMOTED]], [[CONV10]]
+; CHECK-NEXT:    [[CMP1213:%.*]] = icmp slt i64 [[ADD1112]], 15
+; CHECK-NEXT:    br i1 [[CMP1213]], label [[FOR_BODY14_PREHEADER:%.*]], label [[FOR_COND27_PREHEADER:%.*]]
+; CHECK:       for.body14.preheader:
+; CHECK-NEXT:    store i8 [[INC]], ptr @k, align 1
+; CHECK-NEXT:    store i16 0, ptr @n, align 2
+; CHECK-NEXT:    store i32 0, ptr @o, align 4
+; CHECK-NEXT:    store i64 [[INC24]], ptr @c, align 8
+; CHECK-NEXT:    [[ADD11:%.*]] = or i64 [[INC24]], [[CONV10]]
+; CHECK-NEXT:    [[CMP12:%.*]] = icmp slt i64 [[ADD11]], 15
+; CHECK-NEXT:    br label [[FOR_BODY14:%.*]]
+; CHECK:       for.cond7.preheader.split.us.split:
+; CHECK-NEXT:    [[CONV10_US:%.*]] = zext nneg i32 [[ADD9_US]] to i64
+; CHECK-NEXT:    [[ADD11_US4:%.*]] = or i64 [[C_PROMOTED]], [[CONV10_US]]
+; CHECK-NEXT:    [[CMP12_US5:%.*]] = icmp slt i64 [[ADD11_US4]], 15
+; CHECK-NEXT:    br i1 [[CMP12_US5]], label [[FOR_BODY14_US_LR_PH:%.*]], label [[FOR_COND27_PREHEADER]]
+; CHECK:       for.body14.us.lr.ph:
+; CHECK-NEXT:    store i16 0, ptr @n, align 2
+; CHECK-NEXT:    [[INC24_US:%.*]] = or i64 [[C_PROMOTED]], 1
+; CHECK-NEXT:    [[ADD11_US:%.*]] = or i64 [[INC24_US]], [[CONV10_US]]
+; CHECK-NEXT:    [[CMP12_US:%.*]] = icmp slt i64 [[ADD11_US]], 15
+; CHECK-NEXT:    br label [[FOR_BODY14_US:%.*]]
+; CHECK:       for.body14.us:
+; CHECK-NEXT:    br i1 [[CMP12_US]], label [[FOR_BODY14_US]], label [[FOR_COND7_US_FOR_COND27_PREHEADER_SPLIT_US_SPLIT_CRIT_EDGE:%.*]]
+; CHECK:       for.cond7.us.for.cond27.preheader.split.us.split_crit_edge:
+; CHECK-NEXT:    [[INC_US:%.*]] = or i8 [[K_PROMOTED]], 1
+; CHECK-NEXT:    store i8 [[INC_US]], ptr @k, align 1
+; CHECK-NEXT:    store i64 [[INC24_US]], ptr @c, align 8
+; CHECK-NEXT:    br label [[FOR_COND27_PREHEADER]]
+; CHECK:       for.cond27.preheader:
+; CHECK-NEXT:    br i1 [[TOBOOL28_NOT]], label [[COMMON_RET]], label [[FOR_INC30_LR_PH:%.*]]
+; CHECK:       for.inc30.lr.ph:
+; CHECK-NEXT:    store i8 0, ptr [[S]], align 1
+; CHECK-NEXT:    br label [[FOR_INC30:%.*]]
+; CHECK:       for.body14:
+; CHECK-NEXT:    br label [[FOR_BODY20:%.*]]
+; CHECK:       for.body20:
+; CHECK-NEXT:    [[TMP2:%.*]] = phi i16 [ 0, [[FOR_BODY14]] ], [ [[INC21:%.*]], [[FOR_BODY20]] ]
+; CHECK-NEXT:    [[INC21]] = add i16 [[TMP2]], 1
+; CHECK-NEXT:    [[CONV17:%.*]] = sext i16 [[INC21]] to i32
+; CHECK-NEXT:    [[ADD18:%.*]] = sub nsw i32 0, [[CONV17]]
+; CHECK-NEXT:    [[TOBOOL19_NOT:%.*]] = icmp eq i32 [[CONV]], [[ADD18]]
+; CHECK-NEXT:    br i1 [[TOBOOL19_NOT]], label [[FOR_COND15_FOR_INC23_CRIT_EDGE:%.*]], label [[FOR_BODY20]]
+; CHECK:       for.cond15.for.inc23_crit_edge:
+; CHECK-NEXT:    br i1 [[CMP12]], label [[FOR_BODY14]], label [[FOR_COND27_PREHEADER]]
+; CHECK:       for.inc30:
+; CHECK-NEXT:    br label [[FOR_INC30]]
+;
+entry:
+  %tobool.not = icmp eq i32 %.pre, 0
+  br i1 %tobool.not, label %for.cond5, label %common.ret
+
+common.ret:  ; preds = %for.cond5, %entry
+  ret void
+
+for.cond5:  ; preds = %for.cond27, %entry
+  %storemerge4 = phi i32 [ -3, %entry ], [ %.pre, %for.cond27 ]
+  %cmp = icmp slt i32 %storemerge4, 0
+  br i1 %cmp, label %for.cond7, label %common.ret
+
+for.cond7:  ; preds = %for.inc23, %for.cond5
+  %add = add nsw i32 %storemerge4, 8
+  %and.i.i = and i32 %add, 8
+  %cmp.i.i = icmp eq i32 %and.i.i, 0
+  br i1 %cmp.i.i, label %fn3.exit, label %if.end.i.i
+
+if.end.i.i:  ; preds = %for.cond7
+  %and2.i.i = and i32 %add, 12
+  %cmp3.i.i = icmp eq i32 %and2.i.i, 0
+  br i1 %cmp3.i.i, label %fn3.exit, label %if.end5.i.i
+
+if.end5.i.i:  ; preds = %if.end.i.i
+  %and7.i.i = and i32 %storemerge4, 1
+  %cmp8.i.i = icmp eq i32 %and7.i.i, 0
+  br i1 %cmp8.i.i, label %fn3.exit, label %if.end10.i.i
+
+if.end10.i.i:  ; preds = %if.end5.i.i
+  %tobool.not.i.i = icmp eq i32 %add, 0
+  %..i.i = select i1 %tobool.not.i.i, i32 0, i32 3
+  br label %fn3.exit
+
+fn3.exit:  ; preds = %if.end10.i.i, %if.end5.i.i, %if.end.i.i, %for.cond7
+  %retval.0.i.i = phi i32 [ 0, %for.cond7 ], [ 1, %if.end.i.i ], [ 0, %if.end5.i.i ], [ %..i.i, %if.end10.i.i ]
+  %1 = load i8, ptr @e, align 1
+  %conv = sext i8 %1 to i32
+  %add8 = or i32 %conv, %retval.0.i.i
+  %add9 = add i32 %add8, 9
+  %conv10 = sext i32 %add9 to i64
+  %2 = load i64, ptr @c, align 8
+  %add11 = or i64 %conv10, %2
+  %cmp12 = icmp slt i64 %add11, 15
+  br i1 %cmp12, label %for.body14, label %for.cond27
+
+for.body14:  ; preds = %fn3.exit
+  %3 = load i8, ptr @k, align 1
+  %inc = or i8 %3, 1
+  store i8 %inc, ptr @k, align 1
+  br label %for.cond15
+
+for.cond15:  ; preds = %for.body20, %for.body14
+  %4 = phi i16 [ 0, %for.body14 ], [ %inc21, %for.body20 ]
+  store i16 0, ptr @n, align 2
+  %conv17 = sext i16 %4 to i32
+  %add18 = sub i32 0, %conv17
+  %tobool19.not = icmp eq i32 %conv, %add18
+  br i1 %tobool19.not, label %for.inc23, label %for.body20
+
+for.body20:  ; preds = %for.cond15
+  store i32 0, ptr @o, align 4
+  %inc21 = add i16 %4, 1
+  br label %for.cond15
+
+for.inc23:  ; preds = %for.cond15
+  %inc24 = or i64 %2, 1
+  store i64 %inc24, ptr @c, align 8
+  br label %for.cond7
+
+for.cond27:  ; preds = %for.inc30, %fn3.exit
+  %tobool28.not = icmp eq i8 %0, 0
+  br i1 %tobool28.not, label %for.cond5, label %for.inc30
+
+for.inc30:  ; preds = %for.cond27
+  store i8 0, ptr %s, align 1
+  br label %for.cond27
+}
+
+define i32 @pr71330_main() local_unnamed_addr {
+; CHECK-LABEL: define i32 @pr71330_main(
+; CHECK-SAME: ) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr @e, align 1
+; CHECK-NEXT:    [[DOTFR_I:%.*]] = freeze i8 [[TMP0]]
+; CHECK-NEXT:    [[CONV_I:%.*]] = sext i8 [[DOTFR_I]] to i32
+; CHECK-NEXT:    [[C_PROMOTED_I:%.*]] = load i64, ptr @c, align 8
+; CHECK-NEXT:    [[K_PROMOTED_I:%.*]] = load i8, ptr @k, align 1
+; CHECK-NEXT:    [[TOBOOL19_NOT1_I:%.*]] = icmp eq i8 [[DOTFR_I]], 0
+; CHECK-NEXT:    [[ADD9_US_I:%.*]] = add nsw i32 [[CONV_I]], 9
+; CHECK-NEXT:    br i1 [[TOBOOL19_NOT1_I]], label [[FOR_COND7_PREHEADER_SPLIT_US_SPLIT_I:%.*]], label [[FOR_COND7_PREHEADER10_I:%.*]]
+; CHECK:       for.cond7.preheader10.i:
+; CHECK-NEXT:    [[CONV10_I:%.*]] = sext i32 [[ADD9_US_I]] to i64
+; CHECK-NEXT:    [[ADD11_I1:%.*]] = or i64 [[C_PROMOTED_I]], [[CONV10_I]]
+; CHECK-NEXT:    [[CMP12_I2:%.*]] = icmp slt i64 [[ADD11_I1]], 15
+; CHECK-NEXT:    br i1 [[CMP12_I2]], label [[FOR_BODY14_I_LR_PH:%.*]], label [[PR71330_EXIT:%.*]]
+; CHECK:       for.body14.i.lr.ph:
+; CHECK-NEXT:    [[INC24_I:%.*]] = or i64 [[C_PROMOTED_I]], 1
+; CHECK-NEXT:    [[INC_I:%.*]] = or i8 [[K_PROMOTED_I]], 1
+; CHECK-NEXT:    store i8 [[INC_I]], ptr @k, align 1
+; CHECK-NEXT:    store i16 0, ptr @n, align 2
+; CHECK-NEXT:    store i32 0, ptr @o, align 4
+; CHECK-NEXT:    store i64 [[INC24_I]], ptr @c, align 8
+; CHECK-NEXT:    [[ADD11_I:%.*]] = or i64 [[INC24_I]], [[CONV10_I]]
+; CHECK-NEXT:    [[CMP12_I:%.*]] = icmp slt i64 [[ADD11_I]], 15
+; CHECK-NEXT:    br i1 [[CMP12_I]], label [[FOR_BODY14_I_US:%.*]], label [[FOR_BODY20_I:%.*]]
+; CHECK:       for.body14.i.us:
+; CHECK-NEXT:    br label [[FOR_BODY20_I_US:%.*]]
+; CHECK:       for.body20.i.us:
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i16 [ 0, [[FOR_BODY14_I_US]] ], [ [[INC21_I_US:%.*]], [[FOR_BODY20_I_US]] ]
+; CHECK-NEXT:    [[INC21_I_US]] = add i16 [[TMP1]], 1
+; CHECK-NEXT:    [[CONV17_I_US:%.*]] = sext i16 [[INC21_I_US]] to i32
+; CHECK-NEXT:    [[ADD18_I_US:%.*]] = sub nsw i32 0, [[CONV17_I_US]]
+; CHECK-NEXT:    [[TOBOOL19_NOT_I_US:%.*]] = icmp eq i32 [[CONV_I]], [[ADD18_I_US]]
+; CHECK-NEXT:    br i1 [[TOBOOL19_NOT_I_US]], label [[FOR_BODY14_I_US]], label [[FOR_BODY20_I_US]]
+; CHECK:       for.cond7.preheader.split.us.split.i:
+; CHECK-NEXT:    [[CONV10_US_I:%.*]] = zext nneg i32 [[ADD9_US_I]] to i64
+; CHECK-NEXT:    [[ADD11_US4_I:%.*]] = or i64 [[C_PROMOTED_I]], [[CONV10_US_I]]
+; CHECK-NEXT:    [[CMP12_US5_I:%.*]] = icmp slt i64 [[ADD11_US4_I]], 15
+; CHECK-NEXT:    br i1 [[CMP12_US5_I]], label [[FOR_BODY14_US_LR_PH_I:%.*]], label [[PR71330_EXIT]]
+; CHECK:       for.body14.us.lr.ph.i:
+; CHECK-NEXT:    store i16 0, ptr @n, align 2
+; CHECK-NEXT:    [[INC24_US_I:%.*]] = or i64 [[C_PROMOTED_I]], 1
+; CHECK-NEXT:    [[ADD11_US_I:%.*]] = or i64 [[INC24_US_I]], [[CONV10_US_I]]
+; CHECK-NEXT:    [[CMP12_US_I:%.*]] = icmp slt i64 [[ADD11_US_I]], 15
+; CHECK-NEXT:    br i1 [[CMP12_US_I]], label [[FOR_BODY14_US_I:%.*]], label [[FOR_COND7_US_FOR_COND27_PREHEADER_SPLIT_US_SPLIT_CRIT_EDGE_I:%.*]]
+; CHECK:       for.body14.us.i:
+; CHECK-NEXT:    br label [[FOR_BODY14_US_I]]
+; CHECK:       for.cond7.us.for.cond27.preheader.split.us.split_crit_edge.i:
+; CHECK-NEXT:    [[INC_US_I:%.*]] = or i8 [[K_PROMOTED_I]], 1
+; CHECK-NEXT:    store i8 [[INC_US_I]], ptr @k, align 1
+; CHECK-NEXT:    store i64 [[INC24_US_I]], ptr @c, align 8
+; CHECK-NEXT:    br label [[PR71330_EXIT]]
+; CHECK:       for.body20.i:
+; CHECK-NEXT:    [[TMP2:%.*]] = phi i16 [ [[INC21_I:%.*]], [[FOR_BODY20_I]] ], [ 0, [[FOR_BODY14_I_LR_PH]] ]
+; CHECK-NEXT:    [[INC21_I]] = add i16 [[TMP2]], 1
+; CHECK-NEXT:    [[CONV17_I:%.*]] = sext i16 [[INC21_I]] to i32
+; CHECK-NEXT:    [[ADD18_I:%.*]] = sub nsw i32 0, [[CONV17_I]]
+; CHECK-NEXT:    [[TOBOOL19_NOT_I:%.*]] = icmp eq i32 [[CONV_I]], [[ADD18_I]]
+; CHECK-NEXT:    br i1 [[TOBOOL19_NOT_I]], label [[PR71330_EXIT]], label [[FOR_BODY20_I]]
+; CHECK:       pr71330.exit:
+; CHECK-NEXT:    [[TMP3:%.*]] = phi i8 [ [[K_PROMOTED_I]], [[FOR_COND7_PREHEADER10_I]] ], [ [[K_PROMOTED_I]], [[FOR_COND7_PREHEADER_SPLIT_US_SPLIT_I]] ], [ [[INC_US_I]], [[FOR_COND7_US_FOR_COND27_PREHEADER_SPLIT_US_SPLIT_CRIT_EDGE_I]] ], [ [[INC_I]], [[FOR_BODY20_I]] ]
+; CHECK-NEXT:    [[CONV1:%.*]] = sext i8 [[TMP3]] to i32
+; CHECK-NEXT:    ret i32 [[CONV1]]
+;
+entry:
+  call void @pr71330(ptr null, i32 0, i8 0)
+  %0 = load i8, ptr @k, align 1
+  %conv1 = sext i8 %0 to i32
+  ret i32 %conv1
+}

``````````

</details>


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


More information about the llvm-commits mailing list