This is an archive of the discontinued LLVM Phabricator instance.

[Mips64] Fix extension of 32-bit integer types.
AbandonedPublic

Authored by vradosavljevic on Nov 27 2015, 9:07 AM.

Details

Reviewers
dsanders
petarj
Summary

For Mips64 N32/N64 ABI, unsigned 32-bit integers should be sign extended. This patch also fixes cases where operand for truncate instruction is in another basic block.

Diff Detail

Repository
rL LLVM

Event Timeline

vradosavljevic retitled this revision from to [Mips64] Fix extension of 32-bit integer types..
vradosavljevic updated this object.
vradosavljevic added reviewers: dsanders, petarj.
vradosavljevic set the repository for this revision to rL LLVM.
vradosavljevic added a subscriber: llvm-commits.

TruncNoExt node is used for values smaller than 32bit, where we don't need to do sign extension.

dsanders edited edge metadata.Nov 27 2015, 11:14 AM
dsanders added a subscriber: vkalintiris.

Could you point me at the original problem you're trying to solve? The new node appears to be doing the same job as AssertZExt and I'm fairly certain this is headed into a bigger problem we encountered back in spring.

The summary of the larger bug is that MIPS64 lacks a 32-bit comparison instruction (the same opcode performs a 64-bit comparison) but the code generator isn't properly aware of this. As a result, the code generator expects the hardware to ignore bits 32-63 but they actually affect the result. This bug gets exposed as we increase our reliance on the code generator getting it right by removing the redundant extends.

@vkalintiris has been working on a fix to the larger problem (D10970 and a second part to handle the operands). Once both are committed we should be able to safely remove any redundant sign extends that remain.

lib/Target/Mips/MipsISelLowering.cpp
2909–2910

Our calling convention doesn't really matter at this point since clang is responsible for emitting appropriate signext/zeroext for the given ABI. We just need to follow what the IR says.

2927–2933

AssertZext already eliminates any extends the the TRUNCATE would otherwise introduce. I suspect something else in the DAG is causing the sign extends you're trying to remove.

test/CodeGen/Mips/divrem.ll
76–186

Please leave these as zeroext. They use zeroext to avoid noise around the interesting generated code and there's no need to match the standard ABI in this kind of test.

test/CodeGen/Mips/mips64-sign-extend.ll
6

This will match any i32->i64 sign extend in the output file, even in different functions. You need some CHECK-LABEL's to restrict the scope of the matching.

31

As above, this could match in any function.

38–45

These CHECK-NOT's don't do what you expect if the earlier CHECK's match in an unexpected function.

test/CodeGen/Mips/octeon_popcnt.ll
24

Please leave these as zeroext. They use zeroext to avoid noise around the interesting generated code and there's no need to match the standard ABI in this kind of test.

Could you point me at the original problem you're trying to solve? The new node appears to be doing the same job as AssertZExt and I'm fairly certain this is headed into a bigger problem we encountered back in spring.

Original problem is where operand for truncate instruction is in another basic block (foo1 function in mips64-sign-extend.ll). SelectionDAG for this case (AssertZext node was created in SelectionDAGBuilder.cpp (RegsForValue::getCopyFromRegs)):

Optimized legalized selection DAG: BB#1 'foo:if.then'
SelectionDAG has 13 nodes:
  t0: ch = EntryToken
            t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
          t4: i64 = AssertZext t2, ValueType:ch:i32
        t5: i32 = truncate t4
      t20: i32 = setcc t5, Constant:i32<-1>, setgt:ch
    t12: ch = brcond t0, t20, BasicBlock:ch<if.else 0x14ad3e0>
  t14: ch = br t12, BasicBlock:ch<if.then4 0x14ad318>

In this case, we need to do sign extension for (trunc (assertzext GPR64:$src)), so I changed this pattern to do sign extension. After this change, for arguments zeroext i1, zeroext i8 and zeroext i16, we got redundant SLL instruction. TruncNoExt node is used to prevent generating SLL instruction in these cases.

This is the same problem Vasileios ran into when he removed some redundant sign extends. The root of the problem is that the legalized SelectionDAG isn't actually legal for MIPS64 since we don't have any 32-bit comparison operations (setlt and friends compare GPR-width values and produce a GPR-width 0 or 1). The legalizer should be promoting both the operands and result of the setcc to i64 which will result in the following DAG:

t0: ch = EntryToken
            t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
          t4: i64 = AssertZext t2, ValueType:ch:i32
        t5: i32 = truncate t4
      t6: i64 = sext t5
    t20: i64 = setcc t6, Constant:i64<-1>, setgt:ch
  t12: ch = brcond t0, t20, BasicBlock:ch<if.else 0x14ad3e0>
t14: ch = br t12, BasicBlock:ch<if.then4 0x14ad318>

the t6: i64 = sext t5 will then lead to a sll instruction.

One other thing to mention is that the redundant SLL instructions you mention in:

After this change, for arguments zeroext i1, zeroext i8 and zeroext i16, we got redundant SLL instruction.

are needed to promote the i8 to an i32 (which as noted above, should be an i64) for use in the signed comparison.

This is the same problem Vasileios ran into when he removed some redundant sign extends. The root of the problem is that the legalized SelectionDAG isn't actually legal for MIPS64 since we don't have any 32-bit comparison operations (setlt and friends compare GPR-width values and produce a GPR-width 0 or 1). The legalizer should be promoting both the operands and result of the setcc to i64 which will result in the following DAG:

I applied D10970, but i got compiler error:
llvm/lib/Target/Mips/Mips64r6InstrInfo.td:134:11: error: Couldn't find multiclass 'Cmp_Pats'

What should we do about the problem where operand for truncate instruction is in another basic block?

This is the same problem Vasileios ran into when he removed some redundant sign extends. The root of the problem is that the legalized SelectionDAG isn't actually legal for MIPS64 since we don't have any 32-bit comparison operations (setlt and friends compare GPR-width values and produce a GPR-width 0 or 1). The legalizer should be promoting both the operands and result of the setcc to i64 which will result in the following DAG:

I applied D10970, but i got compiler error:
llvm/lib/Target/Mips/Mips64r6InstrInfo.td:134:11: error: Couldn't find multiclass 'Cmp_Pats'

You'll have to apply D14612 first. I updated the list of dependencies in D10970 to reflect that.

This is the same problem Vasileios ran into when he removed some redundant sign extends. The root of the problem is that the legalized SelectionDAG isn't actually legal for MIPS64 since we don't have any 32-bit comparison operations (setlt and friends compare GPR-width values and produce a GPR-width 0 or 1). The legalizer should be promoting both the operands and result of the setcc to i64 which will result in the following DAG:

I applied D10970, but i got compiler error:
llvm/lib/Target/Mips/Mips64r6InstrInfo.td:134:11: error: Couldn't find multiclass 'Cmp_Pats'

It depends on D14612 so you need to apply that first.

What should we do about the problem where operand for truncate instruction is in another basic block?

It's the same issue, the sign extend is missing because our legalized SelectionDAG is actually illegal for MIPS64. It will be fixed by promoting the setcc to i64.

It depends on D14612 so you need to apply that first.

Nearly forgot to say: This patch is only half the solution. We also need to promote the operands of setcc nodes.