Index: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/trunk/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,18 +1900,36 @@ !isConstantFPBuildVectorOrConstantFP(CF)) return SDValue(); + // Bail out if any constants are opaque because we can't constant fold those. + SDValue CBO = BO->getOperand(SelOpNo ^ 1); + if (!isConstantOrConstantVector(CBO, true) && + !isConstantFPBuildVectorOrConstantFP(CBO)) + return SDValue(); + + EVT VT = Sel.getValueType(); + + // In case of shift value and shift amount may have different VT. For instance + // on x86 shift amount is i8 regardles of LHS type. Bail out if we have + // swapped operands and value types do not match. NB: x86 is fine if operands + // are not swapped with shift amount VT being not bigger than shifted value. + // TODO: that is possible to check for a shift operation, correct VTs and + // still perform optimization on x86 if needed. + if (SelOpNo && VT != CBO.getValueType()) + 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(); + // Example: add (select Cond, CT, CF), CBO --> select Cond, CT + CBO, CF + CBO SDLoc DL(Sel); - SDValue NewCT = DAG.getNode(BinOpcode, DL, VT, CT, C1); + SDValue NewCT = SelOpNo ? DAG.getNode(BinOpcode, DL, VT, CBO, CT) + : DAG.getNode(BinOpcode, DL, VT, CT, CBO); if (!NewCT.isUndef() && !isConstantOrConstantVector(NewCT, true) && !isConstantFPBuildVectorOrConstantFP(NewCT)) return SDValue(); - SDValue NewCF = DAG.getNode(BinOpcode, DL, VT, CF, C1); + SDValue NewCF = SelOpNo ? DAG.getNode(BinOpcode, DL, VT, CBO, CF) + : DAG.getNode(BinOpcode, DL, VT, CF, CBO); if (!NewCF.isUndef() && !isConstantOrConstantVector(NewCF, true) && !isConstantFPBuildVectorOrConstantFP(NewCF)) Index: llvm/trunk/test/CodeGen/AMDGPU/dagcombine-select.ll =================================================================== --- llvm/trunk/test/CodeGen/AMDGPU/dagcombine-select.ll +++ llvm/trunk/test/CodeGen/AMDGPU/dagcombine-select.ll @@ -0,0 +1,182 @@ +; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefix=GCN %s + +; GCN-LABEL: {{^}}sel_constants_sub_constant_sel_constants: +; GCN: 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: {{^}}sel_constants_sub_constant_sel_constants_i16: +; TODO: shrink i16 constant. This is correct but suboptimal. +; GCN: v_mov_b32_e32 [[T:v[0-9]+]], 0xffff0009 +; GCN: v_cndmask_b32_e32 v{{[0-9]+}}, 2, [[T]], +define amdgpu_kernel void @sel_constants_sub_constant_sel_constants_i16(i16 addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, i16 -4, i16 3 + %bo = sub i16 5, %sel + store i16 %bo, i16 addrspace(1)* %p, align 2 + ret void +} + +; GCN-LABEL: {{^}}sel_constants_sub_constant_sel_constants_i16_neg: +; GCN: v_mov_b32_e32 [[F:v[0-9]+]], 0xfffff449 +; GCN: v_cndmask_b32_e64 v{{[0-9]+}}, [[F]], -3, +define amdgpu_kernel void @sel_constants_sub_constant_sel_constants_i16_neg(i16 addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, i16 4, i16 3000 + %bo = sub i16 1, %sel + store i16 %bo, i16 addrspace(1)* %p, align 2 + ret void +} + +; GCN-LABEL: {{^}}sel_constants_sub_constant_sel_constants_v2i16: +; GCN-DAG: v_mov_b32_e32 [[F:v[0-9]+]], 0x60002 +; GCN-DAG: v_mov_b32_e32 [[T:v[0-9]+]], 0x50009 +; GCN: v_cndmask_b32_e32 v{{[0-9]+}}, [[F]], [[T]], +define amdgpu_kernel void @sel_constants_sub_constant_sel_constants_v2i16(<2 x i16> addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, <2 x i16> , <2 x i16> + %bo = sub <2 x i16> , %sel + store <2 x i16> %bo, <2 x i16> addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}sel_constants_sub_constant_sel_constants_v4i32: +; GCN-DAG: v_cndmask_b32_e64 v{{[0-9]+}}, 2, 9, +; GCN-DAG: v_cndmask_b32_e64 v{{[0-9]+}}, 6, 5, +; GCN-DAG: v_cndmask_b32_e64 v{{[0-9]+}}, 10, 6, +; GCN-DAG: v_cndmask_b32_e64 v{{[0-9]+}}, 14, 7, +define amdgpu_kernel void @sel_constants_sub_constant_sel_constants_v4i32(<4 x i32> addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, <4 x i32> , <4 x i32> + %bo = sub <4 x i32> , %sel + store <4 x i32> %bo, <4 x i32> addrspace(1)* %p, align 32 + ret void +} + +; GCN-LABEL: {{^}}sdiv_constant_sel_constants: +; GCN: 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: +; GCN: 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: +; GCN: 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: +; GCN: 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: +; GCN: 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: +; GCN: 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: +; GCN: v_cndmask_b32_e64 v{{[0-9]+}}, 16, 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: +; GCN: 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: {{^}}fsub_constant_sel_constants_f16: +; TODO: it shall be possible to fold constants with OpSel +; GCN-DAG: v_mov_b32_e32 [[T:v[0-9]+]], 0x3c00 +; GCN-DAG: v_mov_b32_e32 [[F:v[0-9]+]], 0xc400 +; GCN: v_cndmask_b32_e32 v{{[0-9]+}}, [[F]], [[T]], +define amdgpu_kernel void @fsub_constant_sel_constants_f16(half addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, half -2.0, half 3.0 + %bo = fsub half -1.0, %sel + store half %bo, half addrspace(1)* %p, align 2 + ret void +} + +; GCN-LABEL: {{^}}fsub_constant_sel_constants_v2f16: +; GCN-DAG: v_mov_b32_e32 [[T:v[0-9]+]], 0x45003c00 +; GCN: v_cndmask_b32_e32 v{{[0-9]+}}, -2.0, [[T]], +define amdgpu_kernel void @fsub_constant_sel_constants_v2f16(<2 x half> addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, <2 x half> , <2 x half> + %bo = fsub <2 x half> , %sel + store <2 x half> %bo, <2 x half> addrspace(1)* %p, align 4 + ret void +} + +; GCN-LABEL: {{^}}fsub_constant_sel_constants_v4f32: +; GCN-DAG: v_mov_b32_e32 [[T2:v[0-9]+]], 0x40a00000 +; GCN-DAG: v_mov_b32_e32 [[T3:v[0-9]+]], 0x41100000 +; GCN-DAG: v_mov_b32_e32 [[T4:v[0-9]+]], 0x41500000 +; GCN-DAG: v_mov_b32_e32 [[F4:v[0-9]+]], 0x40c00000 +; GCN-DAG: v_cndmask_b32_e64 v{{[0-9]+}}, 0, 1.0, +; GCN-DAG: v_cndmask_b32_e32 v{{[0-9]+}}, 2.0, [[T2]], +; GCN-DAG: v_cndmask_b32_e32 v{{[0-9]+}}, 4.0, [[T3]], +; GCN-DAG: v_cndmask_b32_e32 v{{[0-9]+}}, [[F4]], [[T4]], +define amdgpu_kernel void @fsub_constant_sel_constants_v4f32(<4 x float> addrspace(1)* %p, i1 %cond) { + %sel = select i1 %cond, <4 x float> , <4 x float> + %bo = fsub <4 x float> , %sel + store <4 x float> %bo, <4 x float> addrspace(1)* %p, align 32 + ret void +} + +; GCN-LABEL: {{^}}fdiv_constant_sel_constants: +; GCN: 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: +; GCN: 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: llvm/trunk/test/CodeGen/PowerPC/select_const.ll =================================================================== --- llvm/trunk/test/CodeGen/PowerPC/select_const.ll +++ llvm/trunk/test/CodeGen/PowerPC/select_const.ll @@ -404,23 +404,20 @@ ; ISEL-LABEL: sel_constants_sub_constant_sel_constants: ; ISEL: # %bb.0: ; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: li 4, -4 -; ISEL-NEXT: li 3, 3 +; ISEL-NEXT: li 4, 9 +; ISEL-NEXT: li 3, 2 ; ISEL-NEXT: isel 3, 4, 3, 1 -; ISEL-NEXT: subfic 3, 3, 5 ; 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, -4 -; NO_ISEL-NEXT: li 3, 3 +; NO_ISEL-NEXT: li 4, 9 +; NO_ISEL-NEXT: li 3, 2 ; NO_ISEL-NEXT: bc 12, 1, .LBB23_1 -; NO_ISEL-NEXT: b .LBB23_2 +; NO_ISEL-NEXT: blr ; NO_ISEL-NEXT: .LBB23_1: ; NO_ISEL-NEXT: addi 3, 4, 0 -; NO_ISEL-NEXT: .LBB23_2: -; NO_ISEL-NEXT: subfic 3, 3, 5 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 -4, i8 3 %bo = sub i8 5, %sel @@ -480,25 +477,18 @@ ; ISEL-LABEL: sdiv_constant_sel_constants: ; ISEL: # %bb.0: ; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: li 4, 121 -; ISEL-NEXT: li 12, 120 -; ISEL-NEXT: li 3, 23 -; ISEL-NEXT: isel 3, 4, 3, 1 -; ISEL-NEXT: divwu 3, 12, 3 +; 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 4, 121 -; NO_ISEL-NEXT: li 12, 120 -; NO_ISEL-NEXT: li 3, 23 +; NO_ISEL-NEXT: li 3, 5 ; NO_ISEL-NEXT: bc 12, 1, .LBB26_1 -; NO_ISEL-NEXT: b .LBB26_2 +; NO_ISEL-NEXT: blr ; NO_ISEL-NEXT: .LBB26_1: -; NO_ISEL-NEXT: addi 3, 4, 0 -; NO_ISEL-NEXT: .LBB26_2: -; NO_ISEL-NEXT: divwu 3, 12, 3 +; NO_ISEL-NEXT: addi 3, 0, 0 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 121, i8 23 %bo = sdiv i8 120, %sel @@ -533,25 +523,18 @@ ; ISEL-LABEL: udiv_constant_sel_constants: ; ISEL: # %bb.0: ; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: li 4, 252 -; ISEL-NEXT: li 12, 120 -; ISEL-NEXT: li 3, 23 -; ISEL-NEXT: isel 3, 4, 3, 1 -; ISEL-NEXT: divwu 3, 12, 3 +; 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 4, 252 -; NO_ISEL-NEXT: li 12, 120 -; NO_ISEL-NEXT: li 3, 23 +; NO_ISEL-NEXT: li 3, 5 ; NO_ISEL-NEXT: bc 12, 1, .LBB28_1 -; NO_ISEL-NEXT: b .LBB28_2 +; NO_ISEL-NEXT: blr ; NO_ISEL-NEXT: .LBB28_1: -; NO_ISEL-NEXT: addi 3, 4, 0 -; NO_ISEL-NEXT: .LBB28_2: -; NO_ISEL-NEXT: divwu 3, 12, 3 +; NO_ISEL-NEXT: addi 3, 0, 0 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 -4, i8 23 %bo = udiv i8 120, %sel @@ -589,29 +572,20 @@ ; ISEL-LABEL: srem_constant_sel_constants: ; ISEL: # %bb.0: ; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: li 4, 121 -; ISEL-NEXT: li 12, 120 -; ISEL-NEXT: li 3, 23 +; ISEL-NEXT: li 4, 120 +; ISEL-NEXT: li 3, 5 ; ISEL-NEXT: isel 3, 4, 3, 1 -; ISEL-NEXT: divwu 4, 12, 3 -; ISEL-NEXT: mullw 3, 4, 3 -; ISEL-NEXT: subfic 3, 3, 120 ; 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, 121 -; NO_ISEL-NEXT: li 12, 120 -; NO_ISEL-NEXT: li 3, 23 +; NO_ISEL-NEXT: li 4, 120 +; NO_ISEL-NEXT: li 3, 5 ; NO_ISEL-NEXT: bc 12, 1, .LBB30_1 -; NO_ISEL-NEXT: b .LBB30_2 +; NO_ISEL-NEXT: blr ; NO_ISEL-NEXT: .LBB30_1: ; NO_ISEL-NEXT: addi 3, 4, 0 -; NO_ISEL-NEXT: .LBB30_2: -; NO_ISEL-NEXT: divwu 4, 12, 3 -; NO_ISEL-NEXT: mullw 3, 4, 3 -; NO_ISEL-NEXT: subfic 3, 3, 120 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 121, i8 23 %bo = srem i8 120, %sel @@ -633,29 +607,20 @@ ; ISEL-LABEL: urem_constant_sel_constants: ; ISEL: # %bb.0: ; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: li 4, 252 -; ISEL-NEXT: li 12, 120 -; ISEL-NEXT: li 3, 23 +; ISEL-NEXT: li 4, 120 +; ISEL-NEXT: li 3, 5 ; ISEL-NEXT: isel 3, 4, 3, 1 -; ISEL-NEXT: divwu 4, 12, 3 -; ISEL-NEXT: mullw 3, 4, 3 -; ISEL-NEXT: subfic 3, 3, 120 ; 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, 252 -; NO_ISEL-NEXT: li 12, 120 -; NO_ISEL-NEXT: li 3, 23 +; NO_ISEL-NEXT: li 4, 120 +; NO_ISEL-NEXT: li 3, 5 ; NO_ISEL-NEXT: bc 12, 1, .LBB32_1 -; NO_ISEL-NEXT: b .LBB32_2 +; NO_ISEL-NEXT: blr ; NO_ISEL-NEXT: .LBB32_1: ; NO_ISEL-NEXT: addi 3, 4, 0 -; NO_ISEL-NEXT: .LBB32_2: -; NO_ISEL-NEXT: divwu 4, 12, 3 -; NO_ISEL-NEXT: mullw 3, 4, 3 -; NO_ISEL-NEXT: subfic 3, 3, 120 ; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 -4, i8 23 %bo = urem i8 120, %sel @@ -897,25 +862,31 @@ } define double @fsub_constant_sel_constants(i1 %cond) { -; ALL-LABEL: fsub_constant_sel_constants: -; ALL: # %bb.0: -; ALL-NEXT: andi. 3, 3, 1 -; ALL-NEXT: bc 12, 1, .LBB44_2 -; ALL-NEXT: # %bb.1: -; ALL-NEXT: addis 3, 2, .LCPI44_0@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI44_0@toc@l -; ALL-NEXT: lfdx 0, 0, 3 -; ALL-NEXT: b .LBB44_3 -; ALL-NEXT: .LBB44_2: -; ALL-NEXT: addis 3, 2, .LCPI44_1@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI44_1@toc@l -; ALL-NEXT: lfsx 0, 0, 3 -; ALL-NEXT: .LBB44_3: -; ALL-NEXT: addis 3, 2, .LCPI44_2@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI44_2@toc@l -; ALL-NEXT: lfdx 1, 0, 3 -; ALL-NEXT: xssubdp 1, 1, 0 -; ALL-NEXT: blr +; 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 @@ -984,25 +955,31 @@ } define double @fdiv_constant_sel_constants(i1 %cond) { -; ALL-LABEL: fdiv_constant_sel_constants: -; ALL: # %bb.0: -; ALL-NEXT: andi. 3, 3, 1 -; ALL-NEXT: bc 12, 1, .LBB47_2 -; ALL-NEXT: # %bb.1: -; ALL-NEXT: addis 3, 2, .LCPI47_0@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI47_0@toc@l -; ALL-NEXT: lfdx 0, 0, 3 -; ALL-NEXT: b .LBB47_3 -; ALL-NEXT: .LBB47_2: -; ALL-NEXT: addis 3, 2, .LCPI47_1@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI47_1@toc@l -; ALL-NEXT: lfsx 0, 0, 3 -; ALL-NEXT: .LBB47_3: -; ALL-NEXT: addis 3, 2, .LCPI47_2@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI47_2@toc@l -; ALL-NEXT: lfdx 1, 0, 3 -; ALL-NEXT: xsdivdp 1, 1, 0 -; ALL-NEXT: blr +; 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 @@ -1029,34 +1006,31 @@ } define double @frem_constant_sel_constants(i1 %cond) { -; ALL-LABEL: frem_constant_sel_constants: -; ALL: # %bb.0: -; ALL-NEXT: mflr 0 -; ALL-NEXT: std 0, 16(1) -; ALL-NEXT: stdu 1, -32(1) -; ALL-NEXT: .cfi_def_cfa_offset 32 -; ALL-NEXT: .cfi_offset lr, 16 -; ALL-NEXT: andi. 3, 3, 1 -; ALL-NEXT: bc 12, 1, .LBB49_2 -; ALL-NEXT: # %bb.1: -; ALL-NEXT: addis 3, 2, .LCPI49_0@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI49_0@toc@l -; ALL-NEXT: lfdx 2, 0, 3 -; ALL-NEXT: b .LBB49_3 -; ALL-NEXT: .LBB49_2: -; ALL-NEXT: addis 3, 2, .LCPI49_1@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI49_1@toc@l -; ALL-NEXT: lfsx 2, 0, 3 -; ALL-NEXT: .LBB49_3: -; ALL-NEXT: addis 3, 2, .LCPI49_2@toc@ha -; ALL-NEXT: addi 3, 3, .LCPI49_2@toc@l -; ALL-NEXT: lfdx 1, 0, 3 -; ALL-NEXT: bl fmod -; ALL-NEXT: nop -; ALL-NEXT: addi 1, 1, 32 -; ALL-NEXT: ld 0, 16(1) -; ALL-NEXT: mtlr 0 -; ALL-NEXT: blr +; 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: llvm/trunk/test/CodeGen/X86/dagcombine-select.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/dagcombine-select.ll +++ llvm/trunk/test/CodeGen/X86/dagcombine-select.ll @@ -65,11 +65,9 @@ ; CHECK-LABEL: sel_constants_sub_constant_sel_constants: ; CHECK: # %bb.0: ; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: movl $-4, %eax -; CHECK-NEXT: movl $3, %ecx -; CHECK-NEXT: cmovnel %eax, %ecx -; CHECK-NEXT: movl $5, %eax -; CHECK-NEXT: subl %ecx, %eax +; 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 @@ -79,13 +77,10 @@ define i32 @sdiv_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: sdiv_constant_sel_constants: ; CHECK: # %bb.0: -; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: movl $121, %eax -; CHECK-NEXT: movl $23, %ecx -; CHECK-NEXT: cmovnel %eax, %ecx -; CHECK-NEXT: movl $120, %eax -; CHECK-NEXT: xorl %edx, %edx -; CHECK-NEXT: divl %ecx +; 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 @@ -95,13 +90,10 @@ define i32 @udiv_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: udiv_constant_sel_constants: ; CHECK: # %bb.0: -; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: movl $-4, %eax -; CHECK-NEXT: movl $23, %ecx -; CHECK-NEXT: cmovnel %eax, %ecx -; CHECK-NEXT: movl $120, %eax -; CHECK-NEXT: xorl %edx, %edx -; CHECK-NEXT: divl %ecx +; 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 @@ -112,13 +104,9 @@ ; CHECK-LABEL: srem_constant_sel_constants: ; CHECK: # %bb.0: ; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: movl $121, %eax -; CHECK-NEXT: movl $23, %ecx -; CHECK-NEXT: cmovnel %eax, %ecx -; CHECK-NEXT: movl $120, %eax -; CHECK-NEXT: xorl %edx, %edx -; CHECK-NEXT: divl %ecx -; CHECK-NEXT: movl %edx, %eax +; 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 @@ -129,19 +117,29 @@ ; CHECK-LABEL: urem_constant_sel_constants: ; CHECK: # %bb.0: ; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: movl $-4, %eax -; CHECK-NEXT: movl $23, %ecx -; CHECK-NEXT: cmovnel %eax, %ecx -; CHECK-NEXT: movl $120, %eax -; CHECK-NEXT: xorl %edx, %edx -; CHECK-NEXT: divl %ecx -; CHECK-NEXT: movl %edx, %eax +; 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 @sel_constants_shl_constant(i1 %cond) { +; CHECK-LABEL: sel_constants_shl_constant: +; CHECK: # %bb.0: +; CHECK-NEXT: notb %dil +; CHECK-NEXT: movzbl %dil, %eax +; CHECK-NEXT: andl $1, %eax +; CHECK-NEXT: orl $2, %eax +; CHECK-NEXT: shll $8, %eax +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 2, i32 3 + %bo = shl i32 %sel, 8 + ret i32 %bo +} + define i32 @shl_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: shl_constant_sel_constants: ; CHECK: # %bb.0: @@ -188,15 +186,12 @@ ; CHECK-LABEL: fsub_constant_sel_constants: ; CHECK: # %bb.0: ; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: jne .LBB12_1 +; CHECK-NEXT: jne .LBB13_1 ; CHECK-NEXT: # %bb.2: -; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero -; CHECK-NEXT: jmp .LBB12_3 -; CHECK-NEXT: .LBB12_1: -; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero -; CHECK-NEXT: .LBB12_3: ; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero -; CHECK-NEXT: subsd %xmm1, %xmm0 +; 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 = fsub double 5.1, %sel @@ -207,15 +202,12 @@ ; CHECK-LABEL: fdiv_constant_sel_constants: ; CHECK: # %bb.0: ; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: jne .LBB13_1 +; CHECK-NEXT: jne .LBB14_1 ; CHECK-NEXT: # %bb.2: -; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero -; CHECK-NEXT: jmp .LBB13_3 -; CHECK-NEXT: .LBB13_1: -; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero -; CHECK-NEXT: .LBB13_3: ; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero -; CHECK-NEXT: divsd %xmm1, %xmm0 +; 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 = fdiv double 5.1, %sel @@ -226,15 +218,13 @@ ; CHECK-LABEL: frem_constant_sel_constants: ; CHECK: # %bb.0: ; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: jne .LBB14_1 +; CHECK-NEXT: jne .LBB15_1 ; CHECK-NEXT: # %bb.2: -; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero ; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero -; CHECK-NEXT: jmp fmod # TAILCALL -; CHECK-NEXT: .LBB14_1: -; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB15_1: ; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero -; CHECK-NEXT: jmp fmod # TAILCALL +; CHECK-NEXT: retq %sel = select i1 %cond, double -4.0, double 23.3 %bo = frem double 5.1, %sel ret double %bo