Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1825,8 +1825,18 @@ !match(Or1, m_OneUse(m_LogicalShift(m_Specific(ShVal), m_Value(ShAmt1))))) return nullptr; - auto ShiftOpcode0 = cast(Or0)->getOpcode(); - auto ShiftOpcode1 = cast(Or1)->getOpcode(); + auto getBinaryOperatorOrConstantExprOpcode = [](Value *V) -> unsigned { + if (auto TheBinaryOperator = dyn_cast(V)) + return unsigned(TheBinaryOperator->getOpcode()); + else if (auto TheConstExpr = dyn_cast(V)) + return TheConstExpr->getOpcode(); + else + llvm_unreachable( + "Expected Value to be either a BinaryOperator or ConstantExpr"); + }; + + auto ShiftOpcode0 = getBinaryOperatorOrConstantExprOpcode(Or0); + auto ShiftOpcode1 = getBinaryOperatorOrConstantExprOpcode(Or1); if (ShiftOpcode0 == ShiftOpcode1) return nullptr; Index: test/Transforms/InstCombine/rotate.ll =================================================================== --- test/Transforms/InstCombine/rotate.ll +++ test/Transforms/InstCombine/rotate.ll @@ -689,3 +689,17 @@ ret i24 %r } +; Test that the transform doesn't crash when there's an "or" with a ConstantExpr operand. + +@external_global = external global i8 + +define i32 @rotl_constant_expr(i32 %shamt) { +; CHECK-LABEL: @rotl_constant_expr( +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 ptrtoint (i8* @external_global to i32), [[SHAMT:%.*]] +; CHECK-NEXT: [[R:%.*]] = or i32 [[SHR]], shl (i32 ptrtoint (i8* @external_global to i32), i32 11) +; CHECK-NEXT: ret i32 [[R]] +; + %shr = lshr i32 ptrtoint (i8* @external_global to i32), %shamt + %r = or i32 %shr, shl (i32 ptrtoint (i8* @external_global to i32), i32 11) + ret i32 %r +} \ No newline at end of file