[PATCH] D103458: [SLP]Improve gathering of scalar elements.

Guozhi Wei via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 30 11:03:57 PDT 2021


Carrot added a comment.

The problem is exactly in the merging of two undef into poison.

In our original code, the function foo is actually a class constructor, it initializes two bit fields

  entry:
     ...
     br %cond, label %then, label %bug
  
  then:
     call baz()
     br label %bug
  
  bug:
    word1 = load i64 bitfield1                          
    word1.clear = and i64 word1, mask1
    word1.set = or i64 word1.clear, value1            // set bitfield2
    store i64 word1.set, bitfield1                    // store bitfield1
    word2 = load i64 bitfiled2
    word2.clear = and i64 word2, mask2
    word2.set = or i64 word2.clear, value2           // set bitfield2
    store i64 word2.set, bitfield2                   // store bitfield2
    bar()
    ret
  
  Notice that word1 is a 64b integer which contains bitfield1 and some other bitfields, 
  since it is in constructor, these fields have not been initialized, so word1 is actually undef, 
  LLVM doesn't recognize it because there is a function call in block %then (without precise 
  alias analysis). There is similar conclusion with word2.
  
  In GVN pass, it has the knowledge that word1 must have undef value from control flow
  %entry -> %bug, so the load instruction can be deleted in this path, but not sure from the
   control flow %then -> %bug, so it must keep the load in block %then, similar analysis applies
  to word2, so it changes the IR into the form 
  
  entry:
    %nb = alloca %S, align 8
    br i1 %cond, label %then, label %bug
  
  then:
    call void @baz()
    %ptr_2 = getelementptr inbounds %S, %S* %nb, i64 0, i32 0
    %load2 = load i64, i64* %ptr_2, align 8
    %bf_1 = getelementptr inbounds %S, %S* %nb, i64 0, i32 1
    %ptr_1 = bitcast i40* %bf_1 to i64*
    %load1 = load i64, i64* %ptr_1, align 8
    br label %bug
  
  bug:
    %word1 = phi i64 [ %load1, %then ], [ undef, %entry ]
    %word2 = phi i64 [ %load2, %then ], [ undef, %entry ]
    %ptr2 = getelementptr inbounds %S, %S* %nb, i64 0, i32 0
    %word2.clear = and i64 %word2, -1152921504606846976
    %word2.set = or i64 %word2.clear, 1
    store i64 %word2.set, i64* %ptr2, align 8
    %bf1 = getelementptr inbounds %S, %S* %nb, i64 0, i32 1
    %ptr1 = bitcast i40* %bf1 to i64*
    %word1.clear = and i64 %word1, -68719476736
    %word1.set = or i64 %word1.clear, 21
    store i64 %word1.set, i64* %ptr1, align 8
    call void @bar()
    br label %exit

So the two undef values are actually correct and reasonable. But a poison value makes the code completely wrong.
According to https://llvm.org/docs/LangRef.html#poison-values, A poison value is a result of an erroneous operation.
There is no erroneous operation here.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103458/new/

https://reviews.llvm.org/D103458



More information about the llvm-commits mailing list