[llvm] 8d03c49 - Extend switch condition in optimizeSwitchPhiConst when free

Matthias Braun via llvm-commits llvm-commits at lists.llvm.org
Wed May 18 16:25:01 PDT 2022


Author: Matthias Braun
Date: 2022-05-18T16:23:53-07:00
New Revision: 8d03c49f498cb19358aacd28f57a852549d34ebd

URL: https://github.com/llvm/llvm-project/commit/8d03c49f498cb19358aacd28f57a852549d34ebd
DIFF: https://github.com/llvm/llvm-project/commit/8d03c49f498cb19358aacd28f57a852549d34ebd.diff

LOG: Extend switch condition in optimizeSwitchPhiConst when free

In a case like:

    switch((i32)x) { case 42: phi((i64)42, ...); }

replace `(i64)42` with `zext(x)` when we can do so for free.

This fixes a part of https://github.com/llvm/llvm-project/issues/55153

Differential Revision: https://reviews.llvm.org/D124897

Added: 
    

Modified: 
    llvm/lib/CodeGen/CodeGenPrepare.cpp
    llvm/test/CodeGen/X86/switch-phi-const.ll
    llvm/test/Transforms/CodeGenPrepare/X86/switch-phi-const.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index d1000383c8721..9ed4f5bf43251 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -7048,12 +7048,29 @@ bool CodeGenPrepare::optimizeSwitchPhiConstants(SwitchInst *SI) {
     bool CheckedForSinglePred = false;
     for (PHINode &PHI : CaseBB->phis()) {
       Type *PHIType = PHI.getType();
-      if (PHIType == ConditionType) {
+      // If ZExt is free then we can also catch patterns like this:
+      //   switch((i32)x) { case 42: phi((i64)42, ...); }
+      // and replace `(i64)42` with `zext i32 %x to i64`.
+      bool TryZExt =
+          PHIType->isIntegerTy() &&
+          PHIType->getIntegerBitWidth() > ConditionType->getIntegerBitWidth() &&
+          TLI->isZExtFree(ConditionType, PHIType);
+      if (PHIType == ConditionType || TryZExt) {
         // Set to true to skip this case because of multiple preds.
         bool SkipCase = false;
+        Value *Replacement = nullptr;
         for (unsigned I = 0, E = PHI.getNumIncomingValues(); I != E; I++) {
-          if (PHI.getIncomingValue(I) != CaseValue ||
-              PHI.getIncomingBlock(I) != SwitchBB)
+          Value *PHIValue = PHI.getIncomingValue(I);
+          if (PHIValue != CaseValue) {
+            if (!TryZExt)
+              continue;
+            ConstantInt *PHIValueInt = dyn_cast<ConstantInt>(PHIValue);
+            if (!PHIValueInt ||
+                PHIValueInt->getValue() !=
+                    CaseValue->getValue().zext(PHIType->getIntegerBitWidth()))
+              continue;
+          }
+          if (PHI.getIncomingBlock(I) != SwitchBB)
             continue;
           // We cannot optimize if there are multiple case labels jumping to
           // this block.  This check may get expensive when there are many
@@ -7066,7 +7083,15 @@ bool CodeGenPrepare::optimizeSwitchPhiConstants(SwitchInst *SI) {
             }
           }
 
-          PHI.setIncomingValue(I, Condition);
+          if (Replacement == nullptr) {
+            if (PHIValue == CaseValue) {
+              Replacement = Condition;
+            } else {
+              IRBuilder<> Builder(SI);
+              Replacement = Builder.CreateZExt(Condition, PHIType);
+            }
+          }
+          PHI.setIncomingValue(I, Replacement);
           Changed = true;
         }
         if (SkipCase)

diff  --git a/llvm/test/CodeGen/X86/switch-phi-const.ll b/llvm/test/CodeGen/X86/switch-phi-const.ll
index 625e97a41ed7c..e28169217c01e 100644
--- a/llvm/test/CodeGen/X86/switch-phi-const.ll
+++ b/llvm/test/CodeGen/X86/switch-phi-const.ll
@@ -91,38 +91,33 @@ default:
 define void @switch_trunc_phi_const(i32 %x) {
 ; CHECK-LABEL: switch_trunc_phi_const:
 ; CHECK:       # %bb.0: # %bb0
-; CHECK-NEXT:    movzbl %dil, %r8d
-; CHECK-NEXT:    movl $3895, %ecx # imm = 0xF37
-; CHECK-NEXT:    movl $42, %esi
-; CHECK-NEXT:    movl $13, %edx
-; CHECK-NEXT:    movl $5, %edi
-; CHECK-NEXT:    movl $1, %eax
-; CHECK-NEXT:    decl %r8d
-; CHECK-NEXT:    cmpl $54, %r8d
+; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
+; CHECK-NEXT:    movzbl %dil, %ecx
+; CHECK-NEXT:    movzbl %dil, %eax
+; CHECK-NEXT:    movl $3895, %edx # imm = 0xF37
+; CHECK-NEXT:    decl %ecx
+; CHECK-NEXT:    cmpl $54, %ecx
 ; CHECK-NEXT:    ja .LBB1_8
 ; CHECK-NEXT:  # %bb.1: # %bb0
-; CHECK-NEXT:    jmpq *.LJTI1_0(,%r8,8)
+; CHECK-NEXT:    jmpq *.LJTI1_0(,%rcx,8)
 ; CHECK-NEXT:  .LBB1_8: # %default
 ; CHECK-NEXT:    retq
 ; CHECK-NEXT:  .LBB1_2: # %case_1_loop
 ; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rcx
 ; CHECK-NEXT:    movq $1, (%rcx)
-; CHECK-NEXT:    movq %rax, %rdi
 ; CHECK-NEXT:  .LBB1_3: # %case_5
-; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rax
-; CHECK-NEXT:    movq $5, (%rax)
-; CHECK-NEXT:    movq %rdi, %rdx
+; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rcx
+; CHECK-NEXT:    movq $5, (%rcx)
 ; CHECK-NEXT:  .LBB1_4: # %case_13
-; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rax
-; CHECK-NEXT:    movq $13, (%rax)
-; CHECK-NEXT:    movq %rdx, %rsi
+; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rcx
+; CHECK-NEXT:    movq $13, (%rcx)
 ; CHECK-NEXT:  .LBB1_5: # %case_42
-; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rax
-; CHECK-NEXT:    movq %rsi, (%rax)
-; CHECK-NEXT:    movl $55, %ecx
+; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rcx
+; CHECK-NEXT:    movq %rax, (%rcx)
+; CHECK-NEXT:    movl $55, %edx
 ; CHECK-NEXT:  .LBB1_6: # %case_55
 ; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rax
-; CHECK-NEXT:    movq %rcx, (%rax)
+; CHECK-NEXT:    movq %rdx, (%rax)
 ; CHECK-NEXT:  .LBB1_7: # %case_7
 ; CHECK-NEXT:    movq g64 at GOTPCREL(%rip), %rax
 ; CHECK-NEXT:    movq (%rax), %rax

diff  --git a/llvm/test/Transforms/CodeGenPrepare/X86/switch-phi-const.ll b/llvm/test/Transforms/CodeGenPrepare/X86/switch-phi-const.ll
index 2854cd02c935b..768c8ad6c11eb 100644
--- a/llvm/test/Transforms/CodeGenPrepare/X86/switch-phi-const.ll
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/switch-phi-const.ll
@@ -155,3 +155,71 @@ case_42:
 unreachable:
   unreachable
 }
+
+ at g64 = global i64 0
+ at effect64 = global i64 0
+
+define void @switch_trunc_phi_const(i32 %x) {
+; CHECK-LABEL: @switch_trunc_phi_const(
+; CHECK-NEXT:  bb0:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[X:%.*]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[X]] to i64
+; CHECK-NEXT:    switch i32 [[X]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT:    i32 13, label [[CASE_13:%.*]]
+; CHECK-NEXT:    i32 42, label [[CASE_42:%.*]]
+; CHECK-NEXT:    i32 55, label [[CASE_55:%.*]]
+; CHECK-NEXT:    i32 7, label [[CASE_7:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       case_13:
+; CHECK-NEXT:    [[X0:%.*]] = phi i64 [ [[TMP0]], [[BB0:%.*]] ], [ [[X7:%.*]], [[CASE_7]] ]
+; CHECK-NEXT:    store i64 13, i64* @effect64, align 4
+; CHECK-NEXT:    br label [[CASE_42]]
+; CHECK:       case_42:
+; CHECK-NEXT:    [[X1:%.*]] = phi i64 [ [[TMP1]], [[BB0]] ], [ [[X0]], [[CASE_13]] ]
+; CHECK-NEXT:    store i64 [[X1]], i64* @effect64, align 4
+; CHECK-NEXT:    br label [[CASE_55]]
+; CHECK:       case_55:
+; CHECK-NEXT:    [[X2:%.*]] = phi i64 [ 3895, [[BB0]] ], [ 55, [[CASE_42]] ]
+; CHECK-NEXT:    store i64 [[X2]], i64* @effect64, align 4
+; CHECK-NEXT:    br label [[DEFAULT]]
+; CHECK:       case_7:
+; CHECK-NEXT:    [[X7]] = load i64, i64* @g64, align 4
+; CHECK-NEXT:    store i64 7, i64* @effect64, align 4
+; CHECK-NEXT:    br label [[CASE_13]]
+; CHECK:       default:
+; CHECK-NEXT:    ret void
+;
+bb0:
+  switch i32 %x, label %default [
+  i32 13, label %case_13
+  i32 42, label %case_42
+  i32 55, label %case_55
+  i32 7, label %case_7
+  ]
+
+case_13:
+  ; We should replace 13 with zext %x to i64
+  %x0 = phi i64 [ 13, %bb0 ], [ %x7, %case_7 ]
+  store i64 13, i64* @effect64, align 4
+  br label %case_42
+
+case_42:
+  ; We should replace 42 with zext i32 %x to i64
+  %x1 = phi i64 [ 42, %bb0 ], [ %x0, %case_13 ]
+  store i64 %x1, i64* @effect64, align 4
+  br label %case_55
+
+case_55:
+  ; We must not replace any of the PHI arguments! (3898 == 0xf00 + 55)
+  %x2 = phi i64 [ 3895, %bb0 ], [ 55, %case_42 ]
+  store i64 %x2, i64* @effect64, align 4
+  br label %default
+
+case_7:
+  %x7 = load i64, i64* @g64, align 4
+  store i64 7, i64* @effect64, align 4
+  br label %case_13
+
+default:
+  ret void
+}


        


More information about the llvm-commits mailing list