Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Xtensa] Implement lowering SELECT_CC, SETCC. #97017

Merged
merged 7 commits into from
Jul 11, 2024

Conversation

andreisfr
Copy link
Contributor

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Jun 28, 2024

@llvm/pr-subscribers-testing-tools

Author: Andrei Safronov (andreisfr)

Changes

Patch is 25.78 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/97017.diff

7 Files Affected:

  • (modified) llvm/lib/Target/Xtensa/XtensaISelLowering.cpp (+186)
  • (modified) llvm/lib/Target/Xtensa/XtensaISelLowering.h (+27-1)
  • (modified) llvm/lib/Target/Xtensa/XtensaInstrInfo.td (+32)
  • (modified) llvm/lib/Target/Xtensa/XtensaOperators.td (+9)
  • (added) llvm/test/CodeGen/Xtensa/select-cc.ll (+125)
  • (added) llvm/test/CodeGen/Xtensa/setcc.ll (+232)
  • (modified) llvm/utils/UpdateTestChecks/asm.py (+8)
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 6509793012504..8f19ae1b8e672 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -90,6 +90,26 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::BR_CC, MVT::i64, Expand);
   setOperationAction(ISD::BR_CC, MVT::f32, Expand);
 
+  // Used by legalize types to correctly generate the setcc result.
+  // AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
+  setOperationPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
+  setOperationPromotedToType(ISD::BR_CC, MVT::i1, MVT::i32);
+
+  setOperationAction(ISD::BR_CC, MVT::i32, Legal);
+  setOperationAction(ISD::BR_CC, MVT::i64, Expand);
+
+  setOperationAction(ISD::SELECT, MVT::i32, Expand);
+  setOperationAction(ISD::SELECT, MVT::i64, Expand);
+
+  setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
+  setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);
+
+  setOperationAction(ISD::SETCC, MVT::i32, Custom);
+  setOperationAction(ISD::SETCC, MVT::i64, Expand);
+
+  // make BRCOND legal, its actually only legal for a subset of conds
+  setOperationAction(ISD::BRCOND, MVT::Other, Legal);
+
   // Implement custom stack allocations
   setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom);
   // Implement custom stack save and restore
@@ -514,6 +534,38 @@ XtensaTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
   return DAG.getNode(XtensaISD::RET, DL, MVT::Other, RetOps);
 }
 
+SDValue XtensaTargetLowering::LowerSELECT_CC(SDValue Op,
+                                             SelectionDAG &DAG) const {
+  SDLoc DL(Op);
+  EVT Ty = Op.getOperand(0).getValueType();
+  SDValue LHS = Op.getOperand(0);
+  SDValue RHS = Op.getOperand(1);
+  SDValue TrueValue = Op.getOperand(2);
+  SDValue FalseValue = Op.getOperand(3);
+  ISD::CondCode CC = cast<CondCodeSDNode>(Op->getOperand(4))->get();
+  SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i32);
+
+  // Wrap select nodes
+  return DAG.getNode(XtensaISD::SELECT_CC, DL, Ty, LHS, RHS, TrueValue,
+                     FalseValue, TargetCC);
+}
+
+SDValue XtensaTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
+  SDLoc DL(Op);
+  EVT Ty = Op.getOperand(0).getValueType();
+  SDValue LHS = Op.getOperand(0);
+  SDValue RHS = Op.getOperand(1);
+  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
+  SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i32);
+
+  // Expand to target SELECT_CC
+  SDValue TrueValue = DAG.getConstant(1, DL, Op.getValueType());
+  SDValue FalseValue = DAG.getConstant(0, DL, Op.getValueType());
+
+  return DAG.getNode(XtensaISD::SELECT_CC, DL, Ty, LHS, RHS, TrueValue,
+                     FalseValue, TargetCC);
+}
+
 SDValue XtensaTargetLowering::LowerImmediate(SDValue Op,
                                              SelectionDAG &DAG) const {
   const ConstantSDNode *CN = cast<ConstantSDNode>(Op);
@@ -676,6 +728,10 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
     return LowerJumpTable(Op, DAG);
   case ISD::ConstantPool:
     return LowerConstantPool(cast<ConstantPoolSDNode>(Op), DAG);
+  case ISD::SETCC:
+    return LowerSETCC(Op, DAG);
+  case ISD::SELECT_CC:
+    return LowerSELECT_CC(Op, DAG);
   case ISD::STACKSAVE:
     return LowerSTACKSAVE(Op, DAG);
   case ISD::STACKRESTORE:
@@ -697,6 +753,136 @@ const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
     return "XtensaISD::PCREL_WRAPPER";
   case XtensaISD::RET:
     return "XtensaISD::RET";
+  case XtensaISD::SELECT:
+    return "XtensaISD::SELECT";
+  case XtensaISD::SELECT_CC:
+    return "XtensaISD::SELECT_CC";
   }
   return nullptr;
 }
+
+//===----------------------------------------------------------------------===//
+// Custom insertion
+//===----------------------------------------------------------------------===//
+
+static int GetBranchKind(int Cond, bool &BrInv) {
+  switch (Cond) {
+  case ISD::SETEQ:
+  case ISD::SETOEQ:
+  case ISD::SETUEQ:
+    return Xtensa::BEQ;
+  case ISD::SETNE:
+  case ISD::SETONE:
+  case ISD::SETUNE:
+    return Xtensa::BNE;
+  case ISD::SETLT:
+  case ISD::SETOLT:
+    return Xtensa::BLT;
+  case ISD::SETLE:
+  case ISD::SETOLE:
+    BrInv = true;
+    return Xtensa::BGE;
+  case ISD::SETGT:
+  case ISD::SETOGT:
+    BrInv = true;
+    return Xtensa::BLT;
+  case ISD::SETGE:
+  case ISD::SETOGE:
+    return Xtensa::BGE;
+  case ISD::SETULT:
+    return Xtensa::BLTU;
+  case ISD::SETULE:
+    BrInv = true;
+    return Xtensa::BGEU;
+  case ISD::SETUGT:
+    BrInv = true;
+    return Xtensa::BLTU;
+  case ISD::SETUGE:
+    return Xtensa::BGEU;
+  default:
+    return -1;
+  }
+}
+
+MachineBasicBlock *
+XtensaTargetLowering::emitSelectCC(MachineInstr &MI,
+                                   MachineBasicBlock *MBB) const {
+  const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
+  DebugLoc DL = MI.getDebugLoc();
+
+  MachineOperand &LHS = MI.getOperand(1);
+  MachineOperand &RHS = MI.getOperand(2);
+  MachineOperand &TrueValue = MI.getOperand(3);
+  MachineOperand &FalseValue = MI.getOperand(4);
+  MachineOperand &Cond = MI.getOperand(5);
+
+  // To "insert" a SELECT_CC instruction, we actually have to insert
+  // CopyMBB and SinkMBB  blocks and add branch to MBB. We build phi
+  // operation in SinkMBB like phi (TrueVakue,FalseValue), where TrueValue
+  // is passed from MMB and FalseValue is passed from CopyMBB.
+  //   MBB
+  //   |   \
+  //   |   CopyMBB
+  //   |   /
+  //   SinkMBB
+  // The incoming instruction knows the
+  // destination vreg to set, the condition code register to branch on, the
+  // true/false values to select between, and a branch opcode to use.
+  const BasicBlock *LLVM_BB = MBB->getBasicBlock();
+  MachineFunction::iterator It = ++MBB->getIterator();
+
+  MachineFunction *F = MBB->getParent();
+  MachineBasicBlock *CopyMBB = F->CreateMachineBasicBlock(LLVM_BB);
+  MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
+
+  F->insert(It, CopyMBB);
+  F->insert(It, SinkMBB);
+
+  // Transfer the remainder of MBB and its successor edges to SinkMBB.
+  SinkMBB->splice(SinkMBB->begin(), MBB,
+                  std::next(MachineBasicBlock::iterator(MI)), MBB->end());
+  SinkMBB->transferSuccessorsAndUpdatePHIs(MBB);
+
+  MBB->addSuccessor(CopyMBB);
+  MBB->addSuccessor(SinkMBB);
+
+  bool BrInv = false;
+  int BrKind = GetBranchKind(Cond.getImm(), BrInv);
+  if (BrInv) {
+    BuildMI(MBB, DL, TII.get(BrKind))
+        .addReg(RHS.getReg())
+        .addReg(LHS.getReg())
+        .addMBB(SinkMBB);
+  } else {
+    BuildMI(MBB, DL, TII.get(BrKind))
+        .addReg(LHS.getReg())
+        .addReg(RHS.getReg())
+        .addMBB(SinkMBB);
+  }
+
+  CopyMBB->addSuccessor(SinkMBB);
+
+  //  SinkMBB:
+  //   %Result = phi [ %FalseValue, CopyMBB ], [ %TrueValue, MBB ]
+  //  ...
+
+  BuildMI(*SinkMBB, SinkMBB->begin(), DL, TII.get(Xtensa::PHI),
+          MI.getOperand(0).getReg())
+      .addReg(FalseValue.getReg())
+      .addMBB(CopyMBB)
+      .addReg(TrueValue.getReg())
+      .addMBB(MBB);
+
+  MI.eraseFromParent(); // The pseudo instruction is gone now.
+  return SinkMBB;
+}
+
+MachineBasicBlock *XtensaTargetLowering::EmitInstrWithCustomInserter(
+    MachineInstr &MI, MachineBasicBlock *MBB) const {
+  switch (MI.getOpcode()) {
+  case Xtensa::SELECT:
+    return emitSelectCC(MI, MBB);
+  default:
+    report_fatal_error("Unexpected instr type to insert");
+  }
+}
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
index 23a0217daaa96..8a4491c38db5f 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
@@ -33,7 +33,14 @@ enum {
   // Wraps a TargetGlobalAddress that should be loaded using PC-relative
   // accesses.  Operand 0 is the address.
   PCREL_WRAPPER,
-  RET
+  RET,
+
+  // Selects between operand 0 and operand 1.  Operand 2 is the
+  // mask of condition-code values for which operand 0 should be
+  // chosen over operand 1; it has the same form as BR_CCMASK.
+  // Operand 3 is the flag operand.
+  SELECT,
+  SELECT_CC
 };
 }
 
@@ -44,6 +51,13 @@ class XtensaTargetLowering : public TargetLowering {
   explicit XtensaTargetLowering(const TargetMachine &TM,
                                 const XtensaSubtarget &STI);
 
+  EVT getSetCCResultType(const DataLayout &, LLVMContext &,
+                         EVT VT) const override {
+    if (!VT.isVector())
+      return MVT::i32;
+    return VT.changeVectorElementTypeToInteger();
+  }
+
   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
 
   const char *getTargetNodeName(unsigned Opcode) const override;
@@ -71,6 +85,10 @@ class XtensaTargetLowering : public TargetLowering {
 
   const XtensaSubtarget &getSubtarget() const { return Subtarget; }
 
+  MachineBasicBlock *
+  EmitInstrWithCustomInserter(MachineInstr &MI,
+                              MachineBasicBlock *BB) const override;
+
 private:
   const XtensaSubtarget &Subtarget;
 
@@ -86,6 +104,10 @@ class XtensaTargetLowering : public TargetLowering {
 
   SDValue LowerConstantPool(ConstantPoolSDNode *CP, SelectionDAG &DAG) const;
 
+  SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
+
+  SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
+
   SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
 
   SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const;
@@ -95,6 +117,10 @@ class XtensaTargetLowering : public TargetLowering {
   SDValue getAddrPCRel(SDValue Op, SelectionDAG &DAG) const;
 
   CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const;
+
+  // Implement EmitInstrWithCustomInserter for individual operation types.
+  MachineBasicBlock *emitSelectCC(MachineInstr &MI,
+                                  MachineBasicBlock *BB) const;
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index f68d20dcdd54a..9e3a35808d0b6 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -425,6 +425,29 @@ def : Pat<(brcc SETLE, AR:$s, AR:$t, bb:$target),
 def : Pat<(brcc SETULE, AR:$s, AR:$t, bb:$target),
           (BGEU AR:$t, AR:$s, bb:$target)>;
 
+def : Pat<(brcond (i32 (seteq AR:$s, AR:$t)), bb:$target),
+          (BEQ AR:$s, AR:$t, bb:$target)>;
+def : Pat<(brcond (i32 (setne AR:$s, AR:$t)), bb:$target),
+          (BNE AR:$s, AR:$t, bb:$target)>;
+def : Pat<(brcond (i32 (setge AR:$s, AR:$t)), bb:$target),
+          (BGE AR:$s, AR:$t, bb:$target)>;
+def : Pat<(brcond (i32 (setle AR:$s, AR:$t)), bb:$target),
+          (BLT AR:$s, AR:$t, bb:$target)>;
+def : Pat<(brcond (i32 (setuge AR:$s, AR:$t)), bb:$target),
+          (BGEU AR:$s, AR:$t, bb:$target)>;
+def : Pat<(brcond (i32 (setult AR:$s, AR:$t)), bb:$target),
+          (BLTU AR:$s, AR:$t, bb:$target)>;
+def : Pat<(brcond (i32 (setgt AR:$s, AR:$t)), bb:$target),
+          (BLT AR:$t, AR:$s, bb:$target)>;
+def : Pat<(brcond (i32 (setugt AR:$s, AR:$t)), bb:$target),
+          (BLTU AR:$t, AR:$s, bb:$target)>;
+def : Pat<(brcond (i32 (setle AR:$s, AR:$t)), bb:$target),
+          (BGE AR:$t, AR:$s, bb:$target)>;
+def : Pat<(brcond (i32 (setule AR:$s, AR:$t)), bb:$target),
+          (BGEU AR:$t, AR:$s, bb:$target)>;
+
+def : Pat<(brcond AR:$s, bb:$target), (BNEZ AR:$s, bb:$target)>;
+
 //===----------------------------------------------------------------------===//
 // Call and jump instructions
 //===----------------------------------------------------------------------===//
@@ -574,3 +597,12 @@ let Defs = [SP], Uses = [SP] in {
                                "#ADJCALLSTACKUP",
                                [(Xtensa_callseq_end timm:$amt1, timm:$amt2)]>;
 }
+
+//===----------------------------------------------------------------------===//
+// Generic select instruction
+//===----------------------------------------------------------------------===//
+let usesCustomInserter = 1 in {
+  def SELECT : Pseudo<(outs AR:$dst), (ins AR:$lhs, AR:$rhs, AR:$t, AR:$f, i32imm:$cond),
+                     "!select $dst, $lhs, $rhs, $t, $f, $cond",
+                     [(set AR:$dst, (Xtensa_select_cc AR:$lhs, AR:$rhs, AR:$t, AR:$f, imm:$cond))]>;
+}
diff --git a/llvm/lib/Target/Xtensa/XtensaOperators.td b/llvm/lib/Target/Xtensa/XtensaOperators.td
index 88d3c9dfe7fd8..aab2d2d2bbe79 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperators.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperators.td
@@ -19,6 +19,11 @@ def SDT_XtensaWrapPtr             : SDTypeProfile<1, 1,
 
 def SDT_XtensaBrJT                : SDTypeProfile<0, 2,
                                                  [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>;
+
+def SDT_XtensaSelectCC            : SDTypeProfile<1, 5,
+                                                 [SDTCisSameAs<0, 1>,
+                                                  SDTCisSameAs<2, 3>,
+                                                  SDTCisVT<5, i32>]>;
 //===----------------------------------------------------------------------===//
 // Node definitions
 //===----------------------------------------------------------------------===//
@@ -38,3 +43,7 @@ def Xtensa_callseq_end  : SDNode<"ISD::CALLSEQ_END",   SDT_XtensaCallSeqEnd,
                                  SDNPOutGlue]>;
 
 def Xtensa_brjt: SDNode<"XtensaISD::BR_JT", SDT_XtensaBrJT, [SDNPHasChain]>;
+
+def Xtensa_select : SDNode<"XtensaISD::SELECT", SDTSelect>;
+def Xtensa_select_cc: SDNode<"XtensaISD::SELECT_CC", SDT_XtensaSelectCC,
+                            [SDNPInGlue]>;
diff --git a/llvm/test/CodeGen/Xtensa/select-cc.ll b/llvm/test/CodeGen/Xtensa/select-cc.ll
new file mode 100644
index 0000000000000..6073ee7cc2558
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/select-cc.ll
@@ -0,0 +1,125 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=xtensa -disable-block-placement -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s
+
+define signext i32 @foo(i32 signext %a, ptr %b) nounwind {
+; CHECK-LABEL: foo:
+; CHECK:         l32i a8, a3, 0
+; CHECK-NEXT:    beq a2, a8, .LBB0_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_2:
+; CHECK-NEXT:    bne a2, a8, .LBB0_4
+; CHECK-NEXT:  # %bb.3:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_4:
+; CHECK-NEXT:    bltu a8, a2, .LBB0_6
+; CHECK-NEXT:  # %bb.5:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_6:
+; CHECK-NEXT:    bgeu a2, a8, .LBB0_8
+; CHECK-NEXT:  # %bb.7:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_8:
+; CHECK-NEXT:    bltu a2, a8, .LBB0_10
+; CHECK-NEXT:  # %bb.9:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_10:
+; CHECK-NEXT:    bgeu a8, a2, .LBB0_12
+; CHECK-NEXT:  # %bb.11:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_12:
+; CHECK-NEXT:    blt a8, a2, .LBB0_14
+; CHECK-NEXT:  # %bb.13:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_14:
+; CHECK-NEXT:    bge a2, a8, .LBB0_16
+; CHECK-NEXT:  # %bb.15:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_16:
+; CHECK-NEXT:    blt a2, a8, .LBB0_18
+; CHECK-NEXT:  # %bb.17:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_18:
+; CHECK-NEXT:    bge a8, a2, .LBB0_20
+; CHECK-NEXT:  # %bb.19:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_20:
+; CHECK-NEXT:    movi a9, 1
+; CHECK-NEXT:    blt a8, a9, .LBB0_22
+; CHECK-NEXT:  # %bb.21:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_22:
+; CHECK-NEXT:    movi a9, -1
+; CHECK-NEXT:    blt a9, a8, .LBB0_24
+; CHECK-NEXT:  # %bb.23:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_24:
+; CHECK-NEXT:    movi a9, 1024
+; CHECK-NEXT:    blt a9, a8, .LBB0_26
+; CHECK-NEXT:  # %bb.25:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_26:
+; CHECK-NEXT:    movi a9, 2046
+; CHECK-NEXT:    bltu a9, a8, .LBB0_28
+; CHECK-NEXT:  # %bb.27:
+; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:  .LBB0_28:
+; CHECK-NEXT:    ret
+  %val1 = load i32, ptr %b
+  %tst1 = icmp eq i32 %a, %val1
+  %val2 = select i1 %tst1, i32 %a, i32 %val1
+
+  %val3 = load i32, ptr %b
+  %tst2 = icmp ne i32 %val2, %val3
+  %val4 = select i1 %tst2, i32 %val2, i32 %val3
+
+  %val5 = load i32, ptr %b
+  %tst3 = icmp ugt i32 %val4, %val5
+  %val6 = select i1 %tst3, i32 %val4, i32 %val5
+
+  %val7 = load i32, ptr %b
+  %tst4 = icmp uge i32 %val6, %val7
+  %val8 = select i1 %tst4, i32 %val6, i32 %val7
+
+  %val9 = load i32, ptr %b
+  %tst5 = icmp ult i32 %val8, %val9
+  %val10 = select i1 %tst5, i32 %val8, i32 %val9
+
+  %val11 = load i32, ptr %b
+  %tst6 = icmp ule i32 %val10, %val11
+  %val12 = select i1 %tst6, i32 %val10, i32 %val11
+
+  %val13 = load i32, ptr %b
+  %tst7 = icmp sgt i32 %val12, %val13
+  %val14 = select i1 %tst7, i32 %val12, i32 %val13
+
+  %val15 = load i32, ptr %b
+  %tst8 = icmp sge i32 %val14, %val15
+  %val16 = select i1 %tst8, i32 %val14, i32 %val15
+
+  %val17 = load i32, ptr %b
+  %tst9 = icmp slt i32 %val16, %val17
+  %val18 = select i1 %tst9, i32 %val16, i32 %val17
+
+  %val19 = load i32, ptr %b
+  %tst10 = icmp sle i32 %val18, %val19
+  %val20 = select i1 %tst10, i32 %val18, i32 %val19
+
+  %val21 = load i32, ptr %b
+  %tst11 = icmp slt i32 %val21, 1
+  %val22 = select i1 %tst11, i32 %val20, i32 %val21
+
+  %val23 = load i32, ptr %b
+  %tst12 = icmp sgt i32 %val21, -1
+  %val24 = select i1 %tst12, i32 %val22, i32 %val23
+
+  %val25 = load i32, ptr %b
+  %tst13 = icmp sgt i32 %val25, 1024
+  %val26 = select i1 %tst13, i32 %val24, i32 %val25
+
+  %val27 = load i32, ptr %b
+  %tst14 = icmp ugt i32 %val21, 2046
+  %val28 = select i1 %tst14, i32 %val26, i32 %val27
+  ret i32 %val28
+}
diff --git a/llvm/test/CodeGen/Xtensa/setcc.ll b/llvm/test/CodeGen/Xtensa/setcc.ll
new file mode 100644
index 0000000000000..a8557b2365a31
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/setcc.ll
@@ -0,0 +1,232 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=xtensa-unkonwn-elf -O0 | FileCheck %s
+
+define i32 @f1(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: f1:
+; CHECK:         addi a8, a1, -16
+; CHECK-NEXT:    or a1, a8, a8
+; CHECK-NEXT:    movi a8, 0
+; CHECK-NEXT:    s32i a8, a1, 0 # 4-byte Folded Spill
+; CHECK-NEXT:    movi a8, 1
+; CHECK-NEXT:    s32i a8, a1, 4 # 4-byte Folded Spill
+; CHECK-NEXT:    beq a2, a3, .LBB0_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    l32i a8, a1, 0 # 4-byte Folded Reload
+; CHECK-NEXT:    s32i a8, a1, 4 # 4-byte Folded Spill
+; CHECK-NEXT:  .LBB0_2:
+; CHECK-NEXT:    l32i a2, a1, 4 # 4-byte Folded Reload
+; CHECK-NEXT:    addi a8, a1, 16
+; CHECK-NEXT:    or a1, a8, a8
+; CHECK-NEXT:    ret
+
+  %cond = icmp eq i32 %a, %b
+  %res = zext i1 %cond to i32
+  ret i32 %res
+}
+
+define i32 @f2(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: f2:
+; CHECK:         addi a8, a1, -16
+; CHECK-NEXT:    or a1, a8, a8
+; CHECK-NEXT:    movi a8, 0
+; CHECK-NEXT:    s32i a8, a1, 0 # 4-byte Folded Spill
+; CHECK-NEXT:    movi a8, 1
+; CHECK-NEXT:    s32i a8, a1, 4 # 4-byte Folded Spill
+; CHECK-NEXT:    blt a2, a3, .LBB1_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    l32i a8, a1, 0 # 4-byte Folded Reload
+; CHECK-NEXT:    s32i a8, a1, 4 # 4-byte Folded Spill
+; CHECK-NEXT:  .LBB1_2:
+; CHECK-NEXT:    l32i a2, a1, 4 # 4-byte Folded Reload
+; CHECK-NEXT:    addi a8, a1, 16
+; CHECK-NEXT:    or a1, a8, a8
+; CHECK-NEXT:    ret
+
+  %cond = icmp slt i32 %a, %b
+  %res = zext i1 %cond to i32
+  ret i32 %res
+}
+
+define i32 @f3(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: f3:
+; CHECK:         addi a8, a1, -16
+; CHECK-NEXT:    or a1, a8, a8
+; CHECK-NEXT:    movi a8, 0
+; CHECK-NEXT:    s32i a8, a1, 0 # 4-byte Folded Spill
+; CHECK-NEXT:    movi a8, 1
+; CHECK-NEXT:    s32i a8, a1, 4 # 4-byte Folded Spill
+; CHECK-NEXT:    bge a3, a2, .LBB2_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    l32i a8, a1, 0 # 4-byte Folded Reload
+; CHECK-NEXT:    s32i a8, a1, 4 # 4-byte Folded Spill
+; CHECK-NEXT:  .LBB2_2:
+; CHECK-NEXT:    l32i a2, a1, 4 # 4-byte Folded Reload
+; CHECK-NEXT:    addi a8, a1, 16
+; CHECK-NEXT:    or a1, a8, a8
+; CHECK-NEXT:    ret
+
+  %cond = icmp sle i32 %a, %b
+  %res = zext i1 %cond to i32
+  ret i32 %res
+}
+
+define i32 @f4(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: f4:
+; CHECK:         addi a8, a1, -16
+; CHECK-NEXT:   ...
[truncated]

@andreisfr
Copy link
Contributor Author

@arsenm , @jyknight, @MaskRay , @s-barannikov , PTAL to this PR whenever you have the time.

Copy link

github-actions bot commented Jun 28, 2024

✅ With the latest revision this PR passed the Python code formatter.

@@ -90,6 +90,26 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::BR_CC, MVT::i64, Expand);
setOperationAction(ISD::BR_CC, MVT::f32, Expand);

// Used by legalize types to correctly generate the setcc result.
// AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented out coed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arsenm, thank you very much for comments! Fixed

setOperationAction(ISD::SETCC, MVT::i32, Custom);
setOperationAction(ISD::SETCC, MVT::i64, Expand);

// make BRCOND legal, its actually only legal for a subset of conds
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be covered by setCondCodeAction, which isn't used here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed code related to BRCOND from this PR, seems it is redundant , I will add it in next patches.

llvm/test/CodeGen/Xtensa/select-cc.ll Outdated Show resolved Hide resolved
llvm/utils/UpdateTestChecks/asm.py Outdated Show resolved Hide resolved
Copy link
Contributor

@s-barannikov s-barannikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need tests for branches

llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaOperators.td Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaISelLowering.h Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
Removed redundant operations promotions and actions. Also removed setcc
lowering and redundant branch kind cases from GetBranchKind() function.
Implemented additional br_cc tests.
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaInstrInfo.td Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
llvm/test/CodeGen/Xtensa/select-cc.ll Show resolved Hide resolved
llvm/test/CodeGen/Xtensa/select-cc.ll Outdated Show resolved Hide resolved
@@ -1,10 +1,10 @@
; RUN: llc -march=xtensa < %s | FileCheck %s

; CHECK-LABEL: brcc1:
; CHECK-LABEL: brcc_sgt:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Autogenerate check lines?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't, and -verify-machineinstrs is also missing

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-verify-machineinstrs should be missing. We should stop unconditionally adding it to every test, and only in cases specifically testing things that hit a verifier error

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should never be hit, unless it is an XFAIL test.
From my experience, adding -verify-machineinstrs to llc tests saves a lot of time catching bugs that otherwise could be caught only when building large applications.
Machine verifier is effectively assert(mir.isValid()), I don't see a reason why you woulndn't want this assert when running tests.

I don't insist though (I would if I were a maintainer of this backend).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added "-verify-machineinstrs" argument to the brcc.ll test and generated check lines.

llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
Copy link

github-actions bot commented Jul 9, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Implemented new tests for SELECTCC/SETCC with i64 operands. Added
minor code fixes.
The GT/UGT/LE/ULE code condtions not supported for i32, some expand actions for these codes.
Also corrected brcc.ll/select-cc.ll/setcc.ll tests.
Copy link
Contributor

@s-barannikov s-barannikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some final nits

SDValue FalseValue = Op.getOperand(3);
ISD::CondCode CC = cast<CondCodeSDNode>(Op->getOperand(4))->get();

unsigned BrKind = getBranchOpcode(CC);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) BrOpcode

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

unsigned BrKind = getBranchOpcode(CC);
SDValue TargetCC = DAG.getConstant(BrKind, DL, MVT::i32);

// Wrap select nodes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't wrap anything

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


MachineFunction *F = MBB->getParent();
MachineBasicBlock *CopyMBB = F->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will need a code like this here (for a future patch that adds related tests), see 2dcf051:

  // Set the call frame size on entry to the new basic blocks.
  uint64_t CallFrameSize = TII.getCallFrameSizeAt(MI);
  CopyMBB->setCallFrameSize(CallFrameSize);
  SinkMBB->setCallFrameSize(CallFrameSize);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, I will use this information in future.

// a false value (ops #2 and #3) based on the boolean result of comparing
// the lhs and rhs (ops #0 and #1) of a conditional expression with the
// condition code in op #4
SELECT_CC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SELECT_CC
SELECT_CC,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -95,6 +114,10 @@ class XtensaTargetLowering : public TargetLowering {
SDValue getAddrPCRel(SDValue Op, SelectionDAG &DAG) const;

CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const;

// Implement EmitInstrWithCustomInserter for individual operation types.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment isn't helpful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Renamed variable and removed redundant comments.
@sstefan1 sstefan1 merged commit ce92b2f into llvm:main Jul 11, 2024
7 checks passed
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants