[LLVMdev] Help with definition of subregisters; spill, rematerialization and implicit uses

Mikael Holmén mikael.holmen at ericsson.com
Fri Aug 15 03:42:06 PDT 2014


Hi,

I have a problem regarding sub-register definitions and LiveIntervals on
our target. When a subregister is defined, other parts of the register
are always left untouched - they are neither read or def:ed.

It however seems that Codegen treats subregister definitions as somehow
clobbering the whole register.

The SSA-code looks like this after isel:

(Reg0 and Reg1 are 16bit registers. Reg2, Reg3 and Reg4 are 32 bit
registers with 16bit subregs, hi16 and lo16.)

Reg0 = #imm0
Reg1 = #imm1

Reg2 = IMPLICIT_DEF
Reg3 = INSERT_SUBREG Reg2, Reg0, hi16
Reg4 = INSERT_SUBREG Reg3, Reg1, lo16

After TwoAddressInstructionPass it becomes:

Reg5:hi16<def,read-undef> = Reg0
Reg5:lo16<def>            = Reg1

So, in my world this means a setting of the high 16 bits in Reg5 (not
affecting the low part) followed by a setting of the low 16 bits (not
affecting the high part). Is this how LLVM looks at it too?

(What does the "read-undef" part really mean, since in my
world, the setting of lo16 or hi16 does not in any way affect or
access the other part of the register.)

The question is: How should true subregister definitions be
expressed so that they do not interfere with each other? See the
detailed problem description below.

---

During RA it's decided Reg5 should be spilled and it's also decided Reg5
can be rematerialized:

"Value Reg5:0 at 5000r may remat from Reg5:hi16<def,read-undef> = mv_any16
32766"

So it says Reg5 can be rematerialized by setting it's high part...

We also get:

      reload:   5052r    Reg5<def> = Load40FI <fi#2>
      rewrite: 5056r    Reg5:lo16<def> = mv_nimm6_ar16 0

So it inserts a reload of the full Reg5 prior to the setting of
Reg5:lo16, because it thinks there is an implicit use of Reg5 when
writing the low part??? This seems very weird to me.

The decision is based on the fact that MachineOperand::readsReg()
returns true:

    /// readsReg - Returns true if this operand reads the previous value
of its
    /// register.  A use operand with the <undef> flag set doesn't read its
    /// register.  A sub-register def implicitly reads the other parts 
of the
    /// register being redefined unless the <undef> flag is set.
    ///
    /// This refers to reading the register value from before the current
    /// instruction or bundle. Internal bundle reads are not included.
    bool readsReg() const {
      assert(isReg() && "Wrong MachineOperand accessor");
      return !isUndef() && !isInternalRead() && (isUse() || getSubReg());
    }

I don't get why we automatically should get an implicit use just
because we are writing a subreg.

Since Reg5:lo16 is defined with

Reg5:lo16<def>            = Reg1

isUndef() will return false and getSubReg() true, and thus readsReg()
true and the reload is inserted.

Then we get

*** Bad machine code: Instruction loads from dead spill slot ***

because the spill slot has not been written.

Most grateful for any help,
Mikael Holmén



More information about the llvm-dev mailing list