New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ARM backend incorrectly limits smlal and umlal instructions to amv6 #18021
Comments
Assuming there's a valid reason so that the v5 version should be defined separately, should the DAG selector select them rather than the v6 version when using armv4/armv5? |
From ARM architecture reference manual, we found that v5 (and below) arches have additional constraints on these instructions:
DAGISel relies on the v5 definitions for generating correct code. However, this mechanism renders such instructions unavailable to the IAS. There's already a patch enabling SMULL/UMULL to IAS by defining InstAlias. We can do the same for MUL/MLA/SMLAL/UMLAL. Going through the .td file, I found two questions:
But only MUL is defined using class GPRnopc: def MLA : AsMul1I32<0b0000001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), let Constraints = "@earlyclobber $Rd" in
|
r199026: adds MUL/SMLAL/UMLAL aliases for ARMv4. |
mentioned in issue #19300 |
Extended Description
If I try to compile a simple test that uses inline asm to generate the smlal and umlal instructions clang fails with an error like this:
$ cat smlal.c
void sfoo(signed a, signed b) {
signed lo;
signed hi;
asm volatile ("smlal %0,%1,%2,%3" : "+&r" (lo), "+&r"(hi) : "r" (a), "r" (b));
}
void ufoo(unsigned a, unsigned b) {
unsigned lo;
unsigned hi;
asm volatile ("umlal %0,%1,%2,%3" : "+&r" (lo), "+&r"(hi) : "r" (a), "r" (b));
}
$ clang -O -march=armv4 smlal.c -c
smlal.c:5:17: error: instruction requires: armv6
asm volatile ("smlal %0,%1,%2,%3" : "+&r" (lo), "+&r"(hi) : "r" (a), "r" (b) : "cc");
^
:1:2: note: instantiated into assembly here
smlal r2,r3,r0,r1
^
smlal.c:11:17: error: instruction requires: armv6
asm volatile ("umlal %0,%1,%2,%3" : "+&r" (lo), "+&r"(hi) : "r" (a), "r" (b) : "cc");
^
:1:2: note: instantiated into assembly here
umlal r2,r3,r0,r1
If I compile with gcc or disable the integrated assembler (using -no-integrated-as), it works fine. Looking at the definition for these instructions in ARMInstrInfo.td I see this:
def SMLAL : AsMla1I64<0b0000111, (outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi), IIC_iMAC64,
"smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
RegConstraint<"$RLo = $RdLo, $RHi = $RdHi">, Requires<[IsARM, HasV6]>;
def UMLAL : AsMla1I64<0b0000101, (outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi), IIC_iMAC64,
"umlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
RegConstraint<"$RLo = $RdLo, $RHi = $RdHi">, Requires<[IsARM, HasV6]>;
Both instructions are defined with Requires<[HasV6]>, but the ARM ARM (A8.8.178) says that these instructions are available in armv4* and above (encoding A1).
I also see these definitions in the same file:
def SMLALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi, pred:$p, cc_out:$s),
4, IIC_iMAC64, [],
(SMLAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi,
pred:$p, cc_out:$s)>,
Requires<[IsARM, NoV6]>;
def UMLALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi, pred:$p, cc_out:$s),
4, IIC_iMAC64, [],
(UMLAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi,
pred:$p, cc_out:$s)>,
Requires<[IsARM, NoV6]>;
I am not sure why these are defined separately for non-v6 targets and what they are trying to model.
The text was updated successfully, but these errors were encountered: