/select.patch Secret
Created
January 16, 2021 11:42
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit c4b903e62a8d9da14a73f0eeb44f8916df1173e4 | |
Author: Nikita Popov <nikita.ppv@gmail.com> | |
Date: Sat Jan 16 12:41:35 2021 +0100 | |
select equiv | |
diff --git llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | |
index 5a43b8b20db9..73e1835a7433 100644 | |
--- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | |
+++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | |
@@ -1113,10 +1113,24 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel, | |
// replacement cycle. | |
Value *CmpLHS = Cmp.getOperand(0), *CmpRHS = Cmp.getOperand(1); | |
if (TrueVal != CmpLHS && | |
- isGuaranteedNotToBeUndefOrPoison(CmpRHS, SQ.AC, &Sel, &DT)) | |
+ isGuaranteedNotToBeUndefOrPoison(CmpRHS, SQ.AC, &Sel, &DT)) { | |
if (Value *V = SimplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, SQ, | |
/* AllowRefinement */ true)) | |
return replaceOperand(Sel, Swapped ? 2 : 1, V); | |
+ | |
+ // Even if TrueVal does not simplify, we can simply directly replace a use | |
+ // of CmpLHS with CmpRHS, as long as the instruciton is not used anywhere | |
+ // else. Only do this if CmpRHS is a constant, as profitability is not | |
+ // clear for other cases. | |
+ if (isa<Constant>(CmpRHS) && !isa<ConstantExpr>(CmpRHS)) | |
+ if (auto *I = dyn_cast<Instruction>(TrueVal)) | |
+ if (I->hasOneUse()) | |
+ for (Use &U : I->operands()) | |
+ if (U == CmpLHS) { | |
+ replaceUse(U, CmpRHS); | |
+ return &Sel; | |
+ } | |
+ } | |
if (TrueVal != CmpRHS && | |
isGuaranteedNotToBeUndefOrPoison(CmpLHS, SQ.AC, &Sel, &DT)) | |
if (Value *V = SimplifyWithOpReplaced(TrueVal, CmpRHS, CmpLHS, SQ, | |
diff --git llvm/test/Transforms/InstCombine/select-binop-cmp.ll llvm/test/Transforms/InstCombine/select-binop-cmp.ll | |
index c4a9d0941b96..b54125a53208 100644 | |
--- llvm/test/Transforms/InstCombine/select-binop-cmp.ll | |
+++ llvm/test/Transforms/InstCombine/select-binop-cmp.ll | |
@@ -502,7 +502,7 @@ define i32 @select_xor_icmp_bad_2(i32 %x, i32 %y, i32 %z, i32 %k) { | |
define i32 @select_xor_icmp_bad_3(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_xor_icmp_bad_3( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 3 | |
-; CHECK-NEXT: [[B:%.*]] = xor i32 [[X]], [[Z:%.*]] | |
+; CHECK-NEXT: [[B:%.*]] = xor i32 [[Z:%.*]], 3 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -541,7 +541,7 @@ define i32 @select_xor_icmp_bad_5(i32 %x, i32 %y, i32 %z) { | |
define i32 @select_xor_icmp_bad_6(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_xor_icmp_bad_6( | |
; CHECK-NEXT: [[A_NOT:%.*]] = icmp eq i32 [[X:%.*]], 1 | |
-; CHECK-NEXT: [[B:%.*]] = xor i32 [[X]], [[Z:%.*]] | |
+; CHECK-NEXT: [[B:%.*]] = xor i32 [[Z:%.*]], 1 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A_NOT]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -554,7 +554,7 @@ define i32 @select_xor_icmp_bad_6(i32 %x, i32 %y, i32 %z) { | |
define <2 x i8> @select_xor_icmp_vec_bad(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) { | |
; CHECK-LABEL: @select_xor_icmp_vec_bad( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq <2 x i8> [[X:%.*]], <i8 5, i8 3> | |
-; CHECK-NEXT: [[B:%.*]] = xor <2 x i8> [[X]], [[Z:%.*]] | |
+; CHECK-NEXT: [[B:%.*]] = xor <2 x i8> [[Z:%.*]], <i8 5, i8 3> | |
; CHECK-NEXT: [[C:%.*]] = select <2 x i1> [[A]], <2 x i8> [[B]], <2 x i8> [[Y:%.*]] | |
; CHECK-NEXT: ret <2 x i8> [[C]] | |
; | |
@@ -581,7 +581,7 @@ define <2 x i8> @select_xor_icmp_vec_undef(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z | |
define i32 @select_mul_icmp_bad(i32 %x, i32 %y, i32 %z, i32 %k) { | |
; CHECK-LABEL: @select_mul_icmp_bad( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 3 | |
-; CHECK-NEXT: [[B:%.*]] = mul i32 [[X]], [[Z:%.*]] | |
+; CHECK-NEXT: [[B:%.*]] = mul i32 [[Z:%.*]], 3 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -594,7 +594,7 @@ define i32 @select_mul_icmp_bad(i32 %x, i32 %y, i32 %z, i32 %k) { | |
define i32 @select_add_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_add_icmp_bad( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 1 | |
-; CHECK-NEXT: [[B:%.*]] = add i32 [[X]], [[Z:%.*]] | |
+; CHECK-NEXT: [[B:%.*]] = add i32 [[Z:%.*]], 1 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -619,7 +619,7 @@ define i32 @select_and_icmp_zero(i32 %x, i32 %y, i32 %z) { | |
define i32 @select_or_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_or_icmp_bad( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 3 | |
-; CHECK-NEXT: [[B:%.*]] = or i32 [[X]], [[Z:%.*]] | |
+; CHECK-NEXT: [[B:%.*]] = or i32 [[Z:%.*]], 3 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -940,7 +940,7 @@ define float @select_fsub_fcmp_bad_2(float %x, float %y, float %z) { | |
define i32 @select_sub_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_sub_icmp_bad( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 0 | |
-; CHECK-NEXT: [[B:%.*]] = sub i32 [[X]], [[Z:%.*]] | |
+; CHECK-NEXT: [[B:%.*]] = sub i32 0, [[Z:%.*]] | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -953,7 +953,7 @@ define i32 @select_sub_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
define i32 @select_sub_icmp_bad_2(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_sub_icmp_bad_2( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 1 | |
-; CHECK-NEXT: [[B:%.*]] = sub i32 [[Z:%.*]], [[X]] | |
+; CHECK-NEXT: [[B:%.*]] = add i32 [[Z:%.*]], -1 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -1022,7 +1022,7 @@ define i32 @select_sub_icmp_bad_5(i32 %x, i32 %y, i32 %z, i32 %k) { | |
define i32 @select_shl_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_shl_icmp_bad( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 1 | |
-; CHECK-NEXT: [[B:%.*]] = shl i32 [[Z:%.*]], [[X]] | |
+; CHECK-NEXT: [[B:%.*]] = shl i32 [[Z:%.*]], 1 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -1035,7 +1035,7 @@ define i32 @select_shl_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
define i32 @select_lshr_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_lshr_icmp_bad( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 1 | |
-; CHECK-NEXT: [[B:%.*]] = lshr i32 [[Z:%.*]], [[X]] | |
+; CHECK-NEXT: [[B:%.*]] = lshr i32 [[Z:%.*]], 1 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -1048,7 +1048,7 @@ define i32 @select_lshr_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
define i32 @select_ashr_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_ashr_icmp_bad( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 1 | |
-; CHECK-NEXT: [[B:%.*]] = ashr i32 [[Z:%.*]], [[X]] | |
+; CHECK-NEXT: [[B:%.*]] = ashr i32 [[Z:%.*]], 1 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -1061,7 +1061,7 @@ define i32 @select_ashr_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
define i32 @select_udiv_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_udiv_icmp_bad( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 3 | |
-; CHECK-NEXT: [[B:%.*]] = udiv i32 [[Z:%.*]], [[X]] | |
+; CHECK-NEXT: [[B:%.*]] = udiv i32 [[Z:%.*]], 3 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
@@ -1074,7 +1074,7 @@ define i32 @select_udiv_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
define i32 @select_sdiv_icmp_bad(i32 %x, i32 %y, i32 %z) { | |
; CHECK-LABEL: @select_sdiv_icmp_bad( | |
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 3 | |
-; CHECK-NEXT: [[B:%.*]] = sdiv i32 [[Z:%.*]], [[X]] | |
+; CHECK-NEXT: [[B:%.*]] = sdiv i32 [[Z:%.*]], 3 | |
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 [[Y:%.*]] | |
; CHECK-NEXT: ret i32 [[C]] | |
; | |
diff --git llvm/test/Transforms/InstCombine/select-safe-transforms.ll llvm/test/Transforms/InstCombine/select-safe-transforms.ll | |
index b16985ba1b75..f6dfb672e7f2 100644 | |
--- llvm/test/Transforms/InstCombine/select-safe-transforms.ll | |
+++ llvm/test/Transforms/InstCombine/select-safe-transforms.ll | |
@@ -17,7 +17,7 @@ define i1 @cond_eq_and(i8 %X, i8 %Y, i8 noundef %C) { | |
define i1 @cond_eq_and_const(i8 %X, i8 %Y) { | |
; CHECK-LABEL: @cond_eq_and_const( | |
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[X:%.*]], 10 | |
-; CHECK-NEXT: [[LHS:%.*]] = icmp ult i8 [[X]], [[Y:%.*]] | |
+; CHECK-NEXT: [[LHS:%.*]] = icmp ugt i8 [[Y:%.*]], 10 | |
; CHECK-NEXT: [[RES:%.*]] = select i1 [[COND]], i1 [[LHS]], i1 false | |
; CHECK-NEXT: ret i1 [[RES]] | |
; | |
@@ -43,7 +43,7 @@ define i1 @cond_eq_or(i8 %X, i8 %Y, i8 noundef %C) { | |
define i1 @cond_eq_or_const(i8 %X, i8 %Y) { | |
; CHECK-LABEL: @cond_eq_or_const( | |
; CHECK-NEXT: [[COND:%.*]] = icmp ne i8 [[X:%.*]], 10 | |
-; CHECK-NEXT: [[LHS:%.*]] = icmp ult i8 [[X]], [[Y:%.*]] | |
+; CHECK-NEXT: [[LHS:%.*]] = icmp ugt i8 [[Y:%.*]], 10 | |
; CHECK-NEXT: [[RES:%.*]] = select i1 [[COND]], i1 true, i1 [[LHS]] | |
; CHECK-NEXT: ret i1 [[RES]] | |
; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment