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