LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 49509 - [PowerPC] Infinite loop in PeepholeCROps
Summary: [PowerPC] Infinite loop in PeepholeCROps
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Backend: PowerPC (show other bugs)
Version: trunk
Hardware: PC Linux
: P enhancement
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
Depends on:
Blocks: release-12.0.0
  Show dependency tree
 
Reported: 2021-03-10 05:13 PST by Nikita Popov
Modified: 2021-03-29 16:55 PDT (History)
4 users (show)

See Also:
Fixed By Commit(s): 2489cbaa8057c736475fd88990f4f6dbf022873d 8ca56905dd9b


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nikita Popov 2021-03-10 05:13:44 PST
; RUN: llc -O2 < %s

target datalayout = "E-m:e-p:32:32-i64:64-n32"
target triple = "powerpc-unknown-linux-gnu"

define void @test() {
bb:
  br i1 undef, label %bb2, label %bb1

bb2:                                              ; preds = %bb
  %i = select i1 undef, i64 0, i64 72057594037927936
  store i64 %i, i64* undef, align 8
  ret void

bb1:                                              ; preds = %bb
  %i50 = load i8, i8* undef, align 8
  %i52 = load i128, i128* null, align 8
  %i62 = icmp eq i8 %i50, 0
  br i1 undef, label %bb66, label %bb64

bb64:                                             ; preds = %bb63
  ret void

bb66:                                             ; preds = %bb63
  %i67 = lshr i128 -1, 0
  %i68 = xor i128 %i52, -1
  %i69 = add i128 0, %i68
  %i70 = and i128 %i67, %i69
  %i71 = icmp eq i128 %i70, 0
  %i74 = select i1 %i62, i64 0, i64 72057594037927936
  %i75 = select i1 %i71, i64 144115188075855872, i64 %i74
  store i64 %i75, i64* undef, align 8
  ret void
}

This enters an infinite combine loop inside PPCDAGToDAGISel::PeepholeCROps().
Comment 1 Nikita Popov 2021-03-10 05:19:45 PST
DAG:

Optimized legalized selection DAG: %bb.4 'test:bb66'
SelectionDAG has 30 nodes:
  t0: ch = EntryToken
  t4: i32,ch = CopyFromReg t0, Register:i32 %0
  t20: i1,ch = CopyFromReg t0, Register:i1 %4
  t6: i32,ch = CopyFromReg t4:1, Register:i32 %1
  t8: i32,ch = CopyFromReg t6:1, Register:i32 %2
      t10: i32,ch = CopyFromReg t8:1, Register:i32 %3
    t37: i32 = and t10, t6
    t38: i32 = and t8, t4
  t39: i32 = and t37, t38
          t41: i32 = select t20, Constant:i32<0>, OpaqueConstant:i32<16777216>
        t48: i32 = select_cc t39, Constant:i32<-1>, Constant:i32<33554432>, t41, seteq:ch
      t44: ch = store<(store 4 into `i64* undef`, align 8)> t0, t48, undef:i32, undef:i32
            t29: i1 = setcc t39, Constant:i32<-1>, seteq:ch
          t49: i1 = or t29, t20
        t50: i32 = select t49, Constant:i32<0>, OpaqueConstant:i32<0>
      t46: ch = store<(store 4 into `i64* undef` + 4, basealign 8)> t0, t50, undef:i32, undef:i32
    t47: ch = TokenFactor t44, t46
  t28: ch = PPCISD::RET_FLAG t47

Start of the peephole combine loop:

===== Instruction selection ends:
Creating new machine node: t64: i1 = CRNOR t29, t20
CR Peephole replacing:
Old:    t50: i32 = SELECT_I4 t49, t34, t34

New: t50: i32 = SELECT_I4 t49, t34, t34

CR Peephole replacing:
Old:    t49: i1 = CROR t29, t20

New: t64: i1 = CRNOR t29, t20

CR Peephole replacing:
Old:    t50: i32 = SELECT_I4 t64, t34, t34

New: t50: i32 = SELECT_I4 t64, t34, t34

CR Peephole replacing:
Old:    t64: i1 = CRNOR t29, t20

New: t49: i1 = CROR t29, t20

Creating new machine node: t65: i1 = CRNOR t29, t20
CR Peephole replacing:
Old:    t50: i32 = SELECT_I4 t49, t34, t34

New: t50: i32 = SELECT_I4 t49, t34, t34

CR Peephole replacing:
Old:    t49: i1 = CROR t29, t20

New: t65: i1 = CRNOR t29, t20

CR Peephole replacing:
Old:    t50: i32 = SELECT_I4 t65, t34, t34

New: t50: i32 = SELECT_I4 t65, t34, t34

CR Peephole replacing:
Old:    t65: i1 = CRNOR t29, t20

New: t49: i1 = CROR t29, t20
Comment 2 Nikita Popov 2021-03-10 05:36:40 PST
Here's the DAG when entering PeepholeCROps:

SelectionDAG has 38 nodes:
  t0: ch = EntryToken
  t34: i32 = LI TargetConstant:i32<0>
  t4: i32,ch = CopyFromReg t0, Register:i32 %0
  t20: i1,ch = CopyFromReg t0, Register:i1 %4
  t6: i32,ch = CopyFromReg t4:1, Register:i32 %1
  t8: i32,ch = CopyFromReg t6:1, Register:i32 %2
      t10: i32,ch = CopyFromReg t8:1, Register:i32 %3
    t37: i32 = AND t10, t6
    t38: i32 = AND t8, t4
  t39: i32 = AND t37, t38
  t60: i32 = TargetConstant<16777216>
  t62: i32 = TargetConstant<33554432>
          t58: i32 = CMPWI t39, TargetConstant:i32<65535>
          t31: i32 = LIS TargetConstant:i32<512>
            t35: i32 = LIS TargetConstant:i32<256>
          t41: i32 = SELECT_I4 t20, t34, t35
        t48: i32 = SELECT_CC_I4 t58, t31, t41, TargetConstant:i32<76>
      t44: ch = STW<Mem:(store 4 into `i64* undef`, align 8)> t48, TargetConstant:i32<0>, IMPLICIT_DEF:i32, t0
              t55: i32 = CMPWI t39, TargetConstant:i32<-1>
            t29: i1 = EXTRACT_SUBREG t55, TargetConstant:i32<3>
          t49: i1 = CROR t29, t20
        t50: i32 = SELECT_I4 t49, t34, t34
      t46: ch = STW<Mem:(store 4 into `i64* undef` + 4, basealign 8)> t50, TargetConstant:i32<0>, IMPLICIT_DEF:i32, t0
    t47: ch = TokenFactor t44, t46
  t28: ch = BLR t47

With the problematic part being:

  t34: i32 = LI TargetConstant:i32<0>
  t49: i1 = CROR t29, t20
t50: i32 = SELECT_I4 t49, t34, t34

The transform converts select x, y, y into select !x, y, y swapping the select operands, but of course that doesn't actually do anything if they're equal. And then we can convert that back to select x, y, y etc.
Comment 3 Nikita Popov 2021-03-10 05:48:51 PST
Candidate patch: https://reviews.llvm.org/D98340
Comment 5 Tom Stellard 2021-03-29 16:55:44 PDT
Merged: 8ca56905dd9b