In the case of a conditional branch without a preceding cmp or similar we
used to emit a "and; cmp; b.eq/b.ne" sequence, use tbz/tbnz instead.
rdar://18783875
Differential D15122
AArch64FastISel: Use cbz/cbnz to branch on i1 MatzeB on Dec 1 2015, 10:37 AM. Authored by
Details In the case of a conditional branch without a preceding cmp or similar we rdar://18783875
Diff Detail
Event TimelineComment Actions I don't think this is quite right. The i1 content of a register is only the low bit, isn't it? This is most easily seen outside Darwin (we're the only ones that extend incoming paramters in the caller), but I think this gets miscompiled even for us: define i32 @foo(i32 %in) { entry: %val = trunc i32 %in to i1 br label %do_test do_test: %tst = phi i1 [%val, %entry] br i1 %tst, label %true, label %false true: ret i32 0 false: ret i32 1 } So I think we really do need the TBZ for correctness. Comment Actions I tried your example and even the non-fast-isel produce by "llc -march arm64 -O0" seems to use plain cbz, is this a bug? I was looking at TargetLowering::getBooleanContents() comments: "For targets without i1 registers, this gives the nature of the high-bits of boolean values held in types wider than i1." for aarch64 this is "ZeroOrOneBooleanContent". Comment Actions After discussing this with Tim, I realized that the "getBooleanContents() properties" are only guaranteed only for the usual boolean inputs of branches/selects/... and only after selection DAG legalization. So we shouldn't rely on that in the FastISel variants and I changed the code to use tbz/tbnz which should be as efficient anyway. This new version also removes a BrCond(Trunc) special case which was creating more complicated code than the default case now. (I also see no regressions on the test-suite with this patch). |