Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1877,16 +1877,16 @@ BinOpcode == ISD::FDIV || BinOpcode == ISD::FREM) && "Unexpected binary operator"); - // Bail out if any constants are opaque because we can't constant fold those. - SDValue C1 = BO->getOperand(1); - if (!isConstantOrConstantVector(C1, true) && - !isConstantFPBuildVectorOrConstantFP(C1)) - return SDValue(); - // Don't do this unless the old select is going away. We want to eliminate the // binary operator, not replace a binop with a select. // TODO: Handle ISD::SELECT_CC. + unsigned SelOpNo = 0; SDValue Sel = BO->getOperand(0); + if (Sel.getOpcode() != ISD::SELECT || !Sel.hasOneUse()) { + SelOpNo = 1; + Sel = BO->getOperand(1); + } + if (Sel.getOpcode() != ISD::SELECT || !Sel.hasOneUse()) return SDValue(); @@ -1900,19 +1900,41 @@ !isConstantFPBuildVectorOrConstantFP(CF)) return SDValue(); + // Bail out if any constants are opaque because we can't constant fold those. + // The exception is "and" and "or" with either 0 or -1 in which case we can + // propagate non constant operands into select. + bool CanFoldNonConst = false; + if (BinOpcode == ISD::AND || BinOpcode == ISD::OR) { + ConstantSDNode *CTN = cast(CT); + ConstantSDNode *CFN = cast(CF); + CanFoldNonConst = (CTN->isNullValue() || CTN->isAllOnesValue()) && + (CFN->isNullValue() || CFN->isAllOnesValue()); + } + + SDValue C1 = BO->getOperand(SelOpNo ^ 1); + if (!CanFoldNonConst && + !isConstantOrConstantVector(C1, true) && + !isConstantFPBuildVectorOrConstantFP(C1)) + return SDValue(); + // We have a select-of-constants followed by a binary operator with a // constant. Eliminate the binop by pulling the constant math into the select. // Example: add (select Cond, CT, CF), C1 --> select Cond, CT + C1, CF + C1 EVT VT = Sel.getValueType(); + if (SelOpNo && VT != C1.getValueType()) + return SDValue(); + SDLoc DL(Sel); - SDValue NewCT = DAG.getNode(BinOpcode, DL, VT, CT, C1); - if (!NewCT.isUndef() && + SDValue NewCT = SelOpNo ? DAG.getNode(BinOpcode, DL, VT, C1, CT) + : DAG.getNode(BinOpcode, DL, VT, CT, C1); + if (!CanFoldNonConst && !NewCT.isUndef() && !isConstantOrConstantVector(NewCT, true) && !isConstantFPBuildVectorOrConstantFP(NewCT)) return SDValue(); - SDValue NewCF = DAG.getNode(BinOpcode, DL, VT, CF, C1); - if (!NewCF.isUndef() && + SDValue NewCF = SelOpNo ? DAG.getNode(BinOpcode, DL, VT, C1, CF) + : DAG.getNode(BinOpcode, DL, VT, CF, C1); + if (!CanFoldNonConst && !NewCF.isUndef() && !isConstantOrConstantVector(NewCF, true) && !isConstantFPBuildVectorOrConstantFP(NewCF)) return SDValue(); Index: test/CodeGen/AMDGPU/dagcombine-select.ll =================================================================== --- /dev/null +++ test/CodeGen/AMDGPU/dagcombine-select.ll @@ -0,0 +1,148 @@ +; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefix=GCN %s + +; GCN-LABEL: {{^}}select_and1: +; GCN: v_cndmask_b32_e32 [[SEL:v[0-9]+]], 0, v{{[0-9]+}}, +; GCN-NOT: v_and_b32 +; GCN: store_dword [[SEL]], +define amdgpu_kernel void @select_and1(i32 addrspace(1)* %p, i32 %x, i32 %y) { + %c = icmp slt i32 %x, 11 + %s = select i1 %c, i32 0, i32 -1 + %a = and i32 %y, %s + store i32 %a, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}select_and2: +; GCN: v_cndmask_b32_e32 [[SEL:v[0-9]+]], 0, v{{[0-9]+}}, +; GCN-NOT: v_and_b32 +; GCN: store_dword [[SEL]], +define amdgpu_kernel void @select_and2(i32 addrspace(1)* %p, i32 %x, i32 %y) { + %c = icmp slt i32 %x, 11 + %s = select i1 %c, i32 0, i32 -1 + %a = and i32 %s, %y + store i32 %a, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}select_or1: +; GCN: v_cndmask_b32_e32 [[SEL:v[0-9]+]], -1, v{{[0-9]+}}, +; GCN-NOT: v_or_b32 +; GCN: store_dword [[SEL]], +define amdgpu_kernel void @select_or1(i32 addrspace(1)* %p, i32 %x, i32 %y) { + %c = icmp slt i32 %x, 11 + %s = select i1 %c, i32 0, i32 -1 + %a = or i32 %y, %s + store i32 %a, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}select_or2: +; GCN: v_cndmask_b32_e32 [[SEL:v[0-9]+]], -1, v{{[0-9]+}}, +; GCN-NOT: v_or_b32 +; GCN: store_dword [[SEL]], +define amdgpu_kernel void @select_or2(i32 addrspace(1)* %p, i32 %x, i32 %y) { + %c = icmp slt i32 %x, 11 + %s = select i1 %c, i32 0, i32 -1 + %a = or i32 %s, %y + store i32 %a, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}sel_constants_sub_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, 2, 9, +define amdgpu_kernel void @sel_constants_sub_constant_sel_constants(i32 addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, i32 -4, i32 3 + %bo = sub i32 5, %sel + store i32 %bo, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}sdiv_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, 5, 0, +define amdgpu_kernel void @sdiv_constant_sel_constants(i32 addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, i32 121, i32 23 + %bo = sdiv i32 120, %sel + store i32 %bo, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}udiv_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, 5, 0, +define amdgpu_kernel void @udiv_constant_sel_constants(i32 addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, i32 -4, i32 23 + %bo = udiv i32 120, %sel + store i32 %bo, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}srem_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, 3, 33, +define amdgpu_kernel void @srem_constant_sel_constants(i32 addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, i32 34, i32 15 + %bo = srem i32 33, %sel + store i32 %bo, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}urem_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, 3, 33, +define amdgpu_kernel void @urem_constant_sel_constants(i32 addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, i32 34, i32 15 + %bo = urem i32 33, %sel + store i32 %bo, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}shl_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, 8, 4, +define amdgpu_kernel void @shl_constant_sel_constants(i32 addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, i32 2, i32 3 + %bo = shl i32 1, %sel + store i32 %bo, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}lshr_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, 8, 16, +define amdgpu_kernel void @lshr_constant_sel_constants(i32 addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, i32 2, i32 3 + %bo = lshr i32 64, %sel + store i32 %bo, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}ashr_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, 8, 32, +define amdgpu_kernel void @ashr_constant_sel_constants(i32 addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, i32 2, i32 3 + %bo = ashr i32 128, %sel + store i32 %bo, i32 addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}fsub_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, -4.0, 1.0, +define amdgpu_kernel void @fsub_constant_sel_constants(float addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, float -2.0, float 3.0 + %bo = fsub float -1.0, %sel + store float %bo, float addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}fdiv_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, 4.0, -2.0, +define amdgpu_kernel void @fdiv_constant_sel_constants(float addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, float -4.0, float 2.0 + %bo = fdiv float 8.0, %sel + store float %bo, float addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}frem_constant_sel_constants: +; v_cndmask_b32_e64 v{{[0-9]+}}, 2.0, 1.0, +define amdgpu_kernel void @frem_constant_sel_constants(float addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, float -4.0, float 3.0 + %bo = frem float 5.0, %sel + store float %bo, float addrspace(1)* %p, align 4 + ret void +} Index: test/CodeGen/AMDGPU/udivrem.ll =================================================================== --- test/CodeGen/AMDGPU/udivrem.ll +++ test/CodeGen/AMDGPU/udivrem.ll @@ -31,25 +31,25 @@ ; SI-DAG: v_mul_hi_u32 [[RCP_HI:v[0-9]+]], [[RCP]] ; SI-DAG: v_mul_lo_i32 [[RCP_LO:v[0-9]+]], [[RCP]] ; SI-DAG: v_sub_{{[iu]}}32_e32 [[NEG_RCP_LO:v[0-9]+]], vcc, 0, [[RCP_LO]] -; SI: v_cndmask_b32_e64 -; SI: v_mul_hi_u32 [[E:v[0-9]+]], {{v[0-9]+}}, [[RCP]] +; SI: v_cmp_eq_u32_e64 [[CC1:s\[[0-9:]+\]]], 0, [[RCP_HI]] +; SI: v_cndmask_b32_e64 [[CND1:v[0-9]+]], [[RCP_LO]], [[NEG_RCP_LO]], [[CC1]] +; SI: v_mul_hi_u32 [[E:v[0-9]+]], [[CND1]], [[RCP]] ; SI-DAG: v_add_{{[iu]}}32_e32 [[RCP_A_E:v[0-9]+]], vcc, [[E]], [[RCP]] ; SI-DAG: v_subrev_{{[iu]}}32_e32 [[RCP_S_E:v[0-9]+]], vcc, [[E]], [[RCP]] -; SI: v_cndmask_b32_e64 -; SI: v_mul_hi_u32 [[Quotient:v[0-9]+]] -; SI: v_mul_lo_i32 [[Num_S_Remainder:v[0-9]+]] +; SI: v_cndmask_b32_e64 [[CND2:v[0-9]+]], [[RCP_S_E]], [[RCP_A_E]], [[CC1]] +; SI: v_mul_hi_u32 [[Quotient:v[0-9]+]], [[CND2]], +; SI: v_mul_lo_i32 [[Num_S_Remainder:v[0-9]+]], [[CND2]] ; SI-DAG: v_add_{{[iu]}}32_e32 [[Quotient_A_One:v[0-9]+]], vcc, 1, [[Quotient]] ; SI-DAG: v_sub_{{[iu]}}32_e32 [[Remainder:v[0-9]+]], vcc, {{[vs][0-9]+}}, [[Num_S_Remainder]] ; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_cndmask_b32_e64 ; SI-DAG: v_subrev_{{[iu]}}32_e32 [[Quotient_S_One:v[0-9]+]], ; SI-DAG: v_subrev_{{[iu]}}32_e32 [[Remainder_S_Den:v[0-9]+]], -; SI: v_and_b32_e32 [[Tmp1:v[0-9]+]] ; SI-DAG: v_cndmask_b32_e64 ; SI-DAG: v_cndmask_b32_e64 ; SI-DAG: v_add_{{[iu]}}32_e32 [[Remainder_A_Den:v[0-9]+]], ; SI-DAG: v_cndmask_b32_e64 ; SI-DAG: v_cndmask_b32_e64 +; SI-NOT: v_and_b32 ; SI: s_endpgm define amdgpu_kernel void @test_udivrem(i32 addrspace(1)* %out0, i32 addrspace(1)* %out1, i32 %x, i32 %y) { %result0 = udiv i32 %x, %y @@ -124,8 +124,6 @@ ; SI-DAG: v_mul_lo_i32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_and_b32_e32 ; SI-DAG: v_add_{{[iu]}}32_e32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 @@ -147,8 +145,6 @@ ; SI-DAG: v_mul_lo_i32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_and_b32_e32 ; SI-DAG: v_add_{{[iu]}}32_e32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 @@ -157,6 +153,7 @@ ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 ; SI-DAG: v_cndmask_b32_e64 +; SI-NOT: v_and_b32 ; SI: s_endpgm define amdgpu_kernel void @test_udivrem_v2(<2 x i32> addrspace(1)* %out, <2 x i32> %x, <2 x i32> %y) { %result0 = udiv <2 x i32> %x, %y @@ -274,8 +271,6 @@ ; SI-DAG: v_mul_lo_i32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_and_b32_e32 ; SI-DAG: v_add_{{[iu]}}32_e32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 @@ -297,8 +292,6 @@ ; SI-DAG: v_mul_lo_i32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_and_b32_e32 ; SI-DAG: v_add_{{[iu]}}32_e32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 @@ -320,8 +313,6 @@ ; SI-DAG: v_mul_lo_i32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_cndmask_b32_e64 -; SI-DAG: v_and_b32_e32 ; SI-DAG: v_add_{{[iu]}}32_e32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 @@ -339,6 +330,7 @@ ; SI-DAG: v_add_{{[iu]}}32_e32 ; SI-DAG: v_subrev_{{[iu]}}32_e32 ; SI-DAG: v_cndmask_b32_e64 +; SI-NOT: v_and_b32 ; SI: s_endpgm define amdgpu_kernel void @test_udivrem_v4(<4 x i32> addrspace(1)* %out, <4 x i32> %x, <4 x i32> %y) { %result0 = udiv <4 x i32> %x, %y Index: test/CodeGen/PowerPC/select_const.ll =================================================================== --- test/CodeGen/PowerPC/select_const.ll +++ test/CodeGen/PowerPC/select_const.ll @@ -400,6 +400,30 @@ ret i8 %bo } +define i8 @sel_constants_sub_constant_sel_constants(i1 %cond) { +; ISEL-LABEL: sel_constants_sub_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: li 4, 9 +; ISEL-NEXT: li 3, 2 +; ISEL-NEXT: isel 3, 4, 3, 1 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: sel_constants_sub_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; NO_ISEL-NEXT: li 4, 9 +; NO_ISEL-NEXT: li 3, 2 +; NO_ISEL-NEXT: bc 12, 1, .LBB23_1 +; NO_ISEL-NEXT: blr +; NO_ISEL-NEXT: .LBB23_1: +; NO_ISEL-NEXT: addi 3, 4, 0 +; NO_ISEL-NEXT: blr + %sel = select i1 %cond, i8 -4, i8 3 + %bo = sub i8 5, %sel + ret i8 %bo +} + define i8 @sel_constants_mul_constant(i1 %cond) { ; ISEL-LABEL: sel_constants_mul_constant: ; ISEL: # %bb.0: @@ -439,9 +463,9 @@ ; NO_ISEL: # %bb.0: ; NO_ISEL-NEXT: andi. 3, 3, 1 ; NO_ISEL-NEXT: li 3, 4 -; NO_ISEL-NEXT: bc 12, 1, .LBB24_1 +; NO_ISEL-NEXT: bc 12, 1, .LBB25_1 ; NO_ISEL-NEXT: blr -; NO_ISEL-NEXT: .LBB24_1: +; NO_ISEL-NEXT: .LBB25_1: ; NO_ISEL-NEXT: addi 3, 0, 0 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 -4, i8 23 @@ -449,6 +473,28 @@ ret i8 %bo } +define i8 @sdiv_constant_sel_constants(i1 %cond) { +; ISEL-LABEL: sdiv_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: li 3, 5 +; ISEL-NEXT: isel 3, 0, 3, 1 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: sdiv_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; NO_ISEL-NEXT: li 3, 5 +; NO_ISEL-NEXT: bc 12, 1, .LBB26_1 +; NO_ISEL-NEXT: blr +; NO_ISEL-NEXT: .LBB26_1: +; NO_ISEL-NEXT: addi 3, 0, 0 +; NO_ISEL-NEXT: blr + %sel = select i1 %cond, i8 121, i8 23 + %bo = sdiv i8 120, %sel + ret i8 %bo +} + define i8 @sel_constants_udiv_constant(i1 %cond) { ; ISEL-LABEL: sel_constants_udiv_constant: ; ISEL: # %bb.0: @@ -463,9 +509,9 @@ ; NO_ISEL-NEXT: andi. 3, 3, 1 ; NO_ISEL-NEXT: li 4, 50 ; NO_ISEL-NEXT: li 3, 4 -; NO_ISEL-NEXT: bc 12, 1, .LBB25_1 +; NO_ISEL-NEXT: bc 12, 1, .LBB27_1 ; NO_ISEL-NEXT: blr -; NO_ISEL-NEXT: .LBB25_1: +; NO_ISEL-NEXT: .LBB27_1: ; NO_ISEL-NEXT: addi 3, 4, 0 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 -4, i8 23 @@ -473,6 +519,28 @@ ret i8 %bo } +define i8 @udiv_constant_sel_constants(i1 %cond) { +; ISEL-LABEL: udiv_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: li 3, 5 +; ISEL-NEXT: isel 3, 0, 3, 1 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: udiv_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; 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, 0, 0 +; NO_ISEL-NEXT: blr + %sel = select i1 %cond, i8 -4, i8 23 + %bo = udiv i8 120, %sel + ret i8 %bo +} + define i8 @sel_constants_srem_constant(i1 %cond) { ; ISEL-LABEL: sel_constants_srem_constant: ; ISEL: # %bb.0: @@ -500,6 +568,30 @@ ret i8 %bo } +define i8 @srem_constant_sel_constants(i1 %cond) { +; ISEL-LABEL: srem_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: li 4, 120 +; ISEL-NEXT: li 3, 5 +; ISEL-NEXT: isel 3, 4, 3, 1 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: srem_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; NO_ISEL-NEXT: li 4, 120 +; NO_ISEL-NEXT: li 3, 5 +; NO_ISEL-NEXT: bc 12, 1, .LBB30_1 +; NO_ISEL-NEXT: blr +; NO_ISEL-NEXT: .LBB30_1: +; NO_ISEL-NEXT: addi 3, 4, 0 +; NO_ISEL-NEXT: blr + %sel = select i1 %cond, i8 121, i8 23 + %bo = srem i8 120, %sel + ret i8 %bo +} + define i8 @sel_constants_urem_constant(i1 %cond) { ; ALL-LABEL: sel_constants_urem_constant: ; ALL: # %bb.0: @@ -511,6 +603,30 @@ ret i8 %bo } +define i8 @urem_constant_sel_constants(i1 %cond) { +; ISEL-LABEL: urem_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: li 4, 120 +; ISEL-NEXT: li 3, 5 +; ISEL-NEXT: isel 3, 4, 3, 1 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: urem_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; NO_ISEL-NEXT: li 4, 120 +; NO_ISEL-NEXT: li 3, 5 +; NO_ISEL-NEXT: bc 12, 1, .LBB32_1 +; NO_ISEL-NEXT: blr +; NO_ISEL-NEXT: .LBB32_1: +; NO_ISEL-NEXT: addi 3, 4, 0 +; NO_ISEL-NEXT: blr + %sel = select i1 %cond, i8 -4, i8 23 + %bo = urem i8 120, %sel + ret i8 %bo +} + define i8 @sel_constants_and_constant(i1 %cond) { ; ALL-LABEL: sel_constants_and_constant: ; ALL: # %bb.0: @@ -598,9 +714,9 @@ ; NO_ISEL-NEXT: ori 12, 5, 65535 ; NO_ISEL-NEXT: sldi 3, 3, 5 ; NO_ISEL-NEXT: sldi 4, 12, 7 -; NO_ISEL-NEXT: bc 12, 1, .LBB31_1 +; NO_ISEL-NEXT: bc 12, 1, .LBB36_1 ; NO_ISEL-NEXT: blr -; NO_ISEL-NEXT: .LBB31_1: +; NO_ISEL-NEXT: .LBB36_1: ; NO_ISEL-NEXT: addi 3, 4, 0 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 -4, i8 23 @@ -608,6 +724,19 @@ ret i8 %bo } +define i8 @shl_constant_sel_constants(i1 %cond) { +; ALL-LABEL: shl_constant_sel_constants: +; ALL: # %bb.0: +; ALL-NEXT: rlwinm 3, 3, 0, 31, 31 +; ALL-NEXT: li 4, 1 +; ALL-NEXT: subfic 3, 3, 3 +; ALL-NEXT: slw 3, 4, 3 +; ALL-NEXT: blr + %sel = select i1 %cond, i8 2, i8 3 + %bo = shl i8 1, %sel + ret i8 %bo +} + define i8 @sel_constants_lshr_constant(i1 %cond) { ; ISEL-LABEL: sel_constants_lshr_constant: ; ISEL: # %bb.0: @@ -622,9 +751,9 @@ ; NO_ISEL-NEXT: andi. 3, 3, 1 ; NO_ISEL-NEXT: li 4, 7 ; NO_ISEL-NEXT: li 3, 0 -; NO_ISEL-NEXT: bc 12, 1, .LBB32_1 +; NO_ISEL-NEXT: bc 12, 1, .LBB38_1 ; NO_ISEL-NEXT: blr -; NO_ISEL-NEXT: .LBB32_1: +; NO_ISEL-NEXT: .LBB38_1: ; NO_ISEL-NEXT: addi 3, 4, 0 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 -4, i8 23 @@ -632,6 +761,20 @@ ret i8 %bo } +define i8 @lshr_constant_sel_constants(i1 %cond) { +; ALL-LABEL: lshr_constant_sel_constants: +; ALL: # %bb.0: +; ALL-NEXT: rlwinm 3, 3, 0, 31, 31 +; ALL-NEXT: li 4, 64 +; ALL-NEXT: subfic 3, 3, 3 +; ALL-NEXT: srw 3, 4, 3 +; ALL-NEXT: blr + %sel = select i1 %cond, i8 2, i8 3 + %bo = lshr i8 64, %sel + ret i8 %bo +} + + define i8 @sel_constants_ashr_constant(i1 %cond) { ; ALL-LABEL: sel_constants_ashr_constant: ; ALL: # %bb.0: @@ -643,14 +786,27 @@ ret i8 %bo } +define i8 @ashr_constant_sel_constants(i1 %cond) { +; ALL-LABEL: ashr_constant_sel_constants: +; ALL: # %bb.0: +; ALL-NEXT: rlwinm 3, 3, 0, 31, 31 +; ALL-NEXT: li 4, -128 +; ALL-NEXT: subfic 3, 3, 3 +; ALL-NEXT: sraw 3, 4, 3 +; ALL-NEXT: blr + %sel = select i1 %cond, i8 2, i8 3 + %bo = ashr i8 128, %sel + ret i8 %bo +} + define double @sel_constants_fadd_constant(i1 %cond) { ; ISEL-LABEL: sel_constants_fadd_constant: ; ISEL: # %bb.0: ; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: addis 4, 2, .LCPI34_0@toc@ha -; ISEL-NEXT: addis 3, 2, .LCPI34_1@toc@ha -; ISEL-NEXT: addi 4, 4, .LCPI34_0@toc@l -; ISEL-NEXT: addi 3, 3, .LCPI34_1@toc@l +; ISEL-NEXT: addis 4, 2, .LCPI42_0@toc@ha +; ISEL-NEXT: addis 3, 2, .LCPI42_1@toc@ha +; ISEL-NEXT: addi 4, 4, .LCPI42_0@toc@l +; ISEL-NEXT: addi 3, 3, .LCPI42_1@toc@l ; ISEL-NEXT: isel 3, 3, 4, 1 ; ISEL-NEXT: lfdx 1, 0, 3 ; ISEL-NEXT: blr @@ -658,15 +814,15 @@ ; NO_ISEL-LABEL: sel_constants_fadd_constant: ; NO_ISEL: # %bb.0: ; NO_ISEL-NEXT: andi. 3, 3, 1 -; NO_ISEL-NEXT: addis 4, 2, .LCPI34_0@toc@ha -; NO_ISEL-NEXT: addis 3, 2, .LCPI34_1@toc@ha -; NO_ISEL-NEXT: addi 4, 4, .LCPI34_0@toc@l -; NO_ISEL-NEXT: addi 3, 3, .LCPI34_1@toc@l -; NO_ISEL-NEXT: bc 12, 1, .LBB34_2 +; NO_ISEL-NEXT: addis 4, 2, .LCPI42_0@toc@ha +; NO_ISEL-NEXT: addis 3, 2, .LCPI42_1@toc@ha +; NO_ISEL-NEXT: addi 4, 4, .LCPI42_0@toc@l +; NO_ISEL-NEXT: addi 3, 3, .LCPI42_1@toc@l +; NO_ISEL-NEXT: bc 12, 1, .LBB42_2 ; NO_ISEL-NEXT: # %bb.1: ; NO_ISEL-NEXT: ori 3, 4, 0 -; NO_ISEL-NEXT: b .LBB34_2 -; NO_ISEL-NEXT: .LBB34_2: +; NO_ISEL-NEXT: b .LBB42_2 +; NO_ISEL-NEXT: .LBB42_2: ; NO_ISEL-NEXT: lfdx 1, 0, 3 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, double -4.0, double 23.3 @@ -678,10 +834,10 @@ ; ISEL-LABEL: sel_constants_fsub_constant: ; ISEL: # %bb.0: ; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: addis 4, 2, .LCPI35_0@toc@ha -; ISEL-NEXT: addis 3, 2, .LCPI35_1@toc@ha -; ISEL-NEXT: addi 4, 4, .LCPI35_0@toc@l -; ISEL-NEXT: addi 3, 3, .LCPI35_1@toc@l +; ISEL-NEXT: addis 4, 2, .LCPI43_0@toc@ha +; ISEL-NEXT: addis 3, 2, .LCPI43_1@toc@ha +; ISEL-NEXT: addi 4, 4, .LCPI43_0@toc@l +; ISEL-NEXT: addi 3, 3, .LCPI43_1@toc@l ; ISEL-NEXT: isel 3, 3, 4, 1 ; ISEL-NEXT: lfdx 1, 0, 3 ; ISEL-NEXT: blr @@ -689,15 +845,15 @@ ; NO_ISEL-LABEL: sel_constants_fsub_constant: ; NO_ISEL: # %bb.0: ; NO_ISEL-NEXT: andi. 3, 3, 1 -; NO_ISEL-NEXT: addis 4, 2, .LCPI35_0@toc@ha -; NO_ISEL-NEXT: addis 3, 2, .LCPI35_1@toc@ha -; NO_ISEL-NEXT: addi 4, 4, .LCPI35_0@toc@l -; NO_ISEL-NEXT: addi 3, 3, .LCPI35_1@toc@l -; NO_ISEL-NEXT: bc 12, 1, .LBB35_2 +; NO_ISEL-NEXT: addis 4, 2, .LCPI43_0@toc@ha +; NO_ISEL-NEXT: addis 3, 2, .LCPI43_1@toc@ha +; NO_ISEL-NEXT: addi 4, 4, .LCPI43_0@toc@l +; NO_ISEL-NEXT: addi 3, 3, .LCPI43_1@toc@l +; NO_ISEL-NEXT: bc 12, 1, .LBB43_2 ; NO_ISEL-NEXT: # %bb.1: ; NO_ISEL-NEXT: ori 3, 4, 0 -; NO_ISEL-NEXT: b .LBB35_2 -; NO_ISEL-NEXT: .LBB35_2: +; NO_ISEL-NEXT: b .LBB43_2 +; NO_ISEL-NEXT: .LBB43_2: ; NO_ISEL-NEXT: lfdx 1, 0, 3 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, double -4.0, double 23.3 @@ -705,14 +861,45 @@ ret double %bo } +define double @fsub_constant_sel_constants(i1 %cond) { +; ISEL-LABEL: fsub_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: addis 4, 2, .LCPI44_0@toc@ha +; ISEL-NEXT: addis 3, 2, .LCPI44_1@toc@ha +; ISEL-NEXT: addi 4, 4, .LCPI44_0@toc@l +; ISEL-NEXT: addi 3, 3, .LCPI44_1@toc@l +; ISEL-NEXT: isel 3, 3, 4, 1 +; ISEL-NEXT: lfdx 1, 0, 3 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: fsub_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; NO_ISEL-NEXT: addis 4, 2, .LCPI44_0@toc@ha +; NO_ISEL-NEXT: addis 3, 2, .LCPI44_1@toc@ha +; NO_ISEL-NEXT: addi 4, 4, .LCPI44_0@toc@l +; NO_ISEL-NEXT: addi 3, 3, .LCPI44_1@toc@l +; NO_ISEL-NEXT: bc 12, 1, .LBB44_2 +; NO_ISEL-NEXT: # %bb.1: +; NO_ISEL-NEXT: ori 3, 4, 0 +; NO_ISEL-NEXT: b .LBB44_2 +; NO_ISEL-NEXT: .LBB44_2: +; NO_ISEL-NEXT: lfdx 1, 0, 3 +; NO_ISEL-NEXT: blr + %sel = select i1 %cond, double -4.0, double 23.3 + %bo = fsub double 5.1, %sel + ret double %bo +} + define double @sel_constants_fmul_constant(i1 %cond) { ; ISEL-LABEL: sel_constants_fmul_constant: ; ISEL: # %bb.0: ; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: addis 4, 2, .LCPI36_0@toc@ha -; ISEL-NEXT: addis 3, 2, .LCPI36_1@toc@ha -; ISEL-NEXT: addi 4, 4, .LCPI36_0@toc@l -; ISEL-NEXT: addi 3, 3, .LCPI36_1@toc@l +; ISEL-NEXT: addis 4, 2, .LCPI45_0@toc@ha +; ISEL-NEXT: addis 3, 2, .LCPI45_1@toc@ha +; ISEL-NEXT: addi 4, 4, .LCPI45_0@toc@l +; ISEL-NEXT: addi 3, 3, .LCPI45_1@toc@l ; ISEL-NEXT: isel 3, 3, 4, 1 ; ISEL-NEXT: lfdx 1, 0, 3 ; ISEL-NEXT: blr @@ -720,15 +907,15 @@ ; NO_ISEL-LABEL: sel_constants_fmul_constant: ; NO_ISEL: # %bb.0: ; NO_ISEL-NEXT: andi. 3, 3, 1 -; NO_ISEL-NEXT: addis 4, 2, .LCPI36_0@toc@ha -; NO_ISEL-NEXT: addis 3, 2, .LCPI36_1@toc@ha -; NO_ISEL-NEXT: addi 4, 4, .LCPI36_0@toc@l -; NO_ISEL-NEXT: addi 3, 3, .LCPI36_1@toc@l -; NO_ISEL-NEXT: bc 12, 1, .LBB36_2 +; NO_ISEL-NEXT: addis 4, 2, .LCPI45_0@toc@ha +; NO_ISEL-NEXT: addis 3, 2, .LCPI45_1@toc@ha +; NO_ISEL-NEXT: addi 4, 4, .LCPI45_0@toc@l +; NO_ISEL-NEXT: addi 3, 3, .LCPI45_1@toc@l +; NO_ISEL-NEXT: bc 12, 1, .LBB45_2 ; NO_ISEL-NEXT: # %bb.1: ; NO_ISEL-NEXT: ori 3, 4, 0 -; NO_ISEL-NEXT: b .LBB36_2 -; NO_ISEL-NEXT: .LBB36_2: +; NO_ISEL-NEXT: b .LBB45_2 +; NO_ISEL-NEXT: .LBB45_2: ; NO_ISEL-NEXT: lfdx 1, 0, 3 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, double -4.0, double 23.3 @@ -740,10 +927,10 @@ ; ISEL-LABEL: sel_constants_fdiv_constant: ; ISEL: # %bb.0: ; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: addis 4, 2, .LCPI37_0@toc@ha -; ISEL-NEXT: addis 3, 2, .LCPI37_1@toc@ha -; ISEL-NEXT: addi 4, 4, .LCPI37_0@toc@l -; ISEL-NEXT: addi 3, 3, .LCPI37_1@toc@l +; ISEL-NEXT: addis 4, 2, .LCPI46_0@toc@ha +; ISEL-NEXT: addis 3, 2, .LCPI46_1@toc@ha +; ISEL-NEXT: addi 4, 4, .LCPI46_0@toc@l +; ISEL-NEXT: addi 3, 3, .LCPI46_1@toc@l ; ISEL-NEXT: isel 3, 3, 4, 1 ; ISEL-NEXT: lfdx 1, 0, 3 ; ISEL-NEXT: blr @@ -751,15 +938,15 @@ ; NO_ISEL-LABEL: sel_constants_fdiv_constant: ; NO_ISEL: # %bb.0: ; NO_ISEL-NEXT: andi. 3, 3, 1 -; NO_ISEL-NEXT: addis 4, 2, .LCPI37_0@toc@ha -; NO_ISEL-NEXT: addis 3, 2, .LCPI37_1@toc@ha -; NO_ISEL-NEXT: addi 4, 4, .LCPI37_0@toc@l -; NO_ISEL-NEXT: addi 3, 3, .LCPI37_1@toc@l -; NO_ISEL-NEXT: bc 12, 1, .LBB37_2 +; NO_ISEL-NEXT: addis 4, 2, .LCPI46_0@toc@ha +; NO_ISEL-NEXT: addis 3, 2, .LCPI46_1@toc@ha +; NO_ISEL-NEXT: addi 4, 4, .LCPI46_0@toc@l +; NO_ISEL-NEXT: addi 3, 3, .LCPI46_1@toc@l +; NO_ISEL-NEXT: bc 12, 1, .LBB46_2 ; NO_ISEL-NEXT: # %bb.1: ; NO_ISEL-NEXT: ori 3, 4, 0 -; NO_ISEL-NEXT: b .LBB37_2 -; NO_ISEL-NEXT: .LBB37_2: +; NO_ISEL-NEXT: b .LBB46_2 +; NO_ISEL-NEXT: .LBB46_2: ; NO_ISEL-NEXT: lfdx 1, 0, 3 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, double -4.0, double 23.3 @@ -767,19 +954,50 @@ ret double %bo } +define double @fdiv_constant_sel_constants(i1 %cond) { +; ISEL-LABEL: fdiv_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: addis 4, 2, .LCPI47_0@toc@ha +; ISEL-NEXT: addis 3, 2, .LCPI47_1@toc@ha +; ISEL-NEXT: addi 4, 4, .LCPI47_0@toc@l +; ISEL-NEXT: addi 3, 3, .LCPI47_1@toc@l +; ISEL-NEXT: isel 3, 3, 4, 1 +; ISEL-NEXT: lfdx 1, 0, 3 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: fdiv_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; NO_ISEL-NEXT: addis 4, 2, .LCPI47_0@toc@ha +; NO_ISEL-NEXT: addis 3, 2, .LCPI47_1@toc@ha +; NO_ISEL-NEXT: addi 4, 4, .LCPI47_0@toc@l +; NO_ISEL-NEXT: addi 3, 3, .LCPI47_1@toc@l +; NO_ISEL-NEXT: bc 12, 1, .LBB47_2 +; NO_ISEL-NEXT: # %bb.1: +; NO_ISEL-NEXT: ori 3, 4, 0 +; NO_ISEL-NEXT: b .LBB47_2 +; NO_ISEL-NEXT: .LBB47_2: +; NO_ISEL-NEXT: lfdx 1, 0, 3 +; NO_ISEL-NEXT: blr + %sel = select i1 %cond, double -4.0, double 23.3 + %bo = fdiv double 5.1, %sel + ret double %bo +} + define double @sel_constants_frem_constant(i1 %cond) { ; ALL-LABEL: sel_constants_frem_constant: ; ALL: # %bb.0: ; ALL-NEXT: andi. 3, 3, 1 -; ALL-NEXT: bc 12, 1, .LBB38_2 +; ALL-NEXT: bc 12, 1, .LBB48_2 ; ALL-NEXT: # %bb.1: -; ALL-NEXT: addis 3, 2, .LCPI38_0@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI38_0@toc@l +; ALL-NEXT: addis 3, 2, .LCPI48_0@toc@ha +; ALL-NEXT: addi 3, 3, .LCPI48_0@toc@l ; ALL-NEXT: lfdx 1, 0, 3 ; ALL-NEXT: blr -; ALL-NEXT: .LBB38_2: -; ALL-NEXT: addis 3, 2, .LCPI38_1@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI38_1@toc@l +; ALL-NEXT: .LBB48_2: +; ALL-NEXT: addis 3, 2, .LCPI48_1@toc@ha +; ALL-NEXT: addi 3, 3, .LCPI48_1@toc@l ; ALL-NEXT: lfsx 1, 0, 3 ; ALL-NEXT: blr %sel = select i1 %cond, double -4.0, double 23.3 @@ -787,3 +1005,33 @@ ret double %bo } +define double @frem_constant_sel_constants(i1 %cond) { +; ISEL-LABEL: frem_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: addis 4, 2, .LCPI49_0@toc@ha +; ISEL-NEXT: addis 3, 2, .LCPI49_1@toc@ha +; ISEL-NEXT: addi 4, 4, .LCPI49_0@toc@l +; ISEL-NEXT: addi 3, 3, .LCPI49_1@toc@l +; ISEL-NEXT: isel 3, 3, 4, 1 +; ISEL-NEXT: lfdx 1, 0, 3 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: frem_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; NO_ISEL-NEXT: addis 4, 2, .LCPI49_0@toc@ha +; NO_ISEL-NEXT: addis 3, 2, .LCPI49_1@toc@ha +; NO_ISEL-NEXT: addi 4, 4, .LCPI49_0@toc@l +; NO_ISEL-NEXT: addi 3, 3, .LCPI49_1@toc@l +; NO_ISEL-NEXT: bc 12, 1, .LBB49_2 +; NO_ISEL-NEXT: # %bb.1: +; NO_ISEL-NEXT: ori 3, 4, 0 +; NO_ISEL-NEXT: b .LBB49_2 +; NO_ISEL-NEXT: .LBB49_2: +; NO_ISEL-NEXT: lfdx 1, 0, 3 +; NO_ISEL-NEXT: blr + %sel = select i1 %cond, double -4.0, double 23.3 + %bo = frem double 5.1, %sel + ret double %bo +} Index: test/CodeGen/X86/dagcombine-select.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/dagcombine-select.ll @@ -0,0 +1,209 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64-unknown-unknown -verify-machineinstrs < %s | FileCheck -enable-var-scope %s + +define i32 @select_and1(i32 %x, i32 %y) { +; CHECK-LABEL: select_and1: +; CHECK: # %bb.0: +; CHECK-NEXT: xorl %eax, %eax +; CHECK-NEXT: cmpl $11, %edi +; CHECK-NEXT: cmovgel %esi, %eax +; CHECK-NEXT: retq + %c = icmp slt i32 %x, 11 + %s = select i1 %c, i32 0, i32 -1 + %a = and i32 %y, %s + ret i32 %a +} + +define i32 @select_and2(i32 %x, i32 %y) { +; CHECK-LABEL: select_and2: +; CHECK: # %bb.0: +; CHECK-NEXT: xorl %eax, %eax +; CHECK-NEXT: cmpl $11, %edi +; CHECK-NEXT: cmovgel %esi, %eax +; CHECK-NEXT: retq + %c = icmp slt i32 %x, 11 + %s = select i1 %c, i32 0, i32 -1 + %a = and i32 %s, %y + ret i32 %a +} + +define i32 @select_or1(i32 %x, i32 %y) { +; CHECK-LABEL: select_or1: +; CHECK: # %bb.0: +; CHECK-NEXT: cmpl $11, %edi +; CHECK-NEXT: movl $-1, %eax +; CHECK-NEXT: cmovll %esi, %eax +; CHECK-NEXT: retq + %c = icmp slt i32 %x, 11 + %s = select i1 %c, i32 0, i32 -1 + %a = or i32 %y, %s + ret i32 %a +} + +define i32 @select_or2(i32 %x, i32 %y) { +; CHECK-LABEL: select_or2: +; CHECK: # %bb.0: +; CHECK-NEXT: cmpl $11, %edi +; CHECK-NEXT: movl $-1, %eax +; CHECK-NEXT: cmovll %esi, %eax +; CHECK-NEXT: retq + %c = icmp slt i32 %x, 11 + %s = select i1 %c, i32 0, i32 -1 + %a = or i32 %s, %y + ret i32 %a +} + +define i32 @sel_constants_sub_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: sel_constants_sub_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: movl $9, %ecx +; CHECK-NEXT: movl $2, %eax +; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 -4, i32 3 + %bo = sub i32 5, %sel + ret i32 %bo +} + +define i32 @sdiv_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: sdiv_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: notb %dil +; CHECK-NEXT: movzbl %dil, %eax +; CHECK-NEXT: andl $1, %eax +; CHECK-NEXT: leal (%rax,%rax,4), %eax +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 121, i32 23 + %bo = sdiv i32 120, %sel + ret i32 %bo +} + +define i32 @udiv_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: udiv_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: notb %dil +; CHECK-NEXT: movzbl %dil, %eax +; CHECK-NEXT: andl $1, %eax +; CHECK-NEXT: leal (%rax,%rax,4), %eax +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 -4, i32 23 + %bo = udiv i32 120, %sel + ret i32 %bo +} + +define i32 @srem_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: srem_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: movl $120, %ecx +; CHECK-NEXT: movl $5, %eax +; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 121, i32 23 + %bo = srem i32 120, %sel + ret i32 %bo +} + +define i32 @urem_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: urem_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: movl $120, %ecx +; CHECK-NEXT: movl $5, %eax +; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 -4, i32 23 + %bo = urem i32 120, %sel + ret i32 %bo +} + +define i32 @shl_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: shl_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: andb $1, %dil +; CHECK-NEXT: movb $3, %cl +; CHECK-NEXT: subb %dil, %cl +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 2, i32 3 + %bo = shl i32 1, %sel + ret i32 %bo +} + +define i32 @lshr_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: lshr_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: andb $1, %dil +; CHECK-NEXT: movb $3, %cl +; CHECK-NEXT: subb %dil, %cl +; CHECK-NEXT: movl $64, %eax +; CHECK-NEXT: shrl %cl, %eax +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 2, i32 3 + %bo = lshr i32 64, %sel + ret i32 %bo +} + +define i32 @ashr_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: ashr_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: andb $1, %dil +; CHECK-NEXT: movb $3, %cl +; CHECK-NEXT: subb %dil, %cl +; CHECK-NEXT: movl $128, %eax +; CHECK-NEXT: shrl %cl, %eax +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 2, i32 3 + %bo = ashr i32 128, %sel + ret i32 %bo +} + +define double @fsub_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: fsub_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: jne .LBB12_1 +; CHECK-NEXT: # %bb.2: +; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB12_1: +; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero +; CHECK-NEXT: retq + %sel = select i1 %cond, double -4.0, double 23.3 + %bo = fsub double 5.1, %sel + ret double %bo +} + +define double @fdiv_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: fdiv_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: jne .LBB13_1 +; CHECK-NEXT: # %bb.2: +; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB13_1: +; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero +; CHECK-NEXT: retq + %sel = select i1 %cond, double -4.0, double 23.3 + %bo = fdiv double 5.1, %sel + ret double %bo +} + +define double @frem_constant_sel_constants(i1 %cond) { +; CHECK-LABEL: frem_constant_sel_constants: +; CHECK: # %bb.0: +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: jne .LBB14_1 +; CHECK-NEXT: # %bb.2: +; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB14_1: +; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero +; CHECK-NEXT: retq + %sel = select i1 %cond, double -4.0, double 23.3 + %bo = frem double 5.1, %sel + ret double %bo +}