[llvm] [CodeGen] Expand power-of-2 div/rem at IR level in ExpandIRInsts. (PR #180654)

via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 12 07:21:57 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86

@llvm/pr-subscribers-backend-risc-v

Author: Daniil Fukalov (dfukalov)

<details>
<summary>Changes</summary>

Previously, power-of-2 div/rem operations wider than
MaxLegalDivRemBitWidth were excluded from IR expansion and left for
backend peephole optimizations. Some backends can fail to process such
instructions in case we switch off DAGCombiner.

Now ExpandIRInsts expands them into shift/mask sequences:
- udiv X, 2^C  ->  lshr X, C
- urem X, 2^C  ->  and X, (2^C - 1)
- sdiv X, 2^C  ->  bias adjustment + ashr X, C
- srem X, 2^C  ->  X - (((X + Bias) >> C) << C)

Special cases handled:
- Division/remainder by 1 or -1 (identity, negation, or zero)
- Exact division (sdiv exact skips bias, produces ashr exact)
- Negative power-of-2 divisors (result is negated)
- INT_MIN divisor (correct via countr_zero on bit pattern)

---

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


10 Files Affected:

- (modified) llvm/lib/CodeGen/ExpandIRInsts.cpp (+125-8) 
- (modified) llvm/test/CodeGen/AMDGPU/div_i128.ll (+19-48) 
- (modified) llvm/test/CodeGen/AMDGPU/div_v2i128.ll (+69-1283) 
- (modified) llvm/test/CodeGen/AMDGPU/rem_i128.ll (+34-27) 
- (modified) llvm/test/CodeGen/RISCV/div_minsize.ll (+3-3) 
- (modified) llvm/test/CodeGen/X86/div_i129_v_pow2k.ll (+55-93) 
- (modified) llvm/test/Transforms/ExpandIRInsts/X86/sdiv129.ll (+148) 
- (modified) llvm/test/Transforms/ExpandIRInsts/X86/srem129.ll (+115) 
- (modified) llvm/test/Transforms/ExpandIRInsts/X86/udiv129.ll (+51) 
- (modified) llvm/test/Transforms/ExpandIRInsts/X86/urem129.ll (+25) 


``````````diff
diff --git a/llvm/lib/CodeGen/ExpandIRInsts.cpp b/llvm/lib/CodeGen/ExpandIRInsts.cpp
index 07a07872ea86f..2e545ba1541c6 100644
--- a/llvm/lib/CodeGen/ExpandIRInsts.cpp
+++ b/llvm/lib/CodeGen/ExpandIRInsts.cpp
@@ -84,6 +84,111 @@ bool isSigned(unsigned int Opcode) {
   return Opcode == Instruction::SDiv || Opcode == Instruction::SRem;
 }
 
+/// For signed div/rem by a power of 2, compute the bias-adjusted dividend:
+///   Sign = ashr X, (BitWidth - 1)          -- 0 or -1
+///   Bias = lshr Sign, (BitWidth - ShiftAmt) -- 0 or 2^ShiftAmt - 1
+///   Adjusted = add X, Bias
+/// The bias adds (2^ShiftAmt - 1) for negative X, correcting rounding towards
+/// zero (instead of towards -inf that a plain ashr would give).
+/// The lshr form is used instead of 'and' to avoid large immediate constants.
+static Value *addSignedBias(IRBuilder<> &Builder, Value *X, unsigned BitWidth,
+                            unsigned ShiftAmt) {
+  assert(ShiftAmt > 0 && ShiftAmt < BitWidth &&
+         "ShiftAmt out of range; callers should handle ShiftAmt == 0");
+  Value *Sign = Builder.CreateAShr(X, BitWidth - 1, "sign");
+  Value *Bias = Builder.CreateLShr(Sign, BitWidth - ShiftAmt, "bias");
+  return Builder.CreateAdd(X, Bias, "adjusted");
+}
+
+/// Expand division by a power-of-2 constant.
+/// udiv X, 2^C  ->  lshr X, C
+/// sdiv X, 2^C  ->  ashr (add X, Bias), C  (Bias corrects rounding)
+/// sdiv exact X, 2^C  ->  ashr exact X, C  (no bias needed)
+/// For negative power-of-2 divisors, the result is negated.
+static void expandPow2Division(BinaryOperator *Div) {
+  bool IsSigned = isSigned(Div->getOpcode());
+  bool IsExact = Div->isExact();
+  Value *X = Div->getOperand(0);
+  auto *C = cast<ConstantInt>(Div->getOperand(1));
+  Type *Ty = Div->getType();
+  unsigned BitWidth = Ty->getIntegerBitWidth();
+
+  APInt DivisorVal = C->getValue();
+  bool IsNegativeDivisor = IsSigned && DivisorVal.isNegative();
+  // Use countr_zero() to get the shift amount directly from the bit pattern.
+  // This works correctly for both positive and negative powers of 2, including
+  // INT_MIN, without needing to negate the value first.
+  unsigned ShiftAmt = DivisorVal.countr_zero();
+
+  IRBuilder<> Builder(Div);
+  Value *Result;
+
+  if (ShiftAmt == 0) {
+    // Division by 1 or -1.
+    // X / 1 = X, X / -1 = -X.
+    Result = IsNegativeDivisor ? Builder.CreateNeg(X) : X;
+  } else if (IsSigned) {
+    // For exact division, no bias is needed since there's no rounding.
+    Value *Dividend =
+        IsExact ? X : addSignedBias(Builder, X, BitWidth, ShiftAmt);
+    Result = Builder.CreateAShr(Dividend, ShiftAmt,
+                                IsNegativeDivisor ? "pre.neg" : "", IsExact);
+    if (IsNegativeDivisor)
+      Result = Builder.CreateNeg(Result);
+  } else {
+    Result = Builder.CreateLShr(X, ShiftAmt, "", IsExact);
+  }
+
+  Div->replaceAllUsesWith(Result);
+  // Transfer the name of the original instruction to its replacement,
+  // unless the result is the original dividend itself (div by 1).
+  if (Result != X)
+    if (auto *RI = dyn_cast<Instruction>(Result))
+      RI->takeName(Div);
+  Div->dropAllReferences();
+  Div->eraseFromParent();
+}
+
+/// Expand remainder by a power-of-2 constant (let C = log2(|divisor|)).
+/// urem X, 2^C  ->  and X, (2^C - 1)
+/// srem X, 2^C  ->  sub X, (shl (ashr (add X, Bias), C), C)
+static void expandPow2Remainder(BinaryOperator *Rem) {
+  bool IsSigned = isSigned(Rem->getOpcode());
+  Value *X = Rem->getOperand(0);
+  auto *C = cast<ConstantInt>(Rem->getOperand(1));
+  Type *Ty = Rem->getType();
+  unsigned BitWidth = Ty->getIntegerBitWidth();
+
+  // Use countr_zero() to get the shift amount directly from the bit pattern.
+  // This works for both positive and negative powers of 2, including INT_MIN.
+  unsigned ShiftAmt = C->getValue().countr_zero();
+
+  IRBuilder<> Builder(Rem);
+  Value *Result;
+
+  if (ShiftAmt == 0) {
+    // Remainder by 1 or -1 is always 0.
+    Result = ConstantInt::get(Ty, 0);
+  } else if (IsSigned) {
+    Value *Adjusted = addSignedBias(Builder, X, BitWidth, ShiftAmt);
+    // Clear lower ShiftAmt bits via round-trip shift:
+    //   Truncated = (Adjusted >> ShiftAmt) << ShiftAmt
+    Value *Shifted = Builder.CreateAShr(Adjusted, ShiftAmt, "shifted");
+    Value *Truncated = Builder.CreateShl(Shifted, ShiftAmt, "truncated");
+    Result = Builder.CreateSub(X, Truncated);
+  } else {
+    APInt Mask = APInt::getLowBitsSet(BitWidth, ShiftAmt);
+    Value *MaskVal = ConstantInt::get(Ty, Mask);
+    Result = Builder.CreateAnd(X, MaskVal);
+  }
+
+  Rem->replaceAllUsesWith(Result);
+  if (auto *RI = dyn_cast<Instruction>(Result))
+    RI->takeName(Rem);
+  Rem->dropAllReferences();
+  Rem->eraseFromParent();
+}
+
 /// This class implements a precise expansion of the frem instruction.
 /// The generated code is based on the fmod implementation in the AMD device
 /// libs.
@@ -1083,12 +1188,14 @@ static bool runImpl(Function &F, const TargetLowering &TLI,
     case Instruction::SDiv:
     case Instruction::URem:
     case Instruction::SRem:
+      // TODO: We don't consider vectors here.
+      // Power-of-2 divisors are handled inside the expansion (via efficient
+      // shift/mask sequences) rather than being excluded here, so that
+      // backends that cannot lower wide div/rem even for powers of two
+      // (e.g. when DAGCombiner is disabled) still get valid lowered code.
       return !DisableExpandLargeDivRem &&
              cast<IntegerType>(Ty->getScalarType())->getIntegerBitWidth() >
-                 MaxLegalDivRemBitWidth
-             // The backend has peephole optimizations for powers of two.
-             // TODO: We don't consider vectors here.
-             && !isConstantPowerOfTwo(I.getOperand(1), isSigned(I.getOpcode()));
+                 MaxLegalDivRemBitWidth;
     }
 
     return false;
@@ -1134,14 +1241,24 @@ static bool runImpl(Function &F, const TargetLowering &TLI,
       break;
 
     case Instruction::UDiv:
-    case Instruction::SDiv:
-      expandDivision(cast<BinaryOperator>(I));
+    case Instruction::SDiv: {
+      auto *BO = cast<BinaryOperator>(I);
+      if (isConstantPowerOfTwo(BO->getOperand(1), isSigned(BO->getOpcode())))
+        expandPow2Division(BO);
+      else
+        expandDivision(BO);
       break;
+    }
     case Instruction::URem:
-    case Instruction::SRem:
-      expandRemainder(cast<BinaryOperator>(I));
+    case Instruction::SRem: {
+      auto *BO = cast<BinaryOperator>(I);
+      if (isConstantPowerOfTwo(BO->getOperand(1), isSigned(BO->getOpcode())))
+        expandPow2Remainder(BO);
+      else
+        expandRemainder(BO);
       break;
     }
+    }
   }
 
   return Modified;
diff --git a/llvm/test/CodeGen/AMDGPU/div_i128.ll b/llvm/test/CodeGen/AMDGPU/div_i128.ll
index 5a4aa4effac00..c3c0ac9c1dbcc 100644
--- a/llvm/test/CodeGen/AMDGPU/div_i128.ll
+++ b/llvm/test/CodeGen/AMDGPU/div_i128.ll
@@ -4268,19 +4268,21 @@ define i128 @v_sdiv_i128_v_pow2k(i128 %lhs) {
 ; GFX9-O0-NEXT:    buffer_store_dword v1, off, s[0:3], s32 ; 4-byte Folded Spill
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v1, v0
 ; GFX9-O0-NEXT:    buffer_load_dword v0, off, s[0:3], s32 ; 4-byte Folded Reload
-; GFX9-O0-NEXT:    ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec
-; GFX9-O0-NEXT:    v_mov_b32_e32 v5, v3
 ; GFX9-O0-NEXT:    ; kill: def $vgpr1 killed $vgpr1 def $vgpr1_vgpr2 killed $exec
 ; GFX9-O0-NEXT:    s_waitcnt vmcnt(0)
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v2, v0
+; GFX9-O0-NEXT:    ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec
+; GFX9-O0-NEXT:    v_mov_b32_e32 v5, v3
+; GFX9-O0-NEXT:    s_mov_b32 s4, 63
+; GFX9-O0-NEXT:    v_mov_b32_e32 v7, v5
+; GFX9-O0-NEXT:    v_mov_b32_e32 v6, v4
+; GFX9-O0-NEXT:    v_ashrrev_i64 v[6:7], s4, v[6:7]
+; GFX9-O0-NEXT:    s_mov_b32 s5, 31
+; GFX9-O0-NEXT:    v_lshrrev_b64 v[6:7], s5, v[6:7]
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v0, v1
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v3, v2
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v2, v4
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v1, v5
-; GFX9-O0-NEXT:    s_mov_b32 s4, 63
-; GFX9-O0-NEXT:    v_ashrrev_i64 v[4:5], s4, v[4:5]
-; GFX9-O0-NEXT:    s_mov_b32 s5, 31
-; GFX9-O0-NEXT:    v_lshrrev_b64 v[6:7], s5, v[4:5]
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v5, v6
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v4, v7
 ; GFX9-O0-NEXT:    s_mov_b64 s[8:9], 0
@@ -4291,12 +4293,12 @@ define i128 @v_sdiv_i128_v_pow2k(i128 %lhs) {
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v4, s6
 ; GFX9-O0-NEXT:    v_addc_co_u32_e32 v5, vcc, v2, v4, vcc
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v2, s4
-; GFX9-O0-NEXT:    v_addc_co_u32_e32 v1, vcc, v1, v2, vcc
-; GFX9-O0-NEXT:    ; kill: def $vgpr5 killed $vgpr5 def $vgpr5_vgpr6 killed $exec
-; GFX9-O0-NEXT:    v_mov_b32_e32 v6, v1
-; GFX9-O0-NEXT:    v_mov_b32_e32 v2, v5
+; GFX9-O0-NEXT:    v_addc_co_u32_e32 v2, vcc, v1, v2, vcc
 ; GFX9-O0-NEXT:    ; kill: def $vgpr0 killed $vgpr0 def $vgpr0_vgpr1 killed $exec
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v1, v3
+; GFX9-O0-NEXT:    ; kill: def $vgpr5 killed $vgpr5 def $vgpr5_vgpr6 killed $exec
+; GFX9-O0-NEXT:    v_mov_b32_e32 v6, v2
+; GFX9-O0-NEXT:    v_mov_b32_e32 v2, v5
 ; GFX9-O0-NEXT:    s_mov_b32 s4, 33
 ; GFX9-O0-NEXT:    v_lshrrev_b64 v[0:1], s4, v[0:1]
 ; GFX9-O0-NEXT:    ; kill: def $vgpr0 killed $vgpr0 killed $vgpr0_vgpr1 killed $exec
@@ -4377,13 +4379,7 @@ define i128 @v_sdiv_exact_i128_v_pow2k(i128 %lhs) {
 ; GFX9-LABEL: v_sdiv_exact_i128_v_pow2k:
 ; GFX9:       ; %bb.0:
 ; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX9-NEXT:    v_ashrrev_i32_e32 v4, 31, v3
-; GFX9-NEXT:    v_mov_b32_e32 v5, v4
-; GFX9-NEXT:    v_lshrrev_b64 v[4:5], 31, v[4:5]
-; GFX9-NEXT:    v_add_co_u32_e32 v0, vcc, v0, v4
-; GFX9-NEXT:    v_addc_co_u32_e32 v4, vcc, v1, v5, vcc
-; GFX9-NEXT:    v_addc_co_u32_e32 v2, vcc, 0, v2, vcc
-; GFX9-NEXT:    v_addc_co_u32_e32 v3, vcc, 0, v3, vcc
+; GFX9-NEXT:    v_mov_b32_e32 v4, v1
 ; GFX9-NEXT:    v_lshlrev_b64 v[0:1], 31, v[2:3]
 ; GFX9-NEXT:    v_lshrrev_b32_e32 v2, 1, v4
 ; GFX9-NEXT:    v_or_b32_e32 v0, v2, v0
@@ -4394,42 +4390,17 @@ define i128 @v_sdiv_exact_i128_v_pow2k(i128 %lhs) {
 ; GFX9-O0-LABEL: v_sdiv_exact_i128_v_pow2k:
 ; GFX9-O0:       ; %bb.0:
 ; GFX9-O0-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX9-O0-NEXT:    v_mov_b32_e32 v4, v2
-; GFX9-O0-NEXT:    buffer_store_dword v1, off, s[0:3], s32 ; 4-byte Folded Spill
-; GFX9-O0-NEXT:    v_mov_b32_e32 v1, v0
-; GFX9-O0-NEXT:    buffer_load_dword v0, off, s[0:3], s32 ; 4-byte Folded Reload
-; GFX9-O0-NEXT:    ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec
-; GFX9-O0-NEXT:    v_mov_b32_e32 v5, v3
-; GFX9-O0-NEXT:    ; kill: def $vgpr1 killed $vgpr1 def $vgpr1_vgpr2 killed $exec
-; GFX9-O0-NEXT:    s_waitcnt vmcnt(0)
-; GFX9-O0-NEXT:    v_mov_b32_e32 v2, v0
-; GFX9-O0-NEXT:    v_mov_b32_e32 v0, v1
-; GFX9-O0-NEXT:    v_mov_b32_e32 v3, v2
-; GFX9-O0-NEXT:    v_mov_b32_e32 v2, v4
-; GFX9-O0-NEXT:    v_mov_b32_e32 v1, v5
-; GFX9-O0-NEXT:    s_mov_b32 s4, 63
-; GFX9-O0-NEXT:    v_ashrrev_i64 v[4:5], s4, v[4:5]
-; GFX9-O0-NEXT:    s_mov_b32 s5, 31
-; GFX9-O0-NEXT:    v_lshrrev_b64 v[6:7], s5, v[4:5]
-; GFX9-O0-NEXT:    v_mov_b32_e32 v5, v6
-; GFX9-O0-NEXT:    v_mov_b32_e32 v4, v7
-; GFX9-O0-NEXT:    s_mov_b64 s[8:9], 0
-; GFX9-O0-NEXT:    s_mov_b32 s6, s8
-; GFX9-O0-NEXT:    s_mov_b32 s4, s9
-; GFX9-O0-NEXT:    v_add_co_u32_e32 v0, vcc, v0, v5
-; GFX9-O0-NEXT:    v_addc_co_u32_e32 v3, vcc, v3, v4, vcc
-; GFX9-O0-NEXT:    v_mov_b32_e32 v4, s6
-; GFX9-O0-NEXT:    v_addc_co_u32_e32 v5, vcc, v2, v4, vcc
-; GFX9-O0-NEXT:    v_mov_b32_e32 v2, s4
-; GFX9-O0-NEXT:    v_addc_co_u32_e32 v1, vcc, v1, v2, vcc
+; GFX9-O0-NEXT:    v_mov_b32_e32 v5, v2
+; GFX9-O0-NEXT:    v_mov_b32_e32 v2, v1
+; GFX9-O0-NEXT:    ; kill: def $vgpr0 killed $vgpr0 def $vgpr0_vgpr1 killed $exec
+; GFX9-O0-NEXT:    v_mov_b32_e32 v1, v2
 ; GFX9-O0-NEXT:    ; kill: def $vgpr5 killed $vgpr5 def $vgpr5_vgpr6 killed $exec
-; GFX9-O0-NEXT:    v_mov_b32_e32 v6, v1
+; GFX9-O0-NEXT:    v_mov_b32_e32 v6, v3
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v2, v5
-; GFX9-O0-NEXT:    ; kill: def $vgpr0 killed $vgpr0 def $vgpr0_vgpr1 killed $exec
-; GFX9-O0-NEXT:    v_mov_b32_e32 v1, v3
 ; GFX9-O0-NEXT:    s_mov_b32 s4, 33
 ; GFX9-O0-NEXT:    v_lshrrev_b64 v[0:1], s4, v[0:1]
 ; GFX9-O0-NEXT:    ; kill: def $vgpr0 killed $vgpr0 killed $vgpr0_vgpr1 killed $exec
+; GFX9-O0-NEXT:    s_mov_b32 s5, 31
 ; GFX9-O0-NEXT:    v_lshl_or_b32 v0, v2, s5, v0
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v3, v5
 ; GFX9-O0-NEXT:    v_mov_b32_e32 v4, v6
diff --git a/llvm/test/CodeGen/AMDGPU/div_v2i128.ll b/llvm/test/CodeGen/AMDGPU/div_v2i128.ll
index 2b434c54da9c2..2712ff329c98c 100644
--- a/llvm/test/CodeGen/AMDGPU/div_v2i128.ll
+++ b/llvm/test/CodeGen/AMDGPU/div_v2i128.ll
@@ -824,681 +824,59 @@ define <2 x i128> @v_sdiv_v2i128_vv(<2 x i128> %lhs, <2 x i128> %rhs) {
 
 define <2 x i128> @v_sdiv_v2i128_v_pow2k(<2 x i128> %lhs) {
 ; SDAG-LABEL: v_sdiv_v2i128_v_pow2k:
-; SDAG:       ; %bb.0: ; %_udiv-special-cases_udiv-special-cases
+; SDAG:       ; %bb.0:
 ; SDAG-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SDAG-NEXT:    v_ashrrev_i32_e32 v18, 31, v3
-; SDAG-NEXT:    v_sub_i32_e32 v8, vcc, 0, v0
-; SDAG-NEXT:    v_mov_b32_e32 v9, 0
-; SDAG-NEXT:    s_mov_b64 s[6:7], 0x7f
-; SDAG-NEXT:    v_mov_b32_e32 v19, v18
-; SDAG-NEXT:    v_subb_u32_e32 v10, vcc, 0, v1, vcc
-; SDAG-NEXT:    v_subb_u32_e32 v11, vcc, 0, v2, vcc
-; SDAG-NEXT:    v_cmp_gt_i64_e64 s[4:5], 0, v[2:3]
-; SDAG-NEXT:    v_cndmask_b32_e64 v13, v1, v10, s[4:5]
-; SDAG-NEXT:    v_cndmask_b32_e64 v12, v0, v8, s[4:5]
-; SDAG-NEXT:    v_subb_u32_e32 v0, vcc, 0, v3, vcc
-; SDAG-NEXT:    v_cndmask_b32_e64 v10, v2, v11, s[4:5]
-; SDAG-NEXT:    v_ffbh_u32_e32 v1, v12
-; SDAG-NEXT:    v_ffbh_u32_e32 v2, v13
-; SDAG-NEXT:    v_cndmask_b32_e64 v11, v3, v0, s[4:5]
-; SDAG-NEXT:    v_or_b32_e32 v0, v12, v10
-; SDAG-NEXT:    v_ffbh_u32_e32 v3, v10
-; SDAG-NEXT:    v_add_i32_e32 v8, vcc, 32, v1
-; SDAG-NEXT:    v_or_b32_e32 v1, v13, v11
-; SDAG-NEXT:    v_add_i32_e32 v3, vcc, 32, v3
-; SDAG-NEXT:    v_ffbh_u32_e32 v14, v11
-; SDAG-NEXT:    v_min_u32_e32 v2, v8, v2
-; SDAG-NEXT:    v_cmp_eq_u64_e64 s[4:5], 0, v[0:1]
-; SDAG-NEXT:    v_min_u32_e32 v0, v3, v14
-; SDAG-NEXT:    v_add_i32_e32 v1, vcc, 64, v2
-; SDAG-NEXT:    v_addc_u32_e64 v2, s[8:9], 0, 0, vcc
-; SDAG-NEXT:    v_cmp_ne_u64_e32 vcc, 0, v[10:11]
-; SDAG-NEXT:    v_cndmask_b32_e64 v3, v2, 0, vcc
-; SDAG-NEXT:    v_cndmask_b32_e32 v0, v1, v0, vcc
-; SDAG-NEXT:    v_sub_i32_e32 v2, vcc, 0x5e, v0
-; SDAG-NEXT:    v_subb_u32_e32 v3, vcc, 0, v3, vcc
-; SDAG-NEXT:    v_xor_b32_e32 v0, 0x7f, v2
-; SDAG-NEXT:    v_subb_u32_e32 v8, vcc, 0, v9, vcc
-; SDAG-NEXT:    v_cmp_lt_u64_e64 s[6:7], s[6:7], v[2:3]
-; SDAG-NEXT:    v_cndmask_b32_e64 v14, 0, 1, s[6:7]
-; SDAG-NEXT:    v_subb_u32_e32 v9, vcc, 0, v9, vcc
-; SDAG-NEXT:    v_or_b32_e32 v0, v0, v8
-; SDAG-NEXT:    v_cmp_ne_u64_e32 vcc, 0, v[8:9]
-; SDAG-NEXT:    v_cndmask_b32_e64 v15, 0, 1, vcc
-; SDAG-NEXT:    v_or_b32_e32 v1, v3, v9
-; SDAG-NEXT:    v_cmp_eq_u64_e32 vcc, 0, v[8:9]
-; SDAG-NEXT:    v_cndmask_b32_e32 v14, v15, v14, vcc
-; SDAG-NEXT:    v_cmp_ne_u64_e32 vcc, 0, v[0:1]
-; SDAG-NEXT:    v_and_b32_e32 v0, 1, v14
-; SDAG-NEXT:    v_cmp_eq_u32_e64 s[6:7], 1, v0
-; SDAG-NEXT:    s_or_b64 s[4:5], s[4:5], s[6:7]
-; SDAG-NEXT:    v_cndmask_b32_e64 v1, v11, 0, s[4:5]
-; SDAG-NEXT:    s_xor_b64 s[6:7], s[4:5], -1
-; SDAG-NEXT:    v_cndmask_b32_e64 v0, v10, 0, s[4:5]
-; SDAG-NEXT:    v_cndmask_b32_e64 v16, v13, 0, s[4:5]
-; SDAG-NEXT:    v_cndmask_b32_e64 v17, v12, 0, s[4:5]
-; SDAG-NEXT:    s_and_b64 s[4:5], s[6:7], vcc
-; SDAG-NEXT:    s_and_saveexec_b64 s[6:7], s[4:5]
-; SDAG-NEXT:    s_cbranch_execz .LBB1_6
-; SDAG-NEXT:  ; %bb.1: ; %udiv-bb15
-; SDAG-NEXT:    v_add_i32_e32 v20, vcc, 1, v2
-; SDAG-NEXT:    v_sub_i32_e64 v0, s[4:5], 63, v2
-; SDAG-NEXT:    v_addc_u32_e32 v21, vcc, 0, v3, vcc
-; SDAG-NEXT:    v_lshl_b64 v[0:1], v[12:13], v0
-; SDAG-NEXT:    v_addc_u32_e32 v22, vcc, 0, v8, vcc
-; SDAG-NEXT:    v_addc_u32_e32 v23, vcc, 0, v9, vcc
-; SDAG-NEXT:    v_or_b32_e32 v8, v20, v22
-; SDAG-NEXT:    v_sub_i32_e32 v16, vcc, 0x7f, v2
-; SDAG-NEXT:    v_or_b32_e32 v9, v21, v23
-; SDAG-NEXT:    v_lshl_b64 v[2:3], v[10:11], v16
-; SDAG-NEXT:    v_sub_i32_e32 v17, vcc, 64, v16
-; SDAG-NEXT:    v_lshl_b64 v[14:15], v[12:13], v16
-; SDAG-NEXT:    v_cmp_ne_u64_e32 vcc, 0, v[8:9]
-; SDAG-NEXT:    v_lshr_b64 v[8:9], v[12:13], v17
-; SDAG-NEXT:    v_or_b32_e32 v3, v3, v9
-; SDAG-NEXT:    v_or_b32_e32 v2, v2, v8
-; SDAG-NEXT:    v_cmp_gt_u32_e64 s[4:5], 64, v16
-; SDAG-NEXT:    v_cndmask_b32_e64 v1, v1, v3, s[4:5]
-; SDAG-NEXT:    v_cndmask_b32_e64 v0, v0, v2, s[4:5]
-; SDAG-NEXT:    v_cndmask_b32_e64 v9, 0, v15, s[4:5]
-; SDAG-NEXT:    v_cndmask_b32_e64 v8, 0, v14, s[4:5]
-; SDAG-NEXT:    v_cmp_eq_u32_e64 s[4:5], 0, v16
-; SDAG-NEXT:    v_cndmask_b32_e64 v1, v1, v11, s[4:5]
-; SDAG-NEXT:    v_cndmask_b32_e64 v0, v0, v10, s[4:5]
-; SDAG-NEXT:    v_mov_b32_e32 v2, 0
-; SDAG-NEXT:    v_mov_b32_e32 v3, 0
-; SDAG-NEXT:    s_and_saveexec_b64 s[4:5], vcc
-; SDAG-NEXT:    s_xor_b64 s[8:9], exec, s[4:5]
-; SDAG-NEXT:    s_cbranch_execz .LBB1_5
-; SDAG-NEXT:  ; %bb.2: ; %udiv-preheader4
-; SDAG-NEXT:    v_lshr_b64 v[2:3], v[12:13], v20
-; SDAG-NEXT:    v_sub_i32_e32 v14, vcc, 64, v20
-; SDAG-NEXT:    v_lshl_b64 v[14:15], v[10:11], v14
-; SDAG-NEXT:    v_or_b32_e32 v15, v3, v15
-; SDAG-NEXT:    v_or_b32_e32 v14, v2, v14
-; SDAG-NEXT:    v_cmp_gt_u32_e32 vcc, 64, v20
-; SDAG-NEXT:    v_subrev_i32_e64 v2, s[4:5], 64, v20
-; SDAG-NEXT:    v_lshr_b64 v[2:3], v[10:11], v2
-; SDAG-NEXT:    v_cndmask_b32_e32 v3, v3, v15, vcc
-; SDAG-NEXT:    v_cmp_eq_u32_e64 s[4:5], 0, v20
-; SDAG-NEXT:    v_cndmask_b32_e64 v13, v3, v13, s[4:5]
-; SDAG-NEXT:    v_cndmask_b32_e32 v2, v2, v14, vcc
-; SDAG-NEXT:    v_cndmask_b32_e64 v12, v2, v12, s[4:5]
-; SDAG-NEXT:    v_lshr_b64 v[2:3], v[10:11], v20
-; SDAG-NEXT:    v_cndmask_b32_e32 v15, 0, v3, vcc
-; SDAG-NEXT:    v_cndmask_b32_e32 v14, 0, v2, vcc
-; SDAG-NEXT:    v_mov_b32_e32 v10, 0
-; SDAG-NEXT:    v_mov_b32_e32 v11, 0
-; SDAG-NEXT:    s_mov_b64 s[4:5], 0
-; SDAG-NEXT:    v_mov_b32_e32 v3, 0
-; SDAG-NEXT:    v_mov_b32_e32 v16, 0
-; SDAG-NEXT:    v_mov_b32_e32 v17, 0
-; SDAG-NEXT:  .LBB1_3: ; %udiv-do-while3
-; SDAG-NEXT:    ; =>This Inner Loop Header: Depth=1
-; SDAG-NEXT:    v_lshrrev_b32_e32 v2, 31, v9
-; SDAG-NEXT:    v_lshl_b64 v[8:9], v[8:9], 1
-; SDAG-NEXT:    v_lshl_b64 v[14:15], v[14:15], 1
-; SDAG-NEXT:    v_lshrrev_b32_e32 v24, 31, v13
-; SDAG-NEXT:    v_lshl_b64 v[12:13], v[12:13], 1
-; SDAG-NEXT:    v_lshrrev_b32_e32 v25, 31, v1
-; SDAG-NEXT:    v_lshl_b64 v[0:1], v[0:1], 1
-; SDAG-NEXT:    v_or_b32_e32 v9, v17, v9
-; SDAG-NEXT:    v_or_b32_e32 v8, v16, v8
-; SDAG-NEXT:    v_or_b32_e32 v14, v14, v24
-; SDAG-NEXT:    v_or_b32_e32 v12, v12, v25
-; SDAG-NEXT:    v_or_b32_e32 v0, v0, v2
-; SDAG-NEXT:    v_sub_i32_e32 v2, vcc, -1, v12
-; SDAG-NEXT:    v_subb_u32_e32 v2, vcc, 1, v13, vcc
-; SDAG-NEXT:    v_subb_u32_e32 v2, vcc, 0, v14, vcc
-; SDAG-NEXT:    v_subb_u32_e32 v2, vcc, 0, v15, vcc
-; SDAG-NEXT:    v_ashrrev_i32_e32 v2, 31, v2
-; SDAG-NEXT:    v_subrev_i32_e32 v12, vcc, 0, v12
-; SDAG-NEXT:    v_and_b32_e32 v16, 2, v2
-; SDAG-NEXT:    v_and_b32_e32 v2, 1, v2
-; SDAG-NEXT:    v_subb_u32_e32 v13, vcc, v13, v16, vcc
-; SDAG-NEXT:    v_subbrev_u32_e32 v14, vcc, 0, v14, vcc
-; SDAG-NEXT:    v_subbrev_u32_e32 v15, vcc, 0, v15, vcc
-; SDAG-NEXT:    v_add_i32_e32 v20, vcc, -1, v20
-; SDAG-NEXT:    v_addc_u32_e32 v21, vcc, -1, v21, vcc
-; SDAG-NEXT:    v_addc_u32_e32 v22, vcc, -1, v22, vcc
-; SDAG-NEXT:    v_addc_u32_e32 v23, vcc, -1, v23, vcc
-; SDAG-NEXT:    v_or_b32_e32 v16, v20, v22
-; SDAG-NEXT:    v_or_b32_e32 v17, v21, v23
-; SDAG-NEXT:    v_cmp_eq_u64_e32 vcc, 0, v[16:17]
-; SDAG-NEXT:    v_or_b32_e32 v1, v11, v1
-; SDAG-NEXT:    s_or_b64 s[4:5], vcc, s[4:5]
-; SDAG-NEXT:    v_or_b32_e32 v0, v10, v0
-; SDAG-NEXT:    v_mov_b32_e32 v17, v3
-; SDAG-NEXT:    v_mov_b32_e32 v16, v2
-; SDAG-NEXT:    s_andn2_b64 exec, exec, s[4:5]
-; SDAG-NEXT:    s_cbranch_execnz .LBB1_3
-; SDAG-NEXT:  ; %bb.4: ; %Flow13
-; SDAG-NEXT:    s_or_b64 exec, exec, s[4:5]
-; SDAG-NEXT:  .LBB1_5: ; %Flow14
-; SDAG-NEXT:    s_or_b64 exec, exec, s[8:9]
-; SDAG-NEXT:    v_lshl_b64 v[0:1], v[0:1], 1
-; SDAG-NEXT:    v_lshrrev_b32_e32 v10, 31, v9
-; SDAG-NEXT:    v_lshl_b64 v[8:9], v[8:9], 1
-; SDAG-NEXT:    v_or_b32_e32 v0, v0, v10
-; SDAG-NEXT:    v_or_b32_e32 v16, v3, v9
-; SDAG-NEXT:    v_or_b32_e32 v17, v2, v8
-; SDAG-NE...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list