From 1c7d69bbe2de22f386ffd9ef4480f8a77be28130 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Mon, 8 Oct 2012 18:59:53 +0000 Subject: [PATCH] PR12716: PPC crashes on vector compare Vector compare using altivec 'vcmpxxx' instructions have as third argument a vector register instead of CR one, different from integer and float-point compares. This leads to a failure in code generation, where 'SelectSETCC' expects a DAG with a CR register and gets vector register instead. This patch changes the behavior by just returning a DAG with the vector compare instruction based on the type. The patch also adds a testcase for all vector types llvm defines. It also included a fix on signed 5-bits predicates printing, where signed values were not handled correctly as signed (char are unsigned by default for PowerPC). This generates 'vspltisw' (vector splat) instruction with SIM out of range. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165419 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../PowerPC/InstPrinter/PPCInstPrinter.cpp | 6 +- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 23 ++- lib/Target/PowerPC/PPCISelLowering.cpp | 4 +- test/CodeGen/PowerPC/vec_cmp.ll | 191 ++++++++++++++++++ 4 files changed, 218 insertions(+), 6 deletions(-) create mode 100644 test/CodeGen/PowerPC/vec_cmp.ll diff --git a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp index 413142eb2bf..3d583060d1e 100644 --- a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +++ b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp @@ -136,21 +136,21 @@ void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo, void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { - char Value = MI->getOperand(OpNo).getImm(); + int Value = MI->getOperand(OpNo).getImm(); Value = SignExtend32<5>(Value); O << (int)Value; } void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { - unsigned char Value = MI->getOperand(OpNo).getImm(); + unsigned int Value = MI->getOperand(OpNo).getImm(); assert(Value <= 31 && "Invalid u5imm argument!"); O << (unsigned int)Value; } void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { - unsigned char Value = MI->getOperand(OpNo).getImm(); + unsigned int Value = MI->getOperand(OpNo).getImm(); assert(Value <= 63 && "Invalid u6imm argument!"); O << (unsigned int)Value; } diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index e8f4d16997f..b52452ce89b 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -701,10 +701,29 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDNode *N) { } } + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + + // Altivec Vector compare instructions do not set any CR register by default + if (LHS.getValueType().isVector()) { + unsigned int Opc; + if (LHS.getValueType() == MVT::v16i8) + Opc = PPC::VCMPEQUB; + else if (LHS.getValueType() == MVT::v4i32) + Opc = PPC::VCMPEQUW; + else if (LHS.getValueType() == MVT::v8i16) + Opc = PPC::VCMPEQUH; + else if (LHS.getValueType() == MVT::v4f32) + Opc = PPC::VCMPEQFP; + else + llvm_unreachable("Invalid vector compare type: should be expanded by legalize"); + return CurDAG->SelectNodeTo(N, Opc, LHS.getValueType(), LHS, RHS); + } + bool Inv; int OtherCondIdx; unsigned Idx = getCRIdxForSetCC(CC, Inv, OtherCondIdx); - SDValue CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC, dl); + SDValue CCReg = SelectCC(LHS, RHS, CC, dl); SDValue IntCR; // Force the ccreg into CR7. @@ -717,7 +736,7 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDNode *N) { if (PPCSubTarget.hasMFOCRF() && OtherCondIdx == -1) IntCR = SDValue(CurDAG->getMachineNode(PPC::MFOCRF, dl, MVT::i32, CR7Reg, CCReg), 0); - else + else IntCR = SDValue(CurDAG->getMachineNode(PPC::MFCRpseud, dl, MVT::i32, CR7Reg, CCReg), 0); diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index eaef9d3c3fd..bdda8eaa468 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -542,7 +542,9 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { } EVT PPCTargetLowering::getSetCCResultType(EVT VT) const { - return MVT::i32; + if (!VT.isVector()) + return MVT::i32; + return VT.changeVectorElementTypeToInteger(); } //===----------------------------------------------------------------------===// diff --git a/test/CodeGen/PowerPC/vec_cmp.ll b/test/CodeGen/PowerPC/vec_cmp.ll new file mode 100644 index 00000000000..b2b59db8f18 --- /dev/null +++ b/test/CodeGen/PowerPC/vec_cmp.ll @@ -0,0 +1,191 @@ +; RUN: llc -mattr=+altivec < %s | FileCheck %s + +; Check vector comparisons using altivec. + + +target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64" +target triple = "powerpc64-unknown-linux-gnu" + +define <2 x i8> @v2si8_cmp(<2 x i8> %x, <2 x i8> %y) nounwind readnone { + %cmp = icmp eq <2 x i8> %x, %y + %sext = sext <2 x i1> %cmp to <2 x i8> + ret <2 x i8> %sext +} +; CHECK: v2si8_cmp: +; CHECK: vcmpequb {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <4 x i8> @v4si8_cmp(<4 x i8> %x, <4 x i8> %y) nounwind readnone { + %cmp = icmp eq <4 x i8> %x, %y + %sext = sext <4 x i1> %cmp to <4 x i8> + ret <4 x i8> %sext +} +; CHECK: v4si8_cmp: +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <8 x i8> @v8si8_cmp(<8 x i8> %x, <8 x i8> %y) nounwind readnone { + %cmp = icmp eq <8 x i8> %x, %y + %sext = sext <8 x i1> %cmp to <8 x i8> + ret <8 x i8> %sext +} +; CHECK: v8si8_cmp: +; CHECK: vcmpequh {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <16 x i8> @v16si8_cmp(<16 x i8> %x, <16 x i8> %y) nounwind readnone { + %cmp = icmp eq <16 x i8> %x, %y + %sext = sext <16 x i1> %cmp to <16 x i8> + ret <16 x i8> %sext +} +; CHECK: v16si8_cmp: +; CHECK: vcmpequb {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <32 x i8> @v32si8_cmp(<32 x i8> %x, <32 x i8> %y) nounwind readnone { + %cmp = icmp eq <32 x i8> %x, %y + %sext = sext <32 x i1> %cmp to <32 x i8> + ret <32 x i8> %sext +} +; CHECK: v32si8_cmp: +; CHECK: vcmpequb {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequb {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <2 x i16> @v2si16_cmp(<2 x i16> %x, <2 x i16> %y) nounwind readnone { + %cmp = icmp eq <2 x i16> %x, %y + %sext = sext <2 x i1> %cmp to <2 x i16> + ret <2 x i16> %sext +} +; CHECK: v2si16_cmp: +; CHECK: vcmpequh {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <4 x i16> @v4si16_cmp(<4 x i16> %x, <4 x i16> %y) nounwind readnone { + %cmp = icmp eq <4 x i16> %x, %y + %sext = sext <4 x i1> %cmp to <4 x i16> + ret <4 x i16> %sext +} +; CHECK: v4si16_cmp: +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <8 x i16> @v8si16_cmp(<8 x i16> %x, <8 x i16> %y) nounwind readnone { + %cmp = icmp eq <8 x i16> %x, %y + %sext = sext <8 x i1> %cmp to <8 x i16> + ret <8 x i16> %sext +} +; CHECK: v8si16_cmp: +; CHECK: vcmpequh {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <16 x i16> @v16si16_cmp(<16 x i16> %x, <16 x i16> %y) nounwind readnone { + %cmp = icmp eq <16 x i16> %x, %y + %sext = sext <16 x i1> %cmp to <16 x i16> + ret <16 x i16> %sext +} +; CHECK: v16si16_cmp: +; CHECK: vcmpequh {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequh {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <32 x i16> @v32si16_cmp(<32 x i16> %x, <32 x i16> %y) nounwind readnone { + %cmp = icmp eq <32 x i16> %x, %y + %sext = sext <32 x i1> %cmp to <32 x i16> + ret <32 x i16> %sext +} +; CHECK: v32si16_cmp: +; CHECK: vcmpequh {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequh {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequh {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequh {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <2 x i32> @v2si32_cmp(<2 x i32> %x, <2 x i32> %y) nounwind readnone { + %cmp = icmp eq <2 x i32> %x, %y + %sext = sext <2 x i1> %cmp to <2 x i32> + ret <2 x i32> %sext +} +; CHECK: v2si32_cmp: +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <4 x i32> @v4si32_cmp(<4 x i32> %x, <4 x i32> %y) nounwind readnone { + %cmp = icmp eq <4 x i32> %x, %y + %sext = sext <4 x i1> %cmp to <4 x i32> + ret <4 x i32> %sext +} +; CHECK: v4si32_cmp: +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <8 x i32> @v8si32_cmp(<8 x i32> %x, <8 x i32> %y) nounwind readnone { + %cmp = icmp eq <8 x i32> %x, %y + %sext = sext <8 x i1> %cmp to <8 x i32> + ret <8 x i32> %sext +} +; CHECK: v8si32_cmp: +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <16 x i32> @v16si32_cmp(<16 x i32> %x, <16 x i32> %y) nounwind readnone { + %cmp = icmp eq <16 x i32> %x, %y + %sext = sext <16 x i1> %cmp to <16 x i32> + ret <16 x i32> %sext +} +; CHECK: v16si32_cmp: +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <32 x i32> @v32si32_cmp(<32 x i32> %x, <32 x i32> %y) nounwind readnone { + %cmp = icmp eq <32 x i32> %x, %y + %sext = sext <32 x i1> %cmp to <32 x i32> + ret <32 x i32> %sext +} +; CHECK: v32si32_cmp: +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpequw {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <2 x float> @v2f32_cmp(<2 x float> %x, <2 x float> %y) nounwind readnone { +entry: + %cmp = fcmp oeq <2 x float> %x, %y + %sext = sext <2 x i1> %cmp to <2 x i32> + %0 = bitcast <2 x i32> %sext to <2 x float> + ret <2 x float> %0 +} +; CHECK: v2f32_cmp: +; CHECK: vcmpeqfp {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <4 x float> @v4f32_cmp(<4 x float> %x, <4 x float> %y) nounwind readnone { +entry: + %cmp = fcmp oeq <4 x float> %x, %y + %sext = sext <4 x i1> %cmp to <4 x i32> + %0 = bitcast <4 x i32> %sext to <4 x float> + ret <4 x float> %0 +} +; CHECK: v4f32_cmp: +; CHECK: vcmpeqfp {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} + + +define <8 x float> @v8f32_cmp(<8 x float> %x, <8 x float> %y) nounwind readnone { +entry: + %cmp = fcmp oeq <8 x float> %x, %y + %sext = sext <8 x i1> %cmp to <8 x i32> + %0 = bitcast <8 x i32> %sext to <8 x float> + ret <8 x float> %0 +} +; CHECK: v8f32_cmp: +; CHECK: vcmpeqfp {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} +; CHECK: vcmpeqfp {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} -- 2.34.1