Skip to content

Commit

Permalink
[lanai] Add lowering for SETCCE i32.
Browse files Browse the repository at this point in the history
* 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.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266802 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
jpienaar committed Apr 19, 2016
1 parent 7f0d15f commit 5ea3f52
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 35 deletions.
43 changes: 31 additions & 12 deletions lib/Target/Lanai/LanaiISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand All @@ -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);

Expand Down Expand Up @@ -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:
Expand Down
12 changes: 8 additions & 4 deletions lib/Target/Lanai/LanaiISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,27 @@ 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,

// Wrapper - A wrapper node for TargetConstantPool, TargetExternalSymbol,
// 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
Expand Down Expand Up @@ -87,6 +90,7 @@ class LanaiTargetLowering : public TargetLowering {
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;

Expand Down
47 changes: 29 additions & 18 deletions lib/Target/Lanai/LanaiInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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>;
}
}

Expand All @@ -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),
Expand All @@ -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),
Expand All @@ -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,
Expand All @@ -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)>;
Expand Down Expand Up @@ -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">;
Expand Down Expand Up @@ -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.
Expand Down
108 changes: 108 additions & 0 deletions test/CodeGen/Lanai/comparisons_i64.ll
Original file line number Diff line number Diff line change
@@ -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
}
2 changes: 1 addition & 1 deletion test/CodeGen/Lanai/select.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit 5ea3f52

Please sign in to comment.