Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Event Timeline
llvm/test/CodeGen/X86/known-never-zero.ll | ||
---|---|---|
57 | I'm not sure. The transform happens in: visitCTTZ. See my comment on fshr, but I think there is some inter-dependency with the middle end that might be subtly affecting things. | |
68 | As an aside, this is a todo: Cmp(Cmov(CC, Zero, Non-Zero), Zero) should be (Cmp(CC)) | |
289 | I originally did this, but as I was working on the change I noticed we are also missing non-zero case for funnel-shift in the middle end. I filled in the middle-end case and found it was affecting the CodeGen test and figured it be best to avoid that kind of inter-dependency. Changes to ValueTracking.cpp shouldn't mess with a test in CodeGen/X86. Maybe different llc flags? |
llvm/test/CodeGen/X86/known-never-zero.ll | ||
---|---|---|
289 | CodeGenPrepare (despeculateCountZeros) is trying to prevent CTLZ/CTTZ zero-input branching from appearing, using ValueTracking's variant of isKnownNonZero I wonder if there's something other than CTTZ we could use? |
llvm/test/CodeGen/X86/known-never-zero.ll | ||
---|---|---|
289 | I see. We don't use it in many places. Let me post a patch to try and evaluate SetCC based on known bits, then we can use that. |
llvm/test/CodeGen/X86/known-never-zero.ll | ||
---|---|---|
289 |
Created: D149383, once that goes through I'll update tests to use compare against zero. |
Added fshl and fshr cases as well. But we do have:
define i32 @rotr_known_nonzero(i32 %xx, i32 %y) { ; CHECK-LABEL: rotr_known_nonzero: ; CHECK: # %bb.0: ; CHECK-NEXT: movl %esi, %ecx ; CHECK-NEXT: orl $256, %edi # imm = 0x100 ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: rorl %cl, %edi ; CHECK-NEXT: testl %edi, %edi ; CHECK-NEXT: je .LBB14_1 ; CHECK-NEXT: # %bb.2: # %cond.false ; CHECK-NEXT: rep bsfl %edi, %eax ; CHECK-NEXT: retq ; CHECK-NEXT: .LBB14_1: ; CHECK-NEXT: movl $32, %eax ; CHECK-NEXT: retq %x = or i32 %xx, 256 %shr = lshr i32 %x, %y %sub = sub i32 32, %y %shl = shl i32 %x, %sub %z = or i32 %shl, %shr %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @rotr_maybe_zero(i32 %x, i32 %y) { ; CHECK-LABEL: rotr_maybe_zero: ; CHECK: # %bb.0: ; CHECK-NEXT: movl %esi, %ecx ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: rorl %cl, %edi ; CHECK-NEXT: testl %edi, %edi ; CHECK-NEXT: je .LBB15_1 ; CHECK-NEXT: # %bb.2: # %cond.false ; CHECK-NEXT: rep bsfl %edi, %eax ; CHECK-NEXT: retq ; CHECK-NEXT: .LBB15_1: ; CHECK-NEXT: movl $32, %eax ; CHECK-NEXT: retq %shr = lshr i32 %x, %y %sub = sub i32 32, %y %shl = shl i32 %x, %sub %z = or i32 %shl, %shr %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r }
Which are generating the rotate instructions at the very least.
Any idea why we sometimes get branches and sometimes CMOV? IIRC CodeGenPrepare does attempt to determine if a CTTZ/CTLZ is non-zero?