summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/TargetLowering.h7
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp21
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.h4
-rw-r--r--lib/Target/X86/X86ISelLowering.h4
-rw-r--r--test/CodeGen/PowerPC/crbits.ll2
-rw-r--r--test/CodeGen/PowerPC/select_const.ll180
-rw-r--r--test/CodeGen/X86/avx512-insert-extract.ll10
-rw-r--r--test/CodeGen/X86/avx512-select.ll5
-rw-r--r--test/CodeGen/X86/select_const.ll19
9 files changed, 84 insertions, 168 deletions
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index ab91413e764..b03d35a00b2 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -1388,6 +1388,13 @@ public:
Action != TypeSplitVector;
}
+ /// Return true if a select of constants (select Cond, C1, C2) should be
+ /// transformed into simple math ops with the condition value. For example:
+ /// select Cond, C1, C1-1 --> add (zext Cond), C1-1
+ virtual bool convertSelectOfConstantsToMath() const {
+ return false;
+ }
+
//===--------------------------------------------------------------------===//
// TargetLowering Configuration Methods - These methods should be invoked by
// the derived class constructor to configure this object for the target.
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 8ac41197b62..5b29f18c79b 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -5725,8 +5725,6 @@ SDValue DAGCombiner::foldSelectOfConstants(SDNode *N) {
// transforms in the other direction (create a select from a zext/sext). There
// is also a target-independent combine here in DAGCombiner in the other
// direction for (select Cond, -1, 0) when the condition is not i1.
- // TODO: This could be generalized for any 2 constants that differ by 1:
- // add ({s/z}ext Cond), C
if (CondVT == MVT::i1 && !LegalOperations) {
if (C1->isNullValue() && C2->isOne()) {
// select Cond, 0, 1 --> zext (!Cond)
@@ -5754,6 +5752,25 @@ SDValue DAGCombiner::foldSelectOfConstants(SDNode *N) {
Cond = DAG.getNode(ISD::SIGN_EXTEND, DL, VT, Cond);
return Cond;
}
+
+ // For any constants that differ by 1, we can transform the select into an
+ // extend and add. Use a target hook because some targets may prefer to
+ // transform in the other direction.
+ if (TLI.convertSelectOfConstantsToMath()) {
+ if (C1->getAPIntValue() - 1 == C2->getAPIntValue()) {
+ // select Cond, C1, C1-1 --> add (zext Cond), C1-1
+ if (VT != MVT::i1)
+ Cond = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, Cond);
+ return DAG.getNode(ISD::ADD, DL, VT, Cond, N2);
+ }
+ if (C1->getAPIntValue() + 1 == C2->getAPIntValue()) {
+ // select Cond, C1, C1+1 --> add (sext Cond), C1+1
+ if (VT != MVT::i1)
+ Cond = DAG.getNode(ISD::SIGN_EXTEND, DL, VT, Cond);
+ return DAG.getNode(ISD::ADD, DL, VT, Cond, N2);
+ }
+ }
+
return SDValue();
}
diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h
index d12cd4ab1f3..caaeaa97b0f 100644
--- a/lib/Target/PowerPC/PPCISelLowering.h
+++ b/lib/Target/PowerPC/PPCISelLowering.h
@@ -711,6 +711,10 @@ namespace llvm {
bool shouldConvertConstantLoadToIntImm(const APInt &Imm,
Type *Ty) const override;
+ bool convertSelectOfConstantsToMath() const override {
+ return true;
+ }
+
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
bool getTgtMemIntrinsic(IntrinsicInfo &Info,
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index 14c5531a51b..d9acc1357ec 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -991,6 +991,10 @@ namespace llvm {
bool shouldConvertConstantLoadToIntImm(const APInt &Imm,
Type *Ty) const override;
+ bool convertSelectOfConstantsToMath() const override {
+ return true;
+ }
+
/// Return true if EXTRACT_SUBVECTOR is cheap for this result type
/// with this index.
bool isExtractSubvectorCheap(EVT ResVT, unsigned Index) const override;
diff --git a/test/CodeGen/PowerPC/crbits.ll b/test/CodeGen/PowerPC/crbits.ll
index b894a361d26..a85237195c5 100644
--- a/test/CodeGen/PowerPC/crbits.ll
+++ b/test/CodeGen/PowerPC/crbits.ll
@@ -142,7 +142,7 @@ entry:
ret i32 %cond
; CHECK-LABEL: @exttest7
-; CHECK-DAG: cmplwi {{[0-9]+}}, 3, 5
+; CHECK-DAG: cmpwi {{[0-9]+}}, 3, 5
; CHECK-DAG: li [[REG1:[0-9]+]], 8
; CHECK-DAG: li [[REG2:[0-9]+]], 7
; CHECK: isel 3, [[REG2]], [[REG1]],
diff --git a/test/CodeGen/PowerPC/select_const.ll b/test/CodeGen/PowerPC/select_const.ll
index 142a482bcc1..29548123be8 100644
--- a/test/CodeGen/PowerPC/select_const.ll
+++ b/test/CodeGen/PowerPC/select_const.ll
@@ -218,70 +218,29 @@ define i32 @select_neg1_or_0_signext(i1 signext %cond) {
; select Cond, C+1, C --> add (zext Cond), C
define i32 @select_Cplus1_C(i1 %cond) {
-; ISEL-LABEL: select_Cplus1_C:
-; ISEL: # BB#0:
-; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, 42
-; ISEL-NEXT: li 3, 41
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: blr
-;
-; NO_ISEL-LABEL: select_Cplus1_C:
-; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, 42
-; NO_ISEL-NEXT: li 3, 41
-; NO_ISEL-NEXT: bc 12, 1, .LBB12_1
-; NO_ISEL-NEXT: blr
-; NO_ISEL-NEXT: .LBB12_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: blr
+; ALL-LABEL: select_Cplus1_C:
+; ALL: # BB#0:
+; ALL-NEXT: clrldi 3, 3, 63
+; ALL-NEXT: addi 3, 3, 41
+; ALL-NEXT: blr
%sel = select i1 %cond, i32 42, i32 41
ret i32 %sel
}
define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) {
-; ISEL-LABEL: select_Cplus1_C_zeroext:
-; ISEL: # BB#0:
-; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, 42
-; ISEL-NEXT: li 3, 41
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: blr
-;
-; NO_ISEL-LABEL: select_Cplus1_C_zeroext:
-; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, 42
-; NO_ISEL-NEXT: li 3, 41
-; NO_ISEL-NEXT: bc 12, 1, .LBB13_1
-; NO_ISEL-NEXT: blr
-; NO_ISEL-NEXT: .LBB13_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: blr
+; ALL-LABEL: select_Cplus1_C_zeroext:
+; ALL: # BB#0:
+; ALL-NEXT: addi 3, 3, 41
+; ALL-NEXT: blr
%sel = select i1 %cond, i32 42, i32 41
ret i32 %sel
}
define i32 @select_Cplus1_C_signext(i1 signext %cond) {
-; ISEL-LABEL: select_Cplus1_C_signext:
-; ISEL: # BB#0:
-; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, 42
-; ISEL-NEXT: li 3, 41
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: blr
-;
-; NO_ISEL-LABEL: select_Cplus1_C_signext:
-; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, 42
-; NO_ISEL-NEXT: li 3, 41
-; NO_ISEL-NEXT: bc 12, 1, .LBB14_1
-; NO_ISEL-NEXT: blr
-; NO_ISEL-NEXT: .LBB14_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: blr
+; ALL-LABEL: select_Cplus1_C_signext:
+; ALL: # BB#0:
+; ALL-NEXT: subfic 3, 3, 41
+; ALL-NEXT: blr
%sel = select i1 %cond, i32 42, i32 41
ret i32 %sel
}
@@ -289,70 +248,29 @@ define i32 @select_Cplus1_C_signext(i1 signext %cond) {
; select Cond, C, C+1 --> add (sext Cond), C
define i32 @select_C_Cplus1(i1 %cond) {
-; ISEL-LABEL: select_C_Cplus1:
-; ISEL: # BB#0:
-; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, 41
-; ISEL-NEXT: li 3, 42
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: blr
-;
-; NO_ISEL-LABEL: select_C_Cplus1:
-; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, 41
-; NO_ISEL-NEXT: li 3, 42
-; NO_ISEL-NEXT: bc 12, 1, .LBB15_1
-; NO_ISEL-NEXT: blr
-; NO_ISEL-NEXT: .LBB15_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: blr
+; ALL-LABEL: select_C_Cplus1:
+; ALL: # BB#0:
+; ALL-NEXT: clrldi 3, 3, 63
+; ALL-NEXT: subfic 3, 3, 42
+; ALL-NEXT: blr
%sel = select i1 %cond, i32 41, i32 42
ret i32 %sel
}
define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) {
-; ISEL-LABEL: select_C_Cplus1_zeroext:
-; ISEL: # BB#0:
-; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, 41
-; ISEL-NEXT: li 3, 42
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: blr
-;
-; NO_ISEL-LABEL: select_C_Cplus1_zeroext:
-; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, 41
-; NO_ISEL-NEXT: li 3, 42
-; NO_ISEL-NEXT: bc 12, 1, .LBB16_1
-; NO_ISEL-NEXT: blr
-; NO_ISEL-NEXT: .LBB16_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: blr
+; ALL-LABEL: select_C_Cplus1_zeroext:
+; ALL: # BB#0:
+; ALL-NEXT: subfic 3, 3, 42
+; ALL-NEXT: blr
%sel = select i1 %cond, i32 41, i32 42
ret i32 %sel
}
define i32 @select_C_Cplus1_signext(i1 signext %cond) {
-; ISEL-LABEL: select_C_Cplus1_signext:
-; ISEL: # BB#0:
-; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, 41
-; ISEL-NEXT: li 3, 42
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: blr
-;
-; NO_ISEL-LABEL: select_C_Cplus1_signext:
-; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, 41
-; NO_ISEL-NEXT: li 3, 42
-; NO_ISEL-NEXT: bc 12, 1, .LBB17_1
-; NO_ISEL-NEXT: blr
-; NO_ISEL-NEXT: .LBB17_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: blr
+; ALL-LABEL: select_C_Cplus1_signext:
+; ALL: # BB#0:
+; ALL-NEXT: addi 3, 3, 42
+; ALL-NEXT: blr
%sel = select i1 %cond, i32 41, i32 42
ret i32 %sel
}
@@ -583,48 +501,22 @@ define i8 @sel_constants_srem_constant(i1 %cond) {
}
define i8 @sel_constants_urem_constant(i1 %cond) {
-; ISEL-LABEL: sel_constants_urem_constant:
-; ISEL: # BB#0:
-; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, 2
-; ISEL-NEXT: li 3, 3
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: blr
-;
-; NO_ISEL-LABEL: sel_constants_urem_constant:
-; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, 2
-; NO_ISEL-NEXT: li 3, 3
-; NO_ISEL-NEXT: bc 12, 1, .LBB27_1
-; NO_ISEL-NEXT: blr
-; NO_ISEL-NEXT: .LBB27_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: blr
+; ALL-LABEL: sel_constants_urem_constant:
+; ALL: # BB#0:
+; ALL-NEXT: rlwinm 3, 3, 0, 31, 31
+; ALL-NEXT: subfic 3, 3, 3
+; ALL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = urem i8 %sel, 5
ret i8 %bo
}
define i8 @sel_constants_and_constant(i1 %cond) {
-; ISEL-LABEL: sel_constants_and_constant:
-; ISEL: # BB#0:
-; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, 4
-; ISEL-NEXT: li 3, 5
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: blr
-;
-; NO_ISEL-LABEL: sel_constants_and_constant:
-; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, 4
-; NO_ISEL-NEXT: li 3, 5
-; NO_ISEL-NEXT: bc 12, 1, .LBB28_1
-; NO_ISEL-NEXT: blr
-; NO_ISEL-NEXT: .LBB28_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: blr
+; ALL-LABEL: sel_constants_and_constant:
+; ALL: # BB#0:
+; ALL-NEXT: rlwinm 3, 3, 0, 31, 31
+; ALL-NEXT: subfic 3, 3, 5
+; ALL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = and i8 %sel, 5
ret i8 %bo
diff --git a/test/CodeGen/X86/avx512-insert-extract.ll b/test/CodeGen/X86/avx512-insert-extract.ll
index 9373b4d5007..aee4c6367e2 100644
--- a/test/CodeGen/X86/avx512-insert-extract.ll
+++ b/test/CodeGen/X86/avx512-insert-extract.ll
@@ -1411,10 +1411,8 @@ define zeroext i8 @test_extractelement_v2i1(<2 x i64> %a, <2 x i64> %b) {
; KNL-NEXT: vpxor %xmm2, %xmm1, %xmm1
; KNL-NEXT: vpxor %xmm2, %xmm0, %xmm0
; KNL-NEXT: vpcmpgtq %xmm1, %xmm0, %xmm0
-; KNL-NEXT: vmovq %xmm0, %rax
-; KNL-NEXT: testb $1, %al
-; KNL-NEXT: sete %al
-; KNL-NEXT: addb $3, %al
+; KNL-NEXT: vpextrb $0, %xmm0, %eax
+; KNL-NEXT: addb $4, %al
; KNL-NEXT: movzbl %al, %eax
; KNL-NEXT: retq
;
@@ -1527,9 +1525,7 @@ define zeroext i8 @test_extractelement_v64i1(<64 x i8> %a, <64 x i8> %b) {
; KNL-NEXT: vpcmpgtb %ymm2, %ymm0, %ymm0
; KNL-NEXT: vextracti128 $1, %ymm0, %xmm0
; KNL-NEXT: vpextrb $15, %xmm0, %eax
-; KNL-NEXT: testb $1, %al
-; KNL-NEXT: sete %al
-; KNL-NEXT: addb $3, %al
+; KNL-NEXT: addb $4, %al
; KNL-NEXT: movzbl %al, %eax
; KNL-NEXT: retq
;
diff --git a/test/CodeGen/X86/avx512-select.ll b/test/CodeGen/X86/avx512-select.ll
index 3f427298c17..a2e5a14f78d 100644
--- a/test/CodeGen/X86/avx512-select.ll
+++ b/test/CodeGen/X86/avx512-select.ll
@@ -149,10 +149,7 @@ define i8 @select07(i8 %a.0, i8 %b.0, i8 %m) {
define i64 @pr30249() {
; CHECK-LABEL: pr30249:
; CHECK: ## BB#0:
-; CHECK-NEXT: xorl %ecx, %ecx
-; CHECK-NEXT: cmpb $1, %cl
-; CHECK-NEXT: movl $1, %eax
-; CHECK-NEXT: adcxq %rcx, %rax
+; CHECK-NEXT: movl $2, %eax
; CHECK-NEXT: retq
%v = select i1 undef , i64 1, i64 2
ret i64 %v
diff --git a/test/CodeGen/X86/select_const.ll b/test/CodeGen/X86/select_const.ll
index 716ee70d926..a97e7c299e7 100644
--- a/test/CodeGen/X86/select_const.ll
+++ b/test/CodeGen/X86/select_const.ll
@@ -174,10 +174,9 @@ define i32 @select_Cplus1_C_signext(i1 signext %cond) {
define i32 @select_C_Cplus1(i1 %cond) {
; CHECK-LABEL: select_C_Cplus1:
; CHECK: # BB#0:
-; CHECK-NEXT: andb $1, %dil
-; CHECK-NEXT: cmpb $1, %dil
-; CHECK-NEXT: movl $41, %eax
-; CHECK-NEXT: adcl $0, %eax
+; CHECK-NEXT: andl $1, %edi
+; CHECK-NEXT: movl $42, %eax
+; CHECK-NEXT: subl %edi, %eax
; CHECK-NEXT: retq
%sel = select i1 %cond, i32 41, i32 42
ret i32 %sel
@@ -186,9 +185,9 @@ define i32 @select_C_Cplus1(i1 %cond) {
define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) {
; CHECK-LABEL: select_C_Cplus1_zeroext:
; CHECK: # BB#0:
-; CHECK-NEXT: cmpb $1, %dil
-; CHECK-NEXT: movl $41, %eax
-; CHECK-NEXT: adcl $0, %eax
+; CHECK-NEXT: movzbl %dil, %ecx
+; CHECK-NEXT: movl $42, %eax
+; CHECK-NEXT: subl %ecx, %eax
; CHECK-NEXT: retq
%sel = select i1 %cond, i32 41, i32 42
ret i32 %sel
@@ -198,9 +197,9 @@ define i32 @select_C_Cplus1_signext(i1 signext %cond) {
; CHECK-LABEL: select_C_Cplus1_signext:
; CHECK: # BB#0:
; CHECK-NEXT: andb $1, %dil
-; CHECK-NEXT: cmpb $1, %dil
-; CHECK-NEXT: movl $41, %eax
-; CHECK-NEXT: adcl $0, %eax
+; CHECK-NEXT: movzbl %dil, %ecx
+; CHECK-NEXT: movl $42, %eax
+; CHECK-NEXT: subl %ecx, %eax
; CHECK-NEXT: retq
%sel = select i1 %cond, i32 41, i32 42
ret i32 %sel