From d796cf2e013f98288271bed2848b72252b28c73f Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 21 Dec 2014 16:48:42 +0000 Subject: [PATCH] Enable (sext x) == C --> x == (trunc C) combine 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224691 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 35 ++- lib/Target/R600/SIISelLowering.cpp | 23 +- test/CodeGen/R600/setcc-opt.ll | 232 +++++++++++++++++++- test/CodeGen/R600/trunc-cmp-constant.ll | 169 ++++++++++++++ test/CodeGen/X86/shrink-compare.ll | 148 +++++++++++++ 5 files changed, 570 insertions(+), 37 deletions(-) create mode 100644 test/CodeGen/R600/trunc-cmp-constant.ll diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 9aef5edcd54..72e0aca8408 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1283,36 +1283,53 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, } // (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(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(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); } diff --git a/lib/Target/R600/SIISelLowering.cpp b/lib/Target/R600/SIISelLowering.cpp index 5702ee67123..a2ea2fa3908 100644 --- a/lib/Target/R600/SIISelLowering.cpp +++ b/lib/Target/R600/SIISelLowering.cpp @@ -1361,29 +1361,10 @@ SDValue SITargetLowering::PerformDAGCombine(SDNode *N, 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(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(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: diff --git a/test/CodeGen/R600/setcc-opt.ll b/test/CodeGen/R600/setcc-opt.ll index af48df88e5b..d802bcb8f81 100644 --- a/test/CodeGen/R600/setcc-opt.ll +++ b/test/CodeGen/R600/setcc-opt.ll @@ -1,15 +1,233 @@ ; 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:44 +; 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 addrspace(1)* %b.ptr) nounwind { + %b = load i8 addrspace(1)* %b.ptr + %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_sext_k_neg1_i8_sext_arg: +; SI: s_load_dword [[B:s[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_i8_sext_arg(i1 addrspace(1)* %out, i8 signext %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 +} + +; FIXME: This ends up doing a buffer_load_ubyte, and and compare to +; 255. Seems to be because of ordering problems when not allowing load widths to be reduced. +; Should do a buffer_load_sbyte and compare with -1 + +; FUNC-LABEL: {{^}}cmp_sext_k_neg1_i8_arg: +; SI-DAG: buffer_load_ubyte [[B:v[0-9]+]] +; SI-DAG: v_mov_b32_e32 [[K:v[0-9]+]], 0xff{{$}} +; SI: v_cmp_ne_i32_e32 vcc, [[B]], [[K]]{{$}} +; 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_sext_k_neg1_i8_arg(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 +} diff --git a/test/CodeGen/R600/trunc-cmp-constant.ll b/test/CodeGen/R600/trunc-cmp-constant.ll new file mode 100644 index 00000000000..73c35512d77 --- /dev/null +++ b/test/CodeGen/R600/trunc-cmp-constant.ll @@ -0,0 +1,169 @@ +; 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: s_xor_b64 s{{\[[0-9]+:[0-9]+\]}}, s{{\[[0-9]+:[0-9]+\]}}, -1{{$}} +; 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: The negate should be inverting the 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: s_xor_b64 [[NEG:s\[[0-9]+:[0-9]+\]]], [[CMP0]], -1 +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, [[NEG]] +; 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: s_xor_b64 [[NEG:s\[[0-9]+:[0-9]+\]]], [[CMP0]], -1 +; SI-NEXT: v_cndmask_b32_e64 [[RESULT:v[0-9]+]], 0, 1, [[NEG]] +; 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 +} diff --git a/test/CodeGen/X86/shrink-compare.ll b/test/CodeGen/X86/shrink-compare.ll index fc7ee061f35..4ddef4ca535 100644 --- a/test/CodeGen/X86/shrink-compare.ll +++ b/test/CodeGen/X86/shrink-compare.ll @@ -89,3 +89,151 @@ if.end: ; 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 +} -- 2.34.1