[LLVMdev] MachineSink and EFLAGS

Jakob Stoklund Olesen stoklund at 2pi.dk
Sun Jun 5 10:24:42 PDT 2011


Thanks for spelling it out, now I understand.

On Jun 5, 2011, at 6:11 AM, Galanov, Sergey wrote:

> Well, the point is CMOV_GR* are marked clobbering EFLAGS conservatively just in case they turn out to be lowered into a sequence containing XOR %reg,%reg which indeed clobbers EFLAGS. This means there might not be any instruction which actually uses this EFLAGS value.

This actually looks like a leftover from some older code. EmitLoweredSelect() will never insert an xor, it just creates a branch+phi instruction. It is true that a 0 phi argument could eventually be rematerialized as an xor instruction, but X86InstrInfo::reMaterialize() checks checks for this and uses a mov instead if EFLAGS is live.

> For an example we can look no further than the actual test which has been disabled after the fix (llvm/test/Codegen/X86/sink-hoist.ll, function zzz). 
> 
> BB#0: derived from LLVM BB %entry
> 	%vreg0<def> = MOV8rm <fi#-2>, 1, %noreg, 0, %noreg; mem:LD1[FixedStack-2](align=4) GR8:%vreg0
> 	%vreg1<def> = AND8ri %vreg0, 127, %EFLAGS<imp-def,dead>; GR8:%vreg1,%vreg0
> 	%vreg2<def> = OR8ri %vreg0, -128, %EFLAGS<imp-def,dead>; GR8:%vreg2,%vreg0
> 	CMP8mi <fi#-1>, 1, %noreg, 0, %noreg, 0, %EFLAGS<imp-def>; mem:LD1[FixedStack-1](align=8)
> 	%vreg3<def> = CMOV_GR8 %vreg2<kill>, %vreg1<kill>, 4, %EFLAGS<imp-def,dead>, %EFLAGS<imp-use>; GR8:%vreg3,%vreg2,%vreg1
> 	%vreg4<def> = MOVZX32rr8 %vreg3<kill>; GR32:%vreg4 GR8:%vreg3
> 	%EAX<def> = COPY %vreg4; GR32:%vreg4
> 	RET
> 
> CMOV_GR8 instruction has EFLAGS use which is not marked kill, and that's why EFLAGS is marked live-in in the new blocks created when lowering the pseudo cmov. But besides that it also has an imp-def of EFLAGS marked dead. How can an instruction use and define the same register with def being dead and use not being killed? I believe this is happening just because proper liveness information is not calculated at that point, but anyway we can treat EFLAGS as if it was marked killed in this case, can't we?

You are exactly right.

> So this is precisely my proposal: don't mark EFLAGS live-in in the new blocks in EmitLoweredSelect if EFLAGS is a dead def of the pseudo cmov.

That would work. Alternatively, don't mark the CMOV pseudos as clobbering EFLAGS, because they really don't. This would give the scheduler more freedom when the flags have multiple users.

We only have primitive liveness information before register allocation, so sometimes kill flags are missing. If you remove the EFLAGS clobber, you should check if the kill flag appears. If it doesn't, try to find out why it is missing.

Thanks for looking into this,
/jakob





More information about the llvm-dev mailing list