[llvm] [GISel] Infer the type of an immediate when there is one element in TEC (PR #77399)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 8 17:01:26 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-globalisel

Author: Sergei Barannikov (s-barannikov)

<details>
<summary>Changes</summary>

When there is just one element in the type equivalence class (TEC), `inferNamedOperandType` fails because it does not consider the passed operand as a suitable one. This is incorrect when inferring the type of an (unnamed) immediate operand.

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


2 Files Affected:

- (modified) llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td (+23-4) 
- (modified) llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp (+9-6) 


``````````diff
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td
index c9ffe4e7adb3db..ed4e0e411c7afd 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/type-inference.td
@@ -1,5 +1,5 @@
 // RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \
-// RUN:     -gicombiner-debug-typeinfer -combiners=MyCombiner %s 2>&1 | \
+// RUN:     -gicombiner-debug-typeinfer -combiners=MyCombiner %s 2>&1 >/dev/null | \
 // RUN: FileCheck %s
 
 // Checks reasoning of the inference rules.
@@ -10,13 +10,15 @@ include "llvm/Target/GlobalISel/Combine.td"
 def MyTargetISA : InstrInfo;
 def MyTarget : Target { let InstructionSet = MyTargetISA; }
 
+// This also checks that the type of a def is preferred when inferring the type
+// of an immediate.
 // CHECK:      Rule Operand Type Equivalence Classes for inference_mul_by_neg_one:
 // CHECK-NEXT:         Groups for __inference_mul_by_neg_one_match_0:             [dst, x]
 // CHECK-NEXT:         Groups for __inference_mul_by_neg_one_apply_0:             [dst, x]
 // CHECK-NEXT: Final Type Equivalence Classes: [dst, x]
-// CHECK-NEXT: INFER: imm 0 -> GITypeOf<$x>
+// CHECK-NEXT: INFER: imm 0 -> GITypeOf<$dst>
 // CHECK-NEXT: Apply patterns for rule inference_mul_by_neg_one after inference:
-// CHECK-NEXT:   (CodeGenInstructionPattern name:__inference_mul_by_neg_one_apply_0 G_SUB operands:[<def>$dst, (GITypeOf<$x> 0), $x])
+// CHECK-NEXT:   (CodeGenInstructionPattern name:__inference_mul_by_neg_one_apply_0 G_SUB operands:[<def>$dst, (GITypeOf<$dst> 0), $x])
 def inference_mul_by_neg_one: GICombineRule <
   (defs root:$dst),
   (match (G_MUL $dst, $x, -1)),
@@ -61,8 +63,25 @@ def infer_variadic_outs: GICombineRule <
          (COPY $dst, $tmp))
 >;
 
+// Check that the type of an immediate is inferred when there is just one
+// element in the corresponding equivalence class.
+// CHECK:      Rule Operand Type Equivalence Classes for infer_imm_0:
+// CHECK-NEXT:   Groups for __infer_imm_0_match_0: [dst]
+// CHECK-NEXT:   Groups for __infer_imm_0_apply_0: [dst]
+// CHECK-NEXT: Final Type Equivalence Classes: [dst]
+// CHECK-NEXT: INFER: imm 1 -> GITypeOf<$dst>
+// CHECK-NEXT: INFER: imm 2 -> GITypeOf<$dst>
+// CHECK-NEXT: Apply patterns for rule infer_imm_0 after inference:
+// CHECK-NEXT:   (CodeGenInstructionPattern name:__infer_imm_0_apply_0 G_ADD operands:[<def>$dst, (GITypeOf<$dst> 1), (GITypeOf<$dst> 2)])
+def infer_imm_0 : GICombineRule<
+  (defs root:$dst),
+  (match (G_ADD $dst, 0, 3)),
+  (apply (G_ADD $dst, 1, 2))
+>;
+
 def MyCombiner: GICombiner<"GenMyCombiner", [
   inference_mul_by_neg_one,
   infer_complex_tempreg,
-  infer_variadic_outs
+  infer_variadic_outs,
+  infer_imm_0,
 ]>;
diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
index 89aca87a28ec0d..9121139be93540 100644
--- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
@@ -284,7 +284,8 @@ class CombineRuleOperandTypeChecker : private OperandTypeChecker {
   /// succeed.
   PatternType inferNamedOperandType(const InstructionPattern &IP,
                                     StringRef OpName,
-                                    const TypeEquivalenceClasses &TECs) const;
+                                    const TypeEquivalenceClasses &TECs,
+                                    bool AllowSelf = false) const;
 
   const Record &RuleDef;
   SmallVector<InstructionPattern *, 8> MatchPats;
@@ -428,7 +429,8 @@ PatternType CombineRuleOperandTypeChecker::inferImmediateType(
 
       // Named operand with the same name, try to infer that.
       if (PatternType InferTy =
-              inferNamedOperandType(IP, Op.getOperandName(), TECs))
+              inferNamedOperandType(IP, Op.getOperandName(), TECs,
+                                    /*IncludeSelf=*/true))
         return InferTy;
     }
   }
@@ -438,16 +440,17 @@ PatternType CombineRuleOperandTypeChecker::inferImmediateType(
 
 PatternType CombineRuleOperandTypeChecker::inferNamedOperandType(
     const InstructionPattern &IP, StringRef OpName,
-    const TypeEquivalenceClasses &TECs) const {
+    const TypeEquivalenceClasses &TECs, bool AllowSelf) const {
   // This is the simplest possible case, we just need to find a TEC that
-  // contains OpName. Look at all other operands in equivalence class and try to
-  // find a suitable one.
+  // contains OpName. Look at all operands in equivalence class and try to
+  // find a suitable one. If `AllowSelf` is true, the operand itself is also
+  // considered suitable.
 
   // Check for a def of a matched pattern. This is guaranteed to always
   // be a register so we can blindly use that.
   StringRef GoodOpName;
   for (auto It = TECs.findLeader(OpName); It != TECs.member_end(); ++It) {
-    if (*It == OpName)
+    if (!AllowSelf && *It == OpName)
       continue;
 
     const auto LookupRes = MatchOpTable.lookup(*It);

``````````

</details>


https://github.com/llvm/llvm-project/pull/77399


More information about the llvm-commits mailing list