[llvm-dev] TwoAddressInstructionPass bug?

Jonas Paulsson via llvm-dev llvm-dev at lists.llvm.org
Thu Nov 30 04:04:17 PST 2017


Hi,

we are in the midst of an interesting work that begun with setting 
'guessInstructionProperties = 0' in the SystemZ backend. We have found 
this to be useful, and discovered many instructions where the 
hasSideEffects flag was incorrectly set while it actually shouldn't.

The attached patch and test case triggers an assert in TwoAddress.  
(bin/llc ./tc_TwoAddr_crash.ll -mtriple=s390x-linux-gnu -mcpu=z13)

The only change in the patch is to remove the side effects flag from one 
instruction:

-  def RISBMux : RotateSelectRIEfPseudo<GRX32, GRX32>;
+  let hasSideEffects = 0 in
+    def RISBMux : RotateSelectRIEfPseudo<GRX32, GRX32>;

The input to TwoAddress is:

BB#0: derived from LLVM BB %0
     Live Ins: %r2l
         %vreg0<def> = COPY %r2l<kill>; GR32Bit:%vreg0
         %vreg9<def,tied1> = NIFMux %vreg0<tied0>, 14, 
%cc<imp-def,dead>; GRX32Bit:%vreg9 GR32Bit:%vreg0
         %vreg4<def,tied1> = NIFMux %vreg0<tied0>, 254, 
%cc<imp-def,dead>; GRX32Bit:%vreg4 GR32Bit:%vreg0
         %vreg2<def> = COPY %vreg0<kill>; GR32Bit:%vreg2,%vreg0
         %vreg3<def> = COPY %vreg9<kill>; GR32Bit:%vreg3 GRX32Bit:%vreg9

         ...

The NIFMux instructions will be converted by the SystemZ backend into 
RISBMux instructions. The tied source operand of the RISBMux is 0 
(no-register / undef). This seems necessary as this is after 'Process 
implicit defs' pass.

The big change with the patch is that TwoAddress is now able to 
reschedule the RISBMux close to the killing instruction:

1: MBB->dump() = BB#0: derived from LLVM BB %0
     Live Ins: %r2l
         %vreg0<def> = COPY %r2l<kill>; GR32Bit:%vreg0
         %vreg4<def,tied1> = NIFMux %vreg0<tied0>, 254, 
%cc<imp-def,dead>; GRX32Bit:%vreg4 GR32Bit:%vreg0
         %vreg2<def> = COPY %vreg0; GR32Bit:%vreg2,%vreg0
         %vreg9<def,tied1> = RISBMux %noreg<tied0>, %vreg0<kill>, 28, 
158, 0; GRX32Bit:%vreg9 GR32Bit:%vreg0
         %vreg3<def> = COPY %vreg9<kill>; GR32Bit:%vreg3 GRX32Bit:%vreg9

         ...

This however means that TwoAddress will encounter this instruction once 
more as it iterates through MBB. That's when the assert triggers:

assert(SrcReg && SrcMO.isUse() && "two address instruction invalid");

It seems to me that since the %noreg makes sense (per above), and 
TwoAddress wants to schedule this instruction down the block, this 
assert is wrong here.

Should TwoAddress have a set of rescheduled instructions and not revisit 
them while iterating over MBB? Or is target allowed to actually build 
new 2-addr instructions here (seems odd)?

One alternative might be to first make a set of original instructions 
and only process them.

/Jonas



-------------- next part --------------
A non-text attachment was scrubbed...
Name: RISBMux_noSEFlag.patch
Type: text/x-patch
Size: 728 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20171130/6c2aea24/attachment.bin>
-------------- next part --------------
; ModuleID = '/home/ijonpan/llvm/llvm-dev/test/CodeGen/SystemZ/asm-18.ll'
source_filename = "/home/ijonpan/llvm/llvm-dev/test/CodeGen/SystemZ/asm-18.ll"

define i32 @f23(i32 %old) {
  %and1 = and i32 %old, 14
  %and2 = and i32 %old, 254
  %res1 = call i32 asm "stepa $1, $2, $3", "=h,r,r,0"(i32 %old, i32 %and1, i32 %and2)
  %and3 = and i32 %res1, 127
  %and4 = and i32 %res1, 128
  %res2 = call i32 asm "stepb $1, $2, $3", "=r,h,h,0"(i32 %res1, i32 %and3, i32 %and4)
  ret i32 %res2
}


More information about the llvm-dev mailing list