Index: lib/Analysis/DemandedBits.cpp =================================================================== --- lib/Analysis/DemandedBits.cpp +++ lib/Analysis/DemandedBits.cpp @@ -142,6 +142,21 @@ std::min(BitWidth, Known.countMaxTrailingZeros()+1)); } break; + case Intrinsic::fshl: + case Intrinsic::fshr: + if (auto *SA = dyn_cast(II->getOperand(2))) { + // Normalize to funnel shift left. APInt shifts of BitWidth are well- + // defined, so no need to special-case zero shifts here. + uint64_t ShiftAmt = SA->getValue().urem(BitWidth); + if (II->getIntrinsicID() == Intrinsic::fshr) + ShiftAmt = BitWidth - ShiftAmt; + + if (OperandNo == 0) + AB = AOut.lshr(ShiftAmt); + else if (OperandNo == 1) + AB = AOut.shl(BitWidth - ShiftAmt); + } + break; } break; case Instruction::Add: Index: test/Analysis/DemandedBits/intrinsics.ll =================================================================== --- test/Analysis/DemandedBits/intrinsics.ll +++ test/Analysis/DemandedBits/intrinsics.ll @@ -23,3 +23,54 @@ } declare i32 @llvm.bitreverse.i32(i32) +; Funnel shifts +declare i32 @llvm.fshl.i32(i32, i32, i32) +declare i32 @llvm.fshr.i32(i32, i32, i32) + +; CHECK-DAG: DemandedBits: 0xff for %x2 = or i32 %x, 1 +; CHECK-DAG: DemandedBits: 0xff000000 for %y2 = or i32 %y, 1 +; CHECK-DAG: DemandedBits: 0xffff for %z = call i32 @llvm.fshl.i32(i32 %x2, i32 %y2, i32 8) +; CHECK-DAG: DemandedBits: 0xffffffff for %r = and i32 %z, 65535 +define i32 @test_fshl(i32 %x, i32 %y) { + %x2 = or i32 %x, 1 + %y2 = or i32 %y, 1 + %z = call i32 @llvm.fshl.i32(i32 %x2, i32 %y2, i32 8) + %r = and i32 %z, 65535 + ret i32 %r +} + +; CHECK-DAG: DemandedBits: 0xff for %x2 = or i32 %x, 1 +; CHECK-DAG: DemandedBits: 0xff000000 for %y2 = or i32 %y, 1 +; CHECK-DAG: DemandedBits: 0xffff for %z = call i32 @llvm.fshr.i32(i32 %x2, i32 %y2, i32 24) +; CHECK-DAG: DemandedBits: 0xffffffff for %r = and i32 %z, 65535 +define i32 @test_fshr(i32 %x, i32 %y) { + %x2 = or i32 %x, 1 + %y2 = or i32 %y, 1 + %z = call i32 @llvm.fshr.i32(i32 %x2, i32 %y2, i32 24) + %r = and i32 %z, 65535 + ret i32 %r +} + +; CHECK-DAG: DemandedBits: 0xffff for %x2 = or i32 %x, 1 +; CHECK-DAG: DemandedBits: 0x0 for %y2 = or i32 %y, 1 +; CHECK-DAG: DemandedBits: 0xffff for %z = call i32 @llvm.fshl.i32(i32 %x2, i32 %y2, i32 0) +; CHECK-DAG: DemandedBits: 0xffffffff for %r = and i32 %z, 65535 +define i32 @test_fshl_zero_shift(i32 %x, i32 %y) { + %x2 = or i32 %x, 1 + %y2 = or i32 %y, 1 + %z = call i32 @llvm.fshl.i32(i32 %x2, i32 %y2, i32 0) + %r = and i32 %z, 65535 + ret i32 %r +} + +; CHECK-DAG: DemandedBits: 0x0 for %x2 = or i32 %x, 1 +; CHECK-DAG: DemandedBits: 0xffff for %y2 = or i32 %y, 1 +; CHECK-DAG: DemandedBits: 0xffff for %z = call i32 @llvm.fshr.i32(i32 %x2, i32 %y2, i32 32) +; CHECK-DAG: DemandedBits: 0xffffffff for %r = and i32 %z, 65535 +define i32 @test_fshr_full_shift(i32 %x, i32 %y) { + %x2 = or i32 %x, 1 + %y2 = or i32 %y, 1 + %z = call i32 @llvm.fshr.i32(i32 %x2, i32 %y2, i32 32) + %r = and i32 %z, 65535 + ret i32 %r +}