@@ -697,3 +697,250 @@ llvm.func @transitive_reaching_def() -> !llvm.ptr {
697697 %3 = llvm.load %1 {alignment = 8 : i64 } : !llvm.ptr -> !llvm.ptr
698698 llvm.return %3 : !llvm.ptr
699699}
700+
701+ // -----
702+
703+ // CHECK-LABEL: @load_int_from_float
704+ llvm.func @load_int_from_float () -> i32 {
705+ %0 = llvm.mlir.constant (1 : i32 ) : i32
706+ // CHECK-NOT: llvm.alloca
707+ %1 = llvm.alloca %0 x f32 {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
708+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> i32
709+ // CHECK: %[[UNDEF:.*]] = llvm.mlir.undef
710+ // CHECK: %[[BITCAST:.*]] = llvm.bitcast %[[UNDEF]] : f32 to i32
711+ // CHECK: llvm.return %[[BITCAST:.*]]
712+ llvm.return %2 : i32
713+ }
714+
715+ // -----
716+
717+ // CHECK-LABEL: @load_float_from_int
718+ llvm.func @load_float_from_int () -> f32 {
719+ %0 = llvm.mlir.constant (1 : i32 ) : i32
720+ // CHECK-NOT: llvm.alloca
721+ %1 = llvm.alloca %0 x i32 {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
722+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> f32
723+ // CHECK: %[[UNDEF:.*]] = llvm.mlir.undef
724+ // CHECK: %[[BITCAST:.*]] = llvm.bitcast %[[UNDEF]] : i32 to f32
725+ // CHECK: llvm.return %[[BITCAST:.*]]
726+ llvm.return %2 : f32
727+ }
728+
729+ // -----
730+
731+ // CHECK-LABEL: @load_int_from_vector
732+ llvm.func @load_int_from_vector () -> i32 {
733+ %0 = llvm.mlir.constant (1 : i32 ) : i32
734+ // CHECK-NOT: llvm.alloca
735+ %1 = llvm.alloca %0 x vector <2 xi16 > : (i32 ) -> !llvm.ptr
736+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> i32
737+ // CHECK: %[[UNDEF:.*]] = llvm.mlir.undef
738+ // CHECK: %[[BITCAST:.*]] = llvm.bitcast %[[UNDEF]] : vector<2xi16> to i32
739+ // CHECK: llvm.return %[[BITCAST:.*]]
740+ llvm.return %2 : i32
741+ }
742+
743+ // -----
744+
745+ // LLVM arrays cannot be bitcasted, so the following cannot be promoted.
746+
747+ // CHECK-LABEL: @load_int_from_array
748+ llvm.func @load_int_from_array () -> i32 {
749+ %0 = llvm.mlir.constant (1 : i32 ) : i32
750+ // CHECK: llvm.alloca
751+ %1 = llvm.alloca %0 x !llvm.array <2 x i16 > : (i32 ) -> !llvm.ptr
752+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> i32
753+ // CHECK-NOT: llvm.bitcast
754+ llvm.return %2 : i32
755+ }
756+
757+ // -----
758+
759+ // CHECK-LABEL: @store_int_to_float
760+ // CHECK-SAME: %[[ARG:.*]]: i32
761+ llvm.func @store_int_to_float (%arg: i32 ) -> i32 {
762+ %0 = llvm.mlir.constant (1 : i32 ) : i32
763+ // CHECK-NOT: llvm.alloca
764+ %1 = llvm.alloca %0 x f32 {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
765+ llvm.store %arg , %1 {alignment = 4 : i64 } : i32 , !llvm.ptr
766+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> i32
767+ // CHECK: llvm.return %[[ARG]]
768+ llvm.return %2 : i32
769+ }
770+
771+ // -----
772+
773+ // CHECK-LABEL: @store_float_to_int
774+ // CHECK-SAME: %[[ARG:.*]]: f32
775+ llvm.func @store_float_to_int (%arg: f32 ) -> i32 {
776+ %0 = llvm.mlir.constant (1 : i32 ) : i32
777+ // CHECK-NOT: llvm.alloca
778+ %1 = llvm.alloca %0 x i32 {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
779+ llvm.store %arg , %1 {alignment = 4 : i64 } : f32 , !llvm.ptr
780+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> i32
781+ // CHECK: %[[BITCAST:.*]] = llvm.bitcast %[[ARG]] : f32 to i32
782+ // CHECK: llvm.return %[[BITCAST]]
783+ llvm.return %2 : i32
784+ }
785+
786+ // -----
787+
788+ // CHECK-LABEL: @store_int_to_vector
789+ // CHECK-SAME: %[[ARG:.*]]: i32
790+ llvm.func @store_int_to_vector (%arg: i32 ) -> vector <4 xi8 > {
791+ %0 = llvm.mlir.constant (1 : i32 ) : i32
792+ // CHECK-NOT: llvm.alloca
793+ %1 = llvm.alloca %0 x vector <2 xi16 > {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
794+ llvm.store %arg , %1 {alignment = 4 : i64 } : i32 , !llvm.ptr
795+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> vector <4 xi8 >
796+ // CHECK: %[[BITCAST0:.*]] = llvm.bitcast %[[ARG]] : i32 to vector<2xi16>
797+ // CHECK: %[[BITCAST1:.*]] = llvm.bitcast %[[BITCAST0]] : vector<2xi16> to vector<4xi8>
798+ // CHECK: llvm.return %[[BITCAST1]]
799+ llvm.return %2 : vector <4 xi8 >
800+ }
801+
802+ // -----
803+
804+ // CHECK-LABEL: @load_ptr_from_int
805+ llvm.func @load_ptr_from_int () -> !llvm.ptr {
806+ %0 = llvm.mlir.constant (1 : i32 ) : i32
807+ // CHECK-NOT: llvm.alloca
808+ %1 = llvm.alloca %0 x i64 {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
809+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> !llvm.ptr
810+ // CHECK: %[[UNDEF:.*]] = llvm.mlir.undef
811+ // CHECK: %[[CAST:.*]] = llvm.inttoptr %[[UNDEF]] : i64 to !llvm.ptr
812+ // CHECK: llvm.return %[[CAST:.*]]
813+ llvm.return %2 : !llvm.ptr
814+ }
815+
816+ // -----
817+
818+ // CHECK-LABEL: @load_int_from_ptr
819+ llvm.func @load_int_from_ptr () -> i64 {
820+ %0 = llvm.mlir.constant (1 : i32 ) : i32
821+ // CHECK-NOT: llvm.alloca
822+ %1 = llvm.alloca %0 x !llvm.ptr {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
823+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> i64
824+ // CHECK: %[[UNDEF:.*]] = llvm.mlir.undef
825+ // CHECK: %[[CAST:.*]] = llvm.ptrtoint %[[UNDEF]] : !llvm.ptr to i64
826+ // CHECK: llvm.return %[[CAST:.*]]
827+ llvm.return %2 : i64
828+ }
829+
830+ // -----
831+
832+ // CHECK-LABEL: @load_ptr_addrspace_cast
833+ llvm.func @load_ptr_addrspace_cast () -> !llvm.ptr <2 > {
834+ %0 = llvm.mlir.constant (1 : i32 ) : i32
835+ // CHECK-NOT: llvm.alloca
836+ %1 = llvm.alloca %0 x !llvm.ptr <1 > {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
837+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> !llvm.ptr <2 >
838+ // CHECK: %[[UNDEF:.*]] = llvm.mlir.undef
839+ // CHECK: %[[CAST:.*]] = llvm.addrspacecast %[[UNDEF]] : !llvm.ptr<1> to !llvm.ptr<2>
840+ // CHECK: llvm.return %[[CAST:.*]]
841+ llvm.return %2 : !llvm.ptr <2 >
842+ }
843+
844+ // -----
845+
846+ // CHECK-LABEL: @stores_with_different_types
847+ // CHECK-SAME: %[[ARG0:.*]]: i64
848+ // CHECK-SAME: %[[ARG1:.*]]: f64
849+ llvm.func @stores_with_different_types (%arg0: i64 , %arg1: f64 , %cond: i1 ) -> f64 {
850+ %0 = llvm.mlir.constant (1 : i32 ) : i32
851+ // CHECK-NOT: llvm.alloca
852+ %1 = llvm.alloca %0 x i64 {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
853+ llvm.cond_br %cond , ^bb1 , ^bb2
854+ ^bb1 :
855+ llvm.store %arg0 , %1 {alignment = 4 : i64 } : i64 , !llvm.ptr
856+ // CHECK: llvm.br ^[[BB3:.*]](%[[ARG0]]
857+ llvm.br ^bb3
858+ ^bb2 :
859+ llvm.store %arg1 , %1 {alignment = 4 : i64 } : f64 , !llvm.ptr
860+ // CHECK: %[[BITCAST:.*]] = llvm.bitcast %[[ARG1]] : f64 to i64
861+ // CHECK: llvm.br ^[[BB3]](%[[BITCAST]]
862+ llvm.br ^bb3
863+ // CHECK: ^[[BB3]](%[[BLOCK_ARG:.*]]: i64)
864+ ^bb3 :
865+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> f64
866+ // CHECK: %[[BITCAST:.*]] = llvm.bitcast %[[BLOCK_ARG]] : i64 to f64
867+ // CHECK: llvm.return %[[BITCAST]]
868+ llvm.return %2 : f64
869+ }
870+
871+ // -----
872+
873+ // Verifies that stores with smaller bitsize inputs are not replaced. A trivial
874+ // implementation will be incorrect due to endianness considerations.
875+
876+ // CHECK-LABEL: @stores_with_different_type_sizes
877+ llvm.func @stores_with_different_type_sizes (%arg0: i64 , %arg1: f32 , %cond: i1 ) -> f64 {
878+ %0 = llvm.mlir.constant (1 : i32 ) : i32
879+ // CHECK: llvm.alloca
880+ %1 = llvm.alloca %0 x i64 {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
881+ llvm.cond_br %cond , ^bb1 , ^bb2
882+ ^bb1 :
883+ llvm.store %arg0 , %1 {alignment = 4 : i64 } : i64 , !llvm.ptr
884+ llvm.br ^bb3
885+ ^bb2 :
886+ llvm.store %arg1 , %1 {alignment = 4 : i64 } : f32 , !llvm.ptr
887+ llvm.br ^bb3
888+ ^bb3 :
889+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> f64
890+ llvm.return %2 : f64
891+ }
892+
893+ // -----
894+
895+ // CHECK-LABEL: @load_smaller_int
896+ llvm.func @load_smaller_int () -> i16 {
897+ %0 = llvm.mlir.constant (1 : i32 ) : i32
898+ // CHECK: llvm.alloca
899+ %1 = llvm.alloca %0 x i32 {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
900+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> i16
901+ llvm.return %2 : i16
902+ }
903+
904+ // -----
905+
906+ // CHECK-LABEL: @load_different_type_smaller
907+ llvm.func @load_different_type_smaller () -> f32 {
908+ %0 = llvm.mlir.constant (1 : i32 ) : i32
909+ // CHECK: llvm.alloca
910+ %1 = llvm.alloca %0 x i64 {alignment = 8 : i64 } : (i32 ) -> !llvm.ptr
911+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> f32
912+ llvm.return %2 : f32
913+ }
914+
915+ // -----
916+
917+ // This alloca is too small for the load, still, mem2reg should not touch it.
918+
919+ // CHECK-LABEL: @impossible_load
920+ llvm.func @impossible_load () -> f64 {
921+ %0 = llvm.mlir.constant (1 : i32 ) : i32
922+ // CHECK: llvm.alloca
923+ %1 = llvm.alloca %0 x i32 {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
924+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> f64
925+ llvm.return %2 : f64
926+ }
927+
928+ // -----
929+
930+ // Verifies that mem2reg does not introduce address space casts of pointers
931+ // with different bitsize.
932+
933+ module attributes { dlti.dl_spec = #dlti.dl_spec <
934+ #dlti.dl_entry <!llvm.ptr <1 >, dense <[32 , 64 , 64 ]> : vector <3 xi64 >>,
935+ #dlti.dl_entry <!llvm.ptr <2 >, dense <[64 , 64 , 64 ]> : vector <3 xi64 >>
936+ >} {
937+
938+ // CHECK-LABEL: @load_ptr_addrspace_cast_different_size
939+ llvm.func @load_ptr_addrspace_cast_different_size () -> !llvm.ptr <2 > {
940+ %0 = llvm.mlir.constant (1 : i32 ) : i32
941+ // CHECK: llvm.alloca
942+ %1 = llvm.alloca %0 x !llvm.ptr <1 > {alignment = 4 : i64 } : (i32 ) -> !llvm.ptr
943+ %2 = llvm.load %1 {alignment = 4 : i64 } : !llvm.ptr -> !llvm.ptr <2 >
944+ llvm.return %2 : !llvm.ptr <2 >
945+ }
946+ }
0 commit comments