[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