[llvm-dev] Ensuring chain dependencies with expansion to libcalls
Stephen Rogers via llvm-dev
llvm-dev at lists.llvm.org
Tue Feb 14 03:27:15 PST 2017
Hi all,
Our target does not have native support for 64-bit integers, so we rely on
library calls for certain operations (like sdiv). We recently ran into a
problem where these operations that are expanded to library calls aren't
maintaining the proper ordering in relation to other chains in the DAG.
The following snippet of a DAG demonstrates the problem.
t0: ch = EntryToken
t2: i64,ch,glue = CopyFromReg t0, Register:i64 %reg0
t4: i64,ch,glue = CopyFromReg t2:1, Register:i64 %reg1, t2:1
t6: i64,ch,glue = CopyFromReg t4:1, Register:i64 %reg2, t4:1
t8: i64,ch,glue = CopyFromReg t6:1, Register:i64 %reg3, t6:1
t11: ch = CopyToReg t0, Register:i64 %vreg0, t2
t13: ch = CopyToReg t0, Register:i64 %vreg1, t4
t15: ch = CopyToReg t0, Register:i64 %vreg2, t8
t26: ch = TokenFactor t11, t13, t15, t2:1, t4:1, t6:1, t8:1
t16: i64 = sdiv t2, t4
Before legalization, there is a single sdiv node. After legalization, this
has been expanded to a call sequence:
t0: ch = EntryToken
t2: i64,ch,glue = CopyFromReg t0, Register:i64 %reg0
t4: i64,ch,glue = CopyFromReg t2:1, Register:i64 %reg1, t2:1
t6: i64,ch,glue = CopyFromReg t4:1, Register:i64 %reg2, t4:1
t8: i64,ch,glue = CopyFromReg t6:1, Register:i64 %reg3, t6:1
t46: ch,glue = callseq_start t0, TargetConstant:i32<0>
t47: ch,glue = CopyToReg t46, Register:i64 %reg0, t2
t48: ch,glue = CopyToReg t47, Register:i64 %reg1, t4, t47:1
t50: ch,glue = SHAVEISD::CALL t48, TargetExternalSymbol:i32'__divdi3',
Register:i64 %reg0, Register:i64 %reg1, RegisterMask:Untyped, t48:1
t51: ch,glue = callseq_end t50, TargetConstant:i32<0>,
TargetExternalSymbol:i32'__divdi3', t50:1
t52: i64,ch,glue = CopyFromReg t51, Register:i64 %reg0, t51:1
t11: ch = CopyToReg t0, Register:i64 %vreg0, t2
t13: ch = CopyToReg t0, Register:i64 %vreg1, t4
t15: ch = CopyToReg t0, Register:i64 %vreg2, t8
t26: ch = TokenFactor t11, t13, t15, t2:1, t4:1, t6:1, t8:1
Since the sdiv node is not part of a chain, the EntryToken is used as the
starting point of the chain for the library call. This means that the
ordering between the sequence of CopyFromReg nodes and the call sequence
can be changed. Specifically, we are seeing the two copies from %reg2 and
%reg3 being moved to after the call sequence. This is a problem since the
library call clobbers both of these registers (since they are caller-saved
registers).
If I manually call __divdi3 instead of using / in the source code that
generates this DAG, then we get the following snippet:
t0: ch = EntryToken
t2: i64,ch,glue = CopyFromReg t0, Register:i64 %reg0
t4: i64,ch,glue = CopyFromReg t2:1, Register:i64 %reg1, t2:1
t6: i64,ch,glue = CopyFromReg t4:1, Register:i64 %reg2, t4:1
t8: i64,ch,glue = CopyFromReg t6:1, Register:i64 %reg3, t6:1
t9: ch = TokenFactor t2:1, t4:1, t6:1, t8:1
t19: ch,glue = callseq_start t9, TargetConstant:i32<0>
t20: ch,glue = CopyToReg t19, Register:i64 %reg0, t2
t21: ch,glue = CopyToReg t20, Register:i64 %reg1, t4, t20:1
t23: ch,glue = SHAVEISD::CALL t21, TargetGlobalAddress:i32<i64 (i64,
i64)* @__divdi3> 0, Register:i64 %reg0, Register:i64 %reg1,
RegisterMask:Untyped, t21:1
t24: ch,glue = callseq_end t23, TargetConstant:i32<0>,
TargetGlobalAddress:i32<i64 (i64, i64)* @__divdi3> 0, t23:1
t25: i64,ch,glue = CopyFromReg t24, Register:i64 %reg0, t24:1
t11: ch = CopyToReg t0, Register:i64 %vreg0, t2
t13: ch = CopyToReg t0, Register:i64 %vreg1, t4
t15: ch = CopyToReg t0, Register:i64 %vreg2, t8
t31: ch = TokenFactor t11, t13, t15, t25:1
LLVM correctly uses a TokenFactor to pull the CopyFromReg nodes together
and uses it as the input chain to the call sequence.
Is there a way that I can tell LLVM that i64 sdiv operations have
side-effects for our target and require an input chain?
Thanks,
Stephen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170214/4fe8cd3d/attachment.html>
More information about the llvm-dev
mailing list