Booleans should be extended based on the target's BooleanContent otherwise
always sign extending a 1 bit boolean results in making its value negative.
Details
- Reviewers
t.p.northover kristof.beyls apazos
Diff Detail
- Repository
- rL LLVM
Event Timeline
Here's the failing test case:
cat a.mir
--- |
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--"
define void @test_constant() {
entry:
ret void
}
...
---
name: test_constant
registers:
- { id: 0, class: _ }
body: |
bb.0.entry:
%0:_(s1) = G_CONSTANT i1 1
%1:_(s32) = COPY %0(s1)llc -O0 -run-pass=legalizer a.mir -o -
bb.0.entry:
%2:_(s32) = G_CONSTANT i32 -1
%0:_(s1) = G_TRUNC %2(s32)
%1:_(s32) = COPY %0(s1)MachineIRBuilder.cpp was the only place I could find to intercept the boolean val and zext it. Please let me know if this isn't the proper place to fix this.
| lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | ||
|---|---|---|
| 269–272 | This depends on the TargetBooleanContents | |
This doesn't seem right.
getBooleanContents specifically describes the results and operands for a certain set of DAG operations which require values that are either true or false, but are not represented using i1 after legalization. So we're talking about the result of ISD::SETCC, the condition operand of ISD::SELECT, etc. In SelectionDAG, this set of operations are legalized using PromoteTargetBoolean. (I'm assuming GlobalISel follows similar rules, although I can't find any documentation.)
This general rule does not apply to arbitrary i1 values. When an i1 is stored to memory, it is always zero-extended. And for other operations (logic operations, PHI nodes, etc), the high bits are undefined.
Given that, messing with MachineIRBuilder::buildConstant does nothing useful: you're just hiding a bug that could be exposed by producing a boolean some other way. For example, "trunc i8 %z to i1" gets legalized to a no-op with both SelectionDAG isel and GlobalISel.
This depends on the TargetBooleanContents