[PATCH] D140087: [X86] Replace (31/63 -/^ X) with (NOT X) and ignore (32/64 ^ X) when computing shift count

Noah Goldstein via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 29 08:08:12 PST 2022


goldstein.w.n added a comment.

In D140087#4019429 <https://reviews.llvm.org/D140087#4019429>, @lebedev.ri wrote:

> Alive2 doesn't deal with assembly/dag, only ir.
> I'm asking you to write the proofs for these changes via an IR tests,
> explicitly modelling the implicit modulo of the shift amount, which isn't a thing in IR.

I see. Sorry about that. How about the following:

in.ll:

  define i32 @foo32_(i32 %val, i32 %cnt) {
    %adjcnt = sub i32 31, %cnt
    %result = shl i32 %val, %adjcnt
    ret i32 %result
  }
  
  define i32 @foo32_2(i32 %val, i32 %cnt) {
    %adjcnt = xor i32 31, %cnt
    %result = shl i32 %val, %adjcnt
    ret i32 %result
  }
  
      
  define i32 @foo32_3(i32 %val, i32 %cnt) {
    %adjcnt = xor i32 32, %cnt
    %result = shl i32 %val, %adjcnt
    ret i32 %result
  }
  
  define i64 @foo64_(i64 %val, i64 %cnt) {
    %adjcnt = sub i64 63, %cnt
    %result = shl i64 %val, %adjcnt
    ret i64 %result
  }
  
  define i64 @foo64_2(i64 %val, i64 %cnt) {
    %adjcnt = xor i64 63, %cnt
    %result = shl i64 %val, %adjcnt
    ret i64 %result
  }
  
      
  define i64 @foo64_3(i64 %val, i64 %cnt) {
    %adjcnt = xor i64 64, %cnt
    %result = shl i64 %val, %adjcnt
    ret i64 %result
  }

out.ll

  define i32 @foo32_(i32 %val, i32 %cnt) {
    %adjcnt = xor i32 -1, %cnt
    %shiftcnt = and i32 31, %adjcnt
    %result = shl i32 %val, %shiftcnt
    ret i32 %result
  }
  
  define i32 @foo32_2(i32 %val, i32 %cnt) {
    %adjcnt = xor i32 -1, %cnt
    %shiftcnt = and i32 31, %adjcnt
    %result = shl i32 %val, %shiftcnt
    ret i32 %result
  }
  
  define i32 @foo32_3(i32 %val, i32 %cnt) {
    %shiftcnt = and i32 31, %cnt
    %result = shl i32 %val, %shiftcnt
    ret i32 %result
  }
  
  
  define i64 @foo64_(i64 %val, i64 %cnt) {
    %adjcnt = xor i64 -1, %cnt
    %shiftcnt = and i64 63, %adjcnt
    %result = shl i64 %val, %shiftcnt
    ret i64 %result
  }
  
  define i64 @foo64_2(i64 %val, i64 %cnt) {
    %adjcnt = xor i64 -1, %cnt
    %shiftcnt = and i64 63, %adjcnt
    %result = shl i64 %val, %shiftcnt
    ret i64 %result
  }
  
  define i64 @foo64_3(i64 %val, i64 %cnt) {
    %shiftcnt = and i64 63, %cnt
    %result = shl i64 %val, %shiftcnt
    ret i64 %result
  }

Running:

  $> /home/noah/programs/opensource/llvm-dev/src/alive2/build/alive-tv in.ll out.ll 
  ----------------------------------------
  define i32 @foo32_(i32 %val, i32 %cnt) {
  %0:
    %adjcnt = sub i32 31, %cnt
    %result = shl i32 %val, %adjcnt
    ret i32 %result
  }
  =>
  define i32 @foo32_(i32 %val, i32 %cnt) {
  %0:
    %adjcnt = xor i32 4294967295, %cnt
    %shiftcnt = and i32 31, %adjcnt
    %result = shl i32 %val, %shiftcnt
    ret i32 %result
  }
  Transformation seems to be correct!
  
  
  ----------------------------------------
  define i32 @foo32_2(i32 %val, i32 %cnt) {
  %0:
    %adjcnt = xor i32 31, %cnt
    %result = shl i32 %val, %adjcnt
    ret i32 %result
  }
  =>
  define i32 @foo32_2(i32 %val, i32 %cnt) {
  %0:
    %adjcnt = xor i32 4294967295, %cnt
    %shiftcnt = and i32 31, %adjcnt
    %result = shl i32 %val, %shiftcnt
    ret i32 %result
  }
  Transformation seems to be correct!
  
  
  ----------------------------------------
  define i32 @foo32_3(i32 %val, i32 %cnt) {
  %0:
    %adjcnt = xor i32 32, %cnt
    %result = shl i32 %val, %adjcnt
    ret i32 %result
  }
  =>
  define i32 @foo32_3(i32 %val, i32 %cnt) {
  %0:
    %shiftcnt = and i32 31, %cnt
    %result = shl i32 %val, %shiftcnt
    ret i32 %result
  }
  Transformation seems to be correct!
  
  
  ----------------------------------------
  define i64 @foo64_(i64 %val, i64 %cnt) {
  %0:
    %adjcnt = sub i64 63, %cnt
    %result = shl i64 %val, %adjcnt
    ret i64 %result
  }
  =>
  define i64 @foo64_(i64 %val, i64 %cnt) {
  %0:
    %adjcnt = xor i64 -1, %cnt
    %shiftcnt = and i64 63, %adjcnt
    %result = shl i64 %val, %shiftcnt
    ret i64 %result
  }
  Transformation seems to be correct!
  
  
  ----------------------------------------
  define i64 @foo64_2(i64 %val, i64 %cnt) {
  %0:
    %adjcnt = xor i64 63, %cnt
    %result = shl i64 %val, %adjcnt
    ret i64 %result
  }
  =>
  define i64 @foo64_2(i64 %val, i64 %cnt) {
  %0:
    %adjcnt = xor i64 -1, %cnt
    %shiftcnt = and i64 63, %adjcnt
    %result = shl i64 %val, %shiftcnt
    ret i64 %result
  }
  Transformation seems to be correct!
  
  
  ----------------------------------------
  define i64 @foo64_3(i64 %val, i64 %cnt) {
  %0:
    %adjcnt = xor i64 64, %cnt
    %result = shl i64 %val, %adjcnt
    ret i64 %result
  }
  =>
  define i64 @foo64_3(i64 %val, i64 %cnt) {
  %0:
    %shiftcnt = and i64 63, %cnt
    %result = shl i64 %val, %shiftcnt
    ret i64 %result
  }
  Transformation seems to be correct!
  
  Summary:
    6 correct transformations
    0 incorrect transformations
    0 failed-to-prove transformations
    0 Alive2 errors


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140087



More information about the llvm-commits mailing list