================
@@ -1488,6 +1488,61 @@ static bool SinkCast(CastInst *CI) {
   return MadeChange;
 }
 
+/// Hoists bitcasts to the source block to reduce register pressure
+static bool optimizeBitCast(BitCastInst *BCI, const TargetLowering &TLI,
+                            const DataLayout &DL) {
+  auto *SrcInst = dyn_cast<Instruction>(BCI->getOperand(0));
+  if (!SrcInst || SrcInst->getParent() == BCI->getParent() ||
+      SrcInst->isTerminator())
+    return false;
+
+  EVT SrcVT = TLI.getValueType(DL, SrcInst->getType());
+  EVT DestVT = TLI.getValueType(DL, BCI->getType());
+
+  // Bail out on scalable vectors and illegal destination types
+  if (SrcVT.isScalableVector() || DestVT.isScalableVector() ||
+      !TLI.isTypeLegal(DestVT))
+    return false;
+
+  // Only hoist if it reduces physical register count
+  if (TLI.getNumRegisters(BCI->getContext(), SrcVT) <=
+      TLI.getNumRegisters(BCI->getContext(), DestVT))
+    return false;
+
+  // Prevent large cross-domain scalar hoists
+  Type *DestTy = BCI->getType();
+  Type *SrcTy = SrcInst->getType();
+  bool IsCrossDomain = DestTy->isFPOrFPVectorTy() != SrcTy->isFPOrFPVectorTy();
+  bool IsLargeScalar = !DestTy->isVectorTy() &&
+                       DL.getTypeSizeInBits(DestTy).getFixedValue() > 64;
+  if (IsCrossDomain && IsLargeScalar)
+    return false;
+
+  // SelectionDAG Guard to prevent breaking atomic loop layout
+  auto IsAtomic = [](const Value *V) {
+    const auto *I = dyn_cast<Instruction>(V);
+    return I && I->isAtomic();
+  };
----------------
houngkoungting wrote:

Hi @RKSimon,

Sorry for the delay due to the typhoon. I took some time to isolate the exact 
impact of dropping this atomic guard on "X86/atomic-non-integer.ll". 

Without this blocker, the middle-end prematurely hoists the implicit bitcast 
logic. 

32-bit x86 targets ("X86-SSE1" and "X86-NOSSE") severely lack 64-bit GPRs. 
Also, the hardware rigidly binds "lock cmpxchg8b" to the "EDX:EAX" register 
pair. 
This premature hoisting creates severe register pressure, breaks the liveness 
chain, and results in bad register allocation.

As a result, the backend instruction scheduler is forced to drag the entire x87 
stack transfers ("fstp/fldl") and memory stores ("movl") directly into the hot 
retry loop body (".LBB8_1") across both subtargets:

```
@@ -440,15 +440,17 @@ define double @exchange_double(ptr %fptr, double %x) {
 ; X86-SSE1-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 ; X86-SSE1-NEXT:    movl (%esi), %eax
 ; X86-SSE1-NEXT:    movl 4(%esi), %edx
+; X86-SSE1-NEXT:    fldz
 ; X86-SSE1-NEXT:    .p2align 4
 ; X86-SSE1-NEXT:  .LBB8_1: # %atomicrmw.start
 ; X86-SSE1-NEXT:    # =>This Inner Loop Header: Depth=1
+; X86-SSE1-NEXT:    fstp %st(0)
 ; X86-SSE1-NEXT:    lock cmpxchg8b (%esi)
-; X86-SSE1-NEXT:    jne .LBB8_1
-; X86-SSE1-NEXT:  # %bb.2: # %atomicrmw.end
-; X86-SSE1-NEXT:    movl %eax, (%esp)
 ; X86-SSE1-NEXT:    movl %edx, {{[0-9]+}}(%esp)
+; X86-SSE1-NEXT:    movl %eax, (%esp)    # Injected inside loop (RAW!!!!!!)
 ; X86-SSE1-NEXT:    fldl (%esp)
+; X86-SSE1-NEXT:    jne .LBB8_1          # Loop boundary expanded down here
+; X86-SSE1-NEXT:  # %bb.2: # %atomicrmw.end
 ; X86-SSE1-NEXT:    addl $12, %esp
 ; X86-SSE1-NEXT:    .cfi_def_cfa_offset 12
 ; X86-SSE1-NEXT:    popl %esi

https://github.com/llvm/llvm-project/pull/207568
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to