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

[GlobalIsel] Combine select of binops #76763

Merged
merged 6 commits into from
Jan 6, 2024

Conversation

tschuett
Copy link
Member

@tschuett tschuett commented Jan 2, 2024

No description provided.

@llvmbot
Copy link
Collaborator

llvmbot commented Jan 2, 2024

@llvm/pr-subscribers-backend-aarch64

@llvm/pr-subscribers-llvm-globalisel

Author: Thorsten Schütt (tschuett)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/76763.diff

4 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h (+3)
  • (modified) llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h (+103)
  • (modified) llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp (+63-28)
  • (modified) llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir (+74)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index dcc1a4580b14a2..f3b68623596c46 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -910,6 +910,9 @@ class CombinerHelper {
 
   bool tryFoldSelectOfConstants(GSelect *Select, BuildFnTy &MatchInfo);
 
+  /// Try to fold select(cc, binop(), binop()) -> binop(select(), X)
+  bool tryFoldSelectOfBinOps(GSelect *Select, BuildFnTy &MatchInfo);
+
   bool isOneOrOneSplat(Register Src, bool AllowUndefs);
   bool isZeroOrZeroSplat(Register Src, bool AllowUndefs);
   bool isConstantSplatVector(Register Src, int64_t SplatValue,
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 6ab1d4550c51ca..21d98d30356c93 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -558,6 +558,109 @@ class GVecReduce : public GenericMachineInstr {
   }
 };
 
+// Represents a binary operation, i.e, x = y op z.
+class GBinOp : public GenericMachineInstr {
+public:
+  Register getLHSReg() const { return getReg(1); }
+  Register getRHSReg() const { return getReg(2); }
+
+  static bool classof(const MachineInstr *MI) {
+    switch (MI->getOpcode()) {
+    // Integer.
+    case TargetOpcode::G_ADD:
+    case TargetOpcode::G_SUB:
+    case TargetOpcode::G_MUL:
+    case TargetOpcode::G_SDIV:
+    case TargetOpcode::G_UDIV:
+    case TargetOpcode::G_SREM:
+    case TargetOpcode::G_UREM:
+    case TargetOpcode::G_SMIN:
+    case TargetOpcode::G_SMAX:
+    case TargetOpcode::G_UMIN:
+    case TargetOpcode::G_UMAX:
+    // Floating point.
+    case TargetOpcode::G_FMINNUM:
+    case TargetOpcode::G_FMAXNUM:
+    case TargetOpcode::G_FMINNUM_IEEE:
+    case TargetOpcode::G_FMAXNUM_IEEE:
+    case TargetOpcode::G_FMINIMUM:
+    case TargetOpcode::G_FMAXIMUM:
+    case TargetOpcode::G_FADD:
+    case TargetOpcode::G_FSUB:
+    case TargetOpcode::G_FMUL:
+    case TargetOpcode::G_FDIV:
+    case TargetOpcode::G_FPOW:
+    // Logical.
+    case TargetOpcode::G_AND:
+    case TargetOpcode::G_OR:
+    case TargetOpcode::G_XOR:
+      return true;
+    default:
+      return false;
+    }
+  };
+};
+
+// Represents an integer binary operation.
+class GIntBinOp : public GBinOp {
+public:
+  static bool classof(const MachineInstr *MI) {
+    switch (MI->getOpcode()) {
+    case TargetOpcode::G_ADD:
+    case TargetOpcode::G_SUB:
+    case TargetOpcode::G_MUL:
+    case TargetOpcode::G_SDIV:
+    case TargetOpcode::G_UDIV:
+    case TargetOpcode::G_SREM:
+    case TargetOpcode::G_UREM:
+    case TargetOpcode::G_SMIN:
+    case TargetOpcode::G_SMAX:
+    case TargetOpcode::G_UMIN:
+    case TargetOpcode::G_UMAX:
+      return true;
+    default:
+      return false;
+    }
+  };
+};
+
+// Represents a floating point binary operation.
+class GFBinOp : public GBinOp {
+public:
+  static bool classof(const MachineInstr *MI) {
+    switch (MI->getOpcode()) {
+    case TargetOpcode::G_FMINNUM:
+    case TargetOpcode::G_FMAXNUM:
+    case TargetOpcode::G_FMINNUM_IEEE:
+    case TargetOpcode::G_FMAXNUM_IEEE:
+    case TargetOpcode::G_FMINIMUM:
+    case TargetOpcode::G_FMAXIMUM:
+    case TargetOpcode::G_FADD:
+    case TargetOpcode::G_FSUB:
+    case TargetOpcode::G_FMUL:
+    case TargetOpcode::G_FDIV:
+    case TargetOpcode::G_FPOW:
+      return true;
+    default:
+      return false;
+    }
+  };
+};
+
+// Represents a logical binary operation.
+class GLogicalBinOp : public GBinOp {
+public:
+  static bool classof(const MachineInstr *MI) {
+    switch (MI->getOpcode()) {
+    case TargetOpcode::G_AND:
+    case TargetOpcode::G_OR:
+    case TargetOpcode::G_XOR:
+      return true;
+    default:
+      return false;
+    }
+  };
+};
 
 } // namespace llvm
 
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 8b15bdb0aca30b..102b49c48460b1 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -6390,8 +6390,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
   if (TrueValue.isZero() && FalseValue.isOne()) {
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
-      Register Inner = MRI.createGenericVirtualRegister(CondTy);
-      B.buildNot(Inner, Cond);
+      auto Inner = B.buildNot(CondTy, Cond);
       B.buildZExtOrTrunc(Dest, Inner);
     };
     return true;
@@ -6401,8 +6400,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
   if (TrueValue.isZero() && FalseValue.isAllOnes()) {
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
-      Register Inner = MRI.createGenericVirtualRegister(CondTy);
-      B.buildNot(Inner, Cond);
+      auto Inner = B.buildNot(CondTy, Cond);
       B.buildSExtOrTrunc(Dest, Inner);
     };
     return true;
@@ -6412,8 +6410,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
   if (TrueValue - 1 == FalseValue) {
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
-      Register Inner = MRI.createGenericVirtualRegister(TrueTy);
-      B.buildZExtOrTrunc(Inner, Cond);
+      auto Inner = B.buildZExtOrTrunc(TrueTy, Cond);
       B.buildAdd(Dest, Inner, False);
     };
     return true;
@@ -6423,8 +6420,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
   if (TrueValue + 1 == FalseValue) {
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
-      Register Inner = MRI.createGenericVirtualRegister(TrueTy);
-      B.buildSExtOrTrunc(Inner, Cond);
+      auto Inner = B.buildSExtOrTrunc(TrueTy, Cond);
       B.buildAdd(Dest, Inner, False);
     };
     return true;
@@ -6434,8 +6430,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
   if (TrueValue.isPowerOf2() && FalseValue.isZero()) {
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
-      Register Inner = MRI.createGenericVirtualRegister(TrueTy);
-      B.buildZExtOrTrunc(Inner, Cond);
+      auto Inner = B.buildZExtOrTrunc(TrueTy, Cond);
       // The shift amount must be scalar.
       LLT ShiftTy = TrueTy.isVector() ? TrueTy.getElementType() : TrueTy;
       auto ShAmtC = B.buildConstant(ShiftTy, TrueValue.exactLogBase2());
@@ -6447,8 +6442,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
   if (TrueValue.isAllOnes()) {
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
-      Register Inner = MRI.createGenericVirtualRegister(TrueTy);
-      B.buildSExtOrTrunc(Inner, Cond);
+      auto Inner = B.buildSExtOrTrunc(TrueTy, Cond);
       B.buildOr(Dest, Inner, False, Flags);
     };
     return true;
@@ -6458,10 +6452,8 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
   if (FalseValue.isAllOnes()) {
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
-      Register Not = MRI.createGenericVirtualRegister(CondTy);
-      B.buildNot(Not, Cond);
-      Register Inner = MRI.createGenericVirtualRegister(TrueTy);
-      B.buildSExtOrTrunc(Inner, Not);
+      auto Not = B.buildNot(CondTy, Cond);
+      auto Inner = B.buildSExtOrTrunc(TrueTy, Not);
       B.buildOr(Dest, Inner, True, Flags);
     };
     return true;
@@ -6496,8 +6488,7 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,
   if ((Cond == True) || isOneOrOneSplat(True, /* AllowUndefs */ true)) {
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
-      Register Ext = MRI.createGenericVirtualRegister(TrueTy);
-      B.buildZExtOrTrunc(Ext, Cond);
+      auto Ext = B.buildZExtOrTrunc(TrueTy, Cond);
       B.buildOr(DstReg, Ext, False, Flags);
     };
     return true;
@@ -6508,8 +6499,7 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,
   if ((Cond == False) || isZeroOrZeroSplat(False, /* AllowUndefs */ true)) {
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
-      Register Ext = MRI.createGenericVirtualRegister(TrueTy);
-      B.buildZExtOrTrunc(Ext, Cond);
+      auto Ext = B.buildZExtOrTrunc(TrueTy, Cond);
       B.buildAnd(DstReg, Ext, True);
     };
     return true;
@@ -6520,11 +6510,9 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
       // First the not.
-      Register Inner = MRI.createGenericVirtualRegister(CondTy);
-      B.buildNot(Inner, Cond);
+      auto Inner = B.buildNot(CondTy, Cond);
       // Then an ext to match the destination register.
-      Register Ext = MRI.createGenericVirtualRegister(TrueTy);
-      B.buildZExtOrTrunc(Ext, Inner);
+      auto Ext = B.buildZExtOrTrunc(TrueTy, Inner);
       B.buildOr(DstReg, Ext, True, Flags);
     };
     return true;
@@ -6535,11 +6523,9 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,
     MatchInfo = [=](MachineIRBuilder &B) {
       B.setInstrAndDebugLoc(*Select);
       // First the not.
-      Register Inner = MRI.createGenericVirtualRegister(CondTy);
-      B.buildNot(Inner, Cond);
+      auto Inner = B.buildNot(CondTy, Cond);
       // Then an ext to match the destination register.
-      Register Ext = MRI.createGenericVirtualRegister(TrueTy);
-      B.buildZExtOrTrunc(Ext, Inner);
+      auto Ext = B.buildZExtOrTrunc(TrueTy, Inner);
       B.buildAnd(DstReg, Ext, False);
     };
     return true;
@@ -6548,6 +6534,52 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,
   return false;
 }
 
+bool CombinerHelper::tryFoldSelectOfBinOps(GSelect *Select,
+                                           BuildFnTy &MatchInfo) {
+  Register DstReg = Select->getReg(0);
+  Register Cond = Select->getCondReg();
+  Register False = Select->getFalseReg();
+  Register True = Select->getTrueReg();
+  LLT DstTy = MRI.getType(DstReg);
+
+  GBinOp *LHS = getOpcodeDef<GBinOp>(True, MRI);
+  GBinOp *RHS = getOpcodeDef<GBinOp>(False, MRI);
+
+  // We need two binops of the same kind on the true/false registers.
+  if (!LHS || !RHS || LHS->getOpcode() != RHS->getOpcode())
+    return false;
+
+  // Note that there are no constraints on CondTy.
+  unsigned Flags = LHS->getFlags() & RHS->getFlags();
+  unsigned Opcode = LHS->getOpcode();
+
+  // Fold select(cond, binop(x, y), binop(z, y))
+  //  --> binop(select(cond, x, z), y)
+  if (LHS->getRHSReg() == RHS->getRHSReg()) {
+    MatchInfo = [=](MachineIRBuilder &B) {
+      B.setInstrAndDebugLoc(*Select);
+      auto Sel = B.buildSelect(DstTy, Cond, LHS->getLHSReg(), RHS->getLHSReg());
+      B.buildInstr(Opcode, {DstReg}, {Sel, LHS->getRHSReg()}, Flags);
+    };
+    return true;
+  }
+
+  // Fold select(cond, binop(x, y), binop(x, z))
+  //  --> binop(x, select(cond, y, z))
+  if (LHS->getLHSReg() == RHS->getLHSReg()) {
+    MatchInfo = [=](MachineIRBuilder &B) {
+      B.setInstrAndDebugLoc(*Select);
+      auto Sel = B.buildSelect(DstTy, Cond, LHS->getRHSReg(), RHS->getRHSReg());
+      B.buildInstr(Opcode, {DstReg}, {LHS->getLHSReg(), Sel}, Flags);
+    };
+    return true;
+  }
+
+  // FIXME: use isCommutable().
+
+  return false;
+}
+
 bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) {
   GSelect *Select = cast<GSelect>(&MI);
 
@@ -6557,5 +6589,8 @@ bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) {
   if (tryFoldBoolSelectToLogic(Select, MatchInfo))
     return true;
 
+  if (tryFoldSelectOfBinOps(Select, MatchInfo))
+    return true;
+
   return false;
 }
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir
index be2de620fa456c..7644443f53dc68 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir
@@ -544,3 +544,77 @@ body:             |
     %ext:_(s32) = G_ANYEXT %sel
     $w0 = COPY %ext(s32)
 ...
+---
+# select cond, and(x, y), and(z, y) --> and (select, x, z), y
+name:            select_cond_and_x_y_and_z_y_and_select_x_z_y
+body:             |
+  bb.1:
+    liveins: $x0, $x1, $x2
+    ; CHECK-LABEL: name: select_cond_and_x_y_and_z_y_and_select_x_z_y
+    ; CHECK: liveins: $x0, $x1, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY $x2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY $x3
+    ; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
+    ; CHECK-NEXT: %a:_(s8) = G_TRUNC [[COPY1]](s64)
+    ; CHECK-NEXT: %b:_(s8) = G_TRUNC [[COPY2]](s64)
+    ; CHECK-NEXT: %d:_(s8) = G_TRUNC [[COPY3]](s64)
+    ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s8) = G_SELECT %c(s1), %a, %d
+    ; CHECK-NEXT: %sel:_(s8) = G_AND [[SELECT]], %b
+    ; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s8)
+    ; CHECK-NEXT: $w0 = COPY %ext(s32)
+    %0:_(s64) = COPY $x0
+    %1:_(s64) = COPY $x1
+    %2:_(s64) = COPY $x2
+    %3:_(s64) = COPY $x3
+    %4:_(s64) = COPY $x4
+    %c:_(s1) = G_TRUNC %0
+    %a:_(s8) = G_TRUNC %1
+    %b:_(s8) = G_TRUNC %2
+    %d:_(s8) = G_TRUNC %3
+    %e:_(s8) = G_TRUNC %4
+    %and1:_(s8) = G_AND %a, %b
+    %and2:_(s8) = G_AND %d, %b
+    %sel:_(s8) = G_SELECT %c, %and1, %and2
+    %ext:_(s32) = G_ANYEXT %sel
+    $w0 = COPY %ext(s32)
+...
+---
+# select cond, xor(x, y), xor(x, z) --> xor x, select, x, z)
+name:            select_cond_xor_x_y_xor_x_z_xor_x__select_x_y
+body:             |
+  bb.1:
+    liveins: $x0, $x1, $x2
+    ; CHECK-LABEL: name: select_cond_xor_x_y_xor_x_z_xor_x__select_x_y
+    ; CHECK: liveins: $x0, $x1, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY $x3
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY $x4
+    ; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
+    ; CHECK-NEXT: %a:_(s8) = G_TRUNC [[COPY1]](s64)
+    ; CHECK-NEXT: %d:_(s8) = G_TRUNC [[COPY2]](s64)
+    ; CHECK-NEXT: %e:_(s8) = G_TRUNC [[COPY3]](s64)
+    ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s8) = G_SELECT %c(s1), %e, %d
+    ; CHECK-NEXT: %sel:_(s8) = G_XOR %a, [[SELECT]]
+    ; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s8)
+    ; CHECK-NEXT: $w0 = COPY %ext(s32)
+    %0:_(s64) = COPY $x0
+    %1:_(s64) = COPY $x1
+    %2:_(s64) = COPY $x2
+    %3:_(s64) = COPY $x3
+    %4:_(s64) = COPY $x4
+    %c:_(s1) = G_TRUNC %0
+    %a:_(s8) = G_TRUNC %1
+    %b:_(s8) = G_TRUNC %2
+    %d:_(s8) = G_TRUNC %3
+    %e:_(s8) = G_TRUNC %4
+    %xor1:_(s8) = G_XOR %a, %e
+    %xor2:_(s8) = G_XOR %a, %d
+    %sel:_(s8) = G_SELECT %c, %xor1, %xor2
+    %ext:_(s32) = G_ANYEXT %sel
+    $w0 = COPY %ext(s32)
+...

@tschuett
Copy link
Member Author

tschuett commented Jan 2, 2024

This one has a limited effect. I fixed the coding style violations from the last PR.

Register getRHSReg() const { return getReg(2); }

static bool classof(const MachineInstr *MI) {
switch (MI->getOpcode()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you implement this in terms of GIntBinOp::classof and GFBinOp::classof to avoid listing the opcodes in multiple places?

Copy link
Contributor

Choose a reason for hiding this comment

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

I was going to suggest that too but it won't compile due to not yet seeing the definition of GIntBinOp when parsing this class.

return false;

// Note that there are no constraints on CondTy.
unsigned Flags = LHS->getFlags() & RHS->getFlags();
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't consider the flags on the select itself

Copy link
Member Author

Choose a reason for hiding this comment

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

The DAG combiner intersects the flags of the binops and ignores the select flags.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's also suboptimal for the DAG combiner. I think it should be (LHS & RHS) | Select. Does InstCombine preserve these?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's also quite likely that code was never properly updated for select gaining flags. It was a relatively recent IR change

Copy link
Member Author

Choose a reason for hiding this comment

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

NewBinOp->setFlags(N1->getFlags());
NewBinOp->intersectFlagsWith(N2->getFlags());

It ignores the select flags. I updated my code locally.

%e:_(s8) = G_TRUNC %4
%xor1:_(s8) = G_XOR %a, %e
%xor2:_(s8) = G_XOR %a, %d
%sel:_(s8) = G_SELECT %c, %xor1, %xor2
Copy link
Contributor

Choose a reason for hiding this comment

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

Could use negative test with mismatched opcodes. Also missing tests for the flag handling. Precommitting tests would also be good

@@ -544,3 +544,77 @@ body: |
%ext:_(s32) = G_ANYEXT %sel
$w0 = COPY %ext(s32)
...
---
# select cond, and(x, y), and(z, y) --> and (select, x, z), y
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: comment missing cond on RHS: --> and (select cond, x, z), y

Copy link
Contributor

@aemerson aemerson left a comment

Choose a reason for hiding this comment

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

Need to address Matt's comment.

Register getRHSReg() const { return getReg(2); }

static bool classof(const MachineInstr *MI) {
switch (MI->getOpcode()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I was going to suggest that too but it won't compile due to not yet seeing the definition of GIntBinOp when parsing this class.

@tschuett
Copy link
Member Author

tschuett commented Jan 3, 2024

Please review changes (C++ and mir) regarding flag handling.

return false;

// Note that there are no constraints on CondTy.
unsigned Flags = (LHS->getFlags() & RHS->getFlags()) | Select->getFlags();
Copy link
Member Author

Choose a reason for hiding this comment

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

This line differs from the Dag combiner.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would have split this by matching the DAG behavior in the initial commit but doesn't really matter. I think this is OK but would be nice to have alive verify

MatchInfo = [=](MachineIRBuilder &B) {
B.setInstrAndDebugLoc(*Select);
auto Sel = B.buildSelect(DstTy, Cond, LHS->getLHSReg(), RHS->getLHSReg(),
Select->getFlags());
Copy link
Member Author

Choose a reason for hiding this comment

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

And Flags are added to selects.

; CHECK-NEXT: %d:_(s8) = G_TRUNC [[COPY2]](s64)
; CHECK-NEXT: %e:_(s8) = G_TRUNC [[COPY3]](s64)
; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s8) = ninf exact G_SELECT %c(s1), %e, %d
; CHECK-NEXT: %sel:_(s8) = ninf arcp exact G_XOR %a, [[SELECT]]
Copy link
Member Author

Choose a reason for hiding this comment

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

G_XOR has arcp because both ors had it. And it got exact from the select.

%d:_(s8) = G_TRUNC %3
%e:_(s8) = G_TRUNC %4
%and1:_(s8) = G_AND %a, %b
%or2:_(s8) = G_OR %e, %d
Copy link
Member Author

Choose a reason for hiding this comment

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

This failed because and and or.

@tschuett tschuett merged commit 1687555 into llvm:main Jan 6, 2024
3 of 4 checks passed
@tschuett tschuett deleted the gisel-select-of-binops branch January 6, 2024 10:28
@ronlieb
Copy link
Contributor

ronlieb commented Jan 6, 2024

this lit test is now taking a very long time after this patch landed
./bin/llvm-lit ../llvm/test/CodeGen/AMDGPU/llvm.log2.ll

relevant cmake settings:
-DCMAKE_BUILD_TYPE=Release
-DLLVM_ENABLE_PROJECTS="clang;lld;llvm;flang"
-DLLVM_TARGETS_TO_BUILD="X86;AMDGPU"
-DLLVM_ENABLE_ASSERTIONS=ON
-DLLVM_ENABLE_RUNTIMES="openmp;compiler-rt"
-DCLANG_DEFAULT_LINKER=lld \

@ronlieb
Copy link
Contributor

ronlieb commented Jan 6, 2024

@jhuber6 @jplehr this may also be failing in staging libc bot https://lab.llvm.org/staging/#/builders/134

@tschuett
Copy link
Member Author

tschuett commented Jan 6, 2024

I had also issues with this test. There is also a GH issue: #76821.

@tschuett
Copy link
Member Author

tschuett commented Jan 6, 2024

The file was not changed by this PR and there is no select in the file.

@bzEq
Copy link
Collaborator

bzEq commented Jan 6, 2024

It's also exhausting memory when llvm-lit llvm-project/llvm/test/CodeGen/AMDGPU/llvm.exp2.ll.
See https://lab.llvm.org/buildbot/#/builders/249/builds/13786.

tschuett added a commit that referenced this pull request Jan 6, 2024
@tschuett
Copy link
Member Author

tschuett commented Jan 6, 2024

I reverted the commit.

justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 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.

None yet

6 participants