diff options
| author | Jacques Pienaar <jpienaar@google.com> | 2016-04-19 19:15:25 +0000 |
|---|---|---|
| committer | Jacques Pienaar <jpienaar@google.com> | 2016-04-19 19:15:25 +0000 |
| commit | 50d4e989058d30813754c5dc6cb0988082b127e9 (patch) | |
| tree | 14b914c85fc26271842d16883a4fc0ef86804d77 | |
| parent | b4b27230bfe2f709aac4a82522a160981472c954 (diff) | |
| download | bcm5719-llvm-50d4e989058d30813754c5dc6cb0988082b127e9.tar.gz bcm5719-llvm-50d4e989058d30813754c5dc6cb0988082b127e9.zip | |
[lanai] Add lowering for SETCCE i32.
* Add lowering for SETCCE i32.
* Add test to check lowering of i64 compares uses SETCCE expansion (outside of EQ and NE).
* Fix select.ll test and immediate form selection for RI operations.
llvm-svn: 266802
| -rw-r--r-- | llvm/lib/Target/Lanai/LanaiISelLowering.cpp | 43 | ||||
| -rw-r--r-- | llvm/lib/Target/Lanai/LanaiISelLowering.h | 12 | ||||
| -rw-r--r-- | llvm/lib/Target/Lanai/LanaiInstrInfo.td | 47 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Lanai/comparisons_i64.ll | 108 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Lanai/select.ll | 2 |
5 files changed, 177 insertions, 35 deletions
diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp index aefb5eaa7bb..d4a50e867d4 100644 --- a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp +++ b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp @@ -71,6 +71,7 @@ LanaiTargetLowering::LanaiTargetLowering(const TargetMachine &TM, setOperationAction(ISD::BR_JT, MVT::Other, Expand); setOperationAction(ISD::BRCOND, MVT::Other, Expand); setOperationAction(ISD::SETCC, MVT::i32, Custom); + setOperationAction(ISD::SETCCE, MVT::i32, Custom); setOperationAction(ISD::SELECT, MVT::i32, Expand); setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); @@ -172,6 +173,8 @@ SDValue LanaiTargetLowering::LowerOperation(SDValue Op, return LowerSELECT_CC(Op, DAG); case ISD::SETCC: return LowerSETCC(Op, DAG); + case ISD::SETCCE: + return LowerSETCCE(Op, DAG); case ISD::SRL_PARTS: return LowerSRL_PARTS(Op, DAG); case ISD::VASTART: @@ -779,9 +782,10 @@ SDValue LanaiTargetLowering::LowerCallResult( // Custom Lowerings //===----------------------------------------------------------------------===// -static LPCC::CondCode IntCondCCodeToICC(ISD::CondCode SetCCOpcode, SDLoc DL, - SDValue &LHS, SDValue &RHS, - SelectionDAG &DAG) { +static LPCC::CondCode IntCondCCodeToICC(SDValue CC, SDLoc DL, SDValue &LHS, + SDValue &RHS, SelectionDAG &DAG) { + ISD::CondCode SetCCOpcode = cast<CondCodeSDNode>(CC)->get(); + // For integer, only the SETEQ, SETNE, SETLT, SETLE, SETGT, SETGE, SETULT, // SETULE, SETUGT, and SETUGE opcodes are used (see CodeGen/ISDOpcodes.h) // and Lanai only supports integer comparisons, so only provide definitions @@ -845,14 +849,14 @@ static LPCC::CondCode IntCondCCodeToICC(ISD::CondCode SetCCOpcode, SDLoc DL, SDValue LanaiTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { SDValue Chain = Op.getOperand(0); - ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); + SDValue Cond = Op.getOperand(1); SDValue LHS = Op.getOperand(2); SDValue RHS = Op.getOperand(3); SDValue Dest = Op.getOperand(4); SDLoc DL(Op); - SDValue TargetCC = - DAG.getConstant(IntCondCCodeToICC(CC, DL, LHS, RHS, DAG), DL, MVT::i32); + LPCC::CondCode CC = IntCondCCodeToICC(Cond, DL, LHS, RHS, DAG); + SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i32); SDValue Flag = DAG.getNode(LanaiISD::SET_FLAG, DL, MVT::Glue, LHS, RHS, TargetCC); @@ -946,14 +950,27 @@ SDValue LanaiTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const { return Res; } +SDValue LanaiTargetLowering::LowerSETCCE(SDValue Op, SelectionDAG &DAG) const { + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + SDValue Carry = Op.getOperand(2); + SDValue Cond = Op.getOperand(3); + SDLoc DL(Op); + + LPCC::CondCode CC = IntCondCCodeToICC(Cond, DL, LHS, RHS, DAG); + SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i32); + SDValue Flag = DAG.getNode(LanaiISD::SUBBF, DL, MVT::Glue, LHS, RHS, Carry); + return DAG.getNode(LanaiISD::SETCC, DL, Op.getValueType(), TargetCC, Flag); +} + SDValue LanaiTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); - ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); + SDValue Cond = Op.getOperand(2); SDLoc DL(Op); - SDValue TargetCC = - DAG.getConstant(IntCondCCodeToICC(CC, DL, LHS, RHS, DAG), DL, MVT::i32); + LPCC::CondCode CC = IntCondCCodeToICC(Cond, DL, LHS, RHS, DAG); + SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i32); SDValue Flag = DAG.getNode(LanaiISD::SET_FLAG, DL, MVT::Glue, LHS, RHS, TargetCC); @@ -966,11 +983,11 @@ SDValue LanaiTargetLowering::LowerSELECT_CC(SDValue Op, SDValue RHS = Op.getOperand(1); SDValue TrueV = Op.getOperand(2); SDValue FalseV = Op.getOperand(3); - ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); + SDValue Cond = Op.getOperand(4); SDLoc DL(Op); - SDValue TargetCC = - DAG.getConstant(IntCondCCodeToICC(CC, DL, LHS, RHS, DAG), DL, MVT::i32); + LPCC::CondCode CC = IntCondCCodeToICC(Cond, DL, LHS, RHS, DAG); + SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i32); SDValue Flag = DAG.getNode(LanaiISD::SET_FLAG, DL, MVT::Glue, LHS, RHS, TargetCC); @@ -1084,6 +1101,8 @@ const char *LanaiTargetLowering::getTargetNodeName(unsigned Opcode) const { return "LanaiISD::SELECT_CC"; case LanaiISD::SETCC: return "LanaiISD::SETCC"; + case LanaiISD::SUBBF: + return "LanaiISD::SUBBF"; case LanaiISD::SET_FLAG: return "LanaiISD::SET_FLAG"; case LanaiISD::BR_CC: diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.h b/llvm/lib/Target/Lanai/LanaiISelLowering.h index 8cd1e36e2a7..bd065f76b9c 100644 --- a/llvm/lib/Target/Lanai/LanaiISelLowering.h +++ b/llvm/lib/Target/Lanai/LanaiISelLowering.h @@ -38,12 +38,15 @@ enum { // is condition code and operand 4 is flag operand. SELECT_CC, - // SETCC - Store the conditional to a register + // SETCC - Store the conditional code to a register. SETCC, - // SET_FLAG - Set flag compare + // SET_FLAG - Set flag compare. SET_FLAG, + // SUBBF - Subtract with borrow that sets flags. + SUBBF, + // BR_CC - Used to glue together a conditional branch and comparison BR_CC, @@ -51,11 +54,11 @@ enum { // and TargetGlobalAddress. Wrapper, - // Get the Higher/Lower 16 bits from a 32-bit immediate + // Get the Higher/Lower 16 bits from a 32-bit immediate. HI, LO, - // Small 21-bit immediate in global memory + // Small 21-bit immediate in global memory. SMALL }; } // namespace LanaiISD @@ -87,6 +90,7 @@ public: SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSETCCE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSRL_PARTS(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/Lanai/LanaiInstrInfo.td b/llvm/lib/Target/Lanai/LanaiInstrInfo.td index 70da0d35370..3cc1363e392 100644 --- a/llvm/lib/Target/Lanai/LanaiInstrInfo.td +++ b/llvm/lib/Target/Lanai/LanaiInstrInfo.td @@ -41,12 +41,14 @@ def Call : SDNode<"LanaiISD::CALL", SDT_LanaiCall, SDNPVariadic]>; def RetFlag : SDNode<"LanaiISD::RET_FLAG", SDTNone, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -def CallSeqStart : SDNode<"ISD::CALLSEQ_START", SDT_LanaiCallSeqStart, +def CallSeqStart : SDNode<"ISD::CALLSEQ_START", SDT_LanaiCallSeqStart, [SDNPHasChain, SDNPOutGlue]>; -def CallSeqEnd : SDNode<"ISD::CALLSEQ_END", SDT_LanaiCallSeqEnd, +def CallSeqEnd : SDNode<"ISD::CALLSEQ_END", SDT_LanaiCallSeqEnd, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; def LanaiSetFlag : SDNode<"LanaiISD::SET_FLAG", SDT_LanaiSetFlag, [SDNPOutGlue]>; +def LanaiSubbF : SDNode<"LanaiISD::SUBBF", SDT_LanaiSetFlag, + [SDNPOutGlue, SDNPInGlue]>; def LanaiBrCC : SDNode<"LanaiISD::BR_CC", SDT_LanaiBrCC, [SDNPHasChain, SDNPInGlue]>; def LanaiSelectCC : SDNode<"LanaiISD::SELECT_CC", SDT_LanaiSelectCC, @@ -315,13 +317,13 @@ multiclass ALUlogic<bits<3> subOp, string AsmStr, SDNode OpNode, // Non flag setting ALU operations let isAsCheapAsAMove = 1, F = 0 in { let isCommutable = 1 in { - defm ADD_ : ALUarith<0b000, "add", add, i32lo16s, i32hi16>; + defm ADD_ : ALUarith<0b000, "add", add, i32lo16z, i32hi16>; } - defm SUB_ : ALUarith<0b010, "sub", sub, i32lo16s, i32hi16>; + defm SUB_ : ALUarith<0b010, "sub", sub, i32lo16z, i32hi16>; let isCommutable = 1 in { defm AND_ : ALUlogic<0b100, "and", and, i32lo16and, i32hi16and>; defm OR_ : ALUlogic<0b101, "or", or, i32lo16z, i32hi16>; - defm XOR_ : ALUlogic<0b110, "xor", xor, i32lo16s, i32hi16>; + defm XOR_ : ALUlogic<0b110, "xor", xor, i32lo16z, i32hi16>; } } @@ -348,8 +350,8 @@ def : Pat<(sub GPR:$Rs1, i32neg16:$imm), // Flag (incl. carry) setting addition and subtraction let F = 1, Defs = [SR] in { - defm ADD_F_ : ALUarith<0b000, "add.f", addc, i32lo16s, i32hi16>; - defm SUB_F_ : ALUarith<0b010, "sub.f", subc, i32lo16s, i32hi16>; + defm ADD_F_ : ALUarith<0b000, "add.f", addc, i32lo16z, i32hi16>; + defm SUB_F_ : ALUarith<0b010, "sub.f", subc, i32lo16z, i32hi16>; } def : Pat<(addc GPR:$Rs1, i32lo16z:$imm), @@ -366,8 +368,8 @@ def : Pat<(subc GPR:$Rs1, i32hi16:$imm), // Carry using addition and subtraction let F = 0, Uses = [SR] in { - defm ADDC_ : ALUarith<0b001, "addc", adde, i32lo16s, i32hi16>; - defm SUBB_ : ALUarith<0b011, "subb", sube, i32lo16s, i32hi16>; + defm ADDC_ : ALUarith<0b001, "addc", adde, i32lo16z, i32hi16>; + defm SUBB_ : ALUarith<0b011, "subb", sube, i32lo16z, i32hi16>; } def : Pat<(adde GPR:$Rs1, i32lo16z:$imm), @@ -384,15 +386,27 @@ def : Pat<(sube GPR:$Rs1, i32hi16:$imm), // Flag setting ALU operations let isAsCheapAsAMove = 1, F = 1, Defs = [SR] in { - defm ADDC_F_ : ALUarith<0b001, "addc.f", adde, i32lo16s, i32hi16>; - defm SUBB_F_ : ALUarith<0b011, "subb.f", sube, i32lo16s, i32hi16>; let isCommutable = 1 in { defm AND_F_ : ALUlogic<0b100, "and.f", and, i32lo16and, i32hi16and>; defm OR_F_ : ALUlogic<0b101, "or.f", or, i32lo16z, i32hi16>; - defm XOR_F_ : ALUlogic<0b110, "xor.f", xor, i32lo16s, i32hi16>; + defm XOR_F_ : ALUlogic<0b110, "xor.f", xor, i32lo16z, i32hi16>; } } +let isAsCheapAsAMove = 1, F = 1, Defs = [SR], Uses = [SR] in { + defm ADDC_F_ : ALUarith<0b001, "addc.f", adde, i32lo16z, i32hi16>; + defm SUBB_F_ : ALUarith<0b011, "subb.f", sube, i32lo16z, i32hi16>; +} + +def : Pat<(LanaiSubbF GPR:$Rs1, GPR:$Rs2), + (SUBB_F_R GPR:$Rs1, GPR:$Rs2)>; + +def : Pat<(LanaiSubbF GPR:$Rs1, i32lo16z:$imm), + (SUBB_F_I_LO GPR:$Rs1, i32lo16z:$imm)>; + +def : Pat<(LanaiSubbF GPR:$Rs1, i32hi16:$imm), + (SUBB_F_I_HI GPR:$Rs1, i32hi16:$imm)>; + def : InstAlias<"mov $src, $dst", (ADD_R GPR:$dst, GPR:$src, R0)>; let isAsCheapAsAMove = 1, Rs1 = R0.Num, isCodeGenOnly = 1, H = 1, F = 0, @@ -401,7 +415,7 @@ let isAsCheapAsAMove = 1, Rs1 = R0.Num, isCodeGenOnly = 1, H = 1, F = 0, "mov\t$imm16, $Rd", [(set GPR:$Rd, i32hi16:$imm16)]>; -def : InstAlias<"mov $imm16, $dst", (ADD_I_LO GPR:$dst, R0, i32lo16s:$imm16)>; +def : InstAlias<"mov $imm16, $dst", (ADD_I_LO GPR:$dst, R0, i32lo16z:$imm16)>; def : InstAlias<"mov $imm16, $dst", (ADD_I_HI GPR:$dst, R0, i32hi16:$imm16)>; def : InstAlias<"mov $imm16, $dst", (AND_I_LO GPR:$dst, R1, i32lo16and:$imm16)>; @@ -693,9 +707,9 @@ multiclass SF<bits<3> op2Val, string AsmStr> { !strconcat(AsmStr, "\t$Rs1, $Rs2, %r0"), [(LanaiSetFlag (i32 GPR:$Rs1), (i32 GPR:$Rs2))]>; let F = 1, Rd = R0.Num, H = 0, Defs = [SR] in - def _RI : InstRI<op2Val, (outs), (ins GPR:$Rs1, i32lo16s:$imm16), + def _RI : InstRI<op2Val, (outs), (ins GPR:$Rs1, i32lo16z:$imm16), !strconcat(AsmStr, "\t$Rs1, $imm16, %r0"), - [(LanaiSetFlag (i32 GPR:$Rs1), i32lo16s:$imm16)]>; + [(LanaiSetFlag (i32 GPR:$Rs1), i32lo16z:$imm16)]>; } let isCodeGenOnly = 1 in { defm SFSUB_F : SF<0b010, "sub.f">; @@ -820,9 +834,6 @@ let isCodeGenOnly = 1 in // Non-Instruction Patterns //===----------------------------------------------------------------------===// -// signed 16-bit immediate -def : Pat<(i32 i32lo16s:$imm), (MOVHI imm:$imm)>; - // i32 0 and R0 can be used interchangeably. def : Pat<(i32 0), (i32 R0)>; // i32 -1 and R1 can be used interchangeably. diff --git a/llvm/test/CodeGen/Lanai/comparisons_i64.ll b/llvm/test/CodeGen/Lanai/comparisons_i64.ll new file mode 100644 index 00000000000..853ac139b2d --- /dev/null +++ b/llvm/test/CodeGen/Lanai/comparisons_i64.ll @@ -0,0 +1,108 @@ +; RUN: llc < %s | FileCheck %s + +; Test that basic 64-bit integer comparison operations assemble as expected. + +target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64" +target triple = "lanai" + +; CHECK-LABEL: eq_i64: +; CHECK: xor +; CHECK: xor +; CHECK: or.f +; CHECK-NEXT: seq +define i32 @eq_i64(i64 inreg %x, i64 inreg %y) { + %a = icmp eq i64 %x, %y + %b = zext i1 %a to i32 + ret i32 %b +} + +; CHECK-LABEL: ne_i64: +; CHECK: xor +; CHECK: xor +; CHECK: or.f +; CHECK-NEXT: sne +define i32 @ne_i64(i64 inreg %x, i64 inreg %y) { + %a = icmp ne i64 %x, %y + %b = zext i1 %a to i32 + ret i32 %b +} + +; CHECK-LABEL: slt_i64: +; CHECK: sub.f %r7, %r19, %r3 +; CHECK: subb.f %r6, %r18, %r3 +; CHECK-NEXT: slt +define i32 @slt_i64(i64 inreg %x, i64 inreg %y) { + %a = icmp slt i64 %x, %y + %b = zext i1 %a to i32 + ret i32 %b +} + +; CHECK-LABEL: sle_i64: +; CHECK: sub.f %r19, %r7, %r3 +; CHECK: subb.f %r18, %r6, %r3 +; CHECK-NEXT: sge %rv +define i32 @sle_i64(i64 inreg %x, i64 inreg %y) { + %a = icmp sle i64 %x, %y + %b = zext i1 %a to i32 + ret i32 %b +} + +; CHECK-LABEL: ult_i64: +; CHECK: sub.f %r7, %r19, %r3 +; CHECK: subb.f %r6, %r18, %r3 +; CHECK-NEXT: sult %rv +define i32 @ult_i64(i64 inreg %x, i64 inreg %y) { + %a = icmp ult i64 %x, %y + %b = zext i1 %a to i32 + ret i32 %b +} + +; CHECK-LABEL: ule_i64: +; CHECK: sub.f %r19, %r7, %r3 +; CHECK: subb.f %r18, %r6, %r3 +; CHECK-NEXT: suge %rv +define i32 @ule_i64(i64 inreg %x, i64 inreg %y) { + %a = icmp ule i64 %x, %y + %b = zext i1 %a to i32 + ret i32 %b +} + +; CHECK-LABEL: sgt_i64: +; CHECK: sub.f %r19, %r7, %r3 +; CHECK: subb.f %r18, %r6, %r3 +; CHECK-NEXT: slt %rv +define i32 @sgt_i64(i64 inreg %x, i64 inreg %y) { + %a = icmp sgt i64 %x, %y + %b = zext i1 %a to i32 + ret i32 %b +} + +; CHECK-LABEL: sge_i64: +; CHECK: sub.f %r7, %r19, %r3 +; CHECK: subb.f %r6, %r18, %r3 +; CHECK-NEXT: sge %rv +define i32 @sge_i64(i64 inreg %x, i64 inreg %y) { + %a = icmp sge i64 %x, %y + %b = zext i1 %a to i32 + ret i32 %b +} + +; CHECK-LABEL: ugt_i64: +; CHECK: sub.f %r19, %r7, %r3 +; CHECK: subb.f %r18, %r6, %r3 +; CHECK-NEXT: sult %rv +define i32 @ugt_i64(i64 inreg %x, i64 inreg %y) { + %a = icmp ugt i64 %x, %y + %b = zext i1 %a to i32 + ret i32 %b +} + +; CHECK-LABEL: uge_i64: +; CHECK: sub.f %r7, %r19, %r3 +; CHECK: subb.f %r6, %r18, %r3 +; CHECK-NEXT: suge %rv +define i32 @uge_i64(i64 inreg %x, i64 inreg %y) { + %a = icmp uge i64 %x, %y + %b = zext i1 %a to i32 + ret i32 %b +} diff --git a/llvm/test/CodeGen/Lanai/select.ll b/llvm/test/CodeGen/Lanai/select.ll index 159e8edb283..0c5b2307ab2 100644 --- a/llvm/test/CodeGen/Lanai/select.ll +++ b/llvm/test/CodeGen/Lanai/select.ll @@ -8,7 +8,7 @@ target triple = "lanai" ; CHECK-LABEL: select_i32_bool: ; CHECK: sub.f %r6, 0x0, %r0 ; CHECK: sel.ne %r7, %r18, %rv -define i32 @select_i32_bool(i1 inreg %a, i32 inreg %b, i32 inreg %c) { +define i32 @select_i32_bool(i1 zeroext inreg %a, i32 inreg %b, i32 inreg %c) { %cond = select i1 %a, i32 %b, i32 %c ret i32 %cond } |

