[PATCH] Enable (sext x) == C --> x == (trunc C) combine
Tom Stellard
tom at stellard.net
Thu Dec 11 14:01:02 PST 2014
On Mon, Dec 01, 2014 at 07:59:55PM +0000, Matt Arsenault wrote:
> Extend the existing code which handles this for zext. This makes this more useful for targets with ZeroOrNegativeOne BooleanContent and obsoletes a custom combine SI uses for i1 setcc (sext(i1), 0, setne) since the constant will now be shrunk to i1.
>
LGTM.
> http://reviews.llvm.org/D6466
>
> Files:
> lib/CodeGen/SelectionDAG/TargetLowering.cpp
> lib/Target/R600/SIISelLowering.cpp
> test/CodeGen/R600/setcc-opt.ll
> test/CodeGen/R600/trunc-cmp-constant.ll
> test/CodeGen/X86/shrink-compare.ll
> Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp
> ===================================================================
> --- lib/CodeGen/SelectionDAG/TargetLowering.cpp
> +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp
> @@ -1283,36 +1283,53 @@
> }
>
> // (zext x) == C --> x == (trunc C)
> - if (DCI.isBeforeLegalize() && N0->hasOneUse() &&
> - (Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
> + // (sext x) == C --> x == (trunc C)
> + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
> + DCI.isBeforeLegalize() && N0->hasOneUse()) {
> unsigned MinBits = N0.getValueSizeInBits();
> - SDValue PreZExt;
> + SDValue PreExt;
> + bool Signed = false;
> if (N0->getOpcode() == ISD::ZERO_EXTEND) {
> // ZExt
> MinBits = N0->getOperand(0).getValueSizeInBits();
> - PreZExt = N0->getOperand(0);
> + PreExt = N0->getOperand(0);
> } else if (N0->getOpcode() == ISD::AND) {
> // DAGCombine turns costly ZExts into ANDs
> if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N0->getOperand(1)))
> if ((C->getAPIntValue()+1).isPowerOf2()) {
> MinBits = C->getAPIntValue().countTrailingOnes();
> - PreZExt = N0->getOperand(0);
> + PreExt = N0->getOperand(0);
> }
> + } else if (N0->getOpcode() == ISD::SIGN_EXTEND) {
> + // SExt
> + MinBits = N0->getOperand(0).getValueSizeInBits();
> + PreExt = N0->getOperand(0);
> + Signed = true;
> } else if (LoadSDNode *LN0 = dyn_cast<LoadSDNode>(N0)) {
> - // ZEXTLOAD
> + // ZEXTLOAD / SEXTLOAD
> if (LN0->getExtensionType() == ISD::ZEXTLOAD) {
> MinBits = LN0->getMemoryVT().getSizeInBits();
> - PreZExt = N0;
> + PreExt = N0;
> + } else if (LN0->getExtensionType() == ISD::SEXTLOAD) {
> + Signed = true;
> + MinBits = LN0->getMemoryVT().getSizeInBits();
> + PreExt = N0;
> }
> }
>
> + // Figure out how many bits we need to preserve this constant.
> + unsigned ReqdBits = Signed ?
> + C1.getBitWidth() - C1.getNumSignBits() + 1 :
> + C1.getActiveBits();
> +
> // Make sure we're not losing bits from the constant.
> if (MinBits > 0 &&
> - MinBits < C1.getBitWidth() && MinBits >= C1.getActiveBits()) {
> + MinBits < C1.getBitWidth() &&
> + MinBits >= ReqdBits) {
> EVT MinVT = EVT::getIntegerVT(*DAG.getContext(), MinBits);
> if (isTypeDesirableForOp(ISD::SETCC, MinVT)) {
> // Will get folded away.
> - SDValue Trunc = DAG.getNode(ISD::TRUNCATE, dl, MinVT, PreZExt);
> + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, dl, MinVT, PreExt);
> SDValue C = DAG.getConstant(C1.trunc(MinBits), MinVT);
> return DAG.getSetCC(dl, VT, Trunc, C, Cond);
> }
> Index: lib/Target/R600/SIISelLowering.cpp
> ===================================================================
> --- lib/Target/R600/SIISelLowering.cpp
> +++ lib/Target/R600/SIISelLowering.cpp
> @@ -1375,29 +1375,10 @@
> DAGCombinerInfo &DCI) const {
> SelectionDAG &DAG = DCI.DAG;
> SDLoc DL(N);
> - EVT VT = N->getValueType(0);
>
> switch (N->getOpcode()) {
> - default: return AMDGPUTargetLowering::PerformDAGCombine(N, DCI);
> - case ISD::SETCC: {
> - SDValue Arg0 = N->getOperand(0);
> - SDValue Arg1 = N->getOperand(1);
> - SDValue CC = N->getOperand(2);
> - ConstantSDNode * C = nullptr;
> - ISD::CondCode CCOp = dyn_cast<CondCodeSDNode>(CC)->get();
> -
> - // i1 setcc (sext(i1), 0, setne) -> i1 setcc(i1, 0, setne)
> - if (VT == MVT::i1
> - && Arg0.getOpcode() == ISD::SIGN_EXTEND
> - && Arg0.getOperand(0).getValueType() == MVT::i1
> - && (C = dyn_cast<ConstantSDNode>(Arg1))
> - && C->isNullValue()
> - && CCOp == ISD::SETNE) {
> - return SimplifySetCC(VT, Arg0.getOperand(0),
> - DAG.getConstant(0, MVT::i1), CCOp, true, DCI, DL);
> - }
> - break;
> - }
> + default:
> + return AMDGPUTargetLowering::PerformDAGCombine(N, DCI);
> case ISD::FMAXNUM: // TODO: What about fmax_legacy?
> case ISD::FMINNUM:
> case AMDGPUISD::SMAX:
> Index: test/CodeGen/R600/setcc-opt.ll
> ===================================================================
> --- test/CodeGen/R600/setcc-opt.ll
> +++ test/CodeGen/R600/setcc-opt.ll
> @@ -1,15 +1,201 @@
> ; RUN: llc -march=r600 -mcpu=SI -verify-machineinstrs < %s | FileCheck -check-prefix=SI -check-prefix=FUNC %s
> +; RUN: llc -march=r600 -mcpu=cypress -verify-machineinstrs < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s
>
> -; SI-LABEL: {{^}}sext_bool_icmp_ne:
> -; SI: v_cmp_ne_i32
> -; SI-NEXT: v_cndmask_b32
> -; SI-NOT: v_cmp_ne_i32
> -; SI-NOT: v_cndmask_b32
> -; SI: s_endpgm
> -define void @sext_bool_icmp_ne(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> +; FUNC-LABEL: {{^}}sext_bool_icmp_eq_0:
> +; SI-NOT: v_cmp
> +; SI: v_cmp_ne_i32_e32 vcc,
> +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, vcc
> +; SI-NEXT:buffer_store_byte [[RESULT]]
> +; SI-NEXT: s_endpgm
> +
> +; EG: SETNE_INT * [[CMP:T[0-9]+]].[[CMPCHAN:[XYZW]]], KC0[2].Z, KC0[2].W
> +; EG: AND_INT T{{[0-9]+.[XYZW]}}, PS, 1
> +define void @sext_bool_icmp_eq_0(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> + %icmp0 = icmp eq i32 %a, %b
> + %ext = sext i1 %icmp0 to i32
> + %icmp1 = icmp eq i32 %ext, 0
> + store i1 %icmp1, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}sext_bool_icmp_ne_0:
> +; SI-NOT: v_cmp
> +; SI: v_cmp_ne_i32_e32 vcc,
> +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, vcc
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +; SI-NEXT: s_endpgm
> +
> +; EG: SETNE_INT * [[CMP:T[0-9]+]].[[CMPCHAN:[XYZW]]], KC0[2].Z, KC0[2].W
> +; EG: AND_INT T{{[0-9]+.[XYZW]}}, PS, 1
> +define void @sext_bool_icmp_ne_0(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> + %icmp0 = icmp ne i32 %a, %b
> + %ext = sext i1 %icmp0 to i32
> + %icmp1 = icmp ne i32 %ext, 0
> + store i1 %icmp1, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; This really folds away to false
> +; FUNC-LABEL: {{^}}sext_bool_icmp_eq_1:
> +; SI: v_cmp_eq_i32_e32 vcc,
> +; SI-NEXT: v_cndmask_b32_e64 [[TMP:v[0-9]+]], 0, -1, vcc
> +; SI-NEXT: v_cmp_eq_i32_e64 {{s\[[0-9]+:[0-9]+\]}}, [[TMP]], 1{{$}}
> +; SI-NEXT: v_cndmask_b32_e64 [[TMP:v[0-9]+]], 0, 1,
> +; SI-NEXT: buffer_store_byte [[TMP]]
> +; SI-NEXT: s_endpgm
> +define void @sext_bool_icmp_eq_1(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> + %icmp0 = icmp eq i32 %a, %b
> + %ext = sext i1 %icmp0 to i32
> + %icmp1 = icmp eq i32 %ext, 1
> + store i1 %icmp1, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; This really folds away to true
> +; FUNC-LABEL: {{^}}sext_bool_icmp_ne_1:
> +; SI: v_cmp_ne_i32_e32 vcc,
> +; SI-NEXT: v_cndmask_b32_e64 [[TMP:v[0-9]+]], 0, -1, vcc
> +; SI-NEXT: v_cmp_ne_i32_e64 {{s\[[0-9]+:[0-9]+\]}}, [[TMP]], 1{{$}}
> +; SI-NEXT: v_cndmask_b32_e64 [[TMP:v[0-9]+]], 0, 1,
> +; SI-NEXT: buffer_store_byte [[TMP]]
> +; SI-NEXT: s_endpgm
> +define void @sext_bool_icmp_ne_1(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> %icmp0 = icmp ne i32 %a, %b
> %ext = sext i1 %icmp0 to i32
> + %icmp1 = icmp ne i32 %ext, 1
> + store i1 %icmp1, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}zext_bool_icmp_eq_0:
> +; SI-NOT: v_cmp
> +; SI: v_cmp_ne_i32_e32 vcc,
> +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, vcc
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +; SI-NEXT: s_endpgm
> +define void @zext_bool_icmp_eq_0(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> + %icmp0 = icmp eq i32 %a, %b
> + %ext = zext i1 %icmp0 to i32
> + %icmp1 = icmp eq i32 %ext, 0
> + store i1 %icmp1, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}zext_bool_icmp_ne_0:
> +; SI-NOT: v_cmp
> +; SI: v_cmp_ne_i32_e32 vcc,
> +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, vcc
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +; SI-NEXT: s_endpgm
> +define void @zext_bool_icmp_ne_0(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> + %icmp0 = icmp ne i32 %a, %b
> + %ext = zext i1 %icmp0 to i32
> %icmp1 = icmp ne i32 %ext, 0
> store i1 %icmp1, i1 addrspace(1)* %out
> ret void
> }
> +
> +; FUNC-LABEL: {{^}}zext_bool_icmp_eq_1:
> +; SI-NOT: v_cmp
> +; SI: v_cmp_eq_i32_e32 vcc,
> +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, vcc
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +; SI-NEXT: s_endpgm
> +define void @zext_bool_icmp_eq_1(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> + %icmp0 = icmp eq i32 %a, %b
> + %ext = zext i1 %icmp0 to i32
> + %icmp1 = icmp eq i32 %ext, 1
> + store i1 %icmp1, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}zext_bool_icmp_ne_1:
> +; SI-NOT: v_cmp
> +; SI: v_cmp_eq_i32_e32 vcc,
> +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, vcc
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @zext_bool_icmp_ne_1(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> + %icmp0 = icmp ne i32 %a, %b
> + %ext = zext i1 %icmp0 to i32
> + %icmp1 = icmp ne i32 %ext, 1
> + store i1 %icmp1, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}sext_bool_icmp_ne_k:
> +; SI-DAG: s_load_dword [[A:s[0-9]+]], s{{\[[0-9]+:[0-9]+\]}}, 0xb
> +; SI-DAG: s_load_dword [[B:s[0-9]+]], s{{\[[0-9]+:[0-9]+\]}}, 0xc
> +; SI: v_mov_b32_e32 [[VB:v[0-9]+]], [[B]]
> +; SI: v_cmp_ne_i32_e64 [[CMP:s\[[0-9]+:[0-9]+\]]], [[VB]], 2{{$}}
> +; SI: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, [[CMP]]
> +; SI: buffer_store_byte
> +; SI: s_endpgm
> +define void @sext_bool_icmp_ne_k(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> + %icmp0 = icmp ne i32 %a, %b
> + %ext = sext i1 %icmp0 to i32
> + %icmp1 = icmp ne i32 %ext, 2
> + store i1 %icmp1, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}cmp_zext_k_i8max:
> +; SI: buffer_load_ubyte [[B:v[0-9]+]], s{{\[[0-9]+:[0-9]+\]}}, 0 offset:0x2c
> +; SI: v_mov_b32_e32 [[K255:v[0-9]+]], 0xff{{$}}
> +; SI: v_cmp_ne_i32_e32 vcc, [[B]], [[K255]]
> +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, vcc
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +; SI: s_endpgm
> +define void @cmp_zext_k_i8max(i1 addrspace(1)* %out, i8 %b) nounwind {
> + %b.ext = zext i8 %b to i32
> + %icmp0 = icmp ne i32 %b.ext, 255
> + store i1 %icmp0, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}cmp_sext_k_neg1:
> +; SI: buffer_load_sbyte [[B:v[0-9]+]]
> +; SI: v_cmp_ne_i32_e64 [[CMP:s\[[0-9]+:[0-9]+\]]], [[B]], -1{{$}}
> +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, [[CMP]]
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +; SI: s_endpgm
> +define void @cmp_sext_k_neg1(i1 addrspace(1)* %out, i8 %b) nounwind {
> + %b.ext = sext i8 %b to i32
> + %icmp0 = icmp ne i32 %b.ext, -1
> + store i1 %icmp0, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}cmp_zext_k_neg1:
> +; SI: v_mov_b32_e32 [[RESULT:v[0-9]+]], 1{{$}}
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +; SI: s_endpgm
> +define void @cmp_zext_k_neg1(i1 addrspace(1)* %out, i8 %b) nounwind {
> + %b.ext = zext i8 %b to i32
> + %icmp0 = icmp ne i32 %b.ext, -1
> + store i1 %icmp0, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}zext_bool_icmp_ne_k:
> +; SI: v_mov_b32_e32 [[RESULT:v[0-9]+]], 1{{$}}
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +; SI-NEXT: s_endpgm
> +define void @zext_bool_icmp_ne_k(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> + %icmp0 = icmp ne i32 %a, %b
> + %ext = zext i1 %icmp0 to i32
> + %icmp1 = icmp ne i32 %ext, 2
> + store i1 %icmp1, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}zext_bool_icmp_eq_k:
> +; SI: v_mov_b32_e32 [[RESULT:v[0-9]+]], 0{{$}}
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +; SI-NEXT: s_endpgm
> +define void @zext_bool_icmp_eq_k(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind {
> + %icmp0 = icmp ne i32 %a, %b
> + %ext = zext i1 %icmp0 to i32
> + %icmp1 = icmp eq i32 %ext, 2
> + store i1 %icmp1, i1 addrspace(1)* %out
> + ret void
> +}
> Index: test/CodeGen/R600/trunc-cmp-constant.ll
> ===================================================================
> --- /dev/null
> +++ test/CodeGen/R600/trunc-cmp-constant.ll
> @@ -0,0 +1,173 @@
> +; RUN: llc -march=r600 -mcpu=SI -verify-machineinstrs < %s | FileCheck -check-prefix=SI -check-prefix=FUNC %s
> +
> +; FUNC-LABEL {{^}}sextload_i1_to_i32_trunc_cmp_eq_0:
> +; SI: buffer_load_ubyte [[LOAD:v[0-9]+]]
> +; SI: v_and_b32_e32 [[TMP:v[0-9]+]], 1, [[LOAD]]
> +; SI: v_cmp_eq_i32_e64 [[CMP:s\[[0-9]+:[0-9]+\]]], [[TMP]], 1{{$}}
> +; SI: v_cndmask_b32_e64
> +; SI: v_cndmask_b32_e64
> +; SI: buffer_store_byte
> +define void @sextload_i1_to_i32_trunc_cmp_eq_0(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = sext i1 %load to i32
> + %cmp = icmp eq i32 %ext, 0
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FIXME: This should be one compare
> +; FUNC-LABEL: {{^}}zextload_i1_to_i32_trunc_cmp_eq_0:
> +; SI: buffer_load_ubyte [[LOAD:v[0-9]+]]
> +; SI: v_and_b32_e32 [[TMP:v[0-9]+]], 1, [[LOAD]]
> +; SI: v_cmp_eq_i32_e64 [[CMP0:s\[[0-9]+:[0-9]+\]]], [[TMP]], 1{{$}}
> +; SI-NEXT: v_cndmask_b32_e64 [[TOI32:v[0-9]+]], 0, -1, [[CMP0]]
> +; SI-NEXT: v_xor_b32_e32 [[NEG:v[0-9]+]], -1, [[TOI32]]
> +; SI-NEXT: v_cmp_ne_i32_e64 [[CMP1:s\[[0-9]+:[0-9]+\]]], [[NEG]], 0
> +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, [[CMP1]]
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @zextload_i1_to_i32_trunc_cmp_eq_0(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = zext i1 %load to i32
> + %cmp = icmp eq i32 %ext, 0
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}sextload_i1_to_i32_trunc_cmp_eq_1:
> +; SI: v_mov_b32_e32 [[RESULT:v[0-9]+]], 0{{$}}
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @sextload_i1_to_i32_trunc_cmp_eq_1(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = sext i1 %load to i32
> + %cmp = icmp eq i32 %ext, 1
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}zextload_i1_to_i32_trunc_cmp_eq_1:
> +; SI: buffer_load_ubyte [[LOAD:v[0-9]+]]
> +; SI: v_and_b32_e32 [[RESULT:v[0-9]+]], 1, [[LOAD]]
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @zextload_i1_to_i32_trunc_cmp_eq_1(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = zext i1 %load to i32
> + %cmp = icmp eq i32 %ext, 1
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}sextload_i1_to_i32_trunc_cmp_eq_neg1:
> +; SI: buffer_load_ubyte [[LOAD:v[0-9]+]]
> +; SI: v_and_b32_e32 [[RESULT:v[0-9]+]], 1, [[LOAD]]
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @sextload_i1_to_i32_trunc_cmp_eq_neg1(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = sext i1 %load to i32
> + %cmp = icmp eq i32 %ext, -1
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}zextload_i1_to_i32_trunc_cmp_eq_neg1:
> +; SI: v_mov_b32_e32 [[RESULT:v[0-9]+]], 0{{$}}
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @zextload_i1_to_i32_trunc_cmp_eq_neg1(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = zext i1 %load to i32
> + %cmp = icmp eq i32 %ext, -1
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +
> +; FUNC-LABEL {{^}}sextload_i1_to_i32_trunc_cmp_ne_0:
> +; SI: buffer_load_ubyte [[LOAD:v[0-9]+]]
> +; SI: v_and_b32_e32 [[TMP:v[0-9]+]], 1, [[LOAD]]
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @sextload_i1_to_i32_trunc_cmp_ne_0(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = sext i1 %load to i32
> + %cmp = icmp ne i32 %ext, 0
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}zextload_i1_to_i32_trunc_cmp_ne_0:
> +; SI: buffer_load_ubyte [[LOAD:v[0-9]+]]
> +; SI: v_and_b32_e32 [[TMP:v[0-9]+]], 1, [[LOAD]]
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @zextload_i1_to_i32_trunc_cmp_ne_0(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = zext i1 %load to i32
> + %cmp = icmp ne i32 %ext, 0
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}sextload_i1_to_i32_trunc_cmp_ne_1:
> +; SI: v_mov_b32_e32 [[RESULT:v[0-9]+]], 1{{$}}
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @sextload_i1_to_i32_trunc_cmp_ne_1(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = sext i1 %load to i32
> + %cmp = icmp ne i32 %ext, 1
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}zextload_i1_to_i32_trunc_cmp_ne_1:
> +; SI: buffer_load_ubyte [[LOAD:v[0-9]+]]
> +; SI: v_and_b32_e32 [[TMP:v[0-9]+]], 1, [[LOAD]]
> +; SI: v_cmp_eq_i32_e64 [[CMP0:s\[[0-9]+:[0-9]+\]]], [[TMP]], 1{{$}}
> +; SI-NEXT: v_cndmask_b32_e64 [[TOI32:v[0-9]+]], 0, -1, [[CMP0]]
> +; SI-NEXT: v_xor_b32_e32 [[NEG:v[0-9]+]], -1, [[TOI32]]
> +; SI-NEXT: v_cmp_ne_i32_e64 [[CMP1:s\[[0-9]+:[0-9]+\]]], [[NEG]], 0
> +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, [[CMP1]]
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @zextload_i1_to_i32_trunc_cmp_ne_1(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = zext i1 %load to i32
> + %cmp = icmp ne i32 %ext, 1
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FIXME: This should be one compare.
> +; FUNC-LABEL: {{^}}sextload_i1_to_i32_trunc_cmp_ne_neg1:
> +; XSI: buffer_load_ubyte [[LOAD:v[0-9]+]]
> +; XSI: v_and_b32_e32 [[TMP:v[0-9]+]], 1, [[LOAD]]
> +; XSI: v_cmp_eq_i32_e64 [[CMP0:s\[[0-9]+:[0-9]+\]]], [[TMP]], 0{{$}}
> +; XSI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, [[CMP0]]
> +; XSI-NEXT: buffer_store_byte [[RESULT]]
> +define void @sextload_i1_to_i32_trunc_cmp_ne_neg1(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = sext i1 %load to i32
> + %cmp = icmp ne i32 %ext, -1
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}zextload_i1_to_i32_trunc_cmp_ne_neg1:
> +; SI: v_mov_b32_e32 [[RESULT:v[0-9]+]], 1{{$}}
> +; SI-NEXT: buffer_store_byte [[RESULT]]
> +define void @zextload_i1_to_i32_trunc_cmp_ne_neg1(i1 addrspace(1)* %out, i1 addrspace(1)* %in) nounwind {
> + %load = load i1 addrspace(1)* %in
> + %ext = zext i1 %load to i32
> + %cmp = icmp ne i32 %ext, -1
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}masked_load_i1_to_i32_trunc_cmp_ne_neg1:
> +; SI: buffer_load_sbyte [[LOAD:v[0-9]+]]
> +; SI: v_cmp_ne_i32_e64 {{s\[[0-9]+:[0-9]+\]}}, [[LOAD]], -1{{$}}
> +; SI-NEXT: v_cndmask_b32_e64
> +; SI-NEXT: buffer_store_byte
> +define void @masked_load_i1_to_i32_trunc_cmp_ne_neg1(i1 addrspace(1)* %out, i8 addrspace(1)* %in) nounwind {
> + %load = load i8 addrspace(1)* %in
> + %masked = and i8 %load, 255
> + %ext = sext i8 %masked to i32
> + %cmp = icmp ne i32 %ext, -1
> + store i1 %cmp, i1 addrspace(1)* %out
> + ret void
> +}
> Index: test/CodeGen/X86/shrink-compare.ll
> ===================================================================
> --- test/CodeGen/X86/shrink-compare.ll
> +++ test/CodeGen/X86/shrink-compare.ll
> @@ -89,3 +89,151 @@
> ; CHECK-NOT: cmpl $1,{{.*}}x+4
> ; CHECK: ret
> }
> +
> +; CHECK-LABEL: test2_1:
> +; CHECK: movzbl
> +; CHECK: cmpl $256
> +; CHECK: jne
> +define void @test2_1(i32 %X) nounwind minsize {
> +entry:
> + %and = and i32 %X, 255
> + %cmp = icmp eq i32 %and, 256
> + br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:
> + tail call void @bar() nounwind
> + br label %if.end
> +
> +if.end:
> + ret void
> +}
> +
> +; CHECK-LABEL: test_sext_i8_icmp_1:
> +; CHECK: cmpb $1, %{{dil|cl}}
> +define void @test_sext_i8_icmp_1(i8 %x) nounwind minsize {
> +entry:
> + %sext = sext i8 %x to i32
> + %cmp = icmp eq i32 %sext, 1
> + br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:
> + tail call void @bar() nounwind
> + br label %if.end
> +
> +if.end:
> + ret void
> +}
> +
> +; CHECK-LABEL: test_sext_i8_icmp_47:
> +; CHECK: cmpb $47, %{{dil|cl}}
> +define void @test_sext_i8_icmp_47(i8 %x) nounwind minsize {
> +entry:
> + %sext = sext i8 %x to i32
> + %cmp = icmp eq i32 %sext, 47
> + br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:
> + tail call void @bar() nounwind
> + br label %if.end
> +
> +if.end:
> + ret void
> +}
> +
> +; CHECK-LABEL: test_sext_i8_icmp_127:
> +; CHECK: cmpb $127, %{{dil|cl}}
> +define void @test_sext_i8_icmp_127(i8 %x) nounwind minsize {
> +entry:
> + %sext = sext i8 %x to i32
> + %cmp = icmp eq i32 %sext, 127
> + br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:
> + tail call void @bar() nounwind
> + br label %if.end
> +
> +if.end:
> + ret void
> +}
> +
> +; CHECK-LABEL: test_sext_i8_icmp_neg1:
> +; CHECK: cmpb $-1, %{{dil|cl}}
> +define void @test_sext_i8_icmp_neg1(i8 %x) nounwind minsize {
> +entry:
> + %sext = sext i8 %x to i32
> + %cmp = icmp eq i32 %sext, -1
> + br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:
> + tail call void @bar() nounwind
> + br label %if.end
> +
> +if.end:
> + ret void
> +}
> +
> +; CHECK-LABEL: test_sext_i8_icmp_neg2:
> +; CHECK: cmpb $-2, %{{dil|cl}}
> +define void @test_sext_i8_icmp_neg2(i8 %x) nounwind minsize {
> +entry:
> + %sext = sext i8 %x to i32
> + %cmp = icmp eq i32 %sext, -2
> + br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:
> + tail call void @bar() nounwind
> + br label %if.end
> +
> +if.end:
> + ret void
> +}
> +
> +; CHECK-LABEL: test_sext_i8_icmp_neg127:
> +; CHECK: cmpb $-127, %{{dil|cl}}
> +define void @test_sext_i8_icmp_neg127(i8 %x) nounwind minsize {
> +entry:
> + %sext = sext i8 %x to i32
> + %cmp = icmp eq i32 %sext, -127
> + br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:
> + tail call void @bar() nounwind
> + br label %if.end
> +
> +if.end:
> + ret void
> +}
> +
> +; CHECK-LABEL: test_sext_i8_icmp_neg128:
> +; CHECK: cmpb $-128, %{{dil|cl}}
> +define void @test_sext_i8_icmp_neg128(i8 %x) nounwind minsize {
> +entry:
> + %sext = sext i8 %x to i32
> + %cmp = icmp eq i32 %sext, -128
> + br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:
> + tail call void @bar() nounwind
> + br label %if.end
> +
> +if.end:
> + ret void
> +}
> +
> +; CHECK-LABEL: test_sext_i8_icmp_255:
> +; CHECK: movb $1,
> +; CHECK: testb
> +; CHECK: jne
> +define void @test_sext_i8_icmp_255(i8 %x) nounwind minsize {
> +entry:
> + %sext = sext i8 %x to i32
> + %cmp = icmp eq i32 %sext, 255
> + br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:
> + tail call void @bar() nounwind
> + br label %if.end
> +
> +if.end:
> + ret void
> +}
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list